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