/*
This file is part of KMail , the KDE mail client .
Copyright ( c ) 2002 Don Sanders < sanders @ kde . org >
KMail is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License , version 2 , as
published by the Free Software Foundation .
KMail is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
//
// This file implements various "command" classes. These command classes
// are based on the command design pattern.
//
// Historically various operations were implemented as slots of KMMainWin.
// This proved inadequate as KMail has multiple top level windows
// (KMMainWin, KMReaderMainWin, SearchWindow, KMComposeWin) that may
// benefit from using these operations. It is desirable that these
// classes can operate without depending on or altering the state of
// a KMMainWin, in fact it is possible no KMMainWin object even exists.
//
// Now these operations have been rewritten as KMCommand based classes,
// making them independent of KMMainWin.
//
// The base command class KMCommand is async, which is a difference
// from the conventional command pattern. As normal derived classes implement
// the execute method, but client classes call start() instead of
// calling execute() directly. start() initiates async operations,
// and on completion of these operations calls execute() and then deletes
// the command. (So the client must not construct commands on the stack).
//
// The type of async operation supported by KMCommand is retrieval
// of messages from an IMAP server.
# include "kmcommands.h"
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <errno.h>
# include <mimelib/enum.h>
# include <mimelib/field.h>
# include <mimelib/mimepp.h>
# include <mimelib/string.h>
# include <tdeapplication.h>
# include <dcopclient.h>
# include <tqtextcodec.h>
# include <tqpopupmenu.h>
# include <tqeventloop.h>
# include <libemailfunctions/email.h>
# include <kdcopservicestarter.h>
# include <kdebug.h>
# include <tdefiledialog.h>
# include <tdeabc/stdaddressbook.h>
# include <tdeabc/addresseelist.h>
# include <kdirselectdialog.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <tdeparts/browserextension.h>
# include <kprogress.h>
# include <krun.h>
# include <kbookmarkmanager.h>
# include <kstandarddirs.h>
# include <tdetempfile.h>
# include <tdeimproxy.h>
# include <kuserprofile.h>
// TDEIO headers
# include <tdeio/job.h>
# include <tdeio/netaccess.h>
# include <libkpimidentities/identitymanager.h>
# include "actionscheduler.h"
using KMail : : ActionScheduler ;
# include "mailinglist-magic.h"
# include "kmaddrbook.h"
# include <kaddrbook.h>
# include "composer.h"
# include "kmfiltermgr.h"
# include "kmfoldermbox.h"
# include "kmfolderimap.h"
# include "kmfoldermgr.h"
# include "kmheaders.h"
# include "headeritem.h"
# include "kmmainwidget.h"
# include "kmmsgdict.h"
# include "messagesender.h"
# include "kmmsgpartdlg.h"
# include "undostack.h"
# include "kcursorsaver.h"
# include "partNode.h"
# include "objecttreeparser.h"
# include "csshelper.h"
using KMail : : ObjectTreeParser ;
using KMail : : FolderJob ;
# include "chiasmuskeyselector.h"
# include "mailsourceviewer.h"
using KMail : : MailSourceViewer ;
# include "kmreadermainwin.h"
# include "secondarywindow.h"
using KMail : : SecondaryWindow ;
# include "redirectdialog.h"
using KMail : : RedirectDialog ;
# include "util.h"
# include "templateparser.h"
# include "editorwatcher.h"
# include "korghelper.h"
# include "broadcaststatus.h"
# include "globalsettings.h"
# include <libtdepim/tdefileio.h>
# include "kcalendariface_stub.h"
# include "progressmanager.h"
using KPIM : : ProgressManager ;
using KPIM : : ProgressItem ;
# include <kmime_mdn.h>
using namespace KMime ;
# include <kleo/specialjob.h>
# include <kleo/cryptobackend.h>
# include <kleo/cryptobackendfactory.h>
# include <tqclipboard.h>
# include <memory>
class LaterDeleterWithCommandCompletion : public KMail : : Util : : LaterDeleter
{
public :
LaterDeleterWithCommandCompletion ( KMCommand * command )
: LaterDeleter ( command ) , m_result ( KMCommand : : Failed )
{
}
~ LaterDeleterWithCommandCompletion ( )
{
setResult ( m_result ) ;
KMCommand * command = static_cast < KMCommand * > ( m_object ) ;
emit command - > completed ( command ) ;
}
void setResult ( KMCommand : : Result v ) { m_result = v ; }
private :
KMCommand : : Result m_result ;
} ;
KMCommand : : KMCommand ( TQWidget * parent )
: mProgressDialog ( 0 ) , mResult ( Undefined ) , mDeletesItself ( false ) ,
mEmitsCompletedItself ( false ) , mParent ( parent )
{
}
KMCommand : : KMCommand ( TQWidget * parent , const TQPtrList < KMMsgBase > & msgList )
: mProgressDialog ( 0 ) , mResult ( Undefined ) , mDeletesItself ( false ) ,
mEmitsCompletedItself ( false ) , mParent ( parent ) , mMsgList ( msgList )
{
}
KMCommand : : KMCommand ( TQWidget * parent , KMMsgBase * msgBase )
: mProgressDialog ( 0 ) , mResult ( Undefined ) , mDeletesItself ( false ) ,
mEmitsCompletedItself ( false ) , mParent ( parent )
{
mMsgList . append ( msgBase ) ;
}
KMCommand : : KMCommand ( TQWidget * parent , KMMessage * msg )
: mProgressDialog ( 0 ) , mResult ( Undefined ) , mDeletesItself ( false ) ,
mEmitsCompletedItself ( false ) , mParent ( parent )
{
if ( msg )
mMsgList . append ( & msg - > toMsgBase ( ) ) ;
}
KMCommand : : ~ KMCommand ( )
{
TQValueListIterator < TQGuardedPtr < KMFolder > > fit ;
for ( fit = mFolders . begin ( ) ; fit ! = mFolders . end ( ) ; + + fit ) {
if ( ! ( * fit ) )
continue ;
( * fit ) - > close ( " kmcommand " ) ;
}
}
KMCommand : : Result KMCommand : : result ( )
{
if ( mResult = = Undefined )
kdDebug ( 5006 ) < < k_funcinfo < < " mResult is Undefined " < < endl ;
return mResult ;
}
void KMCommand : : start ( )
{
TQTimer : : singleShot ( 0 , this , TQ_SLOT ( slotStart ( ) ) ) ;
}
const TQPtrList < KMMessage > KMCommand : : retrievedMsgs ( ) const
{
return mRetrievedMsgs ;
}
KMMessage * KMCommand : : retrievedMessage ( ) const
{
return mRetrievedMsgs . getFirst ( ) ;
}
TQWidget * KMCommand : : parentWidget ( ) const
{
return mParent ;
}
int KMCommand : : mCountJobs = 0 ;
void KMCommand : : slotStart ( )
{
connect ( this , TQ_SIGNAL ( messagesTransfered ( KMCommand : : Result ) ) ,
this , TQ_SLOT ( slotPostTransfer ( KMCommand : : Result ) ) ) ;
kmkernel - > filterMgr ( ) - > ref ( ) ;
if ( mMsgList . find ( 0 ) ! = - 1 ) {
emit messagesTransfered ( Failed ) ;
return ;
}
if ( ( mMsgList . count ( ) = = 1 ) & &
( mMsgList . getFirst ( ) - > isMessage ( ) ) & &
( mMsgList . getFirst ( ) - > parent ( ) = = 0 ) )
{
// Special case of operating on message that isn't in a folder
mRetrievedMsgs . append ( ( KMMessage * ) mMsgList . getFirst ( ) ) ;
emit messagesTransfered ( OK ) ;
return ;
}
for ( KMMsgBase * mb = mMsgList . first ( ) ; mb ; mb = mMsgList . next ( ) ) {
if ( mb ) {
if ( ! mb - > parent ( ) ) {
emit messagesTransfered ( Failed ) ;
return ;
} else {
keepFolderOpen ( mb - > parent ( ) ) ;
}
}
}
// transfer the selected messages first
transferSelectedMsgs ( ) ;
}
void KMCommand : : slotPostTransfer ( KMCommand : : Result result )
{
disconnect ( this , TQ_SIGNAL ( messagesTransfered ( KMCommand : : Result ) ) ,
this , TQ_SLOT ( slotPostTransfer ( KMCommand : : Result ) ) ) ;
if ( result = = OK )
result = execute ( ) ;
mResult = result ;
TQPtrListIterator < KMMessage > it ( mRetrievedMsgs ) ;
KMMessage * msg ;
while ( ( msg = it . current ( ) ) ! = 0 )
{
+ + it ;
if ( msg - > parent ( ) )
msg - > setTransferInProgress ( false ) ;
}
kmkernel - > filterMgr ( ) - > deref ( ) ;
if ( ! emitsCompletedItself ( ) )
emit completed ( this ) ;
if ( ! deletesItself ( ) )
deleteLater ( ) ;
}
void KMCommand : : transferSelectedMsgs ( )
{
// make sure no other transfer is active
if ( KMCommand : : mCountJobs > 0 ) {
emit messagesTransfered ( Failed ) ;
return ;
}
bool complete = true ;
KMCommand : : mCountJobs = 0 ;
mCountMsgs = 0 ;
mRetrievedMsgs . clear ( ) ;
mCountMsgs = mMsgList . count ( ) ;
uint totalSize = 0 ;
// the KProgressDialog for the user-feedback. Only enable it if it's needed.
// For some commands like KMSeStatusCommand it's not needed. Note, that
// for some reason the KProgressDialog eats the MouseReleaseEvent (if a
// command is executed after the MousePressEvent), cf. bug #71761.
if ( mCountMsgs > 0 ) {
mProgressDialog = new KProgressDialog ( mParent , " transferProgress " ,
i18n ( " Please wait " ) ,
i18n ( " Please wait while the message is transferred " ,
" Please wait while the %n messages are transferred " , mMsgList . count ( ) ) ,
true ) ;
mProgressDialog - > setMinimumDuration ( 1000 ) ;
}
for ( KMMsgBase * mb = mMsgList . first ( ) ; mb ; mb = mMsgList . next ( ) )
{
// check if all messages are complete
KMMessage * thisMsg = 0 ;
if ( mb - > isMessage ( ) )
thisMsg = static_cast < KMMessage * > ( mb ) ;
else
{
KMFolder * folder = mb - > parent ( ) ;
int idx = folder - > find ( mb ) ;
if ( idx < 0 ) continue ;
thisMsg = folder - > getMsg ( idx ) ;
}
if ( ! thisMsg ) continue ;
if ( thisMsg - > transferInProgress ( ) & &
thisMsg - > parent ( ) - > folderType ( ) = = KMFolderTypeImap )
{
thisMsg - > setTransferInProgress ( false , true ) ;
thisMsg - > parent ( ) - > ignoreJobsForMessage ( thisMsg ) ;
}
if ( thisMsg - > parent ( ) & & ! thisMsg - > isComplete ( ) & &
( ! mProgressDialog | | ! mProgressDialog - > wasCancelled ( ) ) )
{
kdDebug ( 5006 ) < < " ### INCOMPLETE \n " ;
// the message needs to be transferred first
complete = false ;
KMCommand : : mCountJobs + + ;
FolderJob * job = thisMsg - > parent ( ) - > createJob ( thisMsg ) ;
job - > setCancellable ( false ) ;
totalSize + = thisMsg - > msgSizeServer ( ) ;
// emitted when the message was transferred successfully
connect ( job , TQ_SIGNAL ( messageRetrieved ( KMMessage * ) ) ,
this , TQ_SLOT ( slotMsgTransfered ( KMMessage * ) ) ) ;
// emitted when the job is destroyed
connect ( job , TQ_SIGNAL ( finished ( ) ) ,
this , TQ_SLOT ( slotJobFinished ( ) ) ) ;
connect ( job , TQ_SIGNAL ( progress ( unsigned long , unsigned long ) ) ,
this , TQ_SLOT ( slotProgress ( unsigned long , unsigned long ) ) ) ;
// msg musn't be deleted
thisMsg - > setTransferInProgress ( true ) ;
job - > start ( ) ;
} else {
thisMsg - > setTransferInProgress ( true ) ;
mRetrievedMsgs . append ( thisMsg ) ;
}
}
if ( complete )
{
delete mProgressDialog ;
mProgressDialog = 0 ;
emit messagesTransfered ( OK ) ;
} else {
// wait for the transfer and tell the progressBar the necessary steps
if ( mProgressDialog ) {
connect ( mProgressDialog , TQ_SIGNAL ( cancelClicked ( ) ) ,
this , TQ_SLOT ( slotTransferCancelled ( ) ) ) ;
mProgressDialog - > progressBar ( ) - > setTotalSteps ( totalSize ) ;
}
}
}
void KMCommand : : slotMsgTransfered ( KMMessage * msg )
{
if ( mProgressDialog & & mProgressDialog - > wasCancelled ( ) ) {
emit messagesTransfered ( Canceled ) ;
return ;
}
// save the complete messages
mRetrievedMsgs . append ( msg ) ;
}
void KMCommand : : slotProgress ( unsigned long done , unsigned long /*total*/ )
{
mProgressDialog - > progressBar ( ) - > setProgress ( done ) ;
}
void KMCommand : : slotJobFinished ( )
{
// the job is finished (with / without error)
KMCommand : : mCountJobs - - ;
if ( mProgressDialog & & mProgressDialog - > wasCancelled ( ) ) return ;
if ( ( mCountMsgs - static_cast < int > ( mRetrievedMsgs . count ( ) ) ) > KMCommand : : mCountJobs )
{
// the message wasn't retrieved before => error
if ( mProgressDialog )
mProgressDialog - > hide ( ) ;
slotTransferCancelled ( ) ;
return ;
}
// update the progressbar
if ( mProgressDialog ) {
mProgressDialog - > setLabel ( i18n ( " Please wait while the message is transferred " ,
" Please wait while the %n messages are transferred " , KMCommand : : mCountJobs ) ) ;
}
if ( KMCommand : : mCountJobs = = 0 )
{
// all done
delete mProgressDialog ;
mProgressDialog = 0 ;
emit messagesTransfered ( OK ) ;
}
}
void KMCommand : : slotTransferCancelled ( )
{
// kill the pending jobs
TQValueListIterator < TQGuardedPtr < KMFolder > > fit ;
for ( fit = mFolders . begin ( ) ; fit ! = mFolders . end ( ) ; + + fit ) {
if ( ! ( * fit ) )
continue ;
KMFolder * folder = * fit ;
KMFolderImap * imapFolder = dynamic_cast < KMFolderImap * > ( folder ) ;
if ( imapFolder & & imapFolder - > account ( ) ) {
imapFolder - > account ( ) - > killAllJobs ( ) ;
}
}
KMCommand : : mCountJobs = 0 ;
mCountMsgs = 0 ;
// unget the transfered messages
TQPtrListIterator < KMMessage > it ( mRetrievedMsgs ) ;
KMMessage * msg ;
while ( ( msg = it . current ( ) ) ! = 0 )
{
KMFolder * folder = msg - > parent ( ) ;
+ + it ;
if ( ! folder )
continue ;
msg - > setTransferInProgress ( false ) ;
int idx = folder - > find ( msg ) ;
if ( idx > 0 ) folder - > unGetMsg ( idx ) ;
}
mRetrievedMsgs . clear ( ) ;
emit messagesTransfered ( Canceled ) ;
}
void KMCommand : : keepFolderOpen ( KMFolder * folder )
{
folder - > open ( " kmcommand " ) ;
mFolders . append ( folder ) ;
}
KMMailtoComposeCommand : : KMMailtoComposeCommand ( const KURL & url ,
KMMessage * msg )
: mUrl ( url ) , mMessage ( msg )
{
}
KMCommand : : Result KMMailtoComposeCommand : : execute ( )
{
KMMessage * msg = new KMMessage ;
uint id = 0 ;
if ( mMessage & & mMessage - > parent ( ) )
id = mMessage - > parent ( ) - > identity ( ) ;
msg - > initHeader ( id ) ;
msg - > setCharset ( " utf-8 " ) ;
msg - > setTo ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( msg , id ) ;
win - > setCharset ( " " , true ) ;
win - > setFocusToSubject ( ) ;
win - > show ( ) ;
return OK ;
}
KMMailtoReplyCommand : : KMMailtoReplyCommand ( TQWidget * parent ,
const KURL & url , KMMessage * msg , const TQString & selection )
: KMCommand ( parent , msg ) , mUrl ( url ) , mSelection ( selection )
{
}
KMCommand : : Result KMMailtoReplyCommand : : execute ( )
{
//TODO : consider factoring createReply into this method.
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * rmsg = msg - > createReply ( KMail : : ReplyNone , mSelection ) ;
rmsg - > setTo ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( rmsg , 0 ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMMailtoForwardCommand : : KMMailtoForwardCommand ( TQWidget * parent ,
const KURL & url , KMMessage * msg )
: KMCommand ( parent , msg ) , mUrl ( url )
{
}
KMCommand : : Result KMMailtoForwardCommand : : execute ( )
{
//TODO : consider factoring createForward into this method.
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * fmsg = msg - > createForward ( ) ;
fmsg - > setTo ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( fmsg ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > show ( ) ;
return OK ;
}
KMAddBookmarksCommand : : KMAddBookmarksCommand ( const KURL & url , TQWidget * parent )
: KMCommand ( parent ) , mUrl ( url )
{
}
KMCommand : : Result KMAddBookmarksCommand : : execute ( )
{
TQString filename = locateLocal ( " data " , TQString : : fromLatin1 ( " konqueror/bookmarks.xml " ) ) ;
KBookmarkManager * bookManager = KBookmarkManager : : managerForFile ( filename ,
false ) ;
KBookmarkGroup group = bookManager - > root ( ) ;
group . addBookmark ( bookManager , mUrl . path ( ) , KURL ( mUrl ) ) ;
if ( bookManager - > save ( ) ) {
bookManager - > emitChanged ( group ) ;
}
return OK ;
}
KMMailtoAddAddrBookCommand : : KMMailtoAddAddrBookCommand ( const KURL & url ,
TQWidget * parent )
: KMCommand ( parent ) , mUrl ( url )
{
}
KMCommand : : Result KMMailtoAddAddrBookCommand : : execute ( )
{
KAddrBookExternal : : addEmail ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ,
parentWidget ( ) ) ;
return OK ;
}
KMMailtoOpenAddrBookCommand : : KMMailtoOpenAddrBookCommand ( const KURL & url ,
TQWidget * parent )
: KMCommand ( parent ) , mUrl ( url )
{
}
KMCommand : : Result KMMailtoOpenAddrBookCommand : : execute ( )
{
KAddrBookExternal : : openEmail ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ,
parentWidget ( ) ) ;
return OK ;
}
KMUrlCopyCommand : : KMUrlCopyCommand ( const KURL & url , KMMainWidget * mainWidget )
: mUrl ( url ) , mMainWidget ( mainWidget )
{
}
KMCommand : : Result KMUrlCopyCommand : : execute ( )
{
TQClipboard * clip = TQApplication : : clipboard ( ) ;
if ( mUrl . protocol ( ) = = " mailto " ) {
// put the url into the mouse selection and the clipboard
TQString address = KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ;
clip - > setSelectionMode ( true ) ;
clip - > setText ( address ) ;
clip - > setSelectionMode ( false ) ;
clip - > setText ( address ) ;
KPIM : : BroadcastStatus : : instance ( ) - > setStatusMsg ( i18n ( " Address copied to clipboard. " ) ) ;
} else {
// put the url into the mouse selection and the clipboard
clip - > setSelectionMode ( true ) ;
clip - > setText ( mUrl . url ( ) ) ;
clip - > setSelectionMode ( false ) ;
clip - > setText ( mUrl . url ( ) ) ;
KPIM : : BroadcastStatus : : instance ( ) - > setStatusMsg ( i18n ( " URL copied to clipboard. " ) ) ;
}
return OK ;
}
KMUrlOpenCommand : : KMUrlOpenCommand ( const KURL & url , KMReaderWin * readerWin )
: mUrl ( url ) , mReaderWin ( readerWin )
{
}
KMCommand : : Result KMUrlOpenCommand : : execute ( )
{
if ( ! mUrl . isEmpty ( ) )
mReaderWin - > slotUrlOpen ( mUrl , KParts : : URLArgs ( ) ) ;
return OK ;
}
KMUrlSaveCommand : : KMUrlSaveCommand ( const KURL & url , TQWidget * parent )
: KMCommand ( parent ) , mUrl ( url )
{
}
KMCommand : : Result KMUrlSaveCommand : : execute ( )
{
if ( mUrl . isEmpty ( ) )
return OK ;
KURL saveUrl = KFileDialog : : getSaveURL ( mUrl . fileName ( ) , TQString ( ) ,
parentWidget ( ) ) ;
if ( saveUrl . isEmpty ( ) )
return Canceled ;
if ( TDEIO : : NetAccess : : exists ( saveUrl , false , parentWidget ( ) ) )
{
if ( KMessageBox : : warningContinueCancel ( 0 ,
i18n ( " <qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt> " )
. arg ( saveUrl . prettyURL ( ) ) , i18n ( " Save to File " ) , i18n ( " &Replace " ) )
! = KMessageBox : : Continue )
return Canceled ;
}
TDEIO : : Job * job = TDEIO : : file_copy ( mUrl , saveUrl , - 1 , true ) ;
connect ( job , TQ_SIGNAL ( result ( TDEIO : : Job * ) ) , TQ_SLOT ( slotUrlSaveResult ( TDEIO : : Job * ) ) ) ;
setEmitsCompletedItself ( true ) ;
return OK ;
}
void KMUrlSaveCommand : : slotUrlSaveResult ( TDEIO : : Job * job )
{
if ( job - > error ( ) ) {
job - > showErrorDialog ( ) ;
setResult ( Failed ) ;
emit completed ( this ) ;
}
else {
setResult ( OK ) ;
emit completed ( this ) ;
}
}
KMEditMsgCommand : : KMEditMsgCommand ( TQWidget * parent , KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMEditMsgCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > parent ( ) | |
( ! kmkernel - > folderIsDraftOrOutbox ( msg - > parent ( ) ) & &
! kmkernel - > folderIsTemplates ( msg - > parent ( ) ) ) )
return Failed ;
// Remember the old parent, we need it a bit further down to be able
// to put the unchanged messsage back in the original folder if the nth
// edit is discarded, for n > 1.
KMFolder * parent = msg - > parent ( ) ;
if ( parent )
parent - > take ( parent - > find ( msg ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( ) ;
msg - > setTransferInProgress ( false ) ; // From here on on, the composer owns the message.
win - > setMsg ( msg , false , true ) ;
win - > setFolder ( parent ) ;
win - > show ( ) ;
return OK ;
}
KMUseTemplateCommand : : KMUseTemplateCommand ( TQWidget * parent , KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMUseTemplateCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > parent ( ) | |
! kmkernel - > folderIsTemplates ( msg - > parent ( ) ) )
return Failed ;
// Take a copy of the original message, which remains unchanged.
KMMessage * newMsg = new KMMessage ( new DwMessage ( * msg - > asDwMessage ( ) ) ) ;
newMsg - > setComplete ( msg - > isComplete ( ) ) ;
// these fields need to be regenerated for the new message
newMsg - > removeHeaderField ( " Date " ) ;
newMsg - > removeHeaderField ( " Message-ID " ) ;
KMail : : Composer * win = KMail : : makeComposer ( ) ;
newMsg - > setTransferInProgress ( false ) ; // From here on on, the composer owns the message.
win - > setMsg ( newMsg , false , true ) ;
win - > show ( ) ;
return OK ;
}
KMShowMsgSrcCommand : : KMShowMsgSrcCommand ( TQWidget * parent ,
KMMessage * msg , bool fixedFont )
: KMCommand ( parent , msg ) , mFixedFont ( fixedFont )
{
// remember complete state
mMsgWasComplete = msg - > isComplete ( ) ;
}
KMCommand : : Result KMShowMsgSrcCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
if ( msg - > isComplete ( ) & & ! mMsgWasComplete )
msg - > notify ( ) ; // notify observers as msg was transfered
TQString str = msg - > codec ( ) - > toUnicode ( msg - > asString ( ) ) ;
MailSourceViewer * viewer = new MailSourceViewer ( ) ; // deletes itself upon close
viewer - > setCaption ( i18n ( " Message as Plain Text " ) ) ;
viewer - > setText ( str ) ;
if ( mFixedFont )
viewer - > setFont ( TDEGlobalSettings : : fixedFont ( ) ) ;
// Well, there is no widget to be seen here, so we have to use TQCursor::pos()
// Update: (GS) I'm not going to make this code behave according to Xinerama
// configuration because this is quite the hack.
if ( TQApplication : : desktop ( ) - > isVirtualDesktop ( ) ) {
int scnum = TQApplication : : desktop ( ) - > screenNumber ( TQCursor : : pos ( ) ) ;
viewer - > resize ( TQApplication : : desktop ( ) - > screenGeometry ( scnum ) . width ( ) / 2 ,
2 * TQApplication : : desktop ( ) - > screenGeometry ( scnum ) . height ( ) / 3 ) ;
} else {
viewer - > resize ( TQApplication : : desktop ( ) - > geometry ( ) . width ( ) / 2 ,
2 * TQApplication : : desktop ( ) - > geometry ( ) . height ( ) / 3 ) ;
}
viewer - > show ( ) ;
return OK ;
}
static KURL subjectToUrl ( const TQString & subject )
{
// We need to replace colons with underscores since those cause problems with KFileDialog (bug
// in KFileDialog though) and also on Windows filesystems.
// We also look at the special case of ": ", since converting that to "_ " would look strange,
// simply "_" looks better.
// We also don't allow filenames starting with a dot, since then the file is hidden and the poor
// user can't find it anymore.
// Don't allow filenames starting with a tilde either, since that will cause the file dialog to
// discard the filename entirely.
// https://issues.kolab.org/issue3805
const TQString filter = i18n ( " *.mbox|email messages (*.mbox) \n *|all files (*) " ) ;
TQString cleanSubject = subject . stripWhiteSpace ( )
. replace ( TQDir : : separator ( ) , ' _ ' )
. replace ( " : " , " _ " )
. replace ( ' : ' , ' _ ' )
. replace ( ' . ' , ' _ ' )
. replace ( ' ~ ' , ' _ ' ) ;
return KFileDialog : : getSaveURL ( cleanSubject , filter ) ;
}
KMSaveMsgCommand : : KMSaveMsgCommand ( TQWidget * parent , KMMessage * msg )
: KMCommand ( parent ) ,
mMsgListIndex ( 0 ) ,
mStandAloneMessage ( 0 ) ,
mOffset ( 0 ) ,
mTotalSize ( msg ? msg - > msgSize ( ) : 0 )
{
if ( ! msg ) return ;
setDeletesItself ( true ) ;
// If the mail has a serial number, operate on sernums, if it does not
// we need to work with the pointer, but can be reasonably sure it won't
// go away, since it'll be an encapsulated message or one that was opened
// from an .eml file.
if ( msg - > getMsgSerNum ( ) ! = 0 ) {
mMsgList . append ( msg - > getMsgSerNum ( ) ) ;
if ( msg - > parent ( ) ) {
msg - > parent ( ) - > open ( " kmsavemsgcommand " ) ;
}
} else {
mStandAloneMessage = msg ;
}
mUrl = subjectToUrl ( msg - > cleanSubject ( ) ) ;
}
KMSaveMsgCommand : : KMSaveMsgCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList )
: KMCommand ( parent ) ,
mMsgListIndex ( 0 ) ,
mStandAloneMessage ( 0 ) ,
mOffset ( 0 ) ,
mTotalSize ( 0 )
{
if ( ! msgList . getFirst ( ) )
return ;
setDeletesItself ( true ) ;
KMMsgBase * msgBase = msgList . getFirst ( ) ;
// We operate on serNums and not the KMMsgBase pointers, as those can
// change, or become invalid when changing the current message, switching
// folders, etc.
TQPtrListIterator < KMMsgBase > it ( msgList ) ;
while ( it . current ( ) ) {
mMsgList . append ( ( * it ) - > getMsgSerNum ( ) ) ;
mTotalSize + = ( * it ) - > msgSize ( ) ;
if ( ( * it ) - > parent ( ) ! = 0 )
( * it ) - > parent ( ) - > open ( " kmcommand " ) ;
+ + it ;
}
mMsgListIndex = 0 ;
mUrl = subjectToUrl ( msgBase - > cleanSubject ( ) ) ;
}
KURL KMSaveMsgCommand : : url ( )
{
return mUrl ;
}
KMCommand : : Result KMSaveMsgCommand : : execute ( )
{
mJob = TDEIO : : put ( mUrl , S_IRUSR | S_IWUSR , false , false ) ;
mJob - > slotTotalSize ( mTotalSize ) ;
mJob - > setAsyncDataEnabled ( true ) ;
mJob - > setReportDataSent ( true ) ;
connect ( mJob , TQ_SIGNAL ( dataReq ( TDEIO : : Job * , TQByteArray & ) ) ,
TQ_SLOT ( slotSaveDataReq ( ) ) ) ;
connect ( mJob , TQ_SIGNAL ( result ( TDEIO : : Job * ) ) ,
TQ_SLOT ( slotSaveResult ( TDEIO : : Job * ) ) ) ;
setEmitsCompletedItself ( true ) ;
return OK ;
}
void KMSaveMsgCommand : : slotSaveDataReq ( )
{
int remainingBytes = mData . size ( ) - mOffset ;
if ( remainingBytes > 0 ) {
// eat leftovers first
if ( remainingBytes > MAX_CHUNK_SIZE )
remainingBytes = MAX_CHUNK_SIZE ;
TQByteArray data ;
data . duplicate ( mData . data ( ) + mOffset , remainingBytes ) ;
mJob - > sendAsyncData ( data ) ;
mOffset + = remainingBytes ;
return ;
}
// No leftovers, process next message.
if ( mMsgListIndex < mMsgList . size ( ) ) {
KMMessage * msg = 0 ;
int idx = - 1 ;
KMFolder * p = 0 ;
KMMsgDict : : instance ( ) - > getLocation ( mMsgList [ mMsgListIndex ] , & p , & idx ) ;
assert ( p ) ;
assert ( idx > = 0 ) ;
//kdDebug() << "SERNUM: " << mMsgList[mMsgListIndex] << " idx: " << idx << " folder: " << p->prettyURL() << endl;
const bool alreadyGot = p - > isMessage ( idx ) ;
msg = p - > getMsg ( idx ) ;
if ( msg ) {
// Only unGet the message if it isn't already got.
if ( ! alreadyGot ) {
mUngetMsgs . append ( msg ) ;
}
if ( msg - > transferInProgress ( ) ) {
TQByteArray data = TQByteArray ( ) ;
mJob - > sendAsyncData ( data ) ;
}
msg - > setTransferInProgress ( true ) ;
if ( msg - > isComplete ( ) ) {
slotMessageRetrievedForSaving ( msg ) ;
} else {
// retrieve Message first
if ( msg - > parent ( ) & & ! msg - > isComplete ( ) ) {
FolderJob * job = msg - > parent ( ) - > createJob ( msg ) ;
job - > setCancellable ( false ) ;
connect ( job , TQ_SIGNAL ( messageRetrieved ( KMMessage * ) ) ,
this , TQ_SLOT ( slotMessageRetrievedForSaving ( KMMessage * ) ) ) ;
job - > start ( ) ;
}
}
} else {
mJob - > slotError ( TDEIO : : ERR_ABORTED ,
i18n ( " The message was removed while saving it. "
" It has not been saved. " ) ) ;
}
} else {
if ( mStandAloneMessage ) {
// do the special case of a standalone message
slotMessageRetrievedForSaving ( mStandAloneMessage ) ;
mStandAloneMessage = 0 ;
} else {
// No more messages. Tell the putjob we are done.
TQByteArray data = TQByteArray ( ) ;
mJob - > sendAsyncData ( data ) ;
}
}
}
void KMSaveMsgCommand : : slotMessageRetrievedForSaving ( KMMessage * msg )
{
if ( msg ) {
mData = KMFolderMbox : : escapeFrom ( msg - > asDwString ( ) ) ;
KMail : : Util : : insert ( mData , 0 , msg - > mboxMessageSeparator ( ) ) ;
KMail : : Util : : append ( mData , " \n " ) ;
msg - > setTransferInProgress ( false ) ;
mOffset = 0 ;
TQByteArray data ;
int size ;
// Unless it is great than 64 k send the whole message. tdeio buffers for us.
if ( mData . size ( ) > ( unsigned int ) MAX_CHUNK_SIZE )
size = MAX_CHUNK_SIZE ;
else
size = mData . size ( ) ;
data . duplicate ( mData , size ) ;
mJob - > sendAsyncData ( data ) ;
mOffset + = size ;
}
+ + mMsgListIndex ;
// Get rid of the message.
if ( msg & & msg - > parent ( ) & & msg - > getMsgSerNum ( ) & &
mUngetMsgs . contains ( msg ) ) {
int idx = - 1 ;
KMFolder * p = 0 ;
KMMsgDict : : instance ( ) - > getLocation ( msg , & p , & idx ) ;
assert ( p = = msg - > parent ( ) ) ; assert ( idx > = 0 ) ;
p - > unGetMsg ( idx ) ;
p - > close ( " kmcommand " ) ;
}
}
void KMSaveMsgCommand : : slotSaveResult ( TDEIO : : Job * job )
{
if ( job - > error ( ) )
{
if ( job - > error ( ) = = TDEIO : : ERR_FILE_ALREADY_EXIST )
{
if ( KMessageBox : : warningContinueCancel ( 0 ,
i18n ( " File %1 exists. \n Do you want to replace it? " )
. arg ( mUrl . prettyURL ( ) ) , i18n ( " Save to File " ) , i18n ( " &Replace " ) )
= = KMessageBox : : Continue ) {
mOffset = 0 ;
mJob = TDEIO : : put ( mUrl , S_IRUSR | S_IWUSR , true , false ) ;
mJob - > slotTotalSize ( mTotalSize ) ;
mJob - > setAsyncDataEnabled ( true ) ;
mJob - > setReportDataSent ( true ) ;
connect ( mJob , TQ_SIGNAL ( dataReq ( TDEIO : : Job * , TQByteArray & ) ) ,
TQ_SLOT ( slotSaveDataReq ( ) ) ) ;
connect ( mJob , TQ_SIGNAL ( result ( TDEIO : : Job * ) ) ,
TQ_SLOT ( slotSaveResult ( TDEIO : : Job * ) ) ) ;
}
}
else
{
job - > showErrorDialog ( ) ;
setResult ( Failed ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
} else {
setResult ( OK ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
}
//-----------------------------------------------------------------------------
KMOpenMsgCommand : : KMOpenMsgCommand ( TQWidget * parent , const KURL & url ,
const TQString & encoding )
: KMCommand ( parent ) ,
mUrl ( url ) ,
mEncoding ( encoding )
{
setDeletesItself ( true ) ;
}
KMCommand : : Result KMOpenMsgCommand : : execute ( )
{
if ( mUrl . isEmpty ( ) ) {
mUrl = KFileDialog : : getOpenURL ( " :OpenMessage " , " message/rfc822 application/mbox " ,
parentWidget ( ) , i18n ( " Open Message " ) ) ;
}
if ( mUrl . isEmpty ( ) ) {
setDeletesItself ( false ) ;
return Canceled ;
}
mJob = TDEIO : : get ( mUrl , false , false ) ;
mJob - > setReportDataSent ( true ) ;
connect ( mJob , TQ_SIGNAL ( data ( TDEIO : : Job * , const TQByteArray & ) ) ,
this , TQ_SLOT ( slotDataArrived ( TDEIO : : Job * , const TQByteArray & ) ) ) ;
connect ( mJob , TQ_SIGNAL ( result ( TDEIO : : Job * ) ) ,
TQ_SLOT ( slotResult ( TDEIO : : Job * ) ) ) ;
setEmitsCompletedItself ( true ) ;
return OK ;
}
void KMOpenMsgCommand : : slotDataArrived ( TDEIO : : Job * , const TQByteArray & data )
{
if ( data . isEmpty ( ) )
return ;
mMsgString . append ( data . data ( ) , data . size ( ) ) ;
}
void KMOpenMsgCommand : : slotResult ( TDEIO : : Job * job )
{
if ( job - > error ( ) ) {
// handle errors
job - > showErrorDialog ( ) ;
setResult ( Failed ) ;
emit completed ( this ) ;
}
else {
int startOfMessage = 0 ;
if ( mMsgString . compare ( 0 , 5 , " From " , 5 ) = = 0 ) {
startOfMessage = mMsgString . find ( ' \n ' ) ;
if ( startOfMessage = = - 1 ) {
KMessageBox : : sorry ( parentWidget ( ) ,
i18n ( " The file does not contain a message. " ) ) ;
setResult ( Failed ) ;
emit completed ( this ) ;
// Emulate closing of a secondary window so that KMail exits in case it
// was started with the --view command line option. Otherwise an
// invisible KMail would keep running.
SecondaryWindow * win = new SecondaryWindow ( ) ;
win - > close ( ) ;
win - > deleteLater ( ) ;
deleteLater ( ) ;
return ;
}
startOfMessage + = 1 ; // the message starts after the '\n'
}
// check for multiple messages in the file
bool multipleMessages = true ;
int endOfMessage = mMsgString . find ( " \n From " ) ;
if ( endOfMessage = = - 1 ) {
endOfMessage = mMsgString . length ( ) ;
multipleMessages = false ;
}
DwMessage * dwMsg = new DwMessage ;
dwMsg - > FromString ( mMsgString . substr ( startOfMessage ,
endOfMessage - startOfMessage ) ) ;
dwMsg - > Parse ( ) ;
// check whether we have a message ( no headers => this isn't a message )
if ( dwMsg - > Headers ( ) . NumFields ( ) = = 0 ) {
KMessageBox : : sorry ( parentWidget ( ) ,
i18n ( " The file does not contain a message. " ) ) ;
delete dwMsg ; dwMsg = 0 ;
setResult ( Failed ) ;
emit completed ( this ) ;
// Emulate closing of a secondary window (see above).
SecondaryWindow * win = new SecondaryWindow ( ) ;
win - > close ( ) ;
win - > deleteLater ( ) ;
deleteLater ( ) ;
return ;
}
KMMessage * msg = new KMMessage ( dwMsg ) ;
msg - > setReadyToShow ( true ) ;
KMReaderMainWin * win = new KMReaderMainWin ( ) ;
win - > showMsg ( mEncoding , msg ) ;
win - > show ( ) ;
if ( multipleMessages )
KMessageBox : : information ( win ,
i18n ( " The file contains multiple messages. "
" Only the first message is shown. " ) ) ;
setResult ( OK ) ;
emit completed ( this ) ;
}
deleteLater ( ) ;
}
//-----------------------------------------------------------------------------
//TODO: ReplyTo, NoQuoteReplyTo, ReplyList, ReplyToAll, ReplyAuthor
// are all similar and should be factored
KMReplyToCommand : : KMReplyToCommand ( TQWidget * parent , KMMessage * msg ,
const TQString & selection )
: KMCommand ( parent , msg ) , mSelection ( selection )
{
}
KMCommand : : Result KMReplyToCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
// Find the account that held the original message
TQString accountName ;
KMFolder * parentFolder = msg - > parent ( ) ;
if ( parentFolder ) {
KMFolderDir * parentFolderDir = parentFolder - > parent ( ) ;
while ( parentFolderDir ) {
TQString prettyURL = parentFolderDir - > prettyURL ( ) ;
if ( prettyURL ! = " " ) {
accountName = prettyURL ;
}
parentFolderDir = parentFolderDir - > parent ( ) ;
}
}
KMMessage * reply = msg - > createReply ( KMail : : ReplySmart , mSelection , false , true , TQString ( ) , accountName ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMNoQuoteReplyToCommand : : KMNoQuoteReplyToCommand ( TQWidget * parent ,
KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMNoQuoteReplyToCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplySmart , " " , true ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( false ) ;
win - > show ( ) ;
return OK ;
}
KMReplyListCommand : : KMReplyListCommand ( TQWidget * parent ,
KMMessage * msg , const TQString & selection )
: KMCommand ( parent , msg ) , mSelection ( selection )
{
}
KMCommand : : Result KMReplyListCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplyList , mSelection ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( false ) ;
win - > show ( ) ;
return OK ;
}
KMReplyToAllCommand : : KMReplyToAllCommand ( TQWidget * parent ,
KMMessage * msg , const TQString & selection )
: KMCommand ( parent , msg ) , mSelection ( selection )
{
}
KMCommand : : Result KMReplyToAllCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplyAll , mSelection ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMReplyAuthorCommand : : KMReplyAuthorCommand ( TQWidget * parent , KMMessage * msg ,
const TQString & selection )
: KMCommand ( parent , msg ) , mSelection ( selection )
{
}
KMCommand : : Result KMReplyAuthorCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplyAuthor , mSelection ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMForwardInlineCommand : : KMForwardInlineCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList , uint identity )
: KMCommand ( parent , msgList ) ,
mIdentity ( identity )
{
}
KMForwardInlineCommand : : KMForwardInlineCommand ( TQWidget * parent ,
KMMessage * msg , uint identity )
: KMCommand ( parent , msg ) ,
mIdentity ( identity )
{
}
KMCommand : : Result KMForwardInlineCommand : : execute ( )
{
TQPtrList < KMMessage > msgList = retrievedMsgs ( ) ;
if ( msgList . count ( ) > = 2 ) { // Multiple forward
uint id = 0 ;
TQPtrList < KMMessage > linklist ;
for ( KMMessage * msg = msgList . first ( ) ; msg ; msg = msgList . next ( ) ) {
// set the identity
if ( id = = 0 )
id = msg - > headerField ( " X-KMail-Identity " ) . stripWhiteSpace ( ) . toUInt ( ) ;
// msgText += msg->createForwardBody();
linklist . append ( msg ) ;
}
if ( id = = 0 )
id = mIdentity ; // use folder identity if no message had an id set
KMMessage * fwdMsg = new KMMessage ;
fwdMsg - > initHeader ( id ) ;
fwdMsg - > setAutomaticFields ( true ) ;
fwdMsg - > setCharset ( " utf-8 " ) ;
// fwdMsg->setBody( msgText );
for ( KMMessage * msg = linklist . first ( ) ; msg ; msg = linklist . next ( ) ) {
TemplateParser parser ( fwdMsg , TemplateParser : : Forward ) ;
parser . setSelection ( msg - > body ( ) ) ; // FIXME: Why is this needed?
parser . process ( msg , 0 , true ) ;
fwdMsg - > link ( msg , KMMsgStatusForwarded ) ;
}
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( fwdMsg , id ) ;
win - > setCharset ( " " ) ;
win - > show ( ) ;
} else { // forward a single message at most
KMMessage * msg = msgList . getFirst ( ) ;
if ( ! msg | | ! msg - > codec ( ) )
return Failed ;
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * fwdMsg = msg - > createForward ( ) ;
uint id = msg - > headerField ( " X-KMail-Identity " ) . stripWhiteSpace ( ) . toUInt ( ) ;
if ( id = = 0 )
id = mIdentity ;
{
KMail : : Composer * win = KMail : : makeComposer ( fwdMsg , id ) ;
win - > setCharset ( fwdMsg - > codec ( ) - > mimeName ( ) , true ) ;
win - > show ( ) ;
}
}
return OK ;
}
KMForwardAttachedCommand : : KMForwardAttachedCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList , uint identity , KMail : : Composer * win )
: KMCommand ( parent , msgList ) , mIdentity ( identity ) ,
mWin ( TQGuardedPtr < KMail : : Composer > ( win ) )
{
}
KMForwardAttachedCommand : : KMForwardAttachedCommand ( TQWidget * parent ,
KMMessage * msg , uint identity , KMail : : Composer * win )
: KMCommand ( parent , msg ) , mIdentity ( identity ) ,
mWin ( TQGuardedPtr < KMail : : Composer > ( win ) )
{
}
KMCommand : : Result KMForwardAttachedCommand : : execute ( )
{
TQPtrList < KMMessage > msgList = retrievedMsgs ( ) ;
KMMessage * fwdMsg = new KMMessage ;
if ( msgList . count ( ) > = 2 ) {
// don't respect X-KMail-Identity headers because they might differ for
// the selected mails
fwdMsg - > initHeader ( mIdentity ) ;
}
else if ( msgList . count ( ) = = 1 ) {
KMMessage * msg = msgList . getFirst ( ) ;
fwdMsg - > initFromMessage ( msg ) ;
fwdMsg - > setSubject ( msg - > forwardSubject ( ) ) ;
}
fwdMsg - > setAutomaticFields ( true ) ;
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
if ( ! mWin )
mWin = KMail : : makeComposer ( fwdMsg , mIdentity ) ;
// iterate through all the messages to be forwarded
for ( KMMessage * msg = msgList . first ( ) ; msg ; msg = msgList . next ( ) ) {
// remove headers that shouldn't be forwarded
msg - > removePrivateHeaderFields ( ) ;
msg - > removeHeaderField ( " BCC " ) ;
// set the part
KMMessagePart * msgPart = new KMMessagePart ;
msgPart - > setTypeStr ( " message " ) ;
msgPart - > setSubtypeStr ( " rfc822 " ) ;
msgPart - > setName ( " forwarded message " ) ;
msgPart - > setContentDescription ( msg - > from ( ) + " : " + msg - > subject ( ) ) ;
msgPart - > setContentDisposition ( " inline " ) ;
msgPart - > setMessageBody ( KMail : : Util : : ByteArray ( msg - > asDwString ( ) ) ) ;
fwdMsg - > link ( msg , KMMsgStatusForwarded ) ;
mWin - > addAttach ( msgPart ) ;
}
mWin - > show ( ) ;
return OK ;
}
KMForwardDigestCommand : : KMForwardDigestCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList , uint identity , KMail : : Composer * win )
: KMCommand ( parent , msgList ) , mIdentity ( identity ) ,
mWin ( TQGuardedPtr < KMail : : Composer > ( win ) )
{
}
KMForwardDigestCommand : : KMForwardDigestCommand ( TQWidget * parent ,
KMMessage * msg , uint identity , KMail : : Composer * win )
: KMCommand ( parent , msg ) , mIdentity ( identity ) ,
mWin ( TQGuardedPtr < KMail : : Composer > ( win ) )
{
}
KMCommand : : Result KMForwardDigestCommand : : execute ( )
{
TQPtrList < KMMessage > msgList = retrievedMsgs ( ) ;
if ( msgList . count ( ) < 2 )
return Undefined ; // must have more than 1 for a digest
uint id = 0 ;
KMMessage * fwdMsg = new KMMessage ;
KMMessagePart * msgPart = new KMMessagePart ;
TQString msgPartText ;
int msgCnt = 0 ; // incase there are some we can't forward for some reason
// dummy header initialization; initialization with the correct identity
// is done below
fwdMsg - > initHeader ( id ) ;
fwdMsg - > setAutomaticFields ( true ) ;
fwdMsg - > mMsg - > Headers ( ) . ContentType ( ) . CreateBoundary ( 1 ) ;
TQCString boundary ( fwdMsg - > mMsg - > Headers ( ) . ContentType ( ) . Boundary ( ) . c_str ( ) ) ;
msgPartText = i18n ( " \n This is a MIME digest forward. The content of the "
" message is contained in the attachment(s). \n \n \n " ) ;
// iterate through all the messages to be forwarded
for ( KMMessage * msg = msgList . first ( ) ; msg ; msg = msgList . next ( ) ) {
// set the identity
if ( id = = 0 )
id = msg - > headerField ( " X-KMail-Identity " ) . stripWhiteSpace ( ) . toUInt ( ) ;
// set the part header
msgPartText + = " -- " ;
msgPartText + = TQString : : fromLatin1 ( boundary ) ;
msgPartText + = " \n Content-Type: MESSAGE/RFC822 " ;
msgPartText + = TQString ( " ; CHARSET=%1 " ) . arg ( TQString ( msg - > charset ( ) ) ) ;
msgPartText + = ' \n ' ;
DwHeaders dwh ;
dwh . MessageId ( ) . CreateDefault ( ) ;
msgPartText + = TQString ( " Content-ID: %1 \n " ) . arg ( dwh . MessageId ( ) . AsString ( ) . c_str ( ) ) ;
msgPartText + = TQString ( " Content-Description: %1 " ) . arg ( msg - > subject ( ) ) ;
if ( ! msg - > subject ( ) . contains ( " (fwd) " ) )
msgPartText + = " (fwd) " ;
msgPartText + = " \n \n " ;
// remove headers that shouldn't be forwarded
msg - > removePrivateHeaderFields ( ) ;
msg - > removeHeaderField ( " BCC " ) ;
// set the part
msgPartText + = msg - > headerAsString ( ) ;
msgPartText + = ' \n ' ;
msgPartText + = msg - > body ( ) ;
msgPartText + = ' \n ' ; // eot
msgCnt + + ;
fwdMsg - > link ( msg , KMMsgStatusForwarded ) ;
}
if ( id = = 0 )
id = mIdentity ; // use folder identity if no message had an id set
fwdMsg - > initHeader ( id ) ;
msgPartText + = " -- " ;
msgPartText + = TQString : : fromLatin1 ( boundary ) ;
msgPartText + = " -- \n " ;
TQCString tmp ;
msgPart - > setTypeStr ( " MULTIPART " ) ;
tmp . sprintf ( " Digest; boundary= \" %s \" " , boundary . data ( ) ) ;
msgPart - > setSubtypeStr ( tmp ) ;
msgPart - > setName ( " unnamed " ) ;
msgPart - > setCte ( DwMime : : kCte7bit ) ; // does it have to be 7bit?
msgPart - > setContentDescription ( TQString ( " Digest of %1 messages. " ) . arg ( msgCnt ) ) ;
// THIS HAS TO BE AFTER setCte()!!!!
msgPart - > setBodyEncoded ( TQCString ( msgPartText . ascii ( ) ) ) ;
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( fwdMsg , id ) ;
win - > addAttach ( msgPart ) ;
win - > show ( ) ;
return OK ;
}
KMRedirectCommand : : KMRedirectCommand ( TQWidget * parent ,
KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMRedirectCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) )
return Failed ;
RedirectDialog dlg ( parentWidget ( ) , " redirect " , true ,
kmkernel - > msgSender ( ) - > sendImmediate ( ) ) ;
if ( dlg . exec ( ) = = TQDialog : : Rejected ) return Failed ;
KMMessage * newMsg = msg - > createRedirect ( dlg . to ( ) ) ;
KMFilterAction : : sendMDN ( msg , KMime : : MDN : : Dispatched ) ;
const KMail : : MessageSender : : SendMethod method = dlg . sendImmediate ( )
? KMail : : MessageSender : : SendImmediate
: KMail : : MessageSender : : SendLater ;
if ( ! kmkernel - > msgSender ( ) - > send ( newMsg , method ) ) {
kdDebug ( 5006 ) < < " KMRedirectCommand: could not redirect message (sending failed) " < < endl ;
return Failed ; // error: couldn't send
}
return OK ;
}
KMCustomReplyToCommand : : KMCustomReplyToCommand ( TQWidget * parent , KMMessage * msg ,
const TQString & selection ,
const TQString & tmpl )
: KMCommand ( parent , msg ) , mSelection ( selection ) , mTemplate ( tmpl )
{
}
KMCommand : : Result KMCustomReplyToCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplySmart , mSelection ,
false , true , mTemplate ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMCustomReplyAllToCommand : : KMCustomReplyAllToCommand ( TQWidget * parent , KMMessage * msg ,
const TQString & selection ,
const TQString & tmpl )
: KMCommand ( parent , msg ) , mSelection ( selection ) , mTemplate ( tmpl )
{
}
KMCommand : : Result KMCustomReplyAllToCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * reply = msg - > createReply ( KMail : : ReplyAll , mSelection ,
false , true , mTemplate ) ;
KMail : : Composer * win = KMail : : makeComposer ( reply ) ;
win - > setCharset ( msg - > codec ( ) - > mimeName ( ) , true ) ;
win - > setReplyFocus ( ) ;
win - > show ( ) ;
return OK ;
}
KMCustomForwardCommand : : KMCustomForwardCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList , uint identity , const TQString & tmpl )
: KMCommand ( parent , msgList ) ,
mIdentity ( identity ) , mTemplate ( tmpl )
{
}
KMCustomForwardCommand : : KMCustomForwardCommand ( TQWidget * parent ,
KMMessage * msg , uint identity , const TQString & tmpl )
: KMCommand ( parent , msg ) ,
mIdentity ( identity ) , mTemplate ( tmpl )
{
}
KMCommand : : Result KMCustomForwardCommand : : execute ( )
{
TQPtrList < KMMessage > msgList = retrievedMsgs ( ) ;
if ( msgList . count ( ) > = 2 ) { // Multiple forward
uint id = 0 ;
TQPtrList < KMMessage > linklist ;
for ( KMMessage * msg = msgList . first ( ) ; msg ; msg = msgList . next ( ) ) {
// set the identity
if ( id = = 0 )
id = msg - > headerField ( " X-KMail-Identity " ) . stripWhiteSpace ( ) . toUInt ( ) ;
// msgText += msg->createForwardBody();
linklist . append ( msg ) ;
}
if ( id = = 0 )
id = mIdentity ; // use folder identity if no message had an id set
KMMessage * fwdMsg = new KMMessage ;
fwdMsg - > initHeader ( id ) ;
fwdMsg - > setAutomaticFields ( true ) ;
fwdMsg - > setCharset ( " utf-8 " ) ;
// fwdMsg->setBody( msgText );
for ( KMMessage * msg = linklist . first ( ) ; msg ; msg = linklist . next ( ) ) {
TemplateParser parser ( fwdMsg , TemplateParser : : Forward ) ;
parser . setSelection ( msg - > body ( ) ) ; // FIXME: Why is this needed?
parser . process ( msg , 0 , true ) ;
fwdMsg - > link ( msg , KMMsgStatusForwarded ) ;
}
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( fwdMsg , id ) ;
win - > setCharset ( " " ) ;
win - > show ( ) ;
} else { // forward a single message at most
KMMessage * msg = msgList . getFirst ( ) ;
if ( ! msg | | ! msg - > codec ( ) )
return Failed ;
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
KMMessage * fwdMsg = msg - > createForward ( mTemplate ) ;
uint id = msg - > headerField ( " X-KMail-Identity " ) . stripWhiteSpace ( ) . toUInt ( ) ;
if ( id = = 0 )
id = mIdentity ;
{
KMail : : Composer * win = KMail : : makeComposer ( fwdMsg , id ) ;
win - > setCharset ( fwdMsg - > codec ( ) - > mimeName ( ) , true ) ;
win - > show ( ) ;
}
}
return OK ;
}
KMPrintCommand : : KMPrintCommand ( TQWidget * parent , KMMessage * msg ,
const KMail : : HeaderStyle * headerStyle ,
const KMail : : HeaderStrategy * headerStrategy ,
bool htmlOverride , bool htmlLoadExtOverride ,
bool useFixedFont , const TQString & encoding )
: KMCommand ( parent , msg ) ,
mHeaderStyle ( headerStyle ) , mHeaderStrategy ( headerStrategy ) ,
mHtmlOverride ( htmlOverride ) ,
mHtmlLoadExtOverride ( htmlLoadExtOverride ) ,
mUseFixedFont ( useFixedFont ) , mEncoding ( encoding )
{
if ( GlobalSettings : : useDefaultFonts ( ) )
mOverrideFont = TDEGlobalSettings : : generalFont ( ) ;
else {
TDEConfigGroup fonts ( KMKernel : : config ( ) , " Fonts " ) ;
TQString tmp = fonts . readEntry ( " print-font " , TDEGlobalSettings : : generalFont ( ) . toString ( ) ) ;
mOverrideFont . fromString ( tmp ) ;
}
}
void KMPrintCommand : : setOverrideFont ( const TQFont & font )
{
mOverrideFont = font ;
}
KMCommand : : Result KMPrintCommand : : execute ( )
{
KMReaderWin printWin ( 0 , 0 , 0 ) ;
printWin . setPrinting ( true ) ;
printWin . readConfig ( ) ;
if ( mHeaderStyle ! = 0 & & mHeaderStrategy ! = 0 )
printWin . setHeaderStyleAndStrategy ( mHeaderStyle , mHeaderStrategy ) ;
printWin . setHtmlOverride ( mHtmlOverride ) ;
printWin . setHtmlLoadExtOverride ( mHtmlLoadExtOverride ) ;
printWin . setUseFixedFont ( mUseFixedFont ) ;
printWin . setOverrideEncoding ( mEncoding ) ;
printWin . cssHelper ( ) - > setPrintFont ( mOverrideFont ) ;
printWin . setDecryptMessageOverwrite ( true ) ;
printWin . setMsg ( retrievedMessage ( ) , true ) ;
printWin . printMsg ( ) ;
return OK ;
}
KMSeStatusCommand : : KMSeStatusCommand ( KMMsgStatus status ,
const TQValueList < TQ_UINT32 > & serNums , bool toggle )
: mStatus ( status ) , mSerNums ( serNums ) , mToggle ( toggle )
{
}
KMCommand : : Result KMSeStatusCommand : : execute ( )
{
TQValueListIterator < TQ_UINT32 > it ;
int idx = - 1 ;
KMFolder * folder = 0 ;
bool parenStatus = false ;
// Toggle actions on threads toggle the whole thread
// depending on the state of the parent.
if ( mToggle ) {
KMMsgBase * msg ;
KMMsgDict : : instance ( ) - > getLocation ( * mSerNums . begin ( ) , & folder , & idx ) ;
if ( folder ) {
msg = folder - > getMsgBase ( idx ) ;
if ( msg & & ( msg - > status ( ) & mStatus ) )
parenStatus = true ;
else
parenStatus = false ;
}
}
TQMap < KMFolder * , TQValueList < int > > folderMap ;
for ( it = mSerNums . begin ( ) ; it ! = mSerNums . end ( ) ; + + it ) {
KMMsgDict : : instance ( ) - > getLocation ( * it , & folder , & idx ) ;
if ( folder ) {
if ( mToggle ) {
KMMsgBase * msg = folder - > getMsgBase ( idx ) ;
// check if we are already at the target toggle state
if ( msg ) {
bool myStatus ;
if ( msg - > status ( ) & mStatus )
myStatus = true ;
else
myStatus = false ;
if ( myStatus ! = parenStatus )
continue ;
}
}
/* Collect the ids for each folder in a separate list and
send them off in one go at the end . */
folderMap [ folder ] . append ( idx ) ;
}
}
TQMapIterator < KMFolder * , TQValueList < int > > it2 = folderMap . begin ( ) ;
while ( it2 ! = folderMap . end ( ) ) {
KMFolder * f = it2 . key ( ) ;
f - > setStatus ( ( * it2 ) , mStatus , mToggle ) ;
+ + it2 ;
}
//kapp->dcopClient()->emitDCOPSignal( "unreadCountChanged()", TQByteArray() );
return OK ;
}
KMFilterCommand : : KMFilterCommand ( const TQCString & field , const TQString & value )
: mField ( field ) , mValue ( value )
{
}
KMCommand : : Result KMFilterCommand : : execute ( )
{
kmkernel - > filterMgr ( ) - > createFilter ( mField , mValue ) ;
return OK ;
}
KMFilterActionCommand : : KMFilterActionCommand ( TQWidget * parent ,
const TQPtrList < KMMsgBase > & msgList ,
KMFilter * filter )
: KMCommand ( parent , msgList ) , mFilter ( filter )
{
TQPtrListIterator < KMMsgBase > it ( msgList ) ;
while ( it . current ( ) ) {
serNumList . append ( ( * it ) - > getMsgSerNum ( ) ) ;
+ + it ;
}
}
KMCommand : : Result KMFilterActionCommand : : execute ( )
{
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
int msgCount = 0 ;
int msgCountToFilter = serNumList . count ( ) ;
ProgressItem * progressItem =
ProgressManager : : createProgressItem ( " filter " + ProgressManager : : getUniqueID ( ) ,
i18n ( " Filtering messages " ) ) ;
progressItem - > setTotalItems ( msgCountToFilter ) ;
TQValueList < TQ_UINT32 > : : const_iterator it ;
for ( it = serNumList . begin ( ) ; it ! = serNumList . end ( ) ; it + + ) {
TQ_UINT32 serNum = * it ;
int diff = msgCountToFilter - + + msgCount ;
if ( diff < 10 | | ! ( msgCount % 20 ) | | msgCount < = 10 ) {
progressItem - > updateProgress ( ) ;
TQString statusMsg = i18n ( " Filtering message %1 of %2 " ) ;
statusMsg = statusMsg . arg ( msgCount ) . arg ( msgCountToFilter ) ;
KPIM : : BroadcastStatus : : instance ( ) - > setStatusMsg ( statusMsg ) ;
TDEApplication : : kApplication ( ) - > eventLoop ( ) - > processEvents ( TQEventLoop : : ExcludeUserInput , 50 ) ;
}
int filterResult = kmkernel - > filterMgr ( ) - > process ( serNum , mFilter ) ;
if ( filterResult = = 2 ) {
// something went horribly wrong (out of space?)
perror ( " Critical error " ) ;
kmkernel - > emergencyExit ( i18n ( " Not enough free disk space? " ) ) ;
}
progressItem - > incCompletedItems ( ) ;
}
progressItem - > setComplete ( ) ;
progressItem = 0 ;
return OK ;
}
KMMetaFilterActionCommand : : KMMetaFilterActionCommand ( KMFilter * filter ,
KMHeaders * headers ,
KMMainWidget * main )
: TQObject ( main ) ,
mFilter ( filter ) , mHeaders ( headers ) , mMainWidget ( main )
{
}
void KMMetaFilterActionCommand : : start ( )
{
if ( ActionScheduler : : isEnabled ( ) ) {
// use action scheduler
KMFilterMgr : : FilterSet set = KMFilterMgr : : All ;
TQValueList < KMFilter * > filters ;
filters . append ( mFilter ) ;
ActionScheduler * scheduler = new ActionScheduler ( set , filters , mHeaders ) ;
scheduler - > setAlwaysMatch ( true ) ;
scheduler - > setAutoDestruct ( true ) ;
int contentX , contentY ;
HeaderItem * nextItem = mHeaders - > prepareMove ( & contentX , & contentY ) ;
TQPtrList < KMMsgBase > msgList = * mHeaders - > selectedMsgs ( true ) ;
mHeaders - > finalizeMove ( nextItem , contentX , contentY ) ;
for ( KMMsgBase * msg = msgList . first ( ) ; msg ; msg = msgList . next ( ) )
scheduler - > execFilters ( msg ) ;
} else {
KMCommand * filterCommand =
new KMFilterActionCommand ( mMainWidget ,
* mHeaders - > selectedMsgs ( ) , mFilter ) ;
filterCommand - > start ( ) ;
int contentX , contentY ;
HeaderItem * item = mHeaders - > prepareMove ( & contentX , & contentY ) ;
mHeaders - > finalizeMove ( item , contentX , contentY ) ;
}
}
FolderShortcutCommand : : FolderShortcutCommand ( KMMainWidget * mainwidget ,
KMFolder * folder )
: mMainWidget ( mainwidget ) , mFolder ( folder ) , mAction ( 0 )
{
}
FolderShortcutCommand : : ~ FolderShortcutCommand ( )
{
if ( mAction ) mAction - > unplugAll ( ) ;
delete mAction ;
}
void FolderShortcutCommand : : start ( )
{
mMainWidget - > slotSelectFolder ( mFolder ) ;
}
void FolderShortcutCommand : : setAction ( TDEAction * action )
{
mAction = action ;
}
KMMailingListFilterCommand : : KMMailingListFilterCommand ( TQWidget * parent ,
KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMMailingListFilterCommand : : execute ( )
{
TQCString name ;
TQString value ;
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg )
return Failed ;
if ( ! MailingList : : name ( msg , name , value ) . isEmpty ( ) ) {
kmkernel - > filterMgr ( ) - > createFilter ( name , value ) ;
return OK ;
}
else
return Failed ;
}
void KMMenuCommand : : folderToPopupMenu ( bool move ,
TQObject * receiver , KMMenuToFolder * aMenuToFolder , TQPopupMenu * menu )
{
while ( menu - > count ( ) )
{
TQPopupMenu * popup = menu - > findItem ( menu - > idAt ( 0 ) ) - > popup ( ) ;
if ( popup )
delete popup ;
else
menu - > removeItemAt ( 0 ) ;
}
if ( ! kmkernel - > imapFolderMgr ( ) - > dir ( ) . first ( ) & &
! kmkernel - > dimapFolderMgr ( ) - > dir ( ) . first ( ) )
{ // only local folders
makeFolderMenu ( & kmkernel - > folderMgr ( ) - > dir ( ) , move ,
receiver , aMenuToFolder , menu ) ;
} else {
// operate on top-level items
TQPopupMenu * subMenu = new TQPopupMenu ( menu ) ;
makeFolderMenu ( & kmkernel - > folderMgr ( ) - > dir ( ) ,
move , receiver , aMenuToFolder , subMenu ) ;
menu - > insertItem ( i18n ( " Local Folders " ) , subMenu ) ;
KMFolderDir * fdir = & kmkernel - > imapFolderMgr ( ) - > dir ( ) ;
for ( KMFolderNode * node = fdir - > first ( ) ; node ; node = fdir - > next ( ) ) {
if ( node - > isDir ( ) )
continue ;
subMenu = new TQPopupMenu ( menu ) ;
makeFolderMenu ( node , move , receiver , aMenuToFolder , subMenu ) ;
menu - > insertItem ( node - > label ( ) , subMenu ) ;
}
fdir = & kmkernel - > dimapFolderMgr ( ) - > dir ( ) ;
for ( KMFolderNode * node = fdir - > first ( ) ; node ; node = fdir - > next ( ) ) {
if ( node - > isDir ( ) )
continue ;
subMenu = new TQPopupMenu ( menu ) ;
makeFolderMenu ( node , move , receiver , aMenuToFolder , subMenu ) ;
menu - > insertItem ( node - > label ( ) , subMenu ) ;
}
}
}
void KMMenuCommand : : makeFolderMenu ( KMFolderNode * node , bool move ,
TQObject * receiver , KMMenuToFolder * aMenuToFolder , TQPopupMenu * menu )
{
// connect the signals
if ( move )
{
disconnect ( menu , TQ_SIGNAL ( activated ( int ) ) , receiver ,
TQ_SLOT ( moveSelectedToFolder ( int ) ) ) ;
connect ( menu , TQ_SIGNAL ( activated ( int ) ) , receiver ,
TQ_SLOT ( moveSelectedToFolder ( int ) ) ) ;
} else {
disconnect ( menu , TQ_SIGNAL ( activated ( int ) ) , receiver ,
TQ_SLOT ( copySelectedToFolder ( int ) ) ) ;
connect ( menu , TQ_SIGNAL ( activated ( int ) ) , receiver ,
TQ_SLOT ( copySelectedToFolder ( int ) ) ) ;
}
KMFolder * folder = 0 ;
KMFolderDir * folderDir = 0 ;
if ( node - > isDir ( ) ) {
folderDir = static_cast < KMFolderDir * > ( node ) ;
} else {
folder = static_cast < KMFolder * > ( node ) ;
folderDir = folder - > child ( ) ;
}
if ( folder & & ! folder - > noContent ( ) )
{
int menuId ;
if ( move )
menuId = menu - > insertItem ( i18n ( " Move to This Folder " ) ) ;
else
menuId = menu - > insertItem ( i18n ( " Copy to This Folder " ) ) ;
aMenuToFolder - > insert ( menuId , folder ) ;
menu - > setItemEnabled ( menuId , ! folder - > isReadOnly ( ) ) ;
menu - > insertSeparator ( ) ;
}
if ( ! folderDir )
return ;
for ( KMFolderNode * it = folderDir - > first ( ) ; it ; it = folderDir - > next ( ) ) {
if ( it - > isDir ( ) )
continue ;
KMFolder * child = static_cast < KMFolder * > ( it ) ;
TQString label = child - > label ( ) ;
label . replace ( " & " , " && " ) ;
if ( child - > child ( ) & & child - > child ( ) - > first ( ) ) {
// descend
TQPopupMenu * subMenu = new TQPopupMenu ( menu , " subMenu " ) ;
makeFolderMenu ( child , move , receiver ,
aMenuToFolder , subMenu ) ;
menu - > insertItem ( label , subMenu ) ;
} else {
// insert an item
int menuId = menu - > insertItem ( label ) ;
aMenuToFolder - > insert ( menuId , child ) ;
menu - > setItemEnabled ( menuId , ! child - > isReadOnly ( ) ) ;
}
}
return ;
}
KMCopyCommand : : KMCopyCommand ( KMFolder * destFolder ,
const TQPtrList < KMMsgBase > & msgList )
: mDestFolder ( destFolder ) , mMsgList ( msgList )
{
setDeletesItself ( true ) ;
}
KMCopyCommand : : KMCopyCommand ( KMFolder * destFolder , KMMessage * msg )
: mDestFolder ( destFolder )
{
setDeletesItself ( true ) ;
mMsgList . append ( & msg - > toMsgBase ( ) ) ;
}
KMCommand : : Result KMCopyCommand : : execute ( )
{
KMMsgBase * msgBase ;
KMMessage * msg , * newMsg ;
int idx = - 1 ;
bool isMessage ;
TQPtrList < KMMessage > list ;
TQPtrList < KMMessage > localList ;
if ( mDestFolder & & mDestFolder - > open ( " kmcommand " ) ! = 0 )
{
deleteLater ( ) ;
return Failed ;
}
setEmitsCompletedItself ( true ) ;
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
for ( msgBase = mMsgList . first ( ) ; msgBase ; msgBase = mMsgList . next ( ) )
{
KMFolder * srcFolder = msgBase - > parent ( ) ;
if ( ( isMessage = msgBase - > isMessage ( ) ) )
{
msg = static_cast < KMMessage * > ( msgBase ) ;
} else {
idx = srcFolder - > find ( msgBase ) ;
assert ( idx ! = - 1 ) ;
msg = srcFolder - > getMsg ( idx ) ;
// corrupt IMAP cache, see FolderStorage::getMsg()
if ( msg = = 0 ) {
KMessageBox : : error ( parentWidget ( ) , i18n ( " Corrupt IMAP cache detected in folder %1. "
" Copying of messages aborted. " ) . arg ( srcFolder - > prettyURL ( ) ) ) ;
deleteLater ( ) ;
return Failed ;
}
}
if ( srcFolder & & mDestFolder & &
( srcFolder - > folderType ( ) = = KMFolderTypeImap ) & &
( mDestFolder - > folderType ( ) = = KMFolderTypeImap ) & &
( static_cast < KMFolderImap * > ( srcFolder - > storage ( ) ) - > account ( ) = =
static_cast < KMFolderImap * > ( mDestFolder - > storage ( ) ) - > account ( ) ) )
{
// imap => imap with same account
list . append ( msg ) ;
} else {
newMsg = new KMMessage ( new DwMessage ( * msg - > asDwMessage ( ) ) ) ;
newMsg - > setComplete ( msg - > isComplete ( ) ) ;
// make sure the attachment state is only calculated when it's complete
if ( ! newMsg - > isComplete ( ) )
newMsg - > setReadyToShow ( false ) ;
newMsg - > setStatus ( msg - > status ( ) ) ;
if ( srcFolder & & ! newMsg - > isComplete ( ) )
{
// imap => others
newMsg - > setParent ( msg - > parent ( ) ) ;
FolderJob * job = srcFolder - > createJob ( newMsg ) ;
job - > setCancellable ( false ) ;
mPendingJobs < < job ;
connect ( job , TQ_SIGNAL ( messageRetrieved ( KMMessage * ) ) ,
mDestFolder , TQ_SLOT ( reallyAddCopyOfMsg ( KMMessage * ) ) ) ;
connect ( job , TQ_SIGNAL ( result ( KMail : : FolderJob * ) ) ,
this , TQ_SLOT ( slotJobFinished ( KMail : : FolderJob * ) ) ) ;
job - > start ( ) ;
} else {
// local => others
localList . append ( newMsg ) ;
}
}
if ( srcFolder & & ! isMessage & & list . isEmpty ( ) )
{
assert ( idx ! = - 1 ) ;
srcFolder - > unGetMsg ( idx ) ;
}
} // end for
bool deleteNow = false ;
if ( ! localList . isEmpty ( ) )
{
TQValueList < int > index ;
mDestFolder - > addMsg ( localList , index ) ;
for ( TQValueListIterator < int > it = index . begin ( ) ; it ! = index . end ( ) ; + + it ) {
mDestFolder - > unGetMsg ( * it ) ;
}
if ( mDestFolder - > folderType ( ) = = KMFolderTypeImap ) {
if ( mPendingJobs . isEmpty ( ) ) {
// wait for the end of the copy before closing the folder
KMFolderImap * imapDestFolder = static_cast < KMFolderImap * > ( mDestFolder - > storage ( ) ) ;
connect ( imapDestFolder , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
this , TQ_SLOT ( slotFolderComplete ( KMFolderImap * , bool ) ) ) ;
}
} else {
deleteNow = list . isEmpty ( ) & & mPendingJobs . isEmpty ( ) ; // we're done if there are no other mails we need to fetch
}
}
//TODO: Get rid of the other cases just use this one for all types of folder
//TODO: requires adding copyMsg and getFolder methods to KMFolder.h
if ( ! list . isEmpty ( ) )
{
// copy the message(s); note: the list is empty afterwards!
KMFolderImap * imapDestFolder = static_cast < KMFolderImap * > ( mDestFolder - > storage ( ) ) ;
connect ( imapDestFolder , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
this , TQ_SLOT ( slotFolderComplete ( KMFolderImap * , bool ) ) ) ;
imapDestFolder - > copyMsg ( list ) ;
imapDestFolder - > getFolder ( ) ;
}
// only close the folder and delete the job if we're done
// otherwise this is done in slotMsgAdded or slotFolderComplete
if ( deleteNow )
{
mDestFolder - > close ( " kmcommand " ) ;
setResult ( OK ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
return OK ;
}
void KMCopyCommand : : slotJobFinished ( KMail : : FolderJob * job )
{
mPendingJobs . remove ( job ) ;
if ( job - > error ( ) ) {
kdDebug ( 5006 ) < < k_funcinfo < < " folder job failed: " < < job - > error ( ) < < endl ;
// kill all pending jobs
for ( TQValueList < KMail : : FolderJob * > : : Iterator it = mPendingJobs . begin ( ) ; it ! = mPendingJobs . end ( ) ; + + it ) {
disconnect ( ( * it ) , TQ_SIGNAL ( result ( KMail : : FolderJob * ) ) ,
this , TQ_SLOT ( slotJobFinished ( KMail : : FolderJob * ) ) ) ;
( * it ) - > kill ( ) ;
}
mPendingJobs . clear ( ) ;
setResult ( Failed ) ;
}
if ( mPendingJobs . isEmpty ( ) )
{
mDestFolder - > close ( " kmcommand " ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
}
void KMCopyCommand : : slotFolderComplete ( KMFolderImap * , bool success )
{
kdDebug ( 5006 ) < < k_funcinfo < < success < < endl ;
if ( ! success )
setResult ( Failed ) ;
mDestFolder - > close ( " kmcommand " ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
KMMoveCommand : : KMMoveCommand ( KMFolder * destFolder ,
const TQPtrList < KMMsgBase > & msgList )
: mDestFolder ( destFolder ) , mProgressItem ( 0 )
{
TQPtrList < KMMsgBase > tmp = msgList ;
for ( KMMsgBase * msgBase = tmp . first ( ) ; msgBase ; msgBase = tmp . next ( ) )
mSerNumList . append ( msgBase - > getMsgSerNum ( ) ) ;
}
KMMoveCommand : : KMMoveCommand ( KMFolder * destFolder ,
KMMessage * msg )
: mDestFolder ( destFolder ) , mProgressItem ( 0 )
{
mSerNumList . append ( msg - > getMsgSerNum ( ) ) ;
}
KMMoveCommand : : KMMoveCommand ( KMFolder * destFolder ,
KMMsgBase * msgBase )
: mDestFolder ( destFolder ) , mProgressItem ( 0 )
{
mSerNumList . append ( msgBase - > getMsgSerNum ( ) ) ;
}
KMMoveCommand : : KMMoveCommand ( TQ_UINT32 )
: mProgressItem ( 0 )
{
}
KMCommand : : Result KMMoveCommand : : execute ( )
{
setEmitsCompletedItself ( true ) ;
setDeletesItself ( true ) ;
typedef TQMap < KMFolder * , TQPtrList < KMMessage > * > FolderToMessageListMap ;
FolderToMessageListMap folderDeleteList ;
if ( mDestFolder & & mDestFolder - > open ( " kmcommand " ) ! = 0 ) {
completeMove ( Failed ) ;
return Failed ;
}
KCursorSaver busy ( KBusyPtr : : busy ( ) ) ;
// TODO set SSL state according to source and destfolder connection?
Q_ASSERT ( ! mProgressItem ) ;
mProgressItem =
ProgressManager : : createProgressItem (
" move " + ProgressManager : : getUniqueID ( ) ,
mDestFolder ? i18n ( " Moving messages " ) : i18n ( " Deleting messages " ) ) ;
connect ( mProgressItem , TQ_SIGNAL ( progressItemCanceled ( KPIM : : ProgressItem * ) ) ,
this , TQ_SLOT ( slotMoveCanceled ( ) ) ) ;
KMMessage * msg ;
int rc = 0 ;
int index ;
TQPtrList < KMMessage > list ;
int undoId = - 1 ;
mCompleteWithAddedMsg = false ;
if ( mDestFolder ) {
connect ( mDestFolder , TQ_SIGNAL ( msgAdded ( KMFolder * , TQ_UINT32 ) ) ,
this , TQ_SLOT ( slotMsgAddedToDestFolder ( KMFolder * , TQ_UINT32 ) ) ) ;
mLostBoys = mSerNumList ;
}
mProgressItem - > setTotalItems ( mSerNumList . count ( ) ) ;
for ( TQValueList < TQ_UINT32 > : : ConstIterator it = mSerNumList . constBegin ( ) ; it ! = mSerNumList . constEnd ( ) ; + + it ) {
if ( * it = = 0 ) {
kdDebug ( 5006 ) < < k_funcinfo < < " serial number == 0! " < < endl ;
continue ; // invalid message
}
KMFolder * srcFolder = 0 ;
int idx = - 1 ;
KMMsgDict : : instance ( ) - > getLocation ( * it , & srcFolder , & idx ) ;
if ( srcFolder = = mDestFolder )
continue ;
assert ( srcFolder ) ;
assert ( idx ! = - 1 ) ;
if ( ! srcFolder - > isOpened ( ) ) {
srcFolder - > open ( " kmmovecommand " ) ;
mOpenedFolders . append ( srcFolder ) ;
}
msg = srcFolder - > getMsg ( idx ) ;
if ( ! msg ) {
kdDebug ( 5006 ) < < k_funcinfo < < " No message found for serial number " < < * it < < endl ;
continue ;
}
bool undo = msg - > enableUndo ( ) ;
if ( msg & & msg - > transferInProgress ( ) & &
srcFolder - > folderType ( ) = = KMFolderTypeImap )
{
// cancel the download
msg - > setTransferInProgress ( false , true ) ;
static_cast < KMFolderImap * > ( srcFolder - > storage ( ) ) - > ignoreJobsForMessage ( msg ) ;
}
if ( mDestFolder ) {
if ( mDestFolder - > folderType ( ) = = KMFolderTypeImap ) {
/* If we are moving to an imap folder, connect to it's completed
* signal so we notice when all the mails should have showed up in it
* but haven ' t for some reason . */
KMFolderImap * imapFolder = static_cast < KMFolderImap * > ( mDestFolder - > storage ( ) ) ;
disconnect ( imapFolder , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
this , TQ_SLOT ( slotImapFolderCompleted ( KMFolderImap * , bool ) ) ) ;
connect ( imapFolder , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
this , TQ_SLOT ( slotImapFolderCompleted ( KMFolderImap * , bool ) ) ) ;
list . append ( msg ) ;
} else {
// We are moving to a local folder.
if ( srcFolder - > folderType ( ) = = KMFolderTypeImap )
{
// do not complete here but wait until all messages are transferred
mCompleteWithAddedMsg = true ;
}
rc = mDestFolder - > moveMsg ( msg , & index ) ;
if ( rc = = 0 & & index ! = - 1 ) {
KMMsgBase * mb = mDestFolder - > unGetMsg ( mDestFolder - > count ( ) - 1 ) ;
if ( undo & & mb )
{
if ( undoId = = - 1 )
undoId = kmkernel - > undoStack ( ) - > newUndoAction ( srcFolder , mDestFolder ) ;
kmkernel - > undoStack ( ) - > addMsgToAction ( undoId , mb - > getMsgSerNum ( ) ) ;
}
} else if ( rc ! = 0 ) {
// Something went wrong. Stop processing here, it is likely that the
// other moves would fail as well.
completeMove ( Failed ) ;
return Failed ;
}
}
} else {
// really delete messages that are already in the trash folder or if
// we are really, really deleting, not just moving to trash
if ( srcFolder - > folderType ( ) = = KMFolderTypeImap ) {
if ( ! folderDeleteList [ srcFolder ] )
folderDeleteList [ srcFolder ] = new TQPtrList < KMMessage > ;
folderDeleteList [ srcFolder ] - > append ( msg ) ;
} else {
srcFolder - > removeMsg ( idx ) ;
delete msg ;
}
}
}
if ( ! list . isEmpty ( ) & & mDestFolder ) {
// will be completed with folderComplete signal
mDestFolder - > moveMsg ( list , & index ) ;
} else {
FolderToMessageListMap : : Iterator it ;
for ( it = folderDeleteList . begin ( ) ; it ! = folderDeleteList . end ( ) ; + + it ) {
it . key ( ) - > removeMsg ( * it . data ( ) ) ;
delete it . data ( ) ;
}
if ( ! mCompleteWithAddedMsg ) {
// imap folders will be completed in slotMsgAddedToDestFolder
completeMove ( OK ) ;
}
}
return OK ;
}
void KMMoveCommand : : slotImapFolderCompleted ( KMFolderImap * imapFolder , bool success )
{
disconnect ( imapFolder , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
this , TQ_SLOT ( slotImapFolderCompleted ( KMFolderImap * , bool ) ) ) ;
if ( success ) {
// the folder was checked successfully but we were still called, so check
// if we are still waiting for messages to show up. If so, uidValidity
// changed, or something else went wrong. Clean up.
/* Unfortunately older UW imap servers change uid validity for each put job.
* Yes , it is really that broken . * sigh * So we cannot report error here , I guess . */
if ( ! mLostBoys . isEmpty ( ) ) {
kdDebug ( 5006 ) < < " ### Not all moved messages reported back that they were " < < endl
< < " ### added to the target folder. Did uidValidity change? " < < endl ;
}
completeMove ( OK ) ;
} else {
// Should we inform the user here or leave that to the caller?
completeMove ( Failed ) ;
}
}
void KMMoveCommand : : slotMsgAddedToDestFolder ( KMFolder * folder , TQ_UINT32 serNum )
{
if ( folder ! = mDestFolder | | mLostBoys . find ( serNum ) = = mLostBoys . end ( ) ) {
//kdDebug(5006) << "KMMoveCommand::msgAddedToDestFolder different "
// "folder or invalid serial number." << endl;
return ;
}
mLostBoys . remove ( serNum ) ;
if ( mLostBoys . isEmpty ( ) ) {
// we are done. All messages transferred to the host succesfully
disconnect ( mDestFolder , TQ_SIGNAL ( msgAdded ( KMFolder * , TQ_UINT32 ) ) ,
this , TQ_SLOT ( slotMsgAddedToDestFolder ( KMFolder * , TQ_UINT32 ) ) ) ;
if ( mDestFolder & & mDestFolder - > folderType ( ) ! = KMFolderTypeImap ) {
mDestFolder - > sync ( ) ;
}
if ( mCompleteWithAddedMsg ) {
completeMove ( OK ) ;
}
} else {
if ( mProgressItem ) {
mProgressItem - > incCompletedItems ( ) ;
mProgressItem - > updateProgress ( ) ;
}
}
}
void KMMoveCommand : : completeMove ( Result result )
{
if ( mDestFolder )
mDestFolder - > close ( " kmcommand " ) ;
while ( ! mOpenedFolders . empty ( ) ) {
KMFolder * folder = mOpenedFolders . back ( ) ;
mOpenedFolders . pop_back ( ) ;
folder - > close ( " kmcommand " ) ;
}
if ( mProgressItem ) {
mProgressItem - > setComplete ( ) ;
mProgressItem = 0 ;
}
setResult ( result ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
void KMMoveCommand : : slotMoveCanceled ( )
{
completeMove ( Canceled ) ;
}
// srcFolder doesn't make much sense for searchFolders
KMDeleteMsgCommand : : KMDeleteMsgCommand ( KMFolder * srcFolder ,
const TQPtrList < KMMsgBase > & msgList )
: KMMoveCommand ( findTrashFolder ( srcFolder ) , msgList )
{
srcFolder - > open ( " kmcommand " ) ;
mOpenedFolders . push_back ( srcFolder ) ;
}
KMDeleteMsgCommand : : KMDeleteMsgCommand ( KMFolder * srcFolder , KMMessage * msg )
: KMMoveCommand ( findTrashFolder ( srcFolder ) , msg )
{
srcFolder - > open ( " kmcommand " ) ;
mOpenedFolders . push_back ( srcFolder ) ;
}
KMDeleteMsgCommand : : KMDeleteMsgCommand ( TQ_UINT32 sernum )
: KMMoveCommand ( sernum )
{
if ( ! sernum ) {
setDestFolder ( 0 ) ;
return ;
}
KMFolder * srcFolder = 0 ;
int idx ;
KMMsgDict : : instance ( ) - > getLocation ( sernum , & srcFolder , & idx ) ;
if ( srcFolder ) {
KMMsgBase * msg = srcFolder - > getMsgBase ( idx ) ;
srcFolder - > open ( " kmcommand " ) ;
mOpenedFolders . push_back ( srcFolder ) ;
addMsg ( msg ) ;
}
setDestFolder ( findTrashFolder ( srcFolder ) ) ;
}
KMFolder * KMDeleteMsgCommand : : findTrashFolder ( KMFolder * folder )
{
KMFolder * trash = folder - > trashFolder ( ) ;
if ( ! trash )
trash = kmkernel - > trashFolder ( ) ;
if ( trash ! = folder )
return trash ;
return 0 ;
}
KMUrlClickedCommand : : KMUrlClickedCommand ( const KURL & url , uint identity ,
KMReaderWin * readerWin , bool htmlPref , KMMainWidget * mainWidget )
: mUrl ( url ) , mIdentity ( identity ) , mReaderWin ( readerWin ) ,
mHtmlPref ( htmlPref ) , mMainWidget ( mainWidget )
{
}
KMCommand : : Result KMUrlClickedCommand : : execute ( )
{
KMMessage * msg ;
if ( mUrl . protocol ( ) = = " mailto " )
{
msg = new KMMessage ;
msg - > initHeader ( mIdentity ) ;
msg - > setCharset ( " utf-8 " ) ;
msg - > setTo ( KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ) ;
TQString query = mUrl . query ( ) ;
while ( ! query . isEmpty ( ) ) {
TQString queryPart ;
int secondQuery = query . find ( ' ? ' , 1 ) ;
if ( secondQuery ! = - 1 )
queryPart = query . left ( secondQuery ) ;
else
queryPart = query ;
query = query . mid ( queryPart . length ( ) ) ;
if ( queryPart . left ( 9 ) = = " ?subject= " )
msg - > setSubject ( KURL : : decode_string ( queryPart . mid ( 9 ) ) ) ;
else if ( queryPart . left ( 6 ) = = " ?body= " )
// It is correct to convert to latin1() as URL should not contain
// anything except ascii.
msg - > setBody ( KURL : : decode_string ( queryPart . mid ( 6 ) ) . latin1 ( ) ) ;
else if ( queryPart . left ( 4 ) = = " ?cc= " )
msg - > setCc ( KURL : : decode_string ( queryPart . mid ( 4 ) ) ) ;
}
KMail : : Composer * win = KMail : : makeComposer ( msg , mIdentity ) ;
win - > setCharset ( " " , true ) ;
win - > show ( ) ;
}
else if ( mUrl . protocol ( ) = = " im " )
{
kmkernel - > imProxy ( ) - > chatWithContact ( mUrl . path ( ) ) ;
}
else if ( ( mUrl . protocol ( ) = = " http " ) | | ( mUrl . protocol ( ) = = " https " ) | |
( mUrl . protocol ( ) = = " ftp " ) | | ( mUrl . protocol ( ) = = " file " ) | |
( mUrl . protocol ( ) = = " ftps " ) | | ( mUrl . protocol ( ) = = " sftp " ) | |
( mUrl . protocol ( ) = = " help " ) | | ( mUrl . protocol ( ) = = " vnc " ) | |
( mUrl . protocol ( ) = = " smb " ) | | ( mUrl . protocol ( ) = = " fish " ) | |
( mUrl . protocol ( ) = = " news " ) )
{
KPIM : : BroadcastStatus : : instance ( ) - > setStatusMsg ( i18n ( " Opening URL... " ) ) ;
KMimeType : : Ptr mime = KMimeType : : findByURL ( mUrl ) ;
if ( mime - > name ( ) = = " application/x-desktop " | |
mime - > name ( ) = = " application/x-executable " | |
mime - > name ( ) = = " application/x-msdos-program " | |
mime - > name ( ) = = " application/x-shellscript " )
{
if ( KMessageBox : : warningYesNo ( 0 , i18n ( " <qt>Do you really want to execute <b>%1</b>?</qt> " )
. arg ( mUrl . prettyURL ( ) ) , TQString ( ) , i18n ( " Execute " ) , KStdGuiItem : : cancel ( ) ) ! = KMessageBox : : Yes )
return Canceled ;
}
KRun * runner = new KRun ( mUrl ) ;
runner - > setRunExecutables ( false ) ;
}
else
return Failed ;
return OK ;
}
KMSaveAttachmentsCommand : : KMSaveAttachmentsCommand ( TQWidget * parent , KMMessage * msg )
: KMCommand ( parent , msg ) , mImplicitAttachments ( true ) , mEncoded ( false )
{
}
KMSaveAttachmentsCommand : : KMSaveAttachmentsCommand ( TQWidget * parent , const TQPtrList < KMMsgBase > & msgs )
: KMCommand ( parent , msgs ) , mImplicitAttachments ( true ) , mEncoded ( false )
{
}
KMSaveAttachmentsCommand : : KMSaveAttachmentsCommand ( TQWidget * parent , TQPtrList < partNode > & attachments ,
KMMessage * msg , bool encoded )
: KMCommand ( parent ) , mImplicitAttachments ( false ) , mEncoded ( encoded )
{
for ( TQPtrListIterator < partNode > it ( attachments ) ; it . current ( ) ; + + it ) {
mAttachmentMap . insert ( it . current ( ) , msg ) ;
}
}
KMCommand : : Result KMSaveAttachmentsCommand : : execute ( )
{
setEmitsCompletedItself ( true ) ;
if ( mImplicitAttachments ) {
TQPtrList < KMMessage > msgList = retrievedMsgs ( ) ;
KMMessage * msg ;
for ( TQPtrListIterator < KMMessage > itr ( msgList ) ;
( msg = itr . current ( ) ) ;
+ + itr ) {
partNode * rootNode = partNode : : fromMessage ( msg ) ;
for ( partNode * child = rootNode ; child ;
child = child - > firstChild ( ) ) {
for ( partNode * node = child ; node ; node = node - > nextSibling ( ) ) {
if ( node - > type ( ) ! = DwMime : : kTypeMultipart )
mAttachmentMap . insert ( node , msg ) ;
}
}
}
}
setDeletesItself ( true ) ;
// load all parts
KMLoadPartsCommand * command = new KMLoadPartsCommand ( mAttachmentMap ) ;
connect ( command , TQ_SIGNAL ( partsRetrieved ( ) ) ,
this , TQ_SLOT ( slotSaveAll ( ) ) ) ;
command - > start ( ) ;
return OK ;
}
void KMSaveAttachmentsCommand : : slotSaveAll ( )
{
// now that all message parts have been retrieved, remove all parts which
// don't represent an attachment if they were not explicitely passed in the
// c'tor
if ( mImplicitAttachments ) {
for ( PartNodeMessageMap : : iterator it = mAttachmentMap . begin ( ) ;
it ! = mAttachmentMap . end ( ) ; ) {
// only body parts which have a filename or a name parameter (except for
// the root node for which name is set to the message's subject) are
// considered attachments
if ( it . key ( ) - > msgPart ( ) . fileName ( ) . stripWhiteSpace ( ) . isEmpty ( ) & &
( it . key ( ) - > msgPart ( ) . name ( ) . stripWhiteSpace ( ) . isEmpty ( ) | |
! it . key ( ) - > parentNode ( ) ) ) {
PartNodeMessageMap : : iterator delIt = it ;
+ + it ;
mAttachmentMap . remove ( delIt ) ;
}
else
+ + it ;
}
if ( mAttachmentMap . isEmpty ( ) ) {
KMessageBox : : information ( 0 , i18n ( " Found no attachments to save. " ) ) ;
setResult ( OK ) ; // The user has already been informed.
emit completed ( this ) ;
deleteLater ( ) ;
return ;
}
}
KURL url , dirUrl ;
if ( mAttachmentMap . count ( ) > 1 ) {
// get the dir
dirUrl = KDirSelectDialog : : selectDirectory ( TQString ( ) , false ,
parentWidget ( ) ,
i18n ( " Save Attachments To " ) ) ;
if ( ! dirUrl . isValid ( ) ) {
setResult ( Canceled ) ;
emit completed ( this ) ;
deleteLater ( ) ;
return ;
}
// we may not get a slash-terminated url out of KDirSelectDialog
dirUrl . adjustPath ( 1 ) ;
}
else {
// only one item, get the desired filename
partNode * node = mAttachmentMap . begin ( ) . key ( ) ;
// replace all ':' with '_' because ':' isn't allowed on FAT volumes
TQString s =
node - > msgPart ( ) . fileName ( ) . stripWhiteSpace ( ) . replace ( ' : ' , ' _ ' ) ;
if ( s . isEmpty ( ) )
s = node - > msgPart ( ) . name ( ) . stripWhiteSpace ( ) . replace ( ' : ' , ' _ ' ) ;
if ( s . isEmpty ( ) )
s = i18n ( " filename for an unnamed attachment " , " attachment.1 " ) ;
url = KFileDialog : : getSaveURL ( s , TQString ( ) , parentWidget ( ) ,
TQString ( ) ) ;
if ( url . isEmpty ( ) ) {
setResult ( Canceled ) ;
emit completed ( this ) ;
deleteLater ( ) ;
return ;
}
}
TQMap < TQString , int > renameNumbering ;
Result globalResult = OK ;
int unnamedAtmCount = 0 ;
for ( PartNodeMessageMap : : const_iterator it = mAttachmentMap . begin ( ) ;
it ! = mAttachmentMap . end ( ) ;
+ + it ) {
KURL curUrl ;
if ( ! dirUrl . isEmpty ( ) ) {
curUrl = dirUrl ;
TQString s =
it . key ( ) - > msgPart ( ) . fileName ( ) . stripWhiteSpace ( ) . replace ( ' : ' , ' _ ' ) ;
if ( s . isEmpty ( ) )
s = it . key ( ) - > msgPart ( ) . name ( ) . stripWhiteSpace ( ) . replace ( ' : ' , ' _ ' ) ;
if ( s . isEmpty ( ) ) {
+ + unnamedAtmCount ;
s = i18n ( " filename for the %1-th unnamed attachment " ,
" attachment.%1 " )
. arg ( unnamedAtmCount ) ;
}
curUrl . setFileName ( s ) ;
} else {
curUrl = url ;
}
if ( ! curUrl . isEmpty ( ) ) {
// Rename the file if we have already saved one with the same name:
// try appending a number before extension (e.g. "pic.jpg" => "pic_2.jpg")
TQString origFile = curUrl . fileName ( ) ;
TQString file = origFile ;
while ( renameNumbering . contains ( file ) ) {
file = origFile ;
int num = renameNumbering [ file ] + 1 ;
int dotIdx = file . findRev ( ' . ' ) ;
file = file . insert ( ( dotIdx > = 0 ) ? dotIdx : file . length ( ) , TQString ( " _ " ) + TQString : : number ( num ) ) ;
}
curUrl . setFileName ( file ) ;
// Increment the counter for both the old and the new filename
if ( ! renameNumbering . contains ( origFile ) )
renameNumbering [ origFile ] = 1 ;
else
renameNumbering [ origFile ] + + ;
if ( file ! = origFile ) {
if ( ! renameNumbering . contains ( file ) )
renameNumbering [ file ] = 1 ;
else
renameNumbering [ file ] + + ;
}
if ( TDEIO : : NetAccess : : exists ( curUrl , false , parentWidget ( ) ) ) {
if ( KMessageBox : : warningContinueCancel ( parentWidget ( ) ,
i18n ( " A file named %1 already exists. Do you want to overwrite it? " )
. arg ( curUrl . fileName ( ) ) ,
i18n ( " File Already Exists " ) , i18n ( " &Overwrite " ) ) = = KMessageBox : : Cancel ) {
continue ;
}
}
// save
const Result result = saveItem ( it . key ( ) , curUrl ) ;
if ( result ! = OK )
globalResult = result ;
}
}
setResult ( globalResult ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
KMCommand : : Result KMSaveAttachmentsCommand : : saveItem ( partNode * node ,
const KURL & url )
{
bool bSaveEncrypted = false ;
bool bEncryptedParts = node - > encryptionState ( ) ! = KMMsgNotEncrypted ;
if ( bEncryptedParts )
if ( KMessageBox : : questionYesNo ( parentWidget ( ) ,
i18n ( " The part %1 of the message is encrypted. Do you want to keep the encryption when saving? " ) .
arg ( url . fileName ( ) ) ,
i18n ( " KMail Question " ) , i18n ( " Keep Encryption " ) , i18n ( " Do Not Keep " ) ) = =
KMessageBox : : Yes )
bSaveEncrypted = true ;
bool bSaveWithSig = true ;
if ( node - > signatureState ( ) ! = KMMsgNotSigned )
if ( KMessageBox : : questionYesNo ( parentWidget ( ) ,
i18n ( " The part %1 of the message is signed. Do you want to keep the signature when saving? " ) .
arg ( url . fileName ( ) ) ,
i18n ( " KMail Question " ) , i18n ( " Keep Signature " ) , i18n ( " Do Not Keep " ) ) ! =
KMessageBox : : Yes )
bSaveWithSig = false ;
TQByteArray data ;
if ( mEncoded )
{
// This does not decode the Message Content-Transfer-Encoding
// but saves the _original_ content of the message part
data = KMail : : Util : : ByteArray ( node - > msgPart ( ) . dwBody ( ) ) ;
}
else
{
if ( bSaveEncrypted | | ! bEncryptedParts ) {
partNode * dataNode = node ;
TQCString rawReplyString ;
bool gotRawReplyString = false ;
if ( ! bSaveWithSig ) {
if ( DwMime : : kTypeMultipart = = node - > type ( ) & &
DwMime : : kSubtypeSigned = = node - > subType ( ) ) {
// carefully look for the part that is *not* the signature part:
if ( node - > findType ( DwMime : : kTypeApplication ,
DwMime : : kSubtypePgpSignature ,
true , false ) ) {
dataNode = node - > findTypeNot ( DwMime : : kTypeApplication ,
DwMime : : kSubtypePgpSignature ,
true , false ) ;
} else if ( node - > findType ( DwMime : : kTypeApplication ,
DwMime : : kSubtypePkcs7Mime ,
true , false ) ) {
dataNode = node - > findTypeNot ( DwMime : : kTypeApplication ,
DwMime : : kSubtypePkcs7Mime ,
true , false ) ;
} else {
dataNode = node - > findTypeNot ( DwMime : : kTypeMultipart ,
DwMime : : kSubtypeUnknown ,
true , false ) ;
}
} else {
ObjectTreeParser otp ( 0 , 0 , false , false , false ) ;
// process this node and all it's siblings and descendants
dataNode - > setProcessed ( false , true ) ;
otp . parseObjectTree ( dataNode ) ;
rawReplyString = otp . rawReplyString ( ) ;
gotRawReplyString = true ;
}
}
TQByteArray cstr = gotRawReplyString
? rawReplyString
: dataNode - > msgPart ( ) . bodyDecodedBinary ( ) ;
data = cstr ;
size_t size = cstr . size ( ) ;
if ( dataNode - > msgPart ( ) . type ( ) = = DwMime : : kTypeText ) {
// convert CRLF to LF before writing text attachments to disk
size = KMail : : Util : : crlf2lf ( cstr . data ( ) , size ) ;
}
data . resize ( size ) ;
}
}
TQDataStream ds ;
TQFile file ;
KTempFile tf ;
tf . setAutoDelete ( true ) ;
if ( url . isLocalFile ( ) )
{
// save directly
file . setName ( url . path ( ) ) ;
if ( ! file . open ( IO_WriteOnly ) )
{
KMessageBox : : error ( parentWidget ( ) ,
i18n ( " %2 is detailed error description " ,
" Could not write the file %1: \n %2 " )
. arg ( file . name ( ) )
. arg ( TQString : : fromLocal8Bit ( strerror ( errno ) ) ) ,
i18n ( " KMail Error " ) ) ;
return Failed ;
}
// #79685 by default use the umask the user defined, but let it be configurable
if ( GlobalSettings : : self ( ) - > disregardUmask ( ) )
fchmod ( file . handle ( ) , S_IRUSR | S_IWUSR ) ;
ds . setDevice ( & file ) ;
} else
{
// tmp file for upload
ds . setDevice ( tf . file ( ) ) ;
}
ds . writeRawBytes ( data . data ( ) , data . size ( ) ) ;
if ( ! url . isLocalFile ( ) )
{
tf . close ( ) ;
if ( ! TDEIO : : NetAccess : : upload ( tf . name ( ) , url , parentWidget ( ) ) )
{
KMessageBox : : error ( parentWidget ( ) ,
i18n ( " Could not write the file %1. " )
. arg ( url . path ( ) ) ,
i18n ( " KMail Error " ) ) ;
return Failed ;
}
} else
file . close ( ) ;
return OK ;
}
KMLoadPartsCommand : : KMLoadPartsCommand ( TQPtrList < partNode > & parts , KMMessage * msg )
: mNeedsRetrieval ( 0 )
{
for ( TQPtrListIterator < partNode > it ( parts ) ; it . current ( ) ; + + it ) {
mPartMap . insert ( it . current ( ) , msg ) ;
}
}
KMLoadPartsCommand : : KMLoadPartsCommand ( partNode * node , KMMessage * msg )
: mNeedsRetrieval ( 0 )
{
mPartMap . insert ( node , msg ) ;
}
KMLoadPartsCommand : : KMLoadPartsCommand ( PartNodeMessageMap & partMap )
: mNeedsRetrieval ( 0 ) , mPartMap ( partMap )
{
}
void KMLoadPartsCommand : : slotStart ( )
{
for ( PartNodeMessageMap : : const_iterator it = mPartMap . begin ( ) ;
it ! = mPartMap . end ( ) ;
+ + it ) {
if ( ! it . key ( ) - > msgPart ( ) . isComplete ( ) & &
! it . key ( ) - > msgPart ( ) . partSpecifier ( ) . isEmpty ( ) ) {
// incomplete part, so retrieve it first
+ + mNeedsRetrieval ;
KMFolder * curFolder = it . data ( ) - > parent ( ) ;
if ( curFolder ) {
FolderJob * job =
curFolder - > createJob ( it . data ( ) , FolderJob : : tGetMessage ,
0 , it . key ( ) - > msgPart ( ) . partSpecifier ( ) ) ;
job - > setCancellable ( false ) ;
connect ( job , TQ_SIGNAL ( messageUpdated ( KMMessage * , TQString ) ) ,
this , TQ_SLOT ( slotPartRetrieved ( KMMessage * , TQString ) ) ) ;
job - > start ( ) ;
} else
kdWarning ( 5006 ) < < " KMLoadPartsCommand - msg has no parent " < < endl ;
}
}
if ( mNeedsRetrieval = = 0 )
execute ( ) ;
}
void KMLoadPartsCommand : : slotPartRetrieved ( KMMessage * msg ,
TQString partSpecifier )
{
DwBodyPart * part =
msg - > findDwBodyPart ( msg - > getFirstDwBodyPart ( ) , partSpecifier ) ;
if ( part ) {
// update the DwBodyPart in the partNode
for ( PartNodeMessageMap : : const_iterator it = mPartMap . begin ( ) ;
it ! = mPartMap . end ( ) ;
+ + it ) {
if ( it . key ( ) - > dwPart ( ) - > partId ( ) = = part - > partId ( ) )
it . key ( ) - > setDwPart ( part ) ;
}
} else
kdWarning ( 5006 ) < < " KMLoadPartsCommand::slotPartRetrieved - could not find bodypart! " < < endl ;
- - mNeedsRetrieval ;
if ( mNeedsRetrieval = = 0 )
execute ( ) ;
}
KMCommand : : Result KMLoadPartsCommand : : execute ( )
{
emit partsRetrieved ( ) ;
setResult ( OK ) ;
emit completed ( this ) ;
deleteLater ( ) ;
return OK ;
}
KMResendMessageCommand : : KMResendMessageCommand ( TQWidget * parent ,
KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result KMResendMessageCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMMessage * newMsg = new KMMessage ( * msg ) ;
TQStringList whiteList ;
whiteList < < " To " < < " Cc " < < " Bcc " < < " Subject " ;
newMsg - > sanitizeHeaders ( whiteList ) ;
if ( newMsg - > type ( ) = = DwMime : : kTypeText ) {
newMsg - > setCharset ( msg - > codec ( ) - > mimeName ( ) ) ;
}
newMsg - > setParent ( 0 ) ;
// make sure we have an identity set, default, if necessary
newMsg - > setHeaderField ( " X-KMail-Identity " , TQString : : number ( newMsg - > identityUoid ( ) ) ) ;
newMsg - > applyIdentity ( newMsg - > identityUoid ( ) ) ;
KMail : : Composer * win = KMail : : makeComposer ( ) ;
win - > setMsg ( newMsg , false , true ) ;
win - > show ( ) ;
return OK ;
}
KMMailingListCommand : : KMMailingListCommand ( TQWidget * parent , KMFolder * folder )
: KMCommand ( parent ) , mFolder ( folder )
{
}
KMCommand : : Result KMMailingListCommand : : execute ( )
{
KURL : : List lst = urls ( ) ;
TQString handler = ( mFolder - > mailingList ( ) . handler ( ) = = MailingList : : KMail )
? " mailto " : " https " ;
KMCommand * command = 0 ;
for ( KURL : : List : : Iterator itr = lst . begin ( ) ; itr ! = lst . end ( ) ; + + itr ) {
if ( handler = = ( * itr ) . protocol ( ) ) {
command = new KMUrlClickedCommand ( * itr , mFolder - > identity ( ) , 0 , false ) ;
}
}
if ( ! command & & ! lst . empty ( ) ) {
command =
new KMUrlClickedCommand ( lst . first ( ) , mFolder - > identity ( ) , 0 , false ) ;
}
if ( command ) {
connect ( command , TQ_SIGNAL ( completed ( KMCommand * ) ) ,
this , TQ_SLOT ( commandCompleted ( KMCommand * ) ) ) ;
setDeletesItself ( true ) ;
setEmitsCompletedItself ( true ) ;
command - > start ( ) ;
return OK ;
}
return Failed ;
}
void KMMailingListCommand : : commandCompleted ( KMCommand * command )
{
setResult ( command - > result ( ) ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
KMMailingListPostCommand : : KMMailingListPostCommand ( TQWidget * parent , KMFolder * folder )
: KMMailingListCommand ( parent , folder )
{
}
KURL : : List KMMailingListPostCommand : : urls ( ) const
{
return mFolder - > mailingList ( ) . postURLS ( ) ;
}
KMMailingListSubscribeCommand : : KMMailingListSubscribeCommand ( TQWidget * parent , KMFolder * folder )
: KMMailingListCommand ( parent , folder )
{
}
KURL : : List KMMailingListSubscribeCommand : : urls ( ) const
{
return mFolder - > mailingList ( ) . subscribeURLS ( ) ;
}
KMMailingListUnsubscribeCommand : : KMMailingListUnsubscribeCommand ( TQWidget * parent , KMFolder * folder )
: KMMailingListCommand ( parent , folder )
{
}
KURL : : List KMMailingListUnsubscribeCommand : : urls ( ) const
{
return mFolder - > mailingList ( ) . unsubscribeURLS ( ) ;
}
KMMailingListArchivesCommand : : KMMailingListArchivesCommand ( TQWidget * parent , KMFolder * folder )
: KMMailingListCommand ( parent , folder )
{
}
KURL : : List KMMailingListArchivesCommand : : urls ( ) const
{
return mFolder - > mailingList ( ) . archiveURLS ( ) ;
}
KMMailingListHelpCommand : : KMMailingListHelpCommand ( TQWidget * parent , KMFolder * folder )
: KMMailingListCommand ( parent , folder )
{
}
KURL : : List KMMailingListHelpCommand : : urls ( ) const
{
return mFolder - > mailingList ( ) . helpURLS ( ) ;
}
KMIMChatCommand : : KMIMChatCommand ( const KURL & url , KMMessage * msg )
: mUrl ( url ) , mMessage ( msg )
{
}
KMCommand : : Result KMIMChatCommand : : execute ( )
{
kdDebug ( 5006 ) < < k_funcinfo < < " URL is: " < < mUrl < < endl ;
TQString addr = KMMessage : : decodeMailtoUrl ( mUrl . path ( ) ) ;
// find UID for mail address
TDEABC : : AddressBook * addressBook = TDEABC : : StdAddressBook : : self ( true ) ;
TDEABC : : AddresseeList addressees = addressBook - > findByEmail ( KPIM : : getEmailAddress ( addr ) ) ;
// start chat
if ( addressees . count ( ) = = 1 ) {
kmkernel - > imProxy ( ) - > chatWithContact ( addressees [ 0 ] . uid ( ) ) ;
return OK ;
}
else
{
kdDebug ( 5006 ) < < " Didn't find exactly one addressee, couldn't tell who to chat to for that email address. Count = " < < addressees . count ( ) < < endl ;
TQString apology ;
if ( addressees . isEmpty ( ) )
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. " ) ;
else
{
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. " ) ;
TQStringList nameList ;
TDEABC : : AddresseeList : : const_iterator it = addressees . begin ( ) ;
TDEABC : : AddresseeList : : const_iterator end = addressees . end ( ) ;
for ( ; it ! = end ; + + it )
{
nameList . append ( ( * it ) . realName ( ) ) ;
}
TQString names = nameList . join ( TQString : : fromLatin1 ( " , \n " ) ) ;
apology = apology . arg ( names ) ;
}
KMessageBox : : sorry ( parentWidget ( ) , apology ) ;
return Failed ;
}
}
KMHandleAttachmentCommand : : KMHandleAttachmentCommand ( partNode * node ,
KMMessage * msg , int atmId , const TQString & atmName ,
AttachmentAction action , KService : : Ptr offer , TQWidget * parent )
: KMCommand ( parent ) , mNode ( node ) , mMsg ( msg ) , mAtmId ( atmId ) , mAtmName ( atmName ) ,
mAction ( action ) , mOffer ( offer ) , mJob ( 0 )
{
}
void KMHandleAttachmentCommand : : slotStart ( )
{
if ( ! mNode - > msgPart ( ) . isComplete ( ) )
{
// load the part
kdDebug ( 5006 ) < < " load part " < < endl ;
KMLoadPartsCommand * command = new KMLoadPartsCommand ( mNode , mMsg ) ;
connect ( command , TQ_SIGNAL ( partsRetrieved ( ) ) ,
this , TQ_SLOT ( slotPartComplete ( ) ) ) ;
command - > start ( ) ;
} else
{
execute ( ) ;
}
}
void KMHandleAttachmentCommand : : slotPartComplete ( )
{
execute ( ) ;
}
KMCommand : : Result KMHandleAttachmentCommand : : execute ( )
{
switch ( mAction )
{
case Open :
atmOpen ( ) ;
break ;
case OpenWith :
atmOpenWith ( ) ;
break ;
case View :
atmView ( ) ;
break ;
case Save :
atmSave ( ) ;
break ;
case Properties :
atmProperties ( ) ;
break ;
case ChiasmusEncrypt :
atmEncryptWithChiasmus ( ) ;
return Undefined ;
break ;
default :
kdDebug ( 5006 ) < < " unknown action " < < mAction < < endl ;
break ;
}
setResult ( OK ) ;
emit completed ( this ) ;
deleteLater ( ) ;
return OK ;
}
TQString KMHandleAttachmentCommand : : createAtmFileLink ( ) const
{
TQFileInfo atmFileInfo ( mAtmName ) ;
if ( atmFileInfo . size ( ) = = 0 )
{
kdDebug ( 5006 ) < < k_funcinfo < < " rewriting attachment " < < endl ;
// there is something wrong so write the file again
TQByteArray data = mNode - > msgPart ( ) . bodyDecodedBinary ( ) ;
size_t size = data . size ( ) ;
if ( mNode - > msgPart ( ) . type ( ) = = DwMime : : kTypeText & & size ) {
// convert CRLF to LF before writing text attachments to disk
size = KMail : : Util : : crlf2lf ( data . data ( ) , size ) ;
}
KPIM : : kBytesToFile ( data . data ( ) , size , mAtmName , false , false , false ) ;
}
KTempFile * linkFile = new KTempFile ( locateLocal ( " tmp " , atmFileInfo . fileName ( ) + " _[ " ) ,
" ]. " + atmFileInfo . extension ( ) ) ;
linkFile - > setAutoDelete ( true ) ;
TQString linkName = linkFile - > name ( ) ;
delete linkFile ;
if ( : : link ( TQFile : : encodeName ( mAtmName ) , TQFile : : encodeName ( linkName ) ) = = 0 ) {
return linkName ; // success
}
return TQString ( ) ;
}
KService : : Ptr KMHandleAttachmentCommand : : getServiceOffer ( )
{
KMMessagePart & msgPart = mNode - > msgPart ( ) ;
const TQString contentTypeStr =
( msgPart . typeStr ( ) + ' / ' + msgPart . subtypeStr ( ) ) . lower ( ) ;
if ( contentTypeStr = = " text/x-vcard " ) {
atmView ( ) ;
return 0 ;
}
// determine the MIME type of the attachment
KMimeType : : Ptr mimetype ;
// prefer the value of the Content-Type header
mimetype = KMimeType : : mimeType ( contentTypeStr ) ;
if ( mimetype - > name ( ) = = " application/octet-stream " ) {
// consider the filename if Content-Type is application/octet-stream
mimetype = KMimeType : : findByPath ( mAtmName , 0 , true /* no disk access */ ) ;
}
if ( ( mimetype - > name ( ) = = " application/octet-stream " )
& & msgPart . isComplete ( ) ) {
// consider the attachment's contents if neither the Content-Type header
// nor the filename give us a clue
mimetype = KMimeType : : findByFileContent ( mAtmName ) ;
}
return KServiceTypeProfile : : preferredService ( mimetype - > name ( ) , " Application " ) ;
}
void KMHandleAttachmentCommand : : atmOpen ( )
{
if ( ! mOffer )
mOffer = getServiceOffer ( ) ;
if ( ! mOffer ) {
kdDebug ( 5006 ) < < k_funcinfo < < " got no offer " < < endl ;
return ;
}
KURL : : List lst ;
KURL url ;
bool autoDelete = true ;
TQString fname = createAtmFileLink ( ) ;
if ( fname . isNull ( ) ) {
autoDelete = false ;
fname = mAtmName ;
}
url . setPath ( fname ) ;
lst . append ( url ) ;
if ( ( KRun : : run ( * mOffer , lst , autoDelete ) < = 0 ) & & autoDelete ) {
TQFile : : remove ( url . path ( ) ) ;
}
}
void KMHandleAttachmentCommand : : atmOpenWith ( )
{
KURL : : List lst ;
KURL url ;
bool autoDelete = true ;
TQString fname = createAtmFileLink ( ) ;
if ( fname . isNull ( ) ) {
autoDelete = false ;
fname = mAtmName ;
}
url . setPath ( fname ) ;
lst . append ( url ) ;
if ( ( ! KRun : : displayOpenWithDialog ( lst , autoDelete ) ) & & autoDelete ) {
TQFile : : remove ( url . path ( ) ) ;
}
}
void KMHandleAttachmentCommand : : atmView ( )
{
// we do not handle this ourself
emit showAttachment ( mAtmId , mAtmName ) ;
}
void KMHandleAttachmentCommand : : atmSave ( )
{
TQPtrList < partNode > parts ;
parts . append ( mNode ) ;
// save, do not leave encoded
KMSaveAttachmentsCommand * command =
new KMSaveAttachmentsCommand ( parentWidget ( ) , parts , mMsg , false ) ;
command - > start ( ) ;
}
void KMHandleAttachmentCommand : : atmProperties ( )
{
KMMsgPartDialogCompat dlg ( parentWidget ( ) , 0 , true ) ;
KMMessagePart & msgPart = mNode - > msgPart ( ) ;
dlg . setMsgPart ( & msgPart ) ;
dlg . exec ( ) ;
}
void KMHandleAttachmentCommand : : atmEncryptWithChiasmus ( )
{
const partNode * node = mNode ;
Q_ASSERT ( node ) ;
if ( ! node )
return ;
// FIXME: better detection of mimetype??
if ( ! mAtmName . endsWith ( " .xia " , false ) )
return ;
const Kleo : : CryptoBackend : : Protocol * chiasmus =
Kleo : : CryptoBackendFactory : : instance ( ) - > protocol ( " Chiasmus " ) ;
Q_ASSERT ( chiasmus ) ;
if ( ! chiasmus )
return ;
const STD_NAMESPACE_PREFIX unique_ptr < Kleo : : SpecialJob > listjob ( chiasmus - > specialJob ( " x-obtain-keys " , TQStringVariantMap ( ) ) ) ;
if ( ! listjob ) {
const TQString msg = i18n ( " Chiasmus backend does not offer the "
" \" x-obtain-keys \" function. Please report this bug. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
if ( listjob - > exec ( ) ) {
listjob - > showErrorDialog ( parentWidget ( ) , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
const TQVariant result = listjob - > property ( " result " ) ;
if ( result . type ( ) ! = TQVariant : : StringList ) {
const TQString msg = i18n ( " Unexpected return value from Chiasmus backend: "
" The \" x-obtain-keys \" function did not return a "
" string list. Please report this bug. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
const TQStringList keys = result . toStringList ( ) ;
if ( keys . empty ( ) ) {
const TQString msg = i18n ( " No keys have been found. Please check that a "
" valid key path has been set in the Chiasmus "
" configuration. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
ChiasmusKeySelector selectorDlg ( parentWidget ( ) , i18n ( " Chiasmus Decryption Key Selection " ) ,
keys , GlobalSettings : : chiasmusDecryptionKey ( ) ,
GlobalSettings : : chiasmusDecryptionOptions ( ) ) ;
if ( selectorDlg . exec ( ) ! = TQDialog : : Accepted )
return ;
GlobalSettings : : setChiasmusDecryptionOptions ( selectorDlg . options ( ) ) ;
GlobalSettings : : setChiasmusDecryptionKey ( selectorDlg . key ( ) ) ;
assert ( ! GlobalSettings : : chiasmusDecryptionKey ( ) . isEmpty ( ) ) ;
Kleo : : SpecialJob * job = chiasmus - > specialJob ( " x-decrypt " , TQStringVariantMap ( ) ) ;
if ( ! job ) {
const TQString msg = i18n ( " Chiasmus backend does not offer the "
" \" x-decrypt \" function. Please report this bug. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
const TQByteArray input = node - > msgPart ( ) . bodyDecodedBinary ( ) ;
if ( ! job - > setProperty ( " key " , GlobalSettings : : chiasmusDecryptionKey ( ) ) | |
! job - > setProperty ( " options " , GlobalSettings : : chiasmusDecryptionOptions ( ) ) | |
! job - > setProperty ( " input " , input ) ) {
const TQString msg = i18n ( " The \" x-decrypt \" function does not accept "
" the expected parameters. Please report this bug. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
setDeletesItself ( true ) ; // the job below is async, we have to cleanup ourselves
if ( job - > start ( ) ) {
job - > showErrorDialog ( parentWidget ( ) , i18n ( " Chiasmus Decryption Error " ) ) ;
return ;
}
mJob = job ;
connect ( job , TQ_SIGNAL ( result ( const GpgME : : Error & , const TQVariant & ) ) ,
this , TQ_SLOT ( slotAtmDecryptWithChiasmusResult ( const GpgME : : Error & , const TQVariant & ) ) ) ;
}
static const TQString chomp ( const TQString & base , const TQString & suffix , bool cs ) {
return base . endsWith ( suffix , cs ) ? base . left ( base . length ( ) - suffix . length ( ) ) : base ;
}
void KMHandleAttachmentCommand : : slotAtmDecryptWithChiasmusResult ( const GpgME : : Error & err , const TQVariant & result )
{
LaterDeleterWithCommandCompletion d ( this ) ;
if ( ! mJob )
return ;
Q_ASSERT ( mJob = = sender ( ) ) ;
if ( mJob ! = sender ( ) )
return ;
Kleo : : Job * job = mJob ;
mJob = 0 ;
if ( err . isCanceled ( ) )
return ;
if ( err ) {
job - > showErrorDialog ( parentWidget ( ) , i18n ( " Chiasmus Decryption Error " ) ) ;
return ;
}
if ( result . type ( ) ! = TQVariant : : ByteArray ) {
const TQString msg = i18n ( " Unexpected return value from Chiasmus backend: "
" The \" x-decrypt \" function did not return a "
" byte array. Please report this bug. " ) ;
KMessageBox : : error ( parentWidget ( ) , msg , i18n ( " Chiasmus Backend Error " ) ) ;
return ;
}
const KURL url = KFileDialog : : getSaveURL ( chomp ( mAtmName , " .xia " , false ) , TQString ( ) , parentWidget ( ) ) ;
if ( url . isEmpty ( ) )
return ;
bool overwrite = KMail : : Util : : checkOverwrite ( url , parentWidget ( ) ) ;
if ( ! overwrite )
return ;
d . setDisabled ( true ) ; // we got this far, don't delete yet
TDEIO : : Job * uploadJob = TDEIO : : storedPut ( result . toByteArray ( ) , url , - 1 , overwrite , false /*resume*/ ) ;
uploadJob - > setWindow ( parentWidget ( ) ) ;
connect ( uploadJob , TQ_SIGNAL ( result ( TDEIO : : Job * ) ) ,
this , TQ_SLOT ( slotAtmDecryptWithChiasmusUploadResult ( TDEIO : : Job * ) ) ) ;
}
void KMHandleAttachmentCommand : : slotAtmDecryptWithChiasmusUploadResult ( TDEIO : : Job * job )
{
if ( job - > error ( ) )
job - > showErrorDialog ( ) ;
LaterDeleterWithCommandCompletion d ( this ) ;
d . setResult ( OK ) ;
}
AttachmentModifyCommand : : AttachmentModifyCommand ( partNode * node , KMMessage * msg , TQWidget * parent ) :
KMCommand ( parent , msg ) ,
mPartIndex ( node - > nodeId ( ) ) ,
mSernum ( 0 )
{
}
AttachmentModifyCommand : : AttachmentModifyCommand ( int nodeId , KMMessage * msg , TQWidget * parent )
: KMCommand ( parent , msg ) ,
mPartIndex ( nodeId ) ,
mSernum ( 0 )
{
}
AttachmentModifyCommand : : ~ AttachmentModifyCommand ( )
{
}
KMCommand : : Result AttachmentModifyCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg )
return Failed ;
mSernum = msg - > getMsgSerNum ( ) ;
mFolder = msg - > parent ( ) ;
if ( ! mFolder | | ! mFolder - > storage ( ) )
return Failed ;
Result res = doAttachmentModify ( ) ;
if ( res ! = OK )
return res ;
setEmitsCompletedItself ( true ) ;
setDeletesItself ( true ) ;
return OK ;
}
void AttachmentModifyCommand : : storeChangedMessage ( KMMessage * msg )
{
if ( ! mFolder | | ! mFolder - > storage ( ) ) {
kdWarning ( 5006 ) < < k_funcinfo < < " We lost the folder! " < < endl ;
setResult ( Failed ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
int res = mFolder - > addMsg ( msg ) ! = 0 ;
if ( mFolder - > folderType ( ) = = KMFolderTypeImap ) {
KMFolderImap * f = static_cast < KMFolderImap * > ( mFolder - > storage ( ) ) ;
connect ( f , TQ_SIGNAL ( folderComplete ( KMFolderImap * , bool ) ) ,
TQ_SLOT ( messageStoreResult ( KMFolderImap * , bool ) ) ) ;
} else {
messageStoreResult ( 0 , res = = 0 ) ;
}
}
void AttachmentModifyCommand : : messageStoreResult ( KMFolderImap * folder , bool success )
{
Q_UNUSED ( folder ) ;
if ( success ) {
KMCommand * delCmd = new KMDeleteMsgCommand ( mSernum ) ;
connect ( delCmd , TQ_SIGNAL ( completed ( KMCommand * ) ) , TQ_SLOT ( messageDeleteResult ( KMCommand * ) ) ) ;
delCmd - > start ( ) ;
return ;
}
kdWarning ( 5006 ) < < k_funcinfo < < " Adding modified message failed. " < < endl ;
setResult ( Failed ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
void AttachmentModifyCommand : : messageDeleteResult ( KMCommand * cmd )
{
setResult ( cmd - > result ( ) ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
KMDeleteAttachmentCommand : : KMDeleteAttachmentCommand ( partNode * node , KMMessage * msg , TQWidget * parent ) :
AttachmentModifyCommand ( node , msg , parent )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
}
KMDeleteAttachmentCommand : : KMDeleteAttachmentCommand ( int nodeId , KMMessage * msg , TQWidget * parent )
: AttachmentModifyCommand ( nodeId , msg , parent )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
}
KMDeleteAttachmentCommand : : ~ KMDeleteAttachmentCommand ( )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
}
KMCommand : : Result KMDeleteAttachmentCommand : : doAttachmentModify ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > deleteBodyPart ( mPartIndex ) )
return Failed ;
KMMessage * newMsg = new KMMessage ( ) ;
newMsg - > fromDwString ( msg - > asDwString ( ) ) ;
newMsg - > setStatus ( msg - > status ( ) ) ;
storeChangedMessage ( newMsg ) ;
return OK ;
}
KMEditAttachmentCommand : : KMEditAttachmentCommand ( partNode * node , KMMessage * msg , TQWidget * parent ) :
AttachmentModifyCommand ( node , msg , parent )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
mTempFile . setAutoDelete ( true ) ;
}
KMEditAttachmentCommand : : KMEditAttachmentCommand ( int nodeId , KMMessage * msg , TQWidget * parent )
: AttachmentModifyCommand ( nodeId , msg , parent )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
mTempFile . setAutoDelete ( true ) ;
}
KMEditAttachmentCommand : : ~ KMEditAttachmentCommand ( )
{
}
KMCommand : : Result KMEditAttachmentCommand : : doAttachmentModify ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg )
return Failed ;
KMMessagePart part ;
DwBodyPart * dwpart = msg - > findPart ( mPartIndex ) ;
if ( ! dwpart )
return Failed ;
KMMessage : : bodyPart ( dwpart , & part , true ) ;
if ( ! part . isComplete ( ) )
return Failed ;
if ( ! dynamic_cast < DwBody * > ( dwpart - > Parent ( ) ) )
return Failed ;
mTempFile . file ( ) - > writeBlock ( part . bodyDecodedBinary ( ) ) ;
mTempFile . file ( ) - > flush ( ) ;
KMail : : EditorWatcher * watcher =
new KMail : : EditorWatcher ( KURL ( mTempFile . file ( ) - > name ( ) ) ,
part . typeStr ( ) + " / " + part . subtypeStr ( ) ,
false , this , parentWidget ( ) ) ;
connect ( watcher , TQ_SIGNAL ( editDone ( KMail : : EditorWatcher * ) ) , TQ_SLOT ( editDone ( KMail : : EditorWatcher * ) ) ) ;
if ( ! watcher - > start ( ) )
return Failed ;
setEmitsCompletedItself ( true ) ;
setDeletesItself ( true ) ;
return OK ;
}
void KMEditAttachmentCommand : : editDone ( KMail : : EditorWatcher * watcher )
{
kdDebug ( 5006 ) < < k_funcinfo < < endl ;
// anything changed?
if ( ! watcher - > fileChanged ( ) ) {
kdDebug ( 5006 ) < < k_funcinfo < < " File has not been changed " < < endl ;
setResult ( Canceled ) ;
emit completed ( this ) ;
deleteLater ( ) ;
}
mTempFile . file ( ) - > reset ( ) ;
TQByteArray data = mTempFile . file ( ) - > readAll ( ) ;
// build the new message
KMMessage * msg = retrievedMessage ( ) ;
KMMessagePart part ;
DwBodyPart * dwpart = msg - > findPart ( mPartIndex ) ;
KMMessage : : bodyPart ( dwpart , & part , true ) ;
DwBody * parentNode = dynamic_cast < DwBody * > ( dwpart - > Parent ( ) ) ;
assert ( parentNode ) ;
parentNode - > RemoveBodyPart ( dwpart ) ;
KMMessagePart att ;
att . duplicate ( part ) ;
att . setBodyEncodedBinary ( data ) ;
DwBodyPart * newDwPart = msg - > createDWBodyPart ( & att ) ;
parentNode - > AddBodyPart ( newDwPart ) ;
msg - > getTopLevelPart ( ) - > Assemble ( ) ;
KMMessage * newMsg = new KMMessage ( ) ;
newMsg - > fromDwString ( msg - > asDwString ( ) ) ;
newMsg - > setStatus ( msg - > status ( ) ) ;
storeChangedMessage ( newMsg ) ;
}
CreateTodoCommand : : CreateTodoCommand ( TQWidget * parent , KMMessage * msg )
: KMCommand ( parent , msg )
{
}
KMCommand : : Result CreateTodoCommand : : execute ( )
{
KMMessage * msg = retrievedMessage ( ) ;
if ( ! msg | | ! msg - > codec ( ) ) {
return Failed ;
}
KMail : : KorgHelper : : ensureRunning ( ) ;
TQString txt = i18n ( " From: %1 \n To: %2 \n Subject: %3 " ) . arg ( msg - > from ( ) )
. arg ( msg - > to ( ) ) . arg ( msg - > subject ( ) ) ;
KTempFile tf ;
tf . setAutoDelete ( true ) ;
TQString uri = " kmail: " + TQString : : number ( msg - > getMsgSerNum ( ) ) + " / " + msg - > msgId ( ) ;
tf . file ( ) - > writeBlock ( msg - > asDwString ( ) . c_str ( ) , msg - > asDwString ( ) . length ( ) ) ;
tf . close ( ) ;
KCalendarIface_stub * iface = new KCalendarIface_stub ( kapp - > dcopClient ( ) , " korganizer " , " CalendarIface " ) ;
iface - > openTodoEditor ( i18n ( " Mail: %1 " ) . arg ( msg - > subject ( ) ) , txt , uri ,
tf . name ( ) , TQStringList ( ) , " message/rfc822 " , true ) ;
delete iface ;
return OK ;
}
# include "kmcommands.moc"