1/* 2 * Copyright 2004-2013, Haiku, Inc. All rights reserved. 3 * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9//! Performs action depending on matching a header value. 10 11 12#include "RuleFilter.h" 13 14#include <stdlib.h> 15#include <stdio.h> 16 17#include <Catalog.h> 18#include <Directory.h> 19#include <fs_attr.h> 20#include <Node.h> 21#include <String.h> 22 23#include <MailProtocol.h> 24 25#include "MatchHeaderSettings.h" 26 27 28#undef B_TRANSLATION_CONTEXT 29#define B_TRANSLATION_CONTEXT "RuleFilter" 30 31 32RuleFilter::RuleFilter(BMailProtocol& protocol, 33 const BMailAddOnSettings& addOnSettings) 34 : 35 BMailFilter(protocol, &addOnSettings) 36{ 37 MatchHeaderSettings settings(addOnSettings); 38 39 // attribute is adapted to our "capitalize-each-word-in-the-header" policy 40 fAttribute = settings.Attribute(); 41 fAttribute.CapitalizeEachWord(); 42 43 fExpression = settings.Expression(); 44 int32 index = fExpression.FindFirst("REGEX:"); 45 if (index == B_ERROR || index > 0) 46 EscapeRegexTokens(fExpression); 47 else 48 fExpression.RemoveFirst("REGEX:"); 49 50 fMatcher.SetPattern(fExpression, false); 51 52 fAction = settings.Action(); 53 fMoveTarget = settings.MoveTarget(); 54 fSetFlags = settings.SetFlagsTo(); 55 fReplyAccount = settings.ReplyAccount(); 56} 57 58 59BMailFilterAction 60RuleFilter::HeaderFetched(entry_ref& ref, BFile& file, BMessage& attributes) 61{ 62 // That field doesn't exist? NO match 63 if (fAttribute == "") 64 return B_NO_MAIL_ACTION; 65 66 attr_info info; 67 if (file.GetAttrInfo("Subject", &info) != B_OK 68 || info.type != B_STRING_TYPE) 69 return B_NO_MAIL_ACTION; 70 71 BString data = attributes.GetString(fAttribute.String(), NULL); 72 if (data.IsEmpty() || !fMatcher.Match(data)) { 73 // We're not supposed to do anything 74 return B_NO_MAIL_ACTION; 75 } 76 77 switch (fAction) { 78 case ACTION_MOVE_TO: 79 { 80 BDirectory dir(fMoveTarget); 81 node_ref nodeRef; 82 status_t status = dir.GetNodeRef(&nodeRef); 83 if (status != B_OK) 84 return status; 85 86 ref.device = nodeRef.device; 87 ref.directory = nodeRef.node; 88 return B_MOVE_MAIL_ACTION; 89 } 90 91 case ACTION_DELETE_MESSAGE: 92 return B_DELETE_MAIL_ACTION; 93 94 case ACTION_SET_FLAGS_TO: 95 file.WriteAttrString("MAIL:filter_flags", &fSetFlags); 96 break; 97 98 case ACTION_REPLY_WITH: 99 file.WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, &fReplyAccount, 100 sizeof(int32)); 101 break; 102 case ACTION_SET_AS_READ: 103 { 104 BInboundMailProtocol& protocol 105 = (BInboundMailProtocol&)fMailProtocol; 106 protocol.MarkMessageAsRead(ref, B_READ); 107 break; 108 } 109 default: 110 fprintf(stderr,"Unknown do_what: 0x%04x!\n", fAction); 111 } 112 113 return B_NO_MAIL_ACTION; 114} 115 116 117// #pragma mark - 118 119 120BString 121filter_name(const BMailAccountSettings& accountSettings, 122 const BMailAddOnSettings* addOnSettings) 123{ 124 if (addOnSettings != NULL) { 125 MatchHeaderSettings settings(*addOnSettings); 126 if (settings.Attribute() != NULL && settings.Expression() != NULL) { 127 BString name( 128 B_TRANSLATE("Match \"%attribute\" against \"%regex\"")); 129 name.ReplaceAll("%attribute", settings.Attribute()); 130 name.ReplaceAll("%regex", settings.Expression()); 131 return name; 132 } 133 } 134 return B_TRANSLATE("Match header"); 135} 136 137 138BMailFilter* 139instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings) 140{ 141 return new RuleFilter(protocol, settings); 142} 143