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