|
|
|
/* -*- mode: C++; c-file-style: "gnu" -*-
|
|
|
|
* kmail: KDE mail client
|
|
|
|
* This file: Copyright (C) 2006 Dmitry Morozhnikov <dmiceman@mail.ru>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kcalendarsystem.h>
|
|
|
|
#include <kmime_util.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kshell.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
|
|
|
|
#include "kmmessage.h"
|
|
|
|
#include "kmmsgbase.h"
|
|
|
|
#include "kmfolder.h"
|
|
|
|
#include "templatesconfiguration.h"
|
|
|
|
#include "templatesconfiguration_kfg.h"
|
|
|
|
#include "customtemplates_kfg.h"
|
|
|
|
#include "globalsettings_base.h"
|
|
|
|
#include "kmkernel.h"
|
|
|
|
#include <libkpimidentities/identity.h>
|
|
|
|
#include <libkpimidentities/identitymanager.h>
|
|
|
|
#include "partNode.h"
|
|
|
|
#include "attachmentcollector.h"
|
|
|
|
#include "objecttreeparser.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
#include "templateparser.h"
|
|
|
|
#include <mimelib/bodypart.h>
|
|
|
|
|
|
|
|
using namespace KMail;
|
|
|
|
|
|
|
|
TemplateParser::TemplateParser( KMMessage *amsg, const Mode amode ) :
|
|
|
|
mMode( amode ), mFolder( 0 ), mIdentity( 0 ),
|
|
|
|
mAllowDecryption( false ),
|
|
|
|
mDebug( false ), mQuoteString( "> " ), mAppend( false ), mOrigRoot( 0 )
|
|
|
|
{
|
|
|
|
mMsg = amsg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::setSelection( const TQString &selection )
|
|
|
|
{
|
|
|
|
mSelection = selection;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::setAllowDecryption( const bool allowDecryption )
|
|
|
|
{
|
|
|
|
mAllowDecryption = allowDecryption;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TemplateParser::shouldStripSignature() const
|
|
|
|
{
|
|
|
|
// Only strip the signature when replying, it should be preserved when forwarding
|
|
|
|
return ( mMode == Reply || mMode == ReplyAll) && GlobalSettings::stripSignature();
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateParser::~TemplateParser()
|
|
|
|
{
|
|
|
|
delete mOrigRoot;
|
|
|
|
mOrigRoot = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TemplateParser::parseQuotes( const TQString &prefix, const TQString &str,
|
|
|
|
TQString "e ) const
|
|
|
|
{
|
|
|
|
int pos = prefix.length();
|
|
|
|
int len;
|
|
|
|
int str_len = str.length();
|
|
|
|
TQChar qc = '"';
|
|
|
|
TQChar prev = 0;
|
|
|
|
|
|
|
|
pos++;
|
|
|
|
len = pos;
|
|
|
|
|
|
|
|
while ( pos < str_len ) {
|
|
|
|
TQChar c = str[pos];
|
|
|
|
|
|
|
|
pos++;
|
|
|
|
len++;
|
|
|
|
|
|
|
|
if ( prev ) {
|
|
|
|
quote.append( c );
|
|
|
|
prev = 0;
|
|
|
|
} else {
|
|
|
|
if ( c == '\\' ) {
|
|
|
|
prev = c;
|
|
|
|
} else if ( c == qc ) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
quote.append( c );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::getFName( const TQString &str )
|
|
|
|
{
|
|
|
|
// simple logic:
|
|
|
|
// if there is ',' in name, than format is 'Last, First'
|
|
|
|
// else format is 'First Last'
|
|
|
|
// last resort -- return 'name' from 'name@domain'
|
|
|
|
int sep_pos;
|
|
|
|
TQString res;
|
|
|
|
if ( ( sep_pos = str.find( '@' ) ) > 0 ) {
|
|
|
|
int i;
|
|
|
|
for ( i = (sep_pos - 1); i >= 0; --i ) {
|
|
|
|
TQChar c = str[i];
|
|
|
|
if ( c.isLetterOrNumber() ) {
|
|
|
|
res.prepend( c );
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( ( sep_pos = str.find(',') ) > 0 ) {
|
|
|
|
unsigned int i;
|
|
|
|
bool begin = false;
|
|
|
|
for ( i = sep_pos; i < str.length(); ++i ) {
|
|
|
|
TQChar c = str[i];
|
|
|
|
if ( c.isLetterOrNumber() ) {
|
|
|
|
begin = true;
|
|
|
|
res.append( c );
|
|
|
|
} else if ( begin ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsigned int i;
|
|
|
|
for ( i = 0; i < str.length(); ++i ) {
|
|
|
|
TQChar c = str[i];
|
|
|
|
if ( c.isLetterOrNumber() ) {
|
|
|
|
res.append( c );
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::getLName( const TQString &str )
|
|
|
|
{
|
|
|
|
// simple logic:
|
|
|
|
// if there is ',' in name, than format is 'Last, First'
|
|
|
|
// else format is 'First Last'
|
|
|
|
int sep_pos;
|
|
|
|
TQString res;
|
|
|
|
if ( ( sep_pos = str.find(',') ) > 0 ) {
|
|
|
|
int i;
|
|
|
|
for ( i = sep_pos; i >= 0; --i ) {
|
|
|
|
TQChar c = str[i];
|
|
|
|
if ( c.isLetterOrNumber() ) {
|
|
|
|
res.prepend( c );
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( ( sep_pos = str.find( ' ' ) ) > 0 ) {
|
|
|
|
unsigned int i;
|
|
|
|
bool begin = false;
|
|
|
|
for ( i = sep_pos; i < str.length(); ++i ) {
|
|
|
|
TQChar c = str[i];
|
|
|
|
if ( c.isLetterOrNumber() ) {
|
|
|
|
begin = true;
|
|
|
|
res.append( c );
|
|
|
|
} else if ( begin ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::process( KMMessage *aorig_msg, KMFolder *afolder, bool append )
|
|
|
|
{
|
|
|
|
mAppend = append;
|
|
|
|
mOrigMsg = aorig_msg;
|
|
|
|
mFolder = afolder;
|
|
|
|
TQString tmpl = findTemplate();
|
|
|
|
return processWithTemplate( tmpl );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::process( const TQString &tmplName, KMMessage *aorig_msg,
|
|
|
|
KMFolder *afolder, bool append )
|
|
|
|
{
|
|
|
|
mAppend = append;
|
|
|
|
mOrigMsg = aorig_msg;
|
|
|
|
mFolder = afolder;
|
|
|
|
TQString tmpl = findCustomTemplate( tmplName );
|
|
|
|
return processWithTemplate( tmpl );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::processWithTemplate( const TQString &tmpl )
|
|
|
|
{
|
|
|
|
TQString body;
|
|
|
|
int tmpl_len = tmpl.length();
|
|
|
|
bool dnl = false;
|
|
|
|
for ( int i = 0; i < tmpl_len; ++i ) {
|
|
|
|
TQChar c = tmpl[i];
|
|
|
|
// kdDebug() << "Next char: " << c << endl;
|
|
|
|
if ( c == '%' ) {
|
|
|
|
TQString cmd = tmpl.mid( i + 1 );
|
|
|
|
|
|
|
|
if ( cmd.startsWith( "-" ) ) {
|
|
|
|
// dnl
|
|
|
|
kdDebug() << "Command: -" << endl;
|
|
|
|
dnl = true;
|
|
|
|
i += 1;
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "REM=" ) ) {
|
|
|
|
// comments
|
|
|
|
kdDebug() << "Command: REM=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "REM=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "INSERT=" ) ) {
|
|
|
|
// insert content of specified file as is
|
|
|
|
kdDebug() << "Command: INSERT=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "INSERT=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString path = KShell::tildeExpand( q );
|
|
|
|
TQFileInfo finfo( path );
|
|
|
|
if (finfo.isRelative() ) {
|
|
|
|
path = KShell::homeDir( "" );
|
|
|
|
path += '/';
|
|
|
|
path += q;
|
|
|
|
}
|
|
|
|
TQFile file( path );
|
|
|
|
if ( file.open( IO_ReadOnly ) ) {
|
|
|
|
TQByteArray content = file.readAll();
|
|
|
|
TQString str = TQString::fromLocal8Bit( content, content.size() );
|
|
|
|
body.append( str );
|
|
|
|
} else if ( mDebug ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Cannot insert content from file %1: %2" ).
|
|
|
|
arg( path ).arg( file.errorString() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "SYSTEM=" ) ) {
|
|
|
|
// insert content of specified file as is
|
|
|
|
kdDebug() << "Command: SYSTEM=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "SYSTEM=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
TQString str = pipe( pipe_cmd, "" );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "PUT=" ) ) {
|
|
|
|
// insert content of specified file as is
|
|
|
|
kdDebug() << "Command: PUT=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "PUT=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString path = KShell::tildeExpand( q );
|
|
|
|
TQFileInfo finfo( path );
|
|
|
|
if (finfo.isRelative() ) {
|
|
|
|
path = KShell::homeDir( "" );
|
|
|
|
path += '/';
|
|
|
|
path += q;
|
|
|
|
}
|
|
|
|
TQFile file( path );
|
|
|
|
if ( file.open( IO_ReadOnly ) ) {
|
|
|
|
TQByteArray content = file.readAll();
|
|
|
|
body.append( TQString::fromLocal8Bit( content, content.size() ) );
|
|
|
|
} else if ( mDebug ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Cannot insert content from file %1: %2").
|
|
|
|
arg( path ).arg(file.errorString() ));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "QUOTEPIPE=" ) ) {
|
|
|
|
// pipe message body throw command and insert it as quotation
|
|
|
|
kdDebug() << "Command: QUOTEPIPE=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "QUOTEPIPE=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = pipe( pipe_cmd, messageText( false ) );
|
|
|
|
TQString quote = mOrigMsg->asQuotedString( "", mQuoteString, str,
|
|
|
|
shouldStripSignature(), mAllowDecryption );
|
|
|
|
body.append( quote );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "QUOTE" ) ) {
|
|
|
|
kdDebug() << "Command: QUOTE" << endl;
|
|
|
|
i += strlen( "QUOTE" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString quote = mOrigMsg->asQuotedString( "", mQuoteString, messageText( true ),
|
|
|
|
shouldStripSignature(), mAllowDecryption );
|
|
|
|
body.append( quote );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "QHEADERS" ) ) {
|
|
|
|
kdDebug() << "Command: TQHEADERS" << endl;
|
|
|
|
i += strlen( "QHEADERS" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString quote = mOrigMsg->asQuotedString( "", mQuoteString,
|
|
|
|
mOrigMsg->headerAsSendableString(),
|
|
|
|
false, false );
|
|
|
|
body.append( quote );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "HEADERS" ) ) {
|
|
|
|
kdDebug() << "Command: HEADERS" << endl;
|
|
|
|
i += strlen( "HEADERS" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->headerAsSendableString();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TEXTPIPE=" ) ) {
|
|
|
|
// pipe message body throw command and insert it as is
|
|
|
|
kdDebug() << "Command: TEXTPIPE=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "TEXTPIPE=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = pipe(pipe_cmd, messageText( false ) );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "MSGPIPE=" ) ) {
|
|
|
|
// pipe full message throw command and insert result as is
|
|
|
|
kdDebug() << "Command: MSGPIPE=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "MSGPIPE=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = pipe(pipe_cmd, mOrigMsg->asString() );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "BODYPIPE=" ) ) {
|
|
|
|
// pipe message body generated so far throw command and insert result as is
|
|
|
|
kdDebug() << "Command: BODYPIPE=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "BODYPIPE=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
TQString str = pipe( pipe_cmd, body );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CLEARPIPE=" ) ) {
|
|
|
|
// pipe message body generated so far throw command and
|
|
|
|
// insert result as is replacing current body
|
|
|
|
kdDebug() << "Command: CLEARPIPE=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "CLEARPIPE=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString pipe_cmd = q;
|
|
|
|
TQString str = pipe( pipe_cmd, body );
|
|
|
|
body = str;
|
|
|
|
mMsg->setCursorPos( 0 );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TEXT" ) ) {
|
|
|
|
kdDebug() << "Command: TEXT" << endl;
|
|
|
|
i += strlen( "TEXT" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString quote = messageText( false );
|
|
|
|
body.append( quote );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTEXTSIZE" ) ) {
|
|
|
|
kdDebug() << "Command: OTEXTSIZE" << endl;
|
|
|
|
i += strlen( "OTEXTSIZE" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = TQString( "%1" ).arg( mOrigMsg->body().length() );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTEXT" ) ) {
|
|
|
|
kdDebug() << "Command: OTEXT" << endl;
|
|
|
|
i += strlen( "OTEXT" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString quote = messageText( false );
|
|
|
|
body.append( quote );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OADDRESSEESADDR" ) ) {
|
|
|
|
kdDebug() << "Command: OADDRESSEESADDR" << endl;
|
|
|
|
i += strlen( "OADDRESSEESADDR" );
|
|
|
|
const TQString to = mOrigMsg->to();
|
|
|
|
const TQString cc = mOrigMsg->cc();
|
|
|
|
if ( !to.isEmpty() )
|
|
|
|
body.append( i18n( "To:" ) + ' ' + to );
|
|
|
|
if ( !to.isEmpty() && !cc.isEmpty() )
|
|
|
|
body.append( '\n' );
|
|
|
|
if ( !cc.isEmpty() )
|
|
|
|
body.append( i18n( "CC:" ) + ' ' + cc );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CCADDR" ) ) {
|
|
|
|
kdDebug() << "Command: CCADDR" << endl;
|
|
|
|
i += strlen( "CCADDR" );
|
|
|
|
TQString str = mMsg->cc();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CCNAME" ) ) {
|
|
|
|
kdDebug() << "Command: CCNAME" << endl;
|
|
|
|
i += strlen( "CCNAME" );
|
|
|
|
TQString str = mMsg->ccStrip();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CCFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: CCFNAME" << endl;
|
|
|
|
i += strlen( "CCFNAME" );
|
|
|
|
TQString str = mMsg->ccStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CCLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: CCLNAME" << endl;
|
|
|
|
i += strlen( "CCLNAME" );
|
|
|
|
TQString str = mMsg->ccStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TOADDR" ) ) {
|
|
|
|
kdDebug() << "Command: TOADDR" << endl;
|
|
|
|
i += strlen( "TOADDR" );
|
|
|
|
TQString str = mMsg->to();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TONAME" ) ) {
|
|
|
|
kdDebug() << "Command: TONAME" << endl;
|
|
|
|
i += strlen( "TONAME" );
|
|
|
|
TQString str = mMsg->toStrip();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TOFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: TOFNAME" << endl;
|
|
|
|
i += strlen( "TOFNAME" );
|
|
|
|
TQString str = mMsg->toStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TOLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: TOLNAME" << endl;
|
|
|
|
i += strlen( "TOLNAME" );
|
|
|
|
TQString str = mMsg->toStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TOLIST" ) ) {
|
|
|
|
kdDebug() << "Command: TOLIST" << endl;
|
|
|
|
i += strlen( "TOLIST" );
|
|
|
|
TQString str = mMsg->to();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FROMADDR" ) ) {
|
|
|
|
kdDebug() << "Command: FROMADDR" << endl;
|
|
|
|
i += strlen( "FROMADDR" );
|
|
|
|
TQString str = mMsg->from();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FROMNAME" ) ) {
|
|
|
|
kdDebug() << "Command: FROMNAME" << endl;
|
|
|
|
i += strlen( "FROMNAME" );
|
|
|
|
TQString str = mMsg->fromStrip();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FROMFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: FROMFNAME" << endl;
|
|
|
|
i += strlen( "FROMFNAME" );
|
|
|
|
TQString str = mMsg->fromStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FROMLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: FROMLNAME" << endl;
|
|
|
|
i += strlen( "FROMLNAME" );
|
|
|
|
TQString str = mMsg->fromStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FULLSUBJECT" ) ) {
|
|
|
|
kdDebug() << "Command: FULLSUBJECT" << endl;
|
|
|
|
i += strlen( "FULLSUBJECT" );
|
|
|
|
TQString str = mMsg->subject();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "FULLSUBJ" ) ) {
|
|
|
|
kdDebug() << "Command: FULLSUBJ" << endl;
|
|
|
|
i += strlen( "FULLSUBJ" );
|
|
|
|
TQString str = mMsg->subject();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "MSGID" ) ) {
|
|
|
|
kdDebug() << "Command: MSGID" << endl;
|
|
|
|
i += strlen( "MSGID" );
|
|
|
|
TQString str = mMsg->id();
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OHEADER=" ) ) {
|
|
|
|
// insert specified content of header from original message
|
|
|
|
kdDebug() << "Command: OHEADER=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "OHEADER=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString hdr = q;
|
|
|
|
TQString str = mOrigMsg->headerFields(hdr.local8Bit() ).join( ", " );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "HEADER=" ) ) {
|
|
|
|
// insert specified content of header from current message
|
|
|
|
kdDebug() << "Command: HEADER=" << endl;
|
|
|
|
TQString q;
|
|
|
|
int len = parseQuotes( "HEADER=", cmd, q );
|
|
|
|
i += len;
|
|
|
|
TQString hdr = q;
|
|
|
|
TQString str = mMsg->headerFields(hdr.local8Bit() ).join( ", " );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "HEADER( " ) ) {
|
|
|
|
// insert specified content of header from current message
|
|
|
|
kdDebug() << "Command: HEADER( " << endl;
|
|
|
|
TQRegExp re = TQRegExp( "^HEADER\\((.+)\\)" );
|
|
|
|
re.setMinimal( true );
|
|
|
|
int res = re.search( cmd );
|
|
|
|
if ( res != 0 ) {
|
|
|
|
// something wrong
|
|
|
|
i += strlen( "HEADER( " );
|
|
|
|
} else {
|
|
|
|
i += re.matchedLength();
|
|
|
|
TQString hdr = re.cap( 1 );
|
|
|
|
TQString str = mMsg->headerFields( hdr.local8Bit() ).join( ", " );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OCCADDR" ) ) {
|
|
|
|
kdDebug() << "Command: OCCADDR" << endl;
|
|
|
|
i += strlen( "OCCADDR" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->cc();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OCCNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OCCNAME" << endl;
|
|
|
|
i += strlen( "OCCNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->ccStrip();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OCCFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OCCFNAME" << endl;
|
|
|
|
i += strlen( "OCCFNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->ccStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OCCLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OCCLNAME" << endl;
|
|
|
|
i += strlen( "OCCLNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->ccStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTOADDR" ) ) {
|
|
|
|
kdDebug() << "Command: OTOADDR" << endl;
|
|
|
|
i += strlen( "OTOADDR" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->to();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTONAME" ) ) {
|
|
|
|
kdDebug() << "Command: OTONAME" << endl;
|
|
|
|
i += strlen( "OTONAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->toStrip();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTOFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OTOFNAME" << endl;
|
|
|
|
i += strlen( "OTOFNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->toStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTOLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OTOLNAME" << endl;
|
|
|
|
i += strlen( "OTOLNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->toStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTOLIST" ) ) {
|
|
|
|
kdDebug() << "Command: OTOLIST" << endl;
|
|
|
|
i += strlen( "OTOLIST" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->to();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTO" ) ) {
|
|
|
|
kdDebug() << "Command: OTO" << endl;
|
|
|
|
i += strlen( "OTO" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->to();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFROMADDR" ) ) {
|
|
|
|
kdDebug() << "Command: OFROMADDR" << endl;
|
|
|
|
i += strlen( "OFROMADDR" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->from();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFROMNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OFROMNAME" << endl;
|
|
|
|
i += strlen( "OFROMNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->fromStrip();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFROMFNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OFROMFNAME" << endl;
|
|
|
|
i += strlen( "OFROMFNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->fromStrip();
|
|
|
|
body.append( getFName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFROMLNAME" ) ) {
|
|
|
|
kdDebug() << "Command: OFROMLNAME" << endl;
|
|
|
|
i += strlen( "OFROMLNAME" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->fromStrip();
|
|
|
|
body.append( getLName( str ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFULLSUBJECT" ) ) {
|
|
|
|
kdDebug() << "Command: OFULLSUBJECT" << endl;
|
|
|
|
i += strlen( "OFULLSUBJECT" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->subject();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OFULLSUBJ" ) ) {
|
|
|
|
kdDebug() << "Command: OFULLSUBJ" << endl;
|
|
|
|
i += strlen( "OFULLSUBJ" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->subject();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OMSGID" ) ) {
|
|
|
|
kdDebug() << "Command: OMSGID" << endl;
|
|
|
|
i += strlen( "OMSGID" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQString str = mOrigMsg->id();
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DATEEN" ) ) {
|
|
|
|
kdDebug() << "Command: DATEEN" << endl;
|
|
|
|
i += strlen( "DATEEN" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TDELocale locale( "C" );
|
|
|
|
TQString str = locale.formatDate( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DATESHORT" ) ) {
|
|
|
|
kdDebug() << "Command: DATESHORT" << endl;
|
|
|
|
i += strlen( "DATESHORT" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TQString str = TDEGlobal::locale()->formatDate( date.date(), true );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DATE" ) ) {
|
|
|
|
kdDebug() << "Command: DATE" << endl;
|
|
|
|
i += strlen( "DATE" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TQString str = TDEGlobal::locale()->formatDate( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DOW" ) ) {
|
|
|
|
kdDebug() << "Command: DOW" << endl;
|
|
|
|
i += strlen( "DOW" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TQString str = TDEGlobal::locale()->calendar()->weekDayName( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TIMELONGEN" ) ) {
|
|
|
|
kdDebug() << "Command: TIMELONGEN" << endl;
|
|
|
|
i += strlen( "TIMELONGEN" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TDELocale locale( "C");
|
|
|
|
TQString str = locale.formatTime( date.time(), true );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TIMELONG" ) ) {
|
|
|
|
kdDebug() << "Command: TIMELONG" << endl;
|
|
|
|
i += strlen( "TIMELONG" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TQString str = TDEGlobal::locale()->formatTime( date.time(), true );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "TIME" ) ) {
|
|
|
|
kdDebug() << "Command: TIME" << endl;
|
|
|
|
i += strlen( "TIME" );
|
|
|
|
TQDateTime date = TQDateTime::currentDateTime();
|
|
|
|
TQString str = TDEGlobal::locale()->formatTime( date.time(), false );
|
|
|
|
body.append( str );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "ODATEEN" ) ) {
|
|
|
|
kdDebug() << "Command: ODATEEN" << endl;
|
|
|
|
i += strlen( "ODATEEN" );
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TDELocale locale( "C");
|
|
|
|
TQString str = locale.formatDate( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "ODATESHORT") ) {
|
|
|
|
kdDebug() << "Command: ODATESHORT" << endl;
|
|
|
|
i += strlen( "ODATESHORT");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TQString str = TDEGlobal::locale()->formatDate( date.date(), true );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "ODATE") ) {
|
|
|
|
kdDebug() << "Command: ODATE" << endl;
|
|
|
|
i += strlen( "ODATE");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TQString str = TDEGlobal::locale()->formatDate( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "ODOW") ) {
|
|
|
|
kdDebug() << "Command: ODOW" << endl;
|
|
|
|
i += strlen( "ODOW");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TQString str = TDEGlobal::locale()->calendar()->weekDayName( date.date(), false );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTIMELONGEN") ) {
|
|
|
|
kdDebug() << "Command: OTIMELONGEN" << endl;
|
|
|
|
i += strlen( "OTIMELONGEN");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TDELocale locale( "C");
|
|
|
|
TQString str = locale.formatTime( date.time(), true );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTIMELONG") ) {
|
|
|
|
kdDebug() << "Command: OTIMELONG" << endl;
|
|
|
|
i += strlen( "OTIMELONG");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TQString str = TDEGlobal::locale()->formatTime( date.time(), true );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "OTIME") ) {
|
|
|
|
kdDebug() << "Command: OTIME" << endl;
|
|
|
|
i += strlen( "OTIME");
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
TQDateTime date;
|
|
|
|
date.setTime_t( mOrigMsg->date() );
|
|
|
|
TQString str = TDEGlobal::locale()->formatTime( date.time(), false );
|
|
|
|
body.append( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "BLANK" ) ) {
|
|
|
|
// do nothing
|
|
|
|
kdDebug() << "Command: BLANK" << endl;
|
|
|
|
i += strlen( "BLANK" );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "NOP" ) ) {
|
|
|
|
// do nothing
|
|
|
|
kdDebug() << "Command: NOP" << endl;
|
|
|
|
i += strlen( "NOP" );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CLEAR" ) ) {
|
|
|
|
// clear body buffer; not too useful yet
|
|
|
|
kdDebug() << "Command: CLEAR" << endl;
|
|
|
|
i += strlen( "CLEAR" );
|
|
|
|
body = "";
|
|
|
|
mMsg->setCursorPos( 0 );
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DEBUGOFF" ) ) {
|
|
|
|
// turn off debug
|
|
|
|
kdDebug() << "Command: DEBUGOFF" << endl;
|
|
|
|
i += strlen( "DEBUGOFF" );
|
|
|
|
mDebug = false;
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "DEBUG" ) ) {
|
|
|
|
// turn on debug
|
|
|
|
kdDebug() << "Command: DEBUG" << endl;
|
|
|
|
i += strlen( "DEBUG" );
|
|
|
|
mDebug = true;
|
|
|
|
|
|
|
|
} else if ( cmd.startsWith( "CURSOR" ) ) {
|
|
|
|
// turn on debug
|
|
|
|
kdDebug() << "Command: CURSOR" << endl;
|
|
|
|
i += strlen( "CURSOR" );
|
|
|
|
mMsg->setCursorPos( body.length() );
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// wrong command, do nothing
|
|
|
|
body.append( c );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( dnl && ( c == '\n' || c == '\r') ) {
|
|
|
|
// skip
|
|
|
|
if ( ( c == '\n' && tmpl[i + 1] == '\r' ) ||
|
|
|
|
( c == '\r' && tmpl[i + 1] == '\n' ) ) {
|
|
|
|
// skip one more
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
dnl = false;
|
|
|
|
} else {
|
|
|
|
body.append( c );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addProcessedBodyToMessage( body );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::messageText( bool allowSelectionOnly )
|
|
|
|
{
|
|
|
|
if ( !mSelection.isEmpty() && allowSelectionOnly )
|
|
|
|
return mSelection;
|
|
|
|
|
|
|
|
// No selection text, therefore we need to parse the object tree ourselves to get
|
|
|
|
partNode *root = parsedObjectTree();
|
|
|
|
return mOrigMsg->asPlainTextFromObjectTree( root, shouldStripSignature(), mAllowDecryption );
|
|
|
|
}
|
|
|
|
|
|
|
|
partNode* TemplateParser::parsedObjectTree()
|
|
|
|
{
|
|
|
|
if ( mOrigRoot )
|
|
|
|
return mOrigRoot;
|
|
|
|
|
|
|
|
mOrigRoot = partNode::fromMessage( mOrigMsg );
|
|
|
|
ObjectTreeParser otp; // all defaults are ok
|
|
|
|
otp.parseObjectTree( mOrigRoot );
|
|
|
|
return mOrigRoot;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::addProcessedBodyToMessage( const TQString &body )
|
|
|
|
{
|
|
|
|
if ( mAppend ) {
|
|
|
|
|
|
|
|
// ### What happens here if the body is multipart or in some way encoded?
|
|
|
|
TQCString msg_body = mMsg->body();
|
|
|
|
msg_body.append( body.utf8() );
|
|
|
|
mMsg->setBody( msg_body );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
// Get the attachments of the original mail
|
|
|
|
partNode *root = parsedObjectTree();
|
|
|
|
AttachmentCollector ac;
|
|
|
|
ac.collectAttachmentsFrom( root );
|
|
|
|
|
|
|
|
// Now, delete the old content and set the new content, which
|
|
|
|
// is either only the new text or the new text with some attachments.
|
|
|
|
mMsg->deleteBodyParts();
|
|
|
|
|
|
|
|
// Set To and CC from the template
|
|
|
|
if ( mMode == Forward ) {
|
|
|
|
if ( !mTo.isEmpty() ) {
|
|
|
|
mMsg->setTo( mMsg->to() + ',' + mTo );
|
|
|
|
}
|
|
|
|
if ( !mCC.isEmpty() )
|
|
|
|
mMsg->setCc( mMsg->cc() + ',' + mCC );
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have no attachment, simply create a text/plain part and
|
|
|
|
// set the processed template text as the body
|
|
|
|
if ( ac.attachments().empty() || mMode != Forward ) {
|
|
|
|
mMsg->headers().ContentType().FromString( DwString() ); // to get rid of old boundary
|
|
|
|
mMsg->headers().ContentType().Parse();
|
|
|
|
mMsg->headers().ContentType().SetType( DwMime::kTypeText );
|
|
|
|
mMsg->headers().ContentType().SetSubtype( DwMime::kSubtypePlain );
|
|
|
|
mMsg->headers().Assemble();
|
|
|
|
mMsg->setBodyFromUnicode( body );
|
|
|
|
mMsg->assembleIfNeeded();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have some attachments, create a multipart/mixed mail and
|
|
|
|
// add the normal body as well as the attachments
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mMsg->headers().ContentType().SetType( DwMime::kTypeMultipart );
|
|
|
|
mMsg->headers().ContentType().SetSubtype( DwMime::kSubtypeMixed );
|
|
|
|
mMsg->headers().ContentType().CreateBoundary( 0 );
|
|
|
|
|
|
|
|
KMMessagePart textPart;
|
|
|
|
textPart.setBodyFromUnicode( body );
|
|
|
|
mMsg->addDwBodyPart( mMsg->createDWBodyPart( &textPart ) );
|
|
|
|
mMsg->assembleIfNeeded();
|
|
|
|
|
|
|
|
int attachmentNumber = 1;
|
|
|
|
for ( std::vector<partNode*>::const_iterator it = ac.attachments().begin();
|
|
|
|
it != ac.attachments().end(); ++it, attachmentNumber++ ) {
|
|
|
|
|
|
|
|
// When adding this body part, make sure to _not_ add the next bodypart
|
|
|
|
// as well, which mimelib would do, therefore creating a mail with many
|
|
|
|
// duplicate attachments (so many that KMail runs out of memory, in fact).
|
|
|
|
// Body::AddBodyPart is very misleading here...
|
|
|
|
( *it )->dwPart()->SetNext( 0 );
|
|
|
|
|
|
|
|
DwBodyPart *cloned = static_cast<DwBodyPart*>( ( *it )->dwPart()->Clone() );
|
|
|
|
|
|
|
|
// If the content type has no name or filename parameter, add one, since otherwise the name
|
|
|
|
// would be empty in the attachment view of the composer, which looks confusing
|
|
|
|
if ( cloned->Headers().HasContentType() ) {
|
|
|
|
DwMediaType &ct = cloned->Headers().ContentType();
|
|
|
|
|
|
|
|
// Converting to a string here, since DwMediaType does not have a HasParameter() function
|
|
|
|
TQString ctStr = ct.AsString().c_str();
|
|
|
|
if ( !ctStr.lower().contains( "name=" ) && !ctStr.lower().contains( "filename=" ) ) {
|
|
|
|
DwParameter *nameParameter = new DwParameter;
|
|
|
|
nameParameter->SetAttribute( "name" );
|
|
|
|
nameParameter->SetValue( Util::dwString( KMMsgBase::encodeRFC2231StringAutoDetectCharset(
|
|
|
|
i18n( "Attachment %1" ).arg( attachmentNumber ) ) ) );
|
|
|
|
ct.AddParameter( nameParameter );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mMsg->addDwBodyPart( cloned );
|
|
|
|
mMsg->assembleIfNeeded();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::findCustomTemplate( const TQString &tmplName )
|
|
|
|
{
|
|
|
|
CTemplates t( tmplName );
|
|
|
|
mTo = t.to();
|
|
|
|
mCC = t.cC();
|
|
|
|
TQString content = t.content();
|
|
|
|
if ( !content.isEmpty() ) {
|
|
|
|
return content;
|
|
|
|
} else {
|
|
|
|
return findTemplate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::findTemplate()
|
|
|
|
{
|
|
|
|
// import 'Phrases' if it not done yet
|
|
|
|
if ( !GlobalSettings::self()->phrasesConverted() ) {
|
|
|
|
TemplatesConfiguration::importFromPhrases();
|
|
|
|
}
|
|
|
|
|
|
|
|
// kdDebug() << "Trying to find template for mode " << mode << endl;
|
|
|
|
|
|
|
|
TQString tmpl;
|
|
|
|
|
|
|
|
if ( !mFolder ) { // find folder message belongs to
|
|
|
|
mFolder = mMsg->parent();
|
|
|
|
if ( !mFolder ) {
|
|
|
|
if ( mOrigMsg ) {
|
|
|
|
mFolder = mOrigMsg->parent();
|
|
|
|
}
|
|
|
|
if ( !mFolder ) {
|
|
|
|
kdDebug(5006) << "Oops! No folder for message" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
kdDebug(5006) << "Folder found: " << mFolder << endl;
|
|
|
|
|
|
|
|
if ( mFolder ) // only if a folder was found
|
|
|
|
{
|
|
|
|
TQString fid = mFolder->idString();
|
|
|
|
Templates fconf( fid );
|
|
|
|
if ( fconf.useCustomTemplates() ) { // does folder use custom templates?
|
|
|
|
switch( mMode ) {
|
|
|
|
case NewMessage:
|
|
|
|
tmpl = fconf.templateNewMessage();
|
|
|
|
break;
|
|
|
|
case Reply:
|
|
|
|
tmpl = fconf.templateReply();
|
|
|
|
break;
|
|
|
|
case ReplyAll:
|
|
|
|
tmpl = fconf.templateReplyAll();
|
|
|
|
break;
|
|
|
|
case Forward:
|
|
|
|
tmpl = fconf.templateForward();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
kdDebug(5006) << "Unknown message mode: " << mMode << endl;
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
mQuoteString = fconf.quoteString();
|
|
|
|
if ( !tmpl.isEmpty() ) {
|
|
|
|
return tmpl; // use folder-specific template
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !mIdentity ) { // find identity message belongs to
|
|
|
|
mIdentity = mMsg->identityUoid();
|
|
|
|
if ( !mIdentity && mOrigMsg ) {
|
|
|
|
mIdentity = mOrigMsg->identityUoid();
|
|
|
|
}
|
|
|
|
mIdentity = kmkernel->identityManager()->identityForUoidOrDefault( mIdentity ).uoid();
|
|
|
|
if ( !mIdentity ) {
|
|
|
|
kdDebug(5006) << "Oops! No identity for message" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
kdDebug(5006) << "Identity found: " << mIdentity << endl;
|
|
|
|
|
|
|
|
TQString iid;
|
|
|
|
if ( mIdentity ) {
|
|
|
|
iid = TQString("IDENTITY_%1").arg( mIdentity ); // templates ID for that identity
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iid = "IDENTITY_NO_IDENTITY"; // templates ID for no identity
|
|
|
|
}
|
|
|
|
|
|
|
|
Templates iconf( iid );
|
|
|
|
if ( iconf.useCustomTemplates() ) { // does identity use custom templates?
|
|
|
|
switch( mMode ) {
|
|
|
|
case NewMessage:
|
|
|
|
tmpl = iconf.templateNewMessage();
|
|
|
|
break;
|
|
|
|
case Reply:
|
|
|
|
tmpl = iconf.templateReply();
|
|
|
|
break;
|
|
|
|
case ReplyAll:
|
|
|
|
tmpl = iconf.templateReplyAll();
|
|
|
|
break;
|
|
|
|
case Forward:
|
|
|
|
tmpl = iconf.templateForward();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
kdDebug(5006) << "Unknown message mode: " << mMode << endl;
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
mQuoteString = iconf.quoteString();
|
|
|
|
if ( !tmpl.isEmpty() ) {
|
|
|
|
return tmpl; // use identity-specific template
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( mMode ) { // use the global template
|
|
|
|
case NewMessage:
|
|
|
|
tmpl = GlobalSettings::self()->templateNewMessage();
|
|
|
|
break;
|
|
|
|
case Reply:
|
|
|
|
tmpl = GlobalSettings::self()->templateReply();
|
|
|
|
break;
|
|
|
|
case ReplyAll:
|
|
|
|
tmpl = GlobalSettings::self()->templateReplyAll();
|
|
|
|
break;
|
|
|
|
case Forward:
|
|
|
|
tmpl = GlobalSettings::self()->templateForward();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
kdDebug(5006) << "Unknown message mode: " << mMode << endl;
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
mQuoteString = GlobalSettings::self()->quoteString();
|
|
|
|
return tmpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TemplateParser::pipe( const TQString &cmd, const TQString &buf )
|
|
|
|
{
|
|
|
|
mPipeOut = "";
|
|
|
|
mPipeErr = "";
|
|
|
|
mPipeRc = 0;
|
|
|
|
|
|
|
|
TDEProcess proc;
|
|
|
|
TQCString data = buf.local8Bit();
|
|
|
|
|
|
|
|
// kdDebug() << "Command data: " << data << endl;
|
|
|
|
|
|
|
|
proc << KShell::splitArgs( cmd, KShell::TildeExpand );
|
|
|
|
proc.setUseShell( true );
|
|
|
|
connect( &proc, TQT_SIGNAL( receivedStdout( TDEProcess *, char *, int ) ),
|
|
|
|
this, TQT_SLOT( onReceivedStdout( TDEProcess *, char *, int ) ) );
|
|
|
|
connect( &proc, TQT_SIGNAL( receivedStderr( TDEProcess *, char *, int ) ),
|
|
|
|
this, TQT_SLOT( onReceivedStderr( TDEProcess *, char *, int ) ) );
|
|
|
|
connect( &proc, TQT_SIGNAL( wroteStdin( TDEProcess * ) ),
|
|
|
|
this, TQT_SLOT( onWroteStdin( TDEProcess * ) ) );
|
|
|
|
|
|
|
|
if ( proc.start( TDEProcess::NotifyOnExit, TDEProcess::All ) ) {
|
|
|
|
|
|
|
|
bool pipe_filled = proc.writeStdin( data, data.length() );
|
|
|
|
if ( pipe_filled ) {
|
|
|
|
proc.closeStdin();
|
|
|
|
|
|
|
|
bool exited = proc.wait( PipeTimeout );
|
|
|
|
if ( exited ) {
|
|
|
|
|
|
|
|
if ( proc.normalExit() ) {
|
|
|
|
|
|
|
|
mPipeRc = proc.exitStatus();
|
|
|
|
if ( mPipeRc != 0 && mDebug ) {
|
|
|
|
if ( mPipeErr.isEmpty() ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Pipe command exit with status %1: %2").
|
|
|
|
arg( mPipeRc ).arg( cmd ) );
|
|
|
|
} else {
|
|
|
|
KMessageBox::detailedError( 0,
|
|
|
|
i18n( "Pipe command exit with status %1: %2" ).
|
|
|
|
arg( mPipeRc ).arg( cmd ), mPipeErr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
mPipeRc = -( proc.exitSignal() );
|
|
|
|
if ( mPipeRc != 0 && mDebug ) {
|
|
|
|
if ( mPipeErr.isEmpty() ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Pipe command killed by signal %1: %2" ).
|
|
|
|
arg( -(mPipeRc) ).arg( cmd ) );
|
|
|
|
} else {
|
|
|
|
KMessageBox::detailedError( 0,
|
|
|
|
i18n( "Pipe command killed by signal %1: %2" ).
|
|
|
|
arg( -(mPipeRc) ).arg( cmd ), mPipeErr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// process does not exited after TemplateParser::PipeTimeout seconds, kill it
|
|
|
|
proc.kill();
|
|
|
|
proc.detach();
|
|
|
|
if ( mDebug ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Pipe command did not finish within %1 seconds: %2" ).
|
|
|
|
arg( PipeTimeout ).arg( cmd ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// can`t write to stdin of process
|
|
|
|
proc.kill();
|
|
|
|
proc.detach();
|
|
|
|
if ( mDebug ) {
|
|
|
|
if ( mPipeErr.isEmpty() ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Cannot write to process stdin: %1" ).arg( cmd ) );
|
|
|
|
} else {
|
|
|
|
KMessageBox::detailedError( 0,
|
|
|
|
i18n( "Cannot write to process stdin: %1" ).
|
|
|
|
arg( cmd ), mPipeErr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ( mDebug ) {
|
|
|
|
KMessageBox::error( 0,
|
|
|
|
i18n( "Cannot start pipe command from template: %1" ).
|
|
|
|
arg( cmd ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return mPipeOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::onProcessExited( TDEProcess *proc )
|
|
|
|
{
|
|
|
|
Q_UNUSED( proc );
|
|
|
|
// do nothing for now
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::onReceivedStdout( TDEProcess *proc, char *buffer, int buflen )
|
|
|
|
{
|
|
|
|
Q_UNUSED( proc );
|
|
|
|
mPipeOut += TQString::fromLocal8Bit( buffer, buflen );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::onReceivedStderr( TDEProcess *proc, char *buffer, int buflen )
|
|
|
|
{
|
|
|
|
Q_UNUSED( proc );
|
|
|
|
mPipeErr += TQString::fromLocal8Bit( buffer, buflen );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParser::onWroteStdin( TDEProcess *proc )
|
|
|
|
{
|
|
|
|
proc->closeStdin();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "templateparser.moc"
|