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