kmail Library API Documentation

kmfilteraction.cpp

00001 // kmfilteraction.cpp 00002 // The process methods really should use an enum instead of an int 00003 // -1 -> status unchanged, 0 -> success, 1 -> failure, 2-> critical failure 00004 // (GoOn), (Ok), (ErrorButGoOn), (CriticalError) 00005 00006 #ifdef HAVE_CONFIG_H 00007 #include <config.h> 00008 #endif 00009 00010 #include "kmfilteraction.h" 00011 00012 #include "kmcommands.h" 00013 #include "kmmsgpart.h" 00014 #include "kmfiltermgr.h" 00015 #include "kmfolderindex.h" 00016 #include "kmfoldermgr.h" 00017 #include "kmsender.h" 00018 #include "kmidentity.h" 00019 #include "identitymanager.h" 00020 #include "identitycombo.h" 00021 #include "kfileio.h" 00022 #include "kmfawidgets.h" 00023 #include "kmfoldercombobox.h" 00024 #include "kmmsgbase.h" 00025 #include "messageproperty.h" 00026 #include "actionscheduler.h" 00027 using KMail::MessageProperty; 00028 using KMail::ActionScheduler; 00029 #include <kregexp3.h> 00030 #include <ktempfile.h> 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kprocess.h> 00034 #include <kaudioplayer.h> 00035 #include <kurlrequester.h> 00036 00037 #include <qlabel.h> 00038 #include <qlayout.h> 00039 #include <qtextcodec.h> 00040 #include <qtimer.h> 00041 #include <qobject.h> 00042 #include <assert.h> 00043 00044 00045 //============================================================================= 00046 // 00047 // KMFilterAction 00048 // 00049 //============================================================================= 00050 00051 KMFilterAction::KMFilterAction( const char* aName, const QString aLabel ) 00052 { 00053 mName = aName; 00054 mLabel = aLabel; 00055 } 00056 00057 KMFilterAction::~KMFilterAction() 00058 { 00059 } 00060 00061 void KMFilterAction::processAsync(KMMessage* msg) const 00062 { 00063 ActionScheduler *handler = MessageProperty::filterHandler( msg ); 00064 ReturnCode result = process( msg ); 00065 if (handler) 00066 handler->actionMessage( result ); 00067 } 00068 00069 bool KMFilterAction::requiresBody(KMMsgBase*) const 00070 { 00071 return true; 00072 } 00073 00074 KMFilterAction* KMFilterAction::newAction() 00075 { 00076 return 0; 00077 } 00078 00079 QWidget* KMFilterAction::createParamWidget(QWidget* parent) const 00080 { 00081 return new QWidget(parent); 00082 } 00083 00084 void KMFilterAction::applyParamWidgetValue(QWidget*) 00085 { 00086 } 00087 00088 void KMFilterAction::setParamWidgetValue( QWidget * ) const 00089 { 00090 } 00091 00092 void KMFilterAction::clearParamWidget( QWidget * ) const 00093 { 00094 } 00095 00096 bool KMFilterAction::folderRemoved(KMFolder*, KMFolder*) 00097 { 00098 return FALSE; 00099 } 00100 00101 int KMFilterAction::tempOpenFolder(KMFolder* aFolder) 00102 { 00103 return kmkernel->filterMgr()->tempOpenFolder(aFolder); 00104 } 00105 00106 void KMFilterAction::sendMDN( KMMessage * msg, KMime::MDN::DispositionType d, 00107 const QValueList<KMime::MDN::DispositionModifier> & m ) { 00108 if ( !msg ) return; 00109 KMMessage * mdn = msg->createMDN( KMime::MDN::AutomaticAction, d, false, m ); 00110 if ( mdn && !kmkernel->msgSender()->send( mdn, FALSE ) ) { 00111 kdDebug(5006) << "KMFilterAction::sendMDN(): sending failed." << endl; 00112 //delete mdn; 00113 } 00114 } 00115 00116 00117 //============================================================================= 00118 // 00119 // KMFilterActionWithNone 00120 // 00121 //============================================================================= 00122 00123 KMFilterActionWithNone::KMFilterActionWithNone( const char* aName, const QString aLabel ) 00124 : KMFilterAction( aName, aLabel ) 00125 { 00126 } 00127 00128 00129 //============================================================================= 00130 // 00131 // KMFilterActionWithUOID 00132 // 00133 //============================================================================= 00134 00135 KMFilterActionWithUOID::KMFilterActionWithUOID( const char* aName, const QString aLabel ) 00136 : KMFilterAction( aName, aLabel ), mParameter( 0 ) 00137 { 00138 } 00139 00140 void KMFilterActionWithUOID::argsFromString( const QString argsStr ) 00141 { 00142 mParameter = argsStr.stripWhiteSpace().toUInt(); 00143 } 00144 00145 const QString KMFilterActionWithUOID::argsAsString() const 00146 { 00147 return QString::number( mParameter ); 00148 } 00149 00150 //============================================================================= 00151 // 00152 // KMFilterActionWithString 00153 // 00154 //============================================================================= 00155 00156 KMFilterActionWithString::KMFilterActionWithString( const char* aName, const QString aLabel ) 00157 : KMFilterAction( aName, aLabel ) 00158 { 00159 } 00160 00161 QWidget* KMFilterActionWithString::createParamWidget( QWidget* parent ) const 00162 { 00163 QLineEdit *le = new KLineEdit(parent); 00164 le->setText( mParameter ); 00165 return le; 00166 } 00167 00168 void KMFilterActionWithString::applyParamWidgetValue( QWidget* paramWidget ) 00169 { 00170 mParameter = ((QLineEdit*)paramWidget)->text(); 00171 } 00172 00173 void KMFilterActionWithString::setParamWidgetValue( QWidget* paramWidget ) const 00174 { 00175 ((QLineEdit*)paramWidget)->setText( mParameter ); 00176 } 00177 00178 void KMFilterActionWithString::clearParamWidget( QWidget* paramWidget ) const 00179 { 00180 ((QLineEdit*)paramWidget)->clear(); 00181 } 00182 00183 void KMFilterActionWithString::argsFromString( const QString argsStr ) 00184 { 00185 mParameter = argsStr; 00186 } 00187 00188 const QString KMFilterActionWithString::argsAsString() const 00189 { 00190 return mParameter; 00191 } 00192 00193 //============================================================================= 00194 // 00195 // class KMFilterActionWithStringList 00196 // 00197 //============================================================================= 00198 00199 KMFilterActionWithStringList::KMFilterActionWithStringList( const char* aName, const QString aLabel ) 00200 : KMFilterActionWithString( aName, aLabel ) 00201 { 00202 } 00203 00204 QWidget* KMFilterActionWithStringList::createParamWidget( QWidget* parent ) const 00205 { 00206 QComboBox *cb = new QComboBox( FALSE, parent ); 00207 cb->insertStringList( mParameterList ); 00208 setParamWidgetValue( cb ); 00209 return cb; 00210 } 00211 00212 void KMFilterActionWithStringList::applyParamWidgetValue( QWidget* paramWidget ) 00213 { 00214 mParameter = ((QComboBox*)paramWidget)->currentText(); 00215 } 00216 00217 void KMFilterActionWithStringList::setParamWidgetValue( QWidget* paramWidget ) const 00218 { 00219 int idx = mParameterList.findIndex( mParameter ); 00220 ((QComboBox*)paramWidget)->setCurrentItem( idx >= 0 ? idx : 0 ); 00221 } 00222 00223 void KMFilterActionWithStringList::clearParamWidget( QWidget* paramWidget ) const 00224 { 00225 ((QComboBox*)paramWidget)->setCurrentItem(0); 00226 } 00227 00228 void KMFilterActionWithStringList::argsFromString( const QString argsStr ) 00229 { 00230 int idx = mParameterList.findIndex( argsStr ); 00231 if ( idx < 0 ) { 00232 mParameterList.append( argsStr ); 00233 idx = mParameterList.count() - 1; 00234 } 00235 mParameter = *mParameterList.at( idx ); 00236 } 00237 00238 00239 //============================================================================= 00240 // 00241 // class KMFilterActionWithFolder 00242 // 00243 //============================================================================= 00244 00245 KMFilterActionWithFolder::KMFilterActionWithFolder( const char* aName, const QString aLabel ) 00246 : KMFilterAction( aName, aLabel ) 00247 { 00248 mFolder = 0; 00249 } 00250 00251 QWidget* KMFilterActionWithFolder::createParamWidget( QWidget* parent ) const 00252 { 00253 KMFolderComboBox *cb = new KMFolderComboBox( parent ); 00254 cb->showImapFolders( false ); 00255 setParamWidgetValue( cb ); 00256 return cb; 00257 } 00258 00259 void KMFilterActionWithFolder::applyParamWidgetValue( QWidget* paramWidget ) 00260 { 00261 mFolder = ((KMFolderComboBox *)paramWidget)->getFolder(); 00262 if (mFolder) 00263 { 00264 mFolderName = QString::null; 00265 } 00266 else 00267 { 00268 mFolderName = ((KMFolderComboBox *)paramWidget)->currentText(); 00269 } 00270 } 00271 00272 void KMFilterActionWithFolder::setParamWidgetValue( QWidget* paramWidget ) const 00273 { 00274 if ( mFolder ) 00275 ((KMFolderComboBox *)paramWidget)->setFolder( mFolder ); 00276 else 00277 ((KMFolderComboBox *)paramWidget)->setFolder( mFolderName ); 00278 } 00279 00280 void KMFilterActionWithFolder::clearParamWidget( QWidget* paramWidget ) const 00281 { 00282 ((KMFolderComboBox *)paramWidget)->setFolder( kmkernel->draftsFolder() ); 00283 } 00284 00285 void KMFilterActionWithFolder::argsFromString( const QString argsStr ) 00286 { 00287 mFolder = kmkernel->folderMgr()->findIdString( argsStr ); 00288 if (!mFolder) 00289 mFolder = kmkernel->dimapFolderMgr()->findIdString( argsStr ); 00290 if (mFolder) 00291 mFolderName = QString::null; 00292 else 00293 mFolderName = argsStr; 00294 } 00295 00296 const QString KMFilterActionWithFolder::argsAsString() const 00297 { 00298 QString result; 00299 if ( mFolder ) 00300 result = mFolder->idString(); 00301 else 00302 result = mFolderName; 00303 return result; 00304 } 00305 00306 bool KMFilterActionWithFolder::folderRemoved( KMFolder* aFolder, KMFolder* aNewFolder ) 00307 { 00308 if ( aFolder == mFolder ) { 00309 mFolder = aNewFolder; 00310 mFolderName = QString::null; 00311 return TRUE; 00312 } else 00313 return FALSE; 00314 } 00315 00316 //============================================================================= 00317 // 00318 // class KMFilterActionWithAddress 00319 // 00320 //============================================================================= 00321 00322 KMFilterActionWithAddress::KMFilterActionWithAddress( const char* aName, const QString aLabel ) 00323 : KMFilterActionWithString( aName, aLabel ) 00324 { 00325 } 00326 00327 QWidget* KMFilterActionWithAddress::createParamWidget( QWidget* parent ) const 00328 { 00329 KMFilterActionWithAddressWidget *w = new KMFilterActionWithAddressWidget(parent); 00330 w->setText( mParameter ); 00331 return w; 00332 } 00333 00334 void KMFilterActionWithAddress::applyParamWidgetValue( QWidget* paramWidget ) 00335 { 00336 mParameter = ((KMFilterActionWithAddressWidget*)paramWidget)->text(); 00337 } 00338 00339 void KMFilterActionWithAddress::setParamWidgetValue( QWidget* paramWidget ) const 00340 { 00341 ((KMFilterActionWithAddressWidget*)paramWidget)->setText( mParameter ); 00342 } 00343 00344 void KMFilterActionWithAddress::clearParamWidget( QWidget* paramWidget ) const 00345 { 00346 ((KMFilterActionWithAddressWidget*)paramWidget)->clear(); 00347 } 00348 00349 //============================================================================= 00350 // 00351 // class KMFilterActionWithCommand 00352 // 00353 //============================================================================= 00354 00355 KMFilterActionWithCommand::KMFilterActionWithCommand( const char* aName, const QString aLabel ) 00356 : KMFilterActionWithUrl( aName, aLabel ) 00357 { 00358 } 00359 00360 QWidget* KMFilterActionWithCommand::createParamWidget( QWidget* parent ) const 00361 { 00362 return KMFilterActionWithUrl::createParamWidget( parent ); 00363 } 00364 00365 void KMFilterActionWithCommand::applyParamWidgetValue( QWidget* paramWidget ) 00366 { 00367 KMFilterActionWithUrl::applyParamWidgetValue( paramWidget ); 00368 } 00369 00370 void KMFilterActionWithCommand::setParamWidgetValue( QWidget* paramWidget ) const 00371 { 00372 KMFilterActionWithUrl::setParamWidgetValue( paramWidget ); 00373 } 00374 00375 void KMFilterActionWithCommand::clearParamWidget( QWidget* paramWidget ) const 00376 { 00377 KMFilterActionWithUrl::clearParamWidget( paramWidget ); 00378 } 00379 00380 QString KMFilterActionWithCommand::substituteCommandLineArgsFor( KMMessage *aMsg, QPtrList<KTempFile> & aTempFileList ) const 00381 { 00382 QString result = mParameter; 00383 QValueList<int> argList; 00384 QRegExp r( "%[0-9-]+" ); 00385 00386 // search for '%n' 00387 int start = -1; 00388 while ( ( start = r.search( result, start + 1 ) ) > 0 ) { 00389 int len = r.matchedLength(); 00390 // and save the encountered 'n' in a list. 00391 bool OK = false; 00392 int n = result.mid( start + 1, len - 1 ).toInt( &OK ); 00393 if ( OK ) 00394 argList.append( n ); 00395 } 00396 00397 // sort the list of n's 00398 qHeapSort( argList ); 00399 00400 // and use QString::arg to substitute filenames for the %n's. 00401 int lastSeen = -2; 00402 QString tempFileName; 00403 for ( QValueList<int>::Iterator it = argList.begin() ; it != argList.end() ; ++it ) { 00404 // setup temp files with check for duplicate %n's 00405 if ( (*it) != lastSeen ) { 00406 KTempFile *tf = new KTempFile(); 00407 if ( tf->status() != 0 ) { 00408 tf->close(); 00409 delete tf; 00410 kdDebug(5006) << "KMFilterActionWithCommand: Could not create temp file!" << endl; 00411 return QString::null; 00412 } 00413 tf->setAutoDelete(TRUE); 00414 aTempFileList.append( tf ); 00415 tempFileName = tf->name(); 00416 if ((*it) == -1) 00417 kCStringToFile( aMsg->asString(), tempFileName, //### 00418 false, false, false ); 00419 else if (aMsg->numBodyParts() == 0) 00420 kByteArrayToFile( aMsg->bodyDecodedBinary(), tempFileName, 00421 false, false, false ); 00422 else { 00423 KMMessagePart msgPart; 00424 aMsg->bodyPart( (*it), &msgPart ); 00425 kByteArrayToFile( msgPart.bodyDecodedBinary(), tempFileName, 00426 false, false, false ); 00427 } 00428 tf->close(); 00429 } 00430 // QString( "%0 and %1 and %1" ).arg( 0 ).arg( 1 ) 00431 // returns "0 and 1 and %1", so we must call .arg as 00432 // many times as there are %n's, regardless of their multiplicity. 00433 if ((*it) == -1) result.replace( "%-1", tempFileName ); 00434 else result = result.arg( tempFileName ); 00435 } 00436 00437 // And finally, replace the %{foo} with the content of the foo 00438 // header field: 00439 QRegExp header_rx( "%\\{([a-z0-9-]+)\\}", false ); 00440 int idx = 0; 00441 while ( ( idx = header_rx.search( result, idx ) ) != -1 ) { 00442 QString replacement = KProcess::quote( aMsg->headerField( header_rx.cap(1).latin1() ) ); 00443 result.replace( idx, header_rx.matchedLength(), replacement ); 00444 idx += replacement.length(); 00445 } 00446 00447 return result; 00448 } 00449 00450 00451 KMFilterAction::ReturnCode KMFilterActionWithCommand::genericProcess(KMMessage* aMsg, bool withOutput) const 00452 { 00453 Q_ASSERT( aMsg ); 00454 00455 if ( mParameter.isEmpty() ) 00456 return ErrorButGoOn; 00457 00458 // KProcess doesn't support a QProcess::launch() equivalent, so 00459 // we must use a temp file :-( 00460 KTempFile * inFile = new KTempFile; 00461 inFile->setAutoDelete(TRUE); 00462 00463 QPtrList<KTempFile> atmList; 00464 atmList.setAutoDelete(TRUE); 00465 atmList.append( inFile ); 00466 00467 QString commandLine = substituteCommandLineArgsFor( aMsg , atmList ); 00468 if ( commandLine.isEmpty() ) 00469 return ErrorButGoOn; 00470 00471 // The parentheses force the creation of a subshell 00472 // in which the user-specified command is executed. 00473 // This is to really catch all output of the command as well 00474 // as to avoid clashes of our redirection with the ones 00475 // the user may have specified. In the long run, we 00476 // shouldn't be using tempfiles at all for this class, due 00477 // to security aspects. (mmutz) 00478 commandLine = "(" + commandLine + ") <" + inFile->name(); 00479 00480 // write message to file 00481 QString tempFileName = inFile->name(); 00482 kCStringToFile( aMsg->asString(), tempFileName, //### 00483 false, false, false ); 00484 inFile->close(); 00485 00486 KProcess shProc; 00487 shProc.setUseShell(true); 00488 shProc << commandLine; 00489 00490 // let the kernel collect the output for us: 00491 if ( withOutput ) 00492 QObject::connect( &shProc, SIGNAL(receivedStdout(KProcess*,char*,int)), 00493 kmkernel, SLOT(slotCollectStdOut(KProcess*,char*,int)) ); 00494 00495 // run process: 00496 if ( !shProc.start( KProcess::Block, 00497 withOutput ? KProcess::Stdout : KProcess::NoCommunication ) ) 00498 return ErrorButGoOn; 00499 00500 if ( !shProc.normalExit() || shProc.exitStatus() != 0 ) { 00501 // eat the output to avoid acummulation for following processes 00502 if ( withOutput ) 00503 kmkernel->getCollectedStdOut( &shProc ); 00504 return ErrorButGoOn; 00505 } 00506 00507 if ( withOutput ) { 00508 // read altered message: 00509 QByteArray msgText = kmkernel->getCollectedStdOut( &shProc ); 00510 00511 if ( !msgText.isEmpty() ) { 00512 /* If the pipe through alters the message, it could very well 00513 happen that it no longer has a X-UID header afterwards. That is 00514 unfortunate, as we need to removed the original from the folder 00515 using that, and look it up in the message. When the (new) message 00516 is uploaded, the header is stripped anyhow. */ 00517 QString uid = aMsg->headerField("X-UID"); 00518 aMsg->fromByteArray( msgText ); 00519 aMsg->setHeaderField("X-UID",uid); 00520 } 00521 else 00522 return ErrorButGoOn; 00523 } 00524 return GoOn; 00525 } 00526 00527 00528 //============================================================================= 00529 // 00530 // Specific Filter Actions 00531 // 00532 //============================================================================= 00533 00534 //============================================================================= 00535 // KMFilterActionBounce - bounce 00536 // Return mail as undelivered. 00537 //============================================================================= 00538 class KMFilterActionBounce : public KMFilterActionWithNone 00539 { 00540 public: 00541 KMFilterActionBounce(); 00542 virtual ReturnCode process(KMMessage* msg) const; 00543 static KMFilterAction* newAction(void); 00544 }; 00545 00546 KMFilterAction* KMFilterActionBounce::newAction(void) 00547 { 00548 return (new KMFilterActionBounce); 00549 } 00550 00551 KMFilterActionBounce::KMFilterActionBounce() 00552 : KMFilterActionWithNone( "bounce", i18n("bounce") ) 00553 { 00554 } 00555 00556 KMFilterAction::ReturnCode KMFilterActionBounce::process(KMMessage* msg) const 00557 { 00558 KMMessage *bounceMsg = msg->createBounce( FALSE ); 00559 if ( !bounceMsg ) return ErrorButGoOn; 00560 00561 // Queue message. This is a) so that the user can check 00562 // the bounces before sending and b) for speed reasons. 00563 kmkernel->msgSender()->send( bounceMsg, FALSE ); 00564 00565 return GoOn; 00566 } 00567 00568 00569 //============================================================================= 00570 // KMFilterActionSendReceipt - send receipt 00571 // Return delivery receipt. 00572 //============================================================================= 00573 class KMFilterActionSendReceipt : public KMFilterActionWithNone 00574 { 00575 public: 00576 KMFilterActionSendReceipt(); 00577 virtual ReturnCode process(KMMessage* msg) const; 00578 static KMFilterAction* newAction(void); 00579 }; 00580 00581 KMFilterAction* KMFilterActionSendReceipt::newAction(void) 00582 { 00583 return (new KMFilterActionSendReceipt); 00584 } 00585 00586 KMFilterActionSendReceipt::KMFilterActionSendReceipt() 00587 : KMFilterActionWithNone( "confirm delivery", i18n("confirm delivery") ) 00588 { 00589 } 00590 00591 KMFilterAction::ReturnCode KMFilterActionSendReceipt::process(KMMessage* msg) const 00592 { 00593 KMMessage *receipt = msg->createDeliveryReceipt(); 00594 if ( !receipt ) return ErrorButGoOn; 00595 00596 // Queue message. This is a) so that the user can check 00597 // the receipt before sending and b) for speed reasons. 00598 kmkernel->msgSender()->send( receipt, FALSE ); 00599 00600 return GoOn; 00601 } 00602 00603 00604 00605 //============================================================================= 00606 // KMFilterActionSetTransport - set transport to... 00607 // Specify mail transport (smtp server) to be used when replying to a message 00608 //============================================================================= 00609 class KMFilterActionTransport: public KMFilterActionWithString 00610 { 00611 public: 00612 KMFilterActionTransport(); 00613 virtual ReturnCode process(KMMessage* msg) const; 00614 static KMFilterAction* newAction(void); 00615 }; 00616 00617 KMFilterAction* KMFilterActionTransport::newAction(void) 00618 { 00619 return (new KMFilterActionTransport); 00620 } 00621 00622 KMFilterActionTransport::KMFilterActionTransport() 00623 : KMFilterActionWithString( "set transport", i18n("set transport to") ) 00624 { 00625 } 00626 00627 KMFilterAction::ReturnCode KMFilterActionTransport::process(KMMessage* msg) const 00628 { 00629 if ( mParameter.isEmpty() ) 00630 return ErrorButGoOn; 00631 msg->setHeaderField( "X-KMail-Transport", mParameter ); 00632 return GoOn; 00633 } 00634 00635 00636 //============================================================================= 00637 // KMFilterActionReplyTo - set Reply-To to 00638 // Set the Reply-to header in a message 00639 //============================================================================= 00640 class KMFilterActionReplyTo: public KMFilterActionWithString 00641 { 00642 public: 00643 KMFilterActionReplyTo(); 00644 virtual ReturnCode process(KMMessage* msg) const; 00645 static KMFilterAction* newAction(void); 00646 }; 00647 00648 KMFilterAction* KMFilterActionReplyTo::newAction(void) 00649 { 00650 return (new KMFilterActionReplyTo); 00651 } 00652 00653 KMFilterActionReplyTo::KMFilterActionReplyTo() 00654 : KMFilterActionWithString( "set Reply-To", i18n("set Reply-To to") ) 00655 { 00656 mParameter = ""; 00657 } 00658 00659 KMFilterAction::ReturnCode KMFilterActionReplyTo::process(KMMessage* msg) const 00660 { 00661 msg->setHeaderField( "Reply-To", mParameter ); 00662 return GoOn; 00663 } 00664 00665 00666 00667 //============================================================================= 00668 // KMFilterActionIdentity - set identity to 00669 // Specify Identity to be used when replying to a message 00670 //============================================================================= 00671 class KMFilterActionIdentity: public KMFilterActionWithUOID 00672 { 00673 public: 00674 KMFilterActionIdentity(); 00675 virtual ReturnCode process(KMMessage* msg) const; 00676 static KMFilterAction* newAction(); 00677 00678 QWidget * createParamWidget( QWidget * parent ) const; 00679 void applyParamWidgetValue( QWidget * parent ); 00680 void setParamWidgetValue( QWidget * parent ) const; 00681 void clearParamWidget( QWidget * param ) const; 00682 }; 00683 00684 KMFilterAction* KMFilterActionIdentity::newAction() 00685 { 00686 return (new KMFilterActionIdentity); 00687 } 00688 00689 KMFilterActionIdentity::KMFilterActionIdentity() 00690 : KMFilterActionWithUOID( "set identity", i18n("set identity to") ) 00691 { 00692 mParameter = kmkernel->identityManager()->defaultIdentity().uoid(); 00693 } 00694 00695 KMFilterAction::ReturnCode KMFilterActionIdentity::process(KMMessage* msg) const 00696 { 00697 msg->setHeaderField( "X-KMail-Identity", QString::number( mParameter ) ); 00698 return GoOn; 00699 } 00700 00701 QWidget * KMFilterActionIdentity::createParamWidget( QWidget * parent ) const 00702 { 00703 IdentityCombo * ic = new IdentityCombo( parent ); 00704 ic->setCurrentIdentity( mParameter ); 00705 return ic; 00706 } 00707 00708 void KMFilterActionIdentity::applyParamWidgetValue( QWidget * paramWidget ) 00709 { 00710 IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget ); 00711 assert( ic ); 00712 mParameter = ic->currentIdentity(); 00713 } 00714 00715 void KMFilterActionIdentity::clearParamWidget( QWidget * paramWidget ) const 00716 { 00717 IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget ); 00718 assert( ic ); 00719 ic->setCurrentItem( 0 ); 00720 //ic->setCurrentIdentity( kmkernel->identityManager()->defaultIdentity() ); 00721 } 00722 00723 void KMFilterActionIdentity::setParamWidgetValue( QWidget * paramWidget ) const 00724 { 00725 IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget ); 00726 assert( ic ); 00727 ic->setCurrentIdentity( mParameter ); 00728 } 00729 00730 //============================================================================= 00731 // KMFilterActionSetStatus - set status to 00732 // Set the status of messages 00733 //============================================================================= 00734 class KMFilterActionSetStatus: public KMFilterActionWithStringList 00735 { 00736 public: 00737 KMFilterActionSetStatus(); 00738 virtual ReturnCode process(KMMessage* msg) const; 00739 virtual bool requiresBody(KMMsgBase*) const; 00740 00741 static KMFilterAction* newAction(); 00742 00743 virtual bool isEmpty() const { return false; } 00744 00745 virtual void argsFromString( const QString argsStr ); 00746 virtual const QString argsAsString() const; 00747 }; 00748 00749 00750 static const KMMsgStatus stati[] = 00751 { 00752 KMMsgStatusFlag, 00753 KMMsgStatusRead, 00754 KMMsgStatusUnread, 00755 KMMsgStatusReplied, 00756 KMMsgStatusForwarded, 00757 KMMsgStatusOld, 00758 KMMsgStatusNew, 00759 KMMsgStatusWatched, 00760 KMMsgStatusIgnored, 00761 KMMsgStatusSpam, 00762 KMMsgStatusHam 00763 }; 00764 static const int StatiCount = sizeof( stati ) / sizeof( KMMsgStatus ); 00765 00766 KMFilterAction* KMFilterActionSetStatus::newAction() 00767 { 00768 return (new KMFilterActionSetStatus); 00769 } 00770 00771 KMFilterActionSetStatus::KMFilterActionSetStatus() 00772 : KMFilterActionWithStringList( "set status", i18n("mark as") ) 00773 { 00774 // if you change this list, also update 00775 // KMFilterActionSetStatus::stati above 00776 mParameterList.append( "" ); 00777 mParameterList.append( i18n("msg status","Important") ); 00778 mParameterList.append( i18n("msg status","Read") ); 00779 mParameterList.append( i18n("msg status","Unread") ); 00780 mParameterList.append( i18n("msg status","Replied") ); 00781 mParameterList.append( i18n("msg status","Forwarded") ); 00782 mParameterList.append( i18n("msg status","Old") ); 00783 mParameterList.append( i18n("msg status","New") ); 00784 mParameterList.append( i18n("msg status","Watched") ); 00785 mParameterList.append( i18n("msg status","Ignored") ); 00786 mParameterList.append( i18n("msg status","Spam") ); 00787 mParameterList.append( i18n("msg status","Ham") ); 00788 00789 mParameter = *mParameterList.at(0); 00790 } 00791 00792 KMFilterAction::ReturnCode KMFilterActionSetStatus::process(KMMessage* msg) const 00793 { 00794 int idx = mParameterList.findIndex( mParameter ); 00795 if ( idx < 1 ) return ErrorButGoOn; 00796 00797 KMMsgStatus status = stati[idx-1] ; 00798 msg->setStatus( status ); 00799 return GoOn; 00800 } 00801 00802 bool KMFilterActionSetStatus::requiresBody(KMMsgBase*) const 00803 { 00804 return false; 00805 } 00806 00807 void KMFilterActionSetStatus::argsFromString( const QString argsStr ) 00808 { 00809 if ( argsStr.length() == 1 ) { 00810 for ( int i = 0 ; i < StatiCount ; i++ ) 00811 if ( KMMsgBase::statusToStr(stati[i])[0] == argsStr[0] ) { 00812 mParameter = *mParameterList.at(i+1); 00813 return; 00814 } 00815 } 00816 mParameter = *mParameterList.at(0); 00817 } 00818 00819 const QString KMFilterActionSetStatus::argsAsString() const 00820 { 00821 int idx = mParameterList.findIndex( mParameter ); 00822 if ( idx < 1 ) return QString::null; 00823 00824 KMMsgStatus status = stati[idx-1]; 00825 return KMMsgBase::statusToStr(status); 00826 } 00827 00828 00829 //============================================================================= 00830 // KMFilterActionFakeDisposition - send fake MDN 00831 // Sends a fake MDN or forces an ignore. 00832 //============================================================================= 00833 class KMFilterActionFakeDisposition: public KMFilterActionWithStringList 00834 { 00835 public: 00836 KMFilterActionFakeDisposition(); 00837 virtual ReturnCode process(KMMessage* msg) const; 00838 static KMFilterAction* newAction() { 00839 return (new KMFilterActionFakeDisposition); 00840 } 00841 00842 virtual bool isEmpty() const { return false; } 00843 00844 virtual void argsFromString( const QString argsStr ); 00845 virtual const QString argsAsString() const; 00846 }; 00847 00848 00849 // if you change this list, also update 00850 // the count in argsFromString 00851 static const KMime::MDN::DispositionType mdns[] = 00852 { 00853 KMime::MDN::Displayed, 00854 KMime::MDN::Deleted, 00855 KMime::MDN::Dispatched, 00856 KMime::MDN::Processed, 00857 KMime::MDN::Denied, 00858 KMime::MDN::Failed, 00859 }; 00860 static const int numMDNs = sizeof mdns / sizeof *mdns; 00861 00862 00863 KMFilterActionFakeDisposition::KMFilterActionFakeDisposition() 00864 : KMFilterActionWithStringList( "fake mdn", i18n("send fake MDN") ) 00865 { 00866 // if you change this list, also update 00867 // mdns above 00868 mParameterList.append( "" ); 00869 mParameterList.append( i18n("MDN type","Ignore") ); 00870 mParameterList.append( i18n("MDN type","Displayed") ); 00871 mParameterList.append( i18n("MDN type","Deleted") ); 00872 mParameterList.append( i18n("MDN type","Dispatched") ); 00873 mParameterList.append( i18n("MDN type","Processed") ); 00874 mParameterList.append( i18n("MDN type","Denied") ); 00875 mParameterList.append( i18n("MDN type","Failed") ); 00876 00877 mParameter = *mParameterList.at(0); 00878 } 00879 00880 KMFilterAction::ReturnCode KMFilterActionFakeDisposition::process(KMMessage* msg) const 00881 { 00882 int idx = mParameterList.findIndex( mParameter ); 00883 if ( idx < 1 ) return ErrorButGoOn; 00884 00885 if ( idx == 1 ) // ignore 00886 msg->setMDNSentState( KMMsgMDNIgnore ); 00887 else // send 00888 sendMDN( msg, mdns[idx-2] ); // skip first two entries: "" and "ignore" 00889 return GoOn; 00890 } 00891 00892 void KMFilterActionFakeDisposition::argsFromString( const QString argsStr ) 00893 { 00894 if ( argsStr.length() == 1 ) { 00895 if ( argsStr[0] == 'I' ) { // ignore 00896 mParameter = *mParameterList.at(1); 00897 return; 00898 } 00899 for ( int i = 0 ; i < numMDNs ; i++ ) 00900 if ( char(mdns[i]) == argsStr[0] ) { // send 00901 mParameter = *mParameterList.at(i+2); 00902 return; 00903 } 00904 } 00905 mParameter = *mParameterList.at(0); 00906 } 00907 00908 const QString KMFilterActionFakeDisposition::argsAsString() const 00909 { 00910 int idx = mParameterList.findIndex( mParameter ); 00911 if ( idx < 1 ) return QString::null; 00912 00913 return QString( QChar( idx < 2 ? 'I' : char(mdns[idx-2]) ) ); 00914 } 00915 00916 00917 //============================================================================= 00918 // KMFilterActionRemoveHeader - remove header 00919 // Remove all instances of the given header field. 00920 //============================================================================= 00921 class KMFilterActionRemoveHeader: public KMFilterActionWithStringList 00922 { 00923 public: 00924 KMFilterActionRemoveHeader(); 00925 virtual ReturnCode process(KMMessage* msg) const; 00926 virtual QWidget* createParamWidget( QWidget* parent ) const; 00927 virtual void setParamWidgetValue( QWidget* paramWidget ) const; 00928 00929 static KMFilterAction* newAction(); 00930 }; 00931 00932 KMFilterAction* KMFilterActionRemoveHeader::newAction() 00933 { 00934 return (new KMFilterActionRemoveHeader); 00935 } 00936 00937 KMFilterActionRemoveHeader::KMFilterActionRemoveHeader() 00938 : KMFilterActionWithStringList( "remove header", i18n("remove header") ) 00939 { 00940 mParameterList << "" 00941 << "Reply-To" 00942 << "Delivered-To" 00943 << "X-KDE-PR-Message" 00944 << "X-KDE-PR-Package" 00945 << "X-KDE-PR-Keywords"; 00946 mParameter = *mParameterList.at(0); 00947 } 00948 00949 QWidget* KMFilterActionRemoveHeader::createParamWidget( QWidget* parent ) const 00950 { 00951 QComboBox *cb = new QComboBox( TRUE/*editable*/, parent ); 00952 cb->setInsertionPolicy( QComboBox::AtBottom ); 00953 setParamWidgetValue( cb ); 00954 return cb; 00955 } 00956 00957 KMFilterAction::ReturnCode KMFilterActionRemoveHeader::process(KMMessage* msg) const 00958 { 00959 if ( mParameter.isEmpty() ) return ErrorButGoOn; 00960 00961 while ( !msg->headerField( mParameter.latin1() ).isEmpty() ) 00962 msg->removeHeaderField( mParameter.latin1() ); 00963 return GoOn; 00964 } 00965 00966 void KMFilterActionRemoveHeader::setParamWidgetValue( QWidget* paramWidget ) const 00967 { 00968 QComboBox * cb = dynamic_cast<QComboBox*>(paramWidget); 00969 Q_ASSERT( cb ); 00970 00971 int idx = mParameterList.findIndex( mParameter ); 00972 cb->clear(); 00973 cb->insertStringList( mParameterList ); 00974 if ( idx < 0 ) { 00975 cb->insertItem( mParameter ); 00976 cb->setCurrentItem( cb->count() - 1 ); 00977 } else { 00978 cb->setCurrentItem( idx ); 00979 } 00980 } 00981 00982 00983 //============================================================================= 00984 // KMFilterActionAddHeader - add header 00985 // Add a header with the given value. 00986 //============================================================================= 00987 class KMFilterActionAddHeader: public KMFilterActionWithStringList 00988 { 00989 public: 00990 KMFilterActionAddHeader(); 00991 virtual ReturnCode process(KMMessage* msg) const; 00992 virtual QWidget* createParamWidget( QWidget* parent ) const; 00993 virtual void setParamWidgetValue( QWidget* paramWidget ) const; 00994 virtual void applyParamWidgetValue( QWidget* paramWidget ); 00995 virtual void clearParamWidget( QWidget* paramWidget ) const; 00996 00997 virtual const QString argsAsString() const; 00998 virtual void argsFromString( const QString argsStr ); 00999 01000 static KMFilterAction* newAction() 01001 { 01002 return (new KMFilterActionAddHeader); 01003 } 01004 private: 01005 QString mValue; 01006 }; 01007 01008 KMFilterActionAddHeader::KMFilterActionAddHeader() 01009 : KMFilterActionWithStringList( "add header", i18n("add header") ) 01010 { 01011 mParameterList << "" 01012 << "Reply-To" 01013 << "Delivered-To" 01014 << "X-KDE-PR-Message" 01015 << "X-KDE-PR-Package" 01016 << "X-KDE-PR-Keywords"; 01017 mParameter = *mParameterList.at(0); 01018 } 01019 01020 KMFilterAction::ReturnCode KMFilterActionAddHeader::process(KMMessage* msg) const 01021 { 01022 if ( mParameter.isEmpty() ) return ErrorButGoOn; 01023 01024 msg->setHeaderField( mParameter.latin1(), mValue ); 01025 return GoOn; 01026 } 01027 01028 QWidget* KMFilterActionAddHeader::createParamWidget( QWidget* parent ) const 01029 { 01030 QWidget *w = new QWidget( parent ); 01031 QHBoxLayout *hbl = new QHBoxLayout( w ); 01032 hbl->setSpacing( 4 ); 01033 QComboBox *cb = new QComboBox( TRUE, w, "combo" ); 01034 cb->setInsertionPolicy( QComboBox::AtBottom ); 01035 hbl->addWidget( cb, 0 /* stretch */ ); 01036 QLabel *l = new QLabel( i18n("with value"), w ); 01037 l->setFixedWidth( l->sizeHint().width() ); 01038 hbl->addWidget( l, 0 ); 01039 QLineEdit *le = new KLineEdit( w, "ledit" ); 01040 hbl->addWidget( le, 1 ); 01041 setParamWidgetValue( w ); 01042 return w; 01043 } 01044 01045 void KMFilterActionAddHeader::setParamWidgetValue( QWidget* paramWidget ) const 01046 { 01047 int idx = mParameterList.findIndex( mParameter ); 01048 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01049 Q_ASSERT( cb ); 01050 cb->clear(); 01051 cb->insertStringList( mParameterList ); 01052 if ( idx < 0 ) { 01053 cb->insertItem( mParameter ); 01054 cb->setCurrentItem( cb->count() - 1 ); 01055 } else { 01056 cb->setCurrentItem( idx ); 01057 } 01058 QLineEdit *le = (QLineEdit*)paramWidget->child("ledit"); 01059 Q_ASSERT( le ); 01060 le->setText( mValue ); 01061 } 01062 01063 void KMFilterActionAddHeader::applyParamWidgetValue( QWidget* paramWidget ) 01064 { 01065 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01066 Q_ASSERT( cb ); 01067 mParameter = cb->currentText(); 01068 01069 QLineEdit *le = (QLineEdit*)paramWidget->child("ledit"); 01070 Q_ASSERT( le ); 01071 mValue = le->text(); 01072 } 01073 01074 void KMFilterActionAddHeader::clearParamWidget( QWidget* paramWidget ) const 01075 { 01076 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01077 Q_ASSERT( cb ); 01078 cb->setCurrentItem(0); 01079 QLineEdit *le = (QLineEdit*)paramWidget->child("ledit"); 01080 Q_ASSERT( le ); 01081 le->clear(); 01082 } 01083 01084 const QString KMFilterActionAddHeader::argsAsString() const 01085 { 01086 QString result = mParameter; 01087 result += '\t'; 01088 result += mValue; 01089 01090 return result; 01091 } 01092 01093 void KMFilterActionAddHeader::argsFromString( const QString argsStr ) 01094 { 01095 QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ ); 01096 QString s; 01097 if ( l.count() < 2 ) { 01098 s = l[0]; 01099 mValue = ""; 01100 } else { 01101 s = l[0]; 01102 mValue = l[1]; 01103 } 01104 01105 int idx = mParameterList.findIndex( s ); 01106 if ( idx < 0 ) { 01107 mParameterList.append( s ); 01108 idx = mParameterList.count() - 1; 01109 } 01110 mParameter = *mParameterList.at( idx ); 01111 } 01112 01113 01114 //============================================================================= 01115 // KMFilterActionRewriteHeader - rewrite header 01116 // Rewrite a header using a regexp. 01117 //============================================================================= 01118 class KMFilterActionRewriteHeader: public KMFilterActionWithStringList 01119 { 01120 public: 01121 KMFilterActionRewriteHeader(); 01122 virtual ReturnCode process(KMMessage* msg) const; 01123 virtual QWidget* createParamWidget( QWidget* parent ) const; 01124 virtual void setParamWidgetValue( QWidget* paramWidget ) const; 01125 virtual void applyParamWidgetValue( QWidget* paramWidget ); 01126 virtual void clearParamWidget( QWidget* paramWidget ) const; 01127 01128 virtual const QString argsAsString() const; 01129 virtual void argsFromString( const QString argsStr ); 01130 01131 static KMFilterAction* newAction() 01132 { 01133 return (new KMFilterActionRewriteHeader); 01134 } 01135 private: 01136 KRegExp3 mRegExp; 01137 QString mReplacementString; 01138 }; 01139 01140 KMFilterActionRewriteHeader::KMFilterActionRewriteHeader() 01141 : KMFilterActionWithStringList( "rewrite header", i18n("rewrite header") ) 01142 { 01143 mParameterList << "" 01144 << "Subject" 01145 << "Reply-To" 01146 << "Delivered-To" 01147 << "X-KDE-PR-Message" 01148 << "X-KDE-PR-Package" 01149 << "X-KDE-PR-Keywords"; 01150 mParameter = *mParameterList.at(0); 01151 } 01152 01153 KMFilterAction::ReturnCode KMFilterActionRewriteHeader::process(KMMessage* msg) const 01154 { 01155 if ( mParameter.isEmpty() || !mRegExp.isValid() ) 01156 return ErrorButGoOn; 01157 01158 KRegExp3 rx = mRegExp; // KRegExp3::replace is not const. 01159 01160 QString newValue = rx.replace( msg->headerField( mParameter.latin1() ), 01161 mReplacementString ); 01162 01163 msg->setHeaderField( mParameter.latin1(), newValue ); 01164 return GoOn; 01165 } 01166 01167 QWidget* KMFilterActionRewriteHeader::createParamWidget( QWidget* parent ) const 01168 { 01169 QWidget *w = new QWidget( parent ); 01170 QHBoxLayout *hbl = new QHBoxLayout( w ); 01171 hbl->setSpacing( 4 ); 01172 01173 QComboBox *cb = new QComboBox( TRUE, w, "combo" ); 01174 cb->setInsertionPolicy( QComboBox::AtBottom ); 01175 hbl->addWidget( cb, 0 /* stretch */ ); 01176 01177 QLabel *l = new QLabel( i18n("replace"), w ); 01178 l->setFixedWidth( l->sizeHint().width() ); 01179 hbl->addWidget( l, 0 ); 01180 01181 QLineEdit *le = new KLineEdit( w, "search" ); 01182 hbl->addWidget( le, 1 ); 01183 01184 l = new QLabel( i18n("with"), w ); 01185 l->setFixedWidth( l->sizeHint().width() ); 01186 hbl->addWidget( l, 0 ); 01187 01188 le = new KLineEdit( w, "replace" ); 01189 hbl->addWidget( le, 1 ); 01190 01191 setParamWidgetValue( w ); 01192 return w; 01193 } 01194 01195 void KMFilterActionRewriteHeader::setParamWidgetValue( QWidget* paramWidget ) const 01196 { 01197 int idx = mParameterList.findIndex( mParameter ); 01198 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01199 Q_ASSERT( cb ); 01200 01201 cb->clear(); 01202 cb->insertStringList( mParameterList ); 01203 if ( idx < 0 ) { 01204 cb->insertItem( mParameter ); 01205 cb->setCurrentItem( cb->count() - 1 ); 01206 } else { 01207 cb->setCurrentItem( idx ); 01208 } 01209 01210 QLineEdit *le = (QLineEdit*)paramWidget->child("search"); 01211 Q_ASSERT( le ); 01212 le->setText( mRegExp.pattern() ); 01213 01214 le = (QLineEdit*)paramWidget->child("replace"); 01215 Q_ASSERT( le ); 01216 le->setText( mReplacementString ); 01217 } 01218 01219 void KMFilterActionRewriteHeader::applyParamWidgetValue( QWidget* paramWidget ) 01220 { 01221 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01222 Q_ASSERT( cb ); 01223 mParameter = cb->currentText(); 01224 01225 QLineEdit *le = (QLineEdit*)paramWidget->child("search"); 01226 Q_ASSERT( le ); 01227 mRegExp.setPattern( le->text() ); 01228 01229 le = (QLineEdit*)paramWidget->child("replace"); 01230 Q_ASSERT( le ); 01231 mReplacementString = le->text(); 01232 } 01233 01234 void KMFilterActionRewriteHeader::clearParamWidget( QWidget* paramWidget ) const 01235 { 01236 QComboBox *cb = (QComboBox*)paramWidget->child("combo"); 01237 Q_ASSERT( cb ); 01238 cb->setCurrentItem(0); 01239 01240 QLineEdit *le = (QLineEdit*)paramWidget->child("search"); 01241 Q_ASSERT( le ); 01242 le->clear(); 01243 01244 le = (QLineEdit*)paramWidget->child("replace"); 01245 Q_ASSERT( le ); 01246 le->clear(); 01247 } 01248 01249 const QString KMFilterActionRewriteHeader::argsAsString() const 01250 { 01251 QString result = mParameter; 01252 result += '\t'; 01253 result += mRegExp.pattern(); 01254 result += '\t'; 01255 result += mReplacementString; 01256 01257 return result; 01258 } 01259 01260 void KMFilterActionRewriteHeader::argsFromString( const QString argsStr ) 01261 { 01262 QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ ); 01263 QString s; 01264 01265 s = l[0]; 01266 mRegExp.setPattern( l[1] ); 01267 mReplacementString = l[2]; 01268 01269 int idx = mParameterList.findIndex( s ); 01270 if ( idx < 0 ) { 01271 mParameterList.append( s ); 01272 idx = mParameterList.count() - 1; 01273 } 01274 mParameter = *mParameterList.at( idx ); 01275 } 01276 01277 01278 //============================================================================= 01279 // KMFilterActionMove - file into folder 01280 // File message into another mail folder 01281 //============================================================================= 01282 class KMFilterActionMove: public KMFilterActionWithFolder 01283 { 01284 public: 01285 KMFilterActionMove(); 01286 virtual ReturnCode process(KMMessage* msg) const; 01287 virtual bool requiresBody(KMMsgBase*) const; 01288 static KMFilterAction* newAction(void); 01289 }; 01290 01291 KMFilterAction* KMFilterActionMove::newAction(void) 01292 { 01293 return (new KMFilterActionMove); 01294 } 01295 01296 KMFilterActionMove::KMFilterActionMove() 01297 : KMFilterActionWithFolder( "transfer", i18n("file into folder") ) 01298 { 01299 } 01300 01301 KMFilterAction::ReturnCode KMFilterActionMove::process(KMMessage* msg) const 01302 { 01303 if ( !mFolder ) 01304 return ErrorButGoOn; 01305 01306 MessageProperty::setFilterFolder( msg, mFolder ); 01307 return GoOn; 01308 } 01309 01310 bool KMFilterActionMove::requiresBody(KMMsgBase*) const 01311 { 01312 return false; //iff mFolder->folderMgr == msgBase->parent()->folderMgr; 01313 } 01314 01315 //============================================================================= 01316 // KMFilterActionForward - forward to 01317 // Forward message to another user 01318 //============================================================================= 01319 class KMFilterActionForward: public KMFilterActionWithAddress 01320 { 01321 public: 01322 KMFilterActionForward(); 01323 virtual ReturnCode process(KMMessage* msg) const; 01324 static KMFilterAction* newAction(void); 01325 }; 01326 01327 KMFilterAction* KMFilterActionForward::newAction(void) 01328 { 01329 return (new KMFilterActionForward); 01330 } 01331 01332 KMFilterActionForward::KMFilterActionForward() 01333 : KMFilterActionWithAddress( "forward", i18n("forward to") ) 01334 { 01335 } 01336 01337 KMFilterAction::ReturnCode KMFilterActionForward::process(KMMessage* aMsg) const 01338 { 01339 if ( mParameter.isEmpty() ) 01340 return ErrorButGoOn; 01341 01342 // Create the forwarded message by hand to make forwarding of messages with 01343 // attachments work. 01344 // Note: This duplicates a lot of code from KMMessage::createForward() and 01345 // KMComposeWin::applyChanges(). 01346 // ### FIXME: Remove the code duplication again. 01347 01348 KMMessage* msg = new KMMessage; 01349 01350 msg->initFromMessage( aMsg ); 01351 01352 QString st = QString::fromUtf8( aMsg->createForwardBody() ); 01353 QCString 01354 encoding = KMMsgBase::autoDetectCharset( aMsg->charset(), 01355 KMMessage::preferredCharsets(), 01356 st ); 01357 if( encoding.isEmpty() ) 01358 encoding = "utf-8"; 01359 QCString str = KMMsgBase::codecForName( encoding )->fromUnicode( st ); 01360 01361 msg->setCharset( encoding ); 01362 msg->setTo( mParameter ); 01363 msg->setSubject( "Fwd: " + aMsg->subject() ); 01364 01365 bool isQP = kmkernel->msgSender()->sendQuotedPrintable(); 01366 01367 if( aMsg->numBodyParts() == 0 ) 01368 { 01369 msg->setAutomaticFields( true ); 01370 msg->setHeaderField( "Content-Type", "text/plain" ); 01371 // msg->setCteStr( isQP ? "quoted-printable": "8bit" ); 01372 QValueList<int> dummy; 01373 msg->setBodyAndGuessCte(str, dummy, !isQP); 01374 msg->setCharset( encoding ); 01375 if( isQP ) 01376 msg->setBodyEncoded( str ); 01377 else 01378 msg->setBody( str ); 01379 } 01380 else 01381 { 01382 KMMessagePart bodyPart, msgPart; 01383 01384 msg->removeHeaderField( "Content-Type" ); 01385 msg->removeHeaderField( "Content-Transfer-Encoding" ); 01386 msg->setAutomaticFields( true ); 01387 msg->setBody( "This message is in MIME format.\n\n" ); 01388 01389 bodyPart.setTypeStr( "text" ); 01390 bodyPart.setSubtypeStr( "plain" ); 01391 // bodyPart.setCteStr( isQP ? "quoted-printable": "8bit" ); 01392 QValueList<int> dummy; 01393 bodyPart.setBodyAndGuessCte(str, dummy, !isQP); 01394 bodyPart.setCharset( encoding ); 01395 bodyPart.setBodyEncoded( str ); 01396 msg->addBodyPart( &bodyPart ); 01397 01398 for( int i = 0; i < aMsg->numBodyParts(); i++ ) 01399 { 01400 aMsg->bodyPart( i, &msgPart ); 01401 if( i > 0 || qstricmp( msgPart.typeStr(), "text" ) != 0 ) 01402 msg->addBodyPart( &msgPart ); 01403 } 01404 } 01405 msg->cleanupHeader(); 01406 msg->link( aMsg, KMMsgStatusForwarded ); 01407 01408 sendMDN( aMsg, KMime::MDN::Dispatched ); 01409 01410 if ( !kmkernel->msgSender()->send( msg, FALSE ) ) { 01411 kdDebug(5006) << "KMFilterAction: could not forward message (sending failed)" << endl; 01412 return ErrorButGoOn; // error: couldn't send 01413 } 01414 return GoOn; 01415 } 01416 01417 01418 //============================================================================= 01419 // KMFilterActionRedirect - redirect to 01420 // Redirect message to another user 01421 //============================================================================= 01422 class KMFilterActionRedirect: public KMFilterActionWithAddress 01423 { 01424 public: 01425 KMFilterActionRedirect(); 01426 virtual ReturnCode process(KMMessage* msg) const; 01427 static KMFilterAction* newAction(void); 01428 }; 01429 01430 KMFilterAction* KMFilterActionRedirect::newAction(void) 01431 { 01432 return (new KMFilterActionRedirect); 01433 } 01434 01435 KMFilterActionRedirect::KMFilterActionRedirect() 01436 : KMFilterActionWithAddress( "redirect", i18n("redirect to") ) 01437 { 01438 } 01439 01440 KMFilterAction::ReturnCode KMFilterActionRedirect::process(KMMessage* aMsg) const 01441 { 01442 KMMessage* msg; 01443 if ( mParameter.isEmpty() ) 01444 return ErrorButGoOn; 01445 01446 msg = aMsg->createRedirect(); 01447 msg->setTo( mParameter ); 01448 01449 sendMDN( aMsg, KMime::MDN::Dispatched ); 01450 01451 if ( !kmkernel->msgSender()->send( msg, FALSE ) ) { 01452 kdDebug(5006) << "KMFilterAction: could not redirect message (sending failed)" << endl; 01453 return ErrorButGoOn; // error: couldn't send 01454 } 01455 return GoOn; 01456 } 01457 01458 01459 //============================================================================= 01460 // KMFilterActionExec - execute command 01461 // Execute a shell command 01462 //============================================================================= 01463 class KMFilterActionExec : public KMFilterActionWithCommand 01464 { 01465 public: 01466 KMFilterActionExec(); 01467 virtual ReturnCode process(KMMessage* msg) const; 01468 static KMFilterAction* newAction(void); 01469 }; 01470 01471 KMFilterAction* KMFilterActionExec::newAction(void) 01472 { 01473 return (new KMFilterActionExec()); 01474 } 01475 01476 KMFilterActionExec::KMFilterActionExec() 01477 : KMFilterActionWithCommand( "execute", i18n("execute command") ) 01478 { 01479 } 01480 01481 KMFilterAction::ReturnCode KMFilterActionExec::process(KMMessage *aMsg) const 01482 { 01483 return KMFilterActionWithCommand::genericProcess( aMsg, false ); // ignore output 01484 } 01485 01486 //============================================================================= 01487 // KMFilterActionExtFilter - use external filter app 01488 // External message filter: executes a shell command with message 01489 // on stdin; altered message is expected on stdout. 01490 //============================================================================= 01491 01492 #include <weaver.h> 01493 class PipeJob : public KPIM::ThreadWeaver::Job 01494 { 01495 public: 01496 PipeJob(QObject* parent = 0 , const char* name = 0, KMMessage* aMsg = 0, QString cmd = 0, QString tempFileName = 0 ) 01497 : Job (parent, name), 01498 mTempFileName(tempFileName), 01499 mCmd(cmd), 01500 mMsg( aMsg ) 01501 { 01502 } 01503 01504 ~PipeJob() {} 01505 virtual void processEvent( KPIM::ThreadWeaver::Event *ev ) 01506 { 01507 KPIM::ThreadWeaver::Job::processEvent( ev ); 01508 if ( ev->action() == KPIM::ThreadWeaver::Event::JobFinished ) 01509 deleteLater( ); 01510 } 01511 protected: 01512 void run() 01513 { 01514 KPIM::ThreadWeaver::debug (1, "PipeJob::run: doing it .\n"); 01515 FILE *p; 01516 QByteArray ba; 01517 01518 p = popen(QFile::encodeName(mCmd), "r"); 01519 int len =100; 01520 char buffer[100]; 01521 // append data to ba: 01522 while (true) { 01523 if (! fgets( buffer, len, p ) ) break; 01524 int oldsize = ba.size(); 01525 ba.resize( oldsize + strlen(buffer) ); 01526 qmemmove( ba.begin() + oldsize, buffer, strlen(buffer) ); 01527 } 01528 pclose(p); 01529 if ( !ba.isEmpty() ) { 01530 KPIM::ThreadWeaver::debug (1, "PipeJob::run: %s", QString(ba).latin1() ); 01531 mMsg->fromByteArray( ba ); 01532 } 01533 01534 KPIM::ThreadWeaver::debug (1, "PipeJob::run: done.\n" ); 01535 // unlink the tempFile 01536 QFile::remove(mTempFileName); 01537 } 01538 QString mTempFileName; 01539 QString mCmd; 01540 KMMessage *mMsg; 01541 }; 01542 01543 class KMFilterActionExtFilter: public KMFilterActionWithCommand 01544 { 01545 public: 01546 KMFilterActionExtFilter(); 01547 virtual ReturnCode process(KMMessage* msg) const; 01548 virtual void processAsync(KMMessage* msg) const; 01549 static KMFilterAction* newAction(void); 01550 }; 01551 01552 KMFilterAction* KMFilterActionExtFilter::newAction(void) 01553 { 01554 return (new KMFilterActionExtFilter); 01555 } 01556 01557 KMFilterActionExtFilter::KMFilterActionExtFilter() 01558 : KMFilterActionWithCommand( "filter app", i18n("pipe through") ) 01559 { 01560 } 01561 KMFilterAction::ReturnCode KMFilterActionExtFilter::process(KMMessage* aMsg) const 01562 { 01563 return KMFilterActionWithCommand::genericProcess( aMsg, true ); // use output 01564 } 01565 01566 void KMFilterActionExtFilter::processAsync(KMMessage* aMsg) const 01567 { 01568 01569 ActionScheduler *handler = MessageProperty::filterHandler( aMsg->getMsgSerNum() ); 01570 KTempFile * inFile = new KTempFile; 01571 inFile->setAutoDelete(FALSE); 01572 01573 QPtrList<KTempFile> atmList; 01574 atmList.setAutoDelete(TRUE); 01575 atmList.append( inFile ); 01576 01577 QString commandLine = substituteCommandLineArgsFor( aMsg , atmList ); 01578 if ( commandLine.isEmpty() ) 01579 handler->actionMessage( ErrorButGoOn ); 01580 01581 // The parentheses force the creation of a subshell 01582 // in which the user-specified command is executed. 01583 // This is to really catch all output of the command as well 01584 // as to avoid clashes of our redirection with the ones 01585 // the user may have specified. In the long run, we 01586 // shouldn't be using tempfiles at all for this class, due 01587 // to security aspects. (mmutz) 01588 commandLine = "(" + commandLine + ") <" + inFile->name(); 01589 01590 // write message to file 01591 QString tempFileName = inFile->name(); 01592 kCStringToFile( aMsg->asString(), tempFileName, //### 01593 false, false, false ); 01594 inFile->close(); 01595 01596 PipeJob *job = new PipeJob(0, 0, aMsg, commandLine, tempFileName); 01597 QObject::connect ( job, SIGNAL( done() ), handler, SLOT( actionMessage() ) ); 01598 kmkernel->weaver()->enqueue(job); 01599 } 01600 01601 //============================================================================= 01602 // KMFilterActionExecSound - execute command 01603 // Execute a sound 01604 //============================================================================= 01605 class KMFilterActionExecSound : public KMFilterActionWithTest 01606 { 01607 public: 01608 KMFilterActionExecSound(); 01609 virtual ReturnCode process(KMMessage* msg) const; 01610 virtual bool requiresBody(KMMsgBase*) const; 01611 static KMFilterAction* newAction(void); 01612 }; 01613 01614 KMFilterActionWithTest::KMFilterActionWithTest( const char* aName, const QString aLabel ) 01615 : KMFilterAction( aName, aLabel ) 01616 { 01617 } 01618 01619 KMFilterActionWithTest::~KMFilterActionWithTest() 01620 { 01621 } 01622 01623 QWidget* KMFilterActionWithTest::createParamWidget( QWidget* parent ) const 01624 { 01625 KMSoundTestWidget *le = new KMSoundTestWidget(parent); 01626 le->setUrl( mParameter ); 01627 return le; 01628 } 01629 01630 01631 void KMFilterActionWithTest::applyParamWidgetValue( QWidget* paramWidget ) 01632 { 01633 mParameter = ((KMSoundTestWidget*)paramWidget)->url(); 01634 } 01635 01636 void KMFilterActionWithTest::setParamWidgetValue( QWidget* paramWidget ) const 01637 { 01638 ((KMSoundTestWidget*)paramWidget)->setUrl( mParameter ); 01639 } 01640 01641 void KMFilterActionWithTest::clearParamWidget( QWidget* paramWidget ) const 01642 { 01643 ((KMSoundTestWidget*)paramWidget)->clear(); 01644 } 01645 01646 void KMFilterActionWithTest::argsFromString( const QString argsStr ) 01647 { 01648 mParameter = argsStr; 01649 } 01650 01651 const QString KMFilterActionWithTest::argsAsString() const 01652 { 01653 return mParameter; 01654 } 01655 01656 01657 KMFilterActionExecSound::KMFilterActionExecSound() 01658 : KMFilterActionWithTest( "play sound", i18n("play a sound") ) 01659 { 01660 } 01661 01662 KMFilterAction* KMFilterActionExecSound::newAction(void) 01663 { 01664 return (new KMFilterActionExecSound()); 01665 } 01666 01667 KMFilterAction::ReturnCode KMFilterActionExecSound::process(KMMessage*) const 01668 { 01669 if ( mParameter.isEmpty() ) 01670 return ErrorButGoOn; 01671 QString play = mParameter; 01672 QString file = QString::fromLatin1("file:"); 01673 if (mParameter.startsWith(file)) 01674 play = mParameter.mid(file.length()); 01675 KAudioPlayer::play(QFile::encodeName(play)); 01676 return GoOn; 01677 } 01678 01679 bool KMFilterActionExecSound::requiresBody(KMMsgBase*) const 01680 { 01681 return false; 01682 } 01683 01684 KMFilterActionWithUrl::KMFilterActionWithUrl( const char* aName, const QString aLabel ) 01685 : KMFilterAction( aName, aLabel ) 01686 { 01687 } 01688 01689 KMFilterActionWithUrl::~KMFilterActionWithUrl() 01690 { 01691 } 01692 01693 QWidget* KMFilterActionWithUrl::createParamWidget( QWidget* parent ) const 01694 { 01695 KURLRequester *le = new KURLRequester(parent); 01696 le->setURL( mParameter ); 01697 return le; 01698 } 01699 01700 01701 void KMFilterActionWithUrl::applyParamWidgetValue( QWidget* paramWidget ) 01702 { 01703 mParameter = ((KURLRequester*)paramWidget)->url(); 01704 } 01705 01706 void KMFilterActionWithUrl::setParamWidgetValue( QWidget* paramWidget ) const 01707 { 01708 ((KURLRequester*)paramWidget)->setURL( mParameter ); 01709 } 01710 01711 void KMFilterActionWithUrl::clearParamWidget( QWidget* paramWidget ) const 01712 { 01713 ((KURLRequester*)paramWidget)->clear(); 01714 } 01715 01716 void KMFilterActionWithUrl::argsFromString( const QString argsStr ) 01717 { 01718 mParameter = argsStr; 01719 } 01720 01721 const QString KMFilterActionWithUrl::argsAsString() const 01722 { 01723 return mParameter; 01724 } 01725 01726 01727 //============================================================================= 01728 // 01729 // Filter Action Dictionary 01730 // 01731 //============================================================================= 01732 void KMFilterActionDict::init(void) 01733 { 01734 insert( KMFilterActionMove::newAction ); 01735 insert( KMFilterActionIdentity::newAction ); 01736 insert( KMFilterActionSetStatus::newAction ); 01737 insert( KMFilterActionFakeDisposition::newAction ); 01738 insert( KMFilterActionTransport::newAction ); 01739 insert( KMFilterActionReplyTo::newAction ); 01740 insert( KMFilterActionForward::newAction ); 01741 insert( KMFilterActionRedirect::newAction ); 01742 insert( KMFilterActionBounce::newAction ); 01743 insert( KMFilterActionSendReceipt::newAction ); 01744 insert( KMFilterActionExec::newAction ); 01745 insert( KMFilterActionExtFilter::newAction ); 01746 insert( KMFilterActionRemoveHeader::newAction ); 01747 insert( KMFilterActionAddHeader::newAction ); 01748 insert( KMFilterActionRewriteHeader::newAction ); 01749 insert( KMFilterActionExecSound::newAction ); 01750 // Register custom filter actions below this line. 01751 } 01752 // The int in the QDict constructor (23) must be a prime 01753 // and should be greater than the double number of KMFilterAction types 01754 KMFilterActionDict::KMFilterActionDict() 01755 : QDict<KMFilterActionDesc>(23) 01756 { 01757 mList.setAutoDelete(TRUE); 01758 init(); 01759 } 01760 01761 void KMFilterActionDict::insert( KMFilterActionNewFunc aNewFunc ) 01762 { 01763 KMFilterAction *action = aNewFunc(); 01764 KMFilterActionDesc* desc = new KMFilterActionDesc; 01765 desc->name = action->name(); 01766 desc->label = action->label(); 01767 desc->create = aNewFunc; 01768 QDict<KMFilterActionDesc>::insert( desc->name, desc ); 01769 QDict<KMFilterActionDesc>::insert( desc->label, desc ); 01770 mList.append( desc ); 01771 delete action; 01772 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:58:00 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003