00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <qstring.h>
00024 #include <qdatetime.h>
00025 #include <klocale.h>
00026 #include <kcalendarsystem.h>
00027 #include <kmime_util.h>
00028 #include <kglobal.h>
00029 #include <kprocess.h>
00030 #include <qregexp.h>
00031 #include <qfile.h>
00032 #include <kmessagebox.h>
00033 #include <kshell.h>
00034 #include <qfileinfo.h>
00035
00036 #include "kmmessage.h"
00037 #include "kmmsgbase.h"
00038 #include "kmfolder.h"
00039 #include "templatesconfiguration.h"
00040 #include "templatesconfiguration_kfg.h"
00041 #include "customtemplates_kfg.h"
00042 #include "globalsettings_base.h"
00043 #include "kmkernel.h"
00044 #include <libkpimidentities/identity.h>
00045 #include <libkpimidentities/identitymanager.h>
00046 #include "partNode.h"
00047 #include "attachmentcollector.h"
00048 #include "objecttreeparser.h"
00049 #include "util.h"
00050
00051 #include "templateparser.h"
00052 #include <mimelib/bodypart.h>
00053
00054 using namespace KMail;
00055
00056 TemplateParser::TemplateParser( KMMessage *amsg, const Mode amode,
00057 const QString aselection,
00058 bool asmartQuote, bool anoQuote,
00059 bool aallowDecryption, bool aselectionIsBody ) :
00060 mMode( amode ), mFolder( 0 ), mIdentity( 0 ), mSelection( aselection ),
00061 mSmartQuote( asmartQuote ), mNoQuote( anoQuote ),
00062 mAllowDecryption( aallowDecryption ), mSelectionIsBody( aselectionIsBody ),
00063 mDebug( false ), mQuoteString( "> " ), mAppend( false ), mOrigRoot( 0 )
00064 {
00065 mMsg = amsg;
00066 }
00067
00068 TemplateParser::~TemplateParser()
00069 {
00070 delete mOrigRoot;
00071 mOrigRoot = 0;
00072 }
00073
00074 int TemplateParser::parseQuotes( const QString &prefix, const QString &str,
00075 QString "e ) const
00076 {
00077 int pos = prefix.length();
00078 int len;
00079 int str_len = str.length();
00080 QChar qc = '"';
00081 QChar prev = 0;
00082
00083 pos++;
00084 len = pos;
00085
00086 while ( pos < str_len ) {
00087 QChar c = str[pos];
00088
00089 pos++;
00090 len++;
00091
00092 if ( prev ) {
00093 quote.append( c );
00094 prev = 0;
00095 } else {
00096 if ( c == '\\' ) {
00097 prev = c;
00098 } else if ( c == qc ) {
00099 break;
00100 } else {
00101 quote.append( c );
00102 }
00103 }
00104 }
00105
00106 return len;
00107 }
00108
00109 QString TemplateParser::getFName( const QString &str )
00110 {
00111
00112
00113
00114
00115 int sep_pos;
00116 QString res;
00117 if ( ( sep_pos = str.find( '@' ) ) > 0 ) {
00118 int i;
00119 for ( i = (sep_pos - 1); i >= 0; --i ) {
00120 QChar c = str[i];
00121 if ( c.isLetterOrNumber() ) {
00122 res.prepend( c );
00123 } else {
00124 break;
00125 }
00126 }
00127 } else if ( ( sep_pos = str.find(',') ) > 0 ) {
00128 unsigned int i;
00129 bool begin = false;
00130 for ( i = sep_pos; i < str.length(); ++i ) {
00131 QChar c = str[i];
00132 if ( c.isLetterOrNumber() ) {
00133 begin = true;
00134 res.append( c );
00135 } else if ( begin ) {
00136 break;
00137 }
00138 }
00139 } else {
00140 unsigned int i;
00141 for ( i = 0; i < str.length(); ++i ) {
00142 QChar c = str[i];
00143 if ( c.isLetterOrNumber() ) {
00144 res.append( c );
00145 } else {
00146 break;
00147 }
00148 }
00149 }
00150 return res;
00151 }
00152
00153 QString TemplateParser::getLName( const QString &str )
00154 {
00155
00156
00157
00158 int sep_pos;
00159 QString res;
00160 if ( ( sep_pos = str.find(',') ) > 0 ) {
00161 int i;
00162 for ( i = sep_pos; i >= 0; --i ) {
00163 QChar c = str[i];
00164 if ( c.isLetterOrNumber() ) {
00165 res.prepend( c );
00166 } else {
00167 break;
00168 }
00169 }
00170 } else {
00171 if ( ( sep_pos = str.find( ' ' ) ) > 0 ) {
00172 unsigned int i;
00173 bool begin = false;
00174 for ( i = sep_pos; i < str.length(); ++i ) {
00175 QChar c = str[i];
00176 if ( c.isLetterOrNumber() ) {
00177 begin = true;
00178 res.append( c );
00179 } else if ( begin ) {
00180 break;
00181 }
00182 }
00183 }
00184 }
00185 return res;
00186 }
00187
00188 void TemplateParser::process( KMMessage *aorig_msg, KMFolder *afolder, bool append )
00189 {
00190 mAppend = append;
00191 mOrigMsg = aorig_msg;
00192 mFolder = afolder;
00193 QString tmpl = findTemplate();
00194 return processWithTemplate( tmpl );
00195 }
00196
00197 void TemplateParser::process( const QString &tmplName, KMMessage *aorig_msg,
00198 KMFolder *afolder, bool append )
00199 {
00200 mAppend = append;
00201 mOrigMsg = aorig_msg;
00202 mFolder = afolder;
00203 QString tmpl = findCustomTemplate( tmplName );
00204 return processWithTemplate( tmpl );
00205 }
00206
00207 void TemplateParser::processWithTemplate( const QString &tmpl )
00208 {
00209 QString body;
00210 int tmpl_len = tmpl.length();
00211 bool dnl = false;
00212 for ( int i = 0; i < tmpl_len; ++i ) {
00213 QChar c = tmpl[i];
00214
00215 if ( c == '%' ) {
00216 QString cmd = tmpl.mid( i + 1 );
00217
00218 if ( cmd.startsWith( "-" ) ) {
00219
00220 kdDebug() << "Command: -" << endl;
00221 dnl = true;
00222 i += 1;
00223
00224 } else if ( cmd.startsWith( "REM=" ) ) {
00225
00226 kdDebug() << "Command: REM=" << endl;
00227 QString q;
00228 int len = parseQuotes( "REM=", cmd, q );
00229 i += len;
00230
00231 } else if ( cmd.startsWith( "INSERT=" ) ) {
00232
00233 kdDebug() << "Command: INSERT=" << endl;
00234 QString q;
00235 int len = parseQuotes( "INSERT=", cmd, q );
00236 i += len;
00237 QString path = KShell::tildeExpand( q );
00238 QFileInfo finfo( path );
00239 if (finfo.isRelative() ) {
00240 path = KShell::homeDir( "" );
00241 path += '/';
00242 path += q;
00243 }
00244 QFile file( path );
00245 if ( file.open( IO_ReadOnly ) ) {
00246 QByteArray content = file.readAll();
00247 QString str = QString::fromLocal8Bit( content, content.size() );
00248 body.append( str );
00249 } else if ( mDebug ) {
00250 KMessageBox::error( 0,
00251 i18n( "Cannot insert content from file %1: %2" ).
00252 arg( path ).arg( file.errorString() ) );
00253 }
00254
00255 } else if ( cmd.startsWith( "SYSTEM=" ) ) {
00256
00257 kdDebug() << "Command: SYSTEM=" << endl;
00258 QString q;
00259 int len = parseQuotes( "SYSTEM=", cmd, q );
00260 i += len;
00261 QString pipe_cmd = q;
00262 QString str = pipe( pipe_cmd, "" );
00263 body.append( str );
00264
00265 } else if ( cmd.startsWith( "PUT=" ) ) {
00266
00267 kdDebug() << "Command: PUT=" << endl;
00268 QString q;
00269 int len = parseQuotes( "PUT=", cmd, q );
00270 i += len;
00271 QString path = KShell::tildeExpand( q );
00272 QFileInfo finfo( path );
00273 if (finfo.isRelative() ) {
00274 path = KShell::homeDir( "" );
00275 path += '/';
00276 path += q;
00277 }
00278 QFile file( path );
00279 if ( file.open( IO_ReadOnly ) ) {
00280 QByteArray content = file.readAll();
00281 body.append( QString::fromLocal8Bit( content, content.size() ) );
00282 } else if ( mDebug ) {
00283 KMessageBox::error( 0,
00284 i18n( "Cannot insert content from file %1: %2").
00285 arg( path ).arg(file.errorString() ));
00286 }
00287
00288 } else if ( cmd.startsWith( "QUOTEPIPE=" ) ) {
00289
00290 kdDebug() << "Command: QUOTEPIPE=" << endl;
00291 QString q;
00292 int len = parseQuotes( "QUOTEPIPE=", cmd, q );
00293 i += len;
00294 QString pipe_cmd = q;
00295 if ( mOrigMsg && !mNoQuote ) {
00296 QString str = pipe( pipe_cmd, messageText( false ) );
00297 QString quote = mOrigMsg->asQuotedString( "", mQuoteString, str,
00298 mSmartQuote, mAllowDecryption );
00299 body.append( quote );
00300 }
00301
00302 } else if ( cmd.startsWith( "QUOTE" ) ) {
00303 kdDebug() << "Command: QUOTE" << endl;
00304 i += strlen( "QUOTE" );
00305 if ( mOrigMsg && !mNoQuote ) {
00306 QString quote = mOrigMsg->asQuotedString( "", mQuoteString, messageText( true ),
00307 mSmartQuote, mAllowDecryption );
00308 body.append( quote );
00309 }
00310
00311 } else if ( cmd.startsWith( "QHEADERS" ) ) {
00312 kdDebug() << "Command: QHEADERS" << endl;
00313 i += strlen( "QHEADERS" );
00314 if ( mOrigMsg && !mNoQuote ) {
00315 QString quote = mOrigMsg->asQuotedString( "", mQuoteString,
00316 mOrigMsg->headerAsSendableString(),
00317 mSmartQuote, false );
00318 body.append( quote );
00319 }
00320
00321 } else if ( cmd.startsWith( "HEADERS" ) ) {
00322 kdDebug() << "Command: HEADERS" << endl;
00323 i += strlen( "HEADERS" );
00324 if ( mOrigMsg && !mNoQuote ) {
00325 QString str = mOrigMsg->headerAsSendableString();
00326 body.append( str );
00327 }
00328
00329 } else if ( cmd.startsWith( "TEXTPIPE=" ) ) {
00330
00331 kdDebug() << "Command: TEXTPIPE=" << endl;
00332 QString q;
00333 int len = parseQuotes( "TEXTPIPE=", cmd, q );
00334 i += len;
00335 QString pipe_cmd = q;
00336 if ( mOrigMsg ) {
00337 QString str = pipe(pipe_cmd, messageText( false ) );
00338 body.append( str );
00339 }
00340
00341 } else if ( cmd.startsWith( "MSGPIPE=" ) ) {
00342
00343 kdDebug() << "Command: MSGPIPE=" << endl;
00344 QString q;
00345 int len = parseQuotes( "MSGPIPE=", cmd, q );
00346 i += len;
00347 QString pipe_cmd = q;
00348 if ( mOrigMsg ) {
00349 QString str = pipe(pipe_cmd, mOrigMsg->asString() );
00350 body.append( str );
00351 }
00352
00353 } else if ( cmd.startsWith( "BODYPIPE=" ) ) {
00354
00355 kdDebug() << "Command: BODYPIPE=" << endl;
00356 QString q;
00357 int len = parseQuotes( "BODYPIPE=", cmd, q );
00358 i += len;
00359 QString pipe_cmd = q;
00360 QString str = pipe( pipe_cmd, body );
00361 body.append( str );
00362
00363 } else if ( cmd.startsWith( "CLEARPIPE=" ) ) {
00364
00365
00366 kdDebug() << "Command: CLEARPIPE=" << endl;
00367 QString q;
00368 int len = parseQuotes( "CLEARPIPE=", cmd, q );
00369 i += len;
00370 QString pipe_cmd = q;
00371 QString str = pipe( pipe_cmd, body );
00372 body = str;
00373 mMsg->setCursorPos( 0 );
00374
00375 } else if ( cmd.startsWith( "TEXT" ) ) {
00376 kdDebug() << "Command: TEXT" << endl;
00377 i += strlen( "TEXT" );
00378 if ( mOrigMsg ) {
00379 QString quote = messageText( false );
00380 body.append( quote );
00381 }
00382
00383 } else if ( cmd.startsWith( "OTEXTSIZE" ) ) {
00384 kdDebug() << "Command: OTEXTSIZE" << endl;
00385 i += strlen( "OTEXTSIZE" );
00386 if ( mOrigMsg ) {
00387 QString str = QString( "%1" ).arg( mOrigMsg->body().length() );
00388 body.append( str );
00389 }
00390
00391 } else if ( cmd.startsWith( "OTEXT" ) ) {
00392 kdDebug() << "Command: OTEXT" << endl;
00393 i += strlen( "OTEXT" );
00394 if ( mOrigMsg ) {
00395 QString quote = messageText( false );
00396 body.append( quote );
00397 }
00398
00399 } else if ( cmd.startsWith( "OADDRESSEESADDR" ) ) {
00400 kdDebug() << "Command: OADDRESSEESADDR";
00401 i += strlen( "OADDRESSEESADDR" );
00402 const QString to = mOrigMsg->to();
00403 const QString cc = mOrigMsg->cc();
00404 if ( !to.isEmpty() )
00405 body.append( i18n( "To:" ) + ' ' + to );
00406 if ( !to.isEmpty() && !cc.isEmpty() )
00407 body.append( '\n' );
00408 if ( !cc.isEmpty() )
00409 body.append( i18n( "CC:" ) + ' ' + cc );
00410
00411 } else if ( cmd.startsWith( "CCADDR" ) ) {
00412 kdDebug() << "Command: CCADDR" << endl;
00413 i += strlen( "CCADDR" );
00414 QString str = mMsg->cc();
00415 body.append( str );
00416
00417 } else if ( cmd.startsWith( "CCNAME" ) ) {
00418 kdDebug() << "Command: CCNAME" << endl;
00419 i += strlen( "CCNAME" );
00420 QString str = mMsg->ccStrip();
00421 body.append( str );
00422
00423 } else if ( cmd.startsWith( "CCFNAME" ) ) {
00424 kdDebug() << "Command: CCFNAME" << endl;
00425 i += strlen( "CCFNAME" );
00426 QString str = mMsg->ccStrip();
00427 body.append( getFName( str ) );
00428
00429 } else if ( cmd.startsWith( "CCLNAME" ) ) {
00430 kdDebug() << "Command: CCLNAME" << endl;
00431 i += strlen( "CCLNAME" );
00432 QString str = mMsg->ccStrip();
00433 body.append( getLName( str ) );
00434
00435 } else if ( cmd.startsWith( "TOADDR" ) ) {
00436 kdDebug() << "Command: TOADDR" << endl;
00437 i += strlen( "TOADDR" );
00438 QString str = mMsg->to();
00439 body.append( str );
00440
00441 } else if ( cmd.startsWith( "TONAME" ) ) {
00442 kdDebug() << "Command: TONAME" << endl;
00443 i += strlen( "TONAME" );
00444 QString str = mMsg->toStrip();
00445 body.append( str );
00446
00447 } else if ( cmd.startsWith( "TOFNAME" ) ) {
00448 kdDebug() << "Command: TOFNAME" << endl;
00449 i += strlen( "TOFNAME" );
00450 QString str = mMsg->toStrip();
00451 body.append( getFName( str ) );
00452
00453 } else if ( cmd.startsWith( "TOLNAME" ) ) {
00454 kdDebug() << "Command: TOLNAME" << endl;
00455 i += strlen( "TOLNAME" );
00456 QString str = mMsg->toStrip();
00457 body.append( getLName( str ) );
00458
00459 } else if ( cmd.startsWith( "TOLIST" ) ) {
00460 kdDebug() << "Command: TOLIST" << endl;
00461 i += strlen( "TOLIST" );
00462 QString str = mMsg->to();
00463 body.append( str );
00464
00465 } else if ( cmd.startsWith( "FROMADDR" ) ) {
00466 kdDebug() << "Command: FROMADDR" << endl;
00467 i += strlen( "FROMADDR" );
00468 QString str = mMsg->from();
00469 body.append( str );
00470
00471 } else if ( cmd.startsWith( "FROMNAME" ) ) {
00472 kdDebug() << "Command: FROMNAME" << endl;
00473 i += strlen( "FROMNAME" );
00474 QString str = mMsg->fromStrip();
00475 body.append( str );
00476
00477 } else if ( cmd.startsWith( "FROMFNAME" ) ) {
00478 kdDebug() << "Command: FROMFNAME" << endl;
00479 i += strlen( "FROMFNAME" );
00480 QString str = mMsg->fromStrip();
00481 body.append( getFName( str ) );
00482
00483 } else if ( cmd.startsWith( "FROMLNAME" ) ) {
00484 kdDebug() << "Command: FROMLNAME" << endl;
00485 i += strlen( "FROMLNAME" );
00486 QString str = mMsg->fromStrip();
00487 body.append( getLName( str ) );
00488
00489 } else if ( cmd.startsWith( "FULLSUBJECT" ) ) {
00490 kdDebug() << "Command: FULLSUBJECT" << endl;
00491 i += strlen( "FULLSUBJECT" );
00492 QString str = mMsg->subject();
00493 body.append( str );
00494
00495 } else if ( cmd.startsWith( "FULLSUBJ" ) ) {
00496 kdDebug() << "Command: FULLSUBJ" << endl;
00497 i += strlen( "FULLSUBJ" );
00498 QString str = mMsg->subject();
00499 body.append( str );
00500
00501 } else if ( cmd.startsWith( "MSGID" ) ) {
00502 kdDebug() << "Command: MSGID" << endl;
00503 i += strlen( "MSGID" );
00504 QString str = mMsg->id();
00505 body.append( str );
00506
00507 } else if ( cmd.startsWith( "OHEADER=" ) ) {
00508
00509 kdDebug() << "Command: OHEADER=" << endl;
00510 QString q;
00511 int len = parseQuotes( "OHEADER=", cmd, q );
00512 i += len;
00513 if ( mOrigMsg ) {
00514 QString hdr = q;
00515 QString str = mOrigMsg->headerFields(hdr.local8Bit() ).join( ", " );
00516 body.append( str );
00517 }
00518
00519 } else if ( cmd.startsWith( "HEADER=" ) ) {
00520
00521 kdDebug() << "Command: HEADER=" << endl;
00522 QString q;
00523 int len = parseQuotes( "HEADER=", cmd, q );
00524 i += len;
00525 QString hdr = q;
00526 QString str = mMsg->headerFields(hdr.local8Bit() ).join( ", " );
00527 body.append( str );
00528
00529 } else if ( cmd.startsWith( "HEADER( " ) ) {
00530
00531 kdDebug() << "Command: HEADER( " << endl;
00532 QRegExp re = QRegExp( "^HEADER\\((.+)\\)" );
00533 re.setMinimal( true );
00534 int res = re.search( cmd );
00535 if ( res != 0 ) {
00536
00537 i += strlen( "HEADER( " );
00538 } else {
00539 i += re.matchedLength();
00540 QString hdr = re.cap( 1 );
00541 QString str = mMsg->headerFields( hdr.local8Bit() ).join( ", " );
00542 body.append( str );
00543 }
00544
00545 } else if ( cmd.startsWith( "OCCADDR" ) ) {
00546 kdDebug() << "Command: OCCADDR" << endl;
00547 i += strlen( "OCCADDR" );
00548 if ( mOrigMsg ) {
00549 QString str = mOrigMsg->cc();
00550 body.append( str );
00551 }
00552
00553 } else if ( cmd.startsWith( "OCCNAME" ) ) {
00554 kdDebug() << "Command: OCCNAME" << endl;
00555 i += strlen( "OCCNAME" );
00556 if ( mOrigMsg ) {
00557 QString str = mOrigMsg->ccStrip();
00558 body.append( str );
00559 }
00560
00561 } else if ( cmd.startsWith( "OCCFNAME" ) ) {
00562 kdDebug() << "Command: OCCFNAME" << endl;
00563 i += strlen( "OCCFNAME" );
00564 if ( mOrigMsg ) {
00565 QString str = mOrigMsg->ccStrip();
00566 body.append( getFName( str ) );
00567 }
00568
00569 } else if ( cmd.startsWith( "OCCLNAME" ) ) {
00570 kdDebug() << "Command: OCCLNAME" << endl;
00571 i += strlen( "OCCLNAME" );
00572 if ( mOrigMsg ) {
00573 QString str = mOrigMsg->ccStrip();
00574 body.append( getLName( str ) );
00575 }
00576
00577 } else if ( cmd.startsWith( "OTOADDR" ) ) {
00578 kdDebug() << "Command: OTOADDR" << endl;
00579 i += strlen( "OTOADDR" );
00580 if ( mOrigMsg ) {
00581 QString str = mOrigMsg->to();
00582 body.append( str );
00583 }
00584
00585 } else if ( cmd.startsWith( "OTONAME" ) ) {
00586 kdDebug() << "Command: OTONAME" << endl;
00587 i += strlen( "OTONAME" );
00588 if ( mOrigMsg ) {
00589 QString str = mOrigMsg->toStrip();
00590 body.append( str );
00591 }
00592
00593 } else if ( cmd.startsWith( "OTOFNAME" ) ) {
00594 kdDebug() << "Command: OTOFNAME" << endl;
00595 i += strlen( "OTOFNAME" );
00596 if ( mOrigMsg ) {
00597 QString str = mOrigMsg->toStrip();
00598 body.append( getFName( str ) );
00599 }
00600
00601 } else if ( cmd.startsWith( "OTOLNAME" ) ) {
00602 kdDebug() << "Command: OTOLNAME" << endl;
00603 i += strlen( "OTOLNAME" );
00604 if ( mOrigMsg ) {
00605 QString str = mOrigMsg->toStrip();
00606 body.append( getLName( str ) );
00607 }
00608
00609 } else if ( cmd.startsWith( "OTOLIST" ) ) {
00610 kdDebug() << "Command: OTOLIST" << endl;
00611 i += strlen( "OTOLIST" );
00612 if ( mOrigMsg ) {
00613 QString str = mOrigMsg->to();
00614 body.append( str );
00615 }
00616
00617 } else if ( cmd.startsWith( "OTO" ) ) {
00618 kdDebug() << "Command: OTO" << endl;
00619 i += strlen( "OTO" );
00620 if ( mOrigMsg ) {
00621 QString str = mOrigMsg->to();
00622 body.append( str );
00623 }
00624
00625 } else if ( cmd.startsWith( "OFROMADDR" ) ) {
00626 kdDebug() << "Command: OFROMADDR" << endl;
00627 i += strlen( "OFROMADDR" );
00628 if ( mOrigMsg ) {
00629 QString str = mOrigMsg->from();
00630 body.append( str );
00631 }
00632
00633 } else if ( cmd.startsWith( "OFROMNAME" ) ) {
00634 kdDebug() << "Command: OFROMNAME" << endl;
00635 i += strlen( "OFROMNAME" );
00636 if ( mOrigMsg ) {
00637 QString str = mOrigMsg->fromStrip();
00638 body.append( str );
00639 }
00640
00641 } else if ( cmd.startsWith( "OFROMFNAME" ) ) {
00642 kdDebug() << "Command: OFROMFNAME" << endl;
00643 i += strlen( "OFROMFNAME" );
00644 if ( mOrigMsg ) {
00645 QString str = mOrigMsg->fromStrip();
00646 body.append( getFName( str ) );
00647 }
00648
00649 } else if ( cmd.startsWith( "OFROMLNAME" ) ) {
00650 kdDebug() << "Command: OFROMLNAME" << endl;
00651 i += strlen( "OFROMLNAME" );
00652 if ( mOrigMsg ) {
00653 QString str = mOrigMsg->fromStrip();
00654 body.append( getLName( str ) );
00655 }
00656
00657 } else if ( cmd.startsWith( "OFULLSUBJECT" ) ) {
00658 kdDebug() << "Command: OFULLSUBJECT" << endl;
00659 i += strlen( "OFULLSUBJECT" );
00660 if ( mOrigMsg ) {
00661 QString str = mOrigMsg->subject();
00662 body.append( str );
00663 }
00664
00665 } else if ( cmd.startsWith( "OFULLSUBJ" ) ) {
00666 kdDebug() << "Command: OFULLSUBJ" << endl;
00667 i += strlen( "OFULLSUBJ" );
00668 if ( mOrigMsg ) {
00669 QString str = mOrigMsg->subject();
00670 body.append( str );
00671 }
00672
00673 } else if ( cmd.startsWith( "OMSGID" ) ) {
00674 kdDebug() << "Command: OMSGID" << endl;
00675 i += strlen( "OMSGID" );
00676 if ( mOrigMsg ) {
00677 QString str = mOrigMsg->id();
00678 body.append( str );
00679 }
00680
00681 } else if ( cmd.startsWith( "DATEEN" ) ) {
00682 kdDebug() << "Command: DATEEN" << endl;
00683 i += strlen( "DATEEN" );
00684 QDateTime date = QDateTime::currentDateTime();
00685 KLocale locale( "C" );
00686 QString str = locale.formatDate( date.date(), false );
00687 body.append( str );
00688
00689 } else if ( cmd.startsWith( "DATESHORT" ) ) {
00690 kdDebug() << "Command: DATESHORT" << endl;
00691 i += strlen( "DATESHORT" );
00692 QDateTime date = QDateTime::currentDateTime();
00693 QString str = KGlobal::locale()->formatDate( date.date(), true );
00694 body.append( str );
00695
00696 } else if ( cmd.startsWith( "DATE" ) ) {
00697 kdDebug() << "Command: DATE" << endl;
00698 i += strlen( "DATE" );
00699 QDateTime date = QDateTime::currentDateTime();
00700 QString str = KGlobal::locale()->formatDate( date.date(), false );
00701 body.append( str );
00702
00703 } else if ( cmd.startsWith( "DOW" ) ) {
00704 kdDebug() << "Command: DOW" << endl;
00705 i += strlen( "DOW" );
00706 QDateTime date = QDateTime::currentDateTime();
00707 QString str = KGlobal::locale()->calendar()->weekDayName( date.date(), false );
00708 body.append( str );
00709
00710 } else if ( cmd.startsWith( "TIMELONGEN" ) ) {
00711 kdDebug() << "Command: TIMELONGEN" << endl;
00712 i += strlen( "TIMELONGEN" );
00713 QDateTime date = QDateTime::currentDateTime();
00714 KLocale locale( "C");
00715 QString str = locale.formatTime( date.time(), true );
00716 body.append( str );
00717
00718 } else if ( cmd.startsWith( "TIMELONG" ) ) {
00719 kdDebug() << "Command: TIMELONG" << endl;
00720 i += strlen( "TIMELONG" );
00721 QDateTime date = QDateTime::currentDateTime();
00722 QString str = KGlobal::locale()->formatTime( date.time(), true );
00723 body.append( str );
00724
00725 } else if ( cmd.startsWith( "TIME" ) ) {
00726 kdDebug() << "Command: TIME" << endl;
00727 i += strlen( "TIME" );
00728 QDateTime date = QDateTime::currentDateTime();
00729 QString str = KGlobal::locale()->formatTime( date.time(), false );
00730 body.append( str );
00731
00732 } else if ( cmd.startsWith( "ODATEEN" ) ) {
00733 kdDebug() << "Command: ODATEEN" << endl;
00734 i += strlen( "ODATEEN" );
00735 if ( mOrigMsg ) {
00736 QDateTime date;
00737 date.setTime_t( mOrigMsg->date() );
00738 KLocale locale( "C");
00739 QString str = locale.formatDate( date.date(), false );
00740 body.append( str );
00741 }
00742
00743 } else if ( cmd.startsWith( "ODATESHORT") ) {
00744 kdDebug() << "Command: ODATESHORT" << endl;
00745 i += strlen( "ODATESHORT");
00746 if ( mOrigMsg ) {
00747 QDateTime date;
00748 date.setTime_t( mOrigMsg->date() );
00749 QString str = KGlobal::locale()->formatDate( date.date(), true );
00750 body.append( str );
00751 }
00752
00753 } else if ( cmd.startsWith( "ODATE") ) {
00754 kdDebug() << "Command: ODATE" << endl;
00755 i += strlen( "ODATE");
00756 if ( mOrigMsg ) {
00757 QDateTime date;
00758 date.setTime_t( mOrigMsg->date() );
00759 QString str = KGlobal::locale()->formatDate( date.date(), false );
00760 body.append( str );
00761 }
00762
00763 } else if ( cmd.startsWith( "ODOW") ) {
00764 kdDebug() << "Command: ODOW" << endl;
00765 i += strlen( "ODOW");
00766 if ( mOrigMsg ) {
00767 QDateTime date;
00768 date.setTime_t( mOrigMsg->date() );
00769 QString str = KGlobal::locale()->calendar()->weekDayName( date.date(), false );
00770 body.append( str );
00771 }
00772
00773 } else if ( cmd.startsWith( "OTIMELONGEN") ) {
00774 kdDebug() << "Command: OTIMELONGEN" << endl;
00775 i += strlen( "OTIMELONGEN");
00776 if ( mOrigMsg ) {
00777 QDateTime date;
00778 date.setTime_t( mOrigMsg->date() );
00779 KLocale locale( "C");
00780 QString str = locale.formatTime( date.time(), true );
00781 body.append( str );
00782 }
00783
00784 } else if ( cmd.startsWith( "OTIMELONG") ) {
00785 kdDebug() << "Command: OTIMELONG" << endl;
00786 i += strlen( "OTIMELONG");
00787 if ( mOrigMsg ) {
00788 QDateTime date;
00789 date.setTime_t( mOrigMsg->date() );
00790 QString str = KGlobal::locale()->formatTime( date.time(), true );
00791 body.append( str );
00792 }
00793
00794 } else if ( cmd.startsWith( "OTIME") ) {
00795 kdDebug() << "Command: OTIME" << endl;
00796 i += strlen( "OTIME");
00797 if ( mOrigMsg ) {
00798 QDateTime date;
00799 date.setTime_t( mOrigMsg->date() );
00800 QString str = KGlobal::locale()->formatTime( date.time(), false );
00801 body.append( str );
00802 }
00803
00804 } else if ( cmd.startsWith( "BLANK" ) ) {
00805
00806 kdDebug() << "Command: BLANK" << endl;
00807 i += strlen( "BLANK" );
00808
00809 } else if ( cmd.startsWith( "NOP" ) ) {
00810
00811 kdDebug() << "Command: NOP" << endl;
00812 i += strlen( "NOP" );
00813
00814 } else if ( cmd.startsWith( "CLEAR" ) ) {
00815
00816 kdDebug() << "Command: CLEAR" << endl;
00817 i += strlen( "CLEAR" );
00818 body = "";
00819 mMsg->setCursorPos( 0 );
00820
00821 } else if ( cmd.startsWith( "DEBUGOFF" ) ) {
00822
00823 kdDebug() << "Command: DEBUGOFF" << endl;
00824 i += strlen( "DEBUGOFF" );
00825 mDebug = false;
00826
00827 } else if ( cmd.startsWith( "DEBUG" ) ) {
00828
00829 kdDebug() << "Command: DEBUG" << endl;
00830 i += strlen( "DEBUG" );
00831 mDebug = true;
00832
00833 } else if ( cmd.startsWith( "CURSOR" ) ) {
00834
00835 kdDebug() << "Command: CURSOR" << endl;
00836 i += strlen( "CURSOR" );
00837 mMsg->setCursorPos( body.length() );
00838
00839 } else {
00840
00841 body.append( c );
00842 }
00843
00844 } else if ( dnl && ( c == '\n' || c == '\r') ) {
00845
00846 if ( ( c == '\n' && tmpl[i + 1] == '\r' ) ||
00847 ( c == '\r' && tmpl[i + 1] == '\n' ) ) {
00848
00849 i += 1;
00850 }
00851 dnl = false;
00852 } else {
00853 body.append( c );
00854 }
00855 }
00856
00857 addProcessedBodyToMessage( body );
00858 }
00859
00860 QString TemplateParser::messageText( bool allowSelectionOnly )
00861 {
00862 if ( !mSelection.isEmpty() && allowSelectionOnly )
00863 return mSelection;
00864
00865
00866 partNode *root = parsedObjectTree();
00867 return mOrigMsg->asPlainTextFromObjectTree( root, mSmartQuote, mAllowDecryption );
00868 }
00869
00870 partNode* TemplateParser::parsedObjectTree()
00871 {
00872 if ( mOrigRoot )
00873 return mOrigRoot;
00874
00875 mOrigRoot = partNode::fromMessage( mOrigMsg );
00876 ObjectTreeParser otp;
00877 otp.parseObjectTree( mOrigRoot );
00878 return mOrigRoot;
00879 }
00880
00881 void TemplateParser::addProcessedBodyToMessage( const QString &body )
00882 {
00883 if ( mAppend ) {
00884
00885
00886 QCString msg_body = mMsg->body();
00887 msg_body.append( body.utf8() );
00888 mMsg->setBody( msg_body );
00889 }
00890 else {
00891
00892
00893 partNode *root = parsedObjectTree();
00894 AttachmentCollector ac;
00895 ac.collectAttachmentsFrom( root );
00896
00897
00898
00899 mMsg->deleteBodyParts();
00900
00901
00902 if ( mMode == Forward ) {
00903 if ( !mTo.isEmpty() ) {
00904 mMsg->setTo( mMsg->to() + ',' + mTo );
00905 }
00906 if ( !mCC.isEmpty() )
00907 mMsg->setCc( mMsg->cc() + ',' + mCC );
00908 }
00909
00910
00911
00912 if ( ac.attachments().empty() || mMode != Forward ) {
00913 mMsg->headers().ContentType().FromString( DwString() );
00914 mMsg->headers().ContentType().Parse();
00915 mMsg->headers().ContentType().SetType( DwMime::kTypeText );
00916 mMsg->headers().ContentType().SetSubtype( DwMime::kSubtypePlain );
00917 mMsg->headers().Assemble();
00918 mMsg->setBodyFromUnicode( body );
00919 mMsg->assembleIfNeeded();
00920 }
00921
00922
00923
00924 else
00925 {
00926 mMsg->headers().ContentType().SetType( DwMime::kTypeMultipart );
00927 mMsg->headers().ContentType().SetSubtype( DwMime::kSubtypeMixed );
00928 mMsg->headers().ContentType().CreateBoundary( 0 );
00929
00930 KMMessagePart textPart;
00931 textPart.setBodyFromUnicode( body );
00932 mMsg->addDwBodyPart( mMsg->createDWBodyPart( &textPart ) );
00933 mMsg->assembleIfNeeded();
00934
00935 int attachmentNumber = 1;
00936 for ( std::vector<partNode*>::const_iterator it = ac.attachments().begin();
00937 it != ac.attachments().end(); ++it, attachmentNumber++ ) {
00938
00939
00940
00941
00942
00943 ( *it )->dwPart()->SetNext( 0 );
00944
00945 DwBodyPart *cloned = static_cast<DwBodyPart*>( ( *it )->dwPart()->Clone() );
00946
00947
00948
00949 if ( cloned->Headers().HasContentType() ) {
00950 DwMediaType &ct = cloned->Headers().ContentType();
00951
00952
00953 QString ctStr = ct.AsString().c_str();
00954 if ( !ctStr.lower().contains( "name=" ) && !ctStr.lower().contains( "filename=" ) ) {
00955 DwParameter *nameParameter = new DwParameter;
00956 nameParameter->SetAttribute( "name" );
00957 nameParameter->SetValue( Util::dwString( KMMsgBase::encodeRFC2231StringAutoDetectCharset(
00958 i18n( "Attachment %1" ).arg( attachmentNumber ) ) ) );
00959 ct.AddParameter( nameParameter );
00960 }
00961 }
00962
00963 mMsg->addDwBodyPart( cloned );
00964 mMsg->assembleIfNeeded();
00965 }
00966 }
00967 }
00968 }
00969
00970 QString TemplateParser::findCustomTemplate( const QString &tmplName )
00971 {
00972 CTemplates t( tmplName );
00973 mTo = t.to();
00974 mCC = t.cC();
00975 QString content = t.content();
00976 if ( !content.isEmpty() ) {
00977 return content;
00978 } else {
00979 return findTemplate();
00980 }
00981 }
00982
00983 QString TemplateParser::findTemplate()
00984 {
00985
00986 if ( !GlobalSettings::self()->phrasesConverted() ) {
00987 TemplatesConfiguration::importFromPhrases();
00988 }
00989
00990
00991
00992 QString tmpl;
00993
00994 if ( !mFolder ) {
00995 mFolder = mMsg->parent();
00996 if ( !mFolder ) {
00997 if ( mOrigMsg ) {
00998 mFolder = mOrigMsg->parent();
00999 }
01000 if ( !mFolder ) {
01001 kdDebug(5006) << "Oops! No folder for message" << endl;
01002 }
01003 }
01004 }
01005 kdDebug(5006) << "Folder found: " << mFolder << endl;
01006
01007 if ( mFolder )
01008 {
01009 QString fid = mFolder->idString();
01010 Templates fconf( fid );
01011 if ( fconf.useCustomTemplates() ) {
01012 switch( mMode ) {
01013 case NewMessage:
01014 tmpl = fconf.templateNewMessage();
01015 break;
01016 case Reply:
01017 tmpl = fconf.templateReply();
01018 break;
01019 case ReplyAll:
01020 tmpl = fconf.templateReplyAll();
01021 break;
01022 case Forward:
01023 tmpl = fconf.templateForward();
01024 break;
01025 default:
01026 kdDebug(5006) << "Unknown message mode: " << mMode << endl;
01027 return "";
01028 }
01029 mQuoteString = fconf.quoteString();
01030 if ( !tmpl.isEmpty() ) {
01031 return tmpl;
01032 }
01033 }
01034 }
01035
01036 if ( !mIdentity ) {
01037 mIdentity = mMsg->identityUoid();
01038 if ( !mIdentity && mOrigMsg ) {
01039 mIdentity = mOrigMsg->identityUoid();
01040 }
01041 mIdentity = kmkernel->identityManager()->identityForUoidOrDefault( mIdentity ).uoid();
01042 if ( !mIdentity ) {
01043 kdDebug(5006) << "Oops! No identity for message" << endl;
01044 }
01045 }
01046 kdDebug(5006) << "Identity found: " << mIdentity << endl;
01047
01048 QString iid;
01049 if ( mIdentity ) {
01050 iid = QString("IDENTITY_%1").arg( mIdentity );
01051 }
01052 else {
01053 iid = "IDENTITY_NO_IDENTITY";
01054 }
01055
01056 Templates iconf( iid );
01057 if ( iconf.useCustomTemplates() ) {
01058 switch( mMode ) {
01059 case NewMessage:
01060 tmpl = iconf.templateNewMessage();
01061 break;
01062 case Reply:
01063 tmpl = iconf.templateReply();
01064 break;
01065 case ReplyAll:
01066 tmpl = iconf.templateReplyAll();
01067 break;
01068 case Forward:
01069 tmpl = iconf.templateForward();
01070 break;
01071 default:
01072 kdDebug(5006) << "Unknown message mode: " << mMode << endl;
01073 return "";
01074 }
01075 mQuoteString = iconf.quoteString();
01076 if ( !tmpl.isEmpty() ) {
01077 return tmpl;
01078 }
01079 }
01080
01081 switch( mMode ) {
01082 case NewMessage:
01083 tmpl = GlobalSettings::self()->templateNewMessage();
01084 break;
01085 case Reply:
01086 tmpl = GlobalSettings::self()->templateReply();
01087 break;
01088 case ReplyAll:
01089 tmpl = GlobalSettings::self()->templateReplyAll();
01090 break;
01091 case Forward:
01092 tmpl = GlobalSettings::self()->templateForward();
01093 break;
01094 default:
01095 kdDebug(5006) << "Unknown message mode: " << mMode << endl;
01096 return "";
01097 }
01098
01099 mQuoteString = GlobalSettings::self()->quoteString();
01100 return tmpl;
01101 }
01102
01103 QString TemplateParser::pipe( const QString &cmd, const QString &buf )
01104 {
01105 mPipeOut = "";
01106 mPipeErr = "";
01107 mPipeRc = 0;
01108
01109 KProcess proc;
01110 QCString data = buf.local8Bit();
01111
01112
01113
01114 proc << KShell::splitArgs( cmd, KShell::TildeExpand );
01115 proc.setUseShell( true );
01116 connect( &proc, SIGNAL( receivedStdout( KProcess *, char *, int ) ),
01117 this, SLOT( onReceivedStdout( KProcess *, char *, int ) ) );
01118 connect( &proc, SIGNAL( receivedStderr( KProcess *, char *, int ) ),
01119 this, SLOT( onReceivedStderr( KProcess *, char *, int ) ) );
01120 connect( &proc, SIGNAL( wroteStdin( KProcess * ) ),
01121 this, SLOT( onWroteStdin( KProcess * ) ) );
01122
01123 if ( proc.start( KProcess::NotifyOnExit, KProcess::All ) ) {
01124
01125 bool pipe_filled = proc.writeStdin( data, data.length() );
01126 if ( pipe_filled ) {
01127 proc.closeStdin();
01128
01129 bool exited = proc.wait( PipeTimeout );
01130 if ( exited ) {
01131
01132 if ( proc.normalExit() ) {
01133
01134 mPipeRc = proc.exitStatus();
01135 if ( mPipeRc != 0 && mDebug ) {
01136 if ( mPipeErr.isEmpty() ) {
01137 KMessageBox::error( 0,
01138 i18n( "Pipe command exit with status %1: %2").
01139 arg( mPipeRc ).arg( cmd ) );
01140 } else {
01141 KMessageBox::detailedError( 0,
01142 i18n( "Pipe command exit with status %1: %2" ).
01143 arg( mPipeRc ).arg( cmd ), mPipeErr );
01144 }
01145 }
01146
01147 } else {
01148
01149 mPipeRc = -( proc.exitSignal() );
01150 if ( mPipeRc != 0 && mDebug ) {
01151 if ( mPipeErr.isEmpty() ) {
01152 KMessageBox::error( 0,
01153 i18n( "Pipe command killed by signal %1: %2" ).
01154 arg( -(mPipeRc) ).arg( cmd ) );
01155 } else {
01156 KMessageBox::detailedError( 0,
01157 i18n( "Pipe command killed by signal %1: %2" ).
01158 arg( -(mPipeRc) ).arg( cmd ), mPipeErr );
01159 }
01160 }
01161 }
01162
01163 } else {
01164
01165 proc.kill();
01166 proc.detach();
01167 if ( mDebug ) {
01168 KMessageBox::error( 0,
01169 i18n( "Pipe command did not finish within %1 seconds: %2" ).
01170 arg( PipeTimeout ).arg( cmd ) );
01171 }
01172 }
01173
01174 } else {
01175
01176 proc.kill();
01177 proc.detach();
01178 if ( mDebug ) {
01179 if ( mPipeErr.isEmpty() ) {
01180 KMessageBox::error( 0,
01181 i18n( "Cannot write to process stdin: %1" ).arg( cmd ) );
01182 } else {
01183 KMessageBox::detailedError( 0,
01184 i18n( "Cannot write to process stdin: %1" ).
01185 arg( cmd ), mPipeErr );
01186 }
01187 }
01188 }
01189
01190 } else if ( mDebug ) {
01191 KMessageBox::error( 0,
01192 i18n( "Cannot start pipe command from template: %1" ).
01193 arg( cmd ) );
01194 }
01195
01196 return mPipeOut;
01197 }
01198
01199 void TemplateParser::onProcessExited( KProcess *proc )
01200 {
01201 Q_UNUSED( proc );
01202
01203 }
01204
01205 void TemplateParser::onReceivedStdout( KProcess *proc, char *buffer, int buflen )
01206 {
01207 Q_UNUSED( proc );
01208 mPipeOut += QString::fromLocal8Bit( buffer, buflen );
01209 }
01210
01211 void TemplateParser::onReceivedStderr( KProcess *proc, char *buffer, int buflen )
01212 {
01213 Q_UNUSED( proc );
01214 mPipeErr += QString::fromLocal8Bit( buffer, buflen );
01215 }
01216
01217 void TemplateParser::onWroteStdin( KProcess *proc )
01218 {
01219 proc->closeStdin();
01220 }
01221
01222 #include "templateparser.moc"