1/*
2 * Copyright 2011-2016, Haiku, Inc. All rights reserved.
3 * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "FilterList.h"
9
10#include <set>
11#include <stdio.h>
12
13#include <Directory.h>
14#include <PathFinder.h>
15#include <Path.h>
16
17
18FilterList::FilterList(direction dir)
19	:
20	fDirection(dir)
21{
22}
23
24
25FilterList::~FilterList()
26{
27	_MakeEmpty();
28}
29
30
31void
32FilterList::Reload()
33{
34	_MakeEmpty();
35
36	std::set<BString> knownNames;
37
38	BString subPath("mail_daemon/");
39	subPath << (fDirection == kIncoming
40		? "inbound_filters" : "outbound_filters");
41
42	BStringList paths;
43	BPathFinder().FindPaths(B_FIND_PATH_ADD_ONS_DIRECTORY, subPath, paths);
44	for (int32 i = 0; i < paths.CountStrings(); i++) {
45		BPath path(paths.StringAt(i));
46
47		BDirectory dir(path.Path());
48		if (dir.InitCheck() != B_OK)
49			continue;
50
51		BEntry entry;
52		while (dir.GetNextEntry(&entry) == B_OK) {
53			// Ignore entries we already had before (ie., user add-ons are
54			// overriding system add-ons)
55			if (knownNames.find(entry.Name()) != knownNames.end())
56				continue;
57
58			if (_LoadAddOn(entry) == B_OK)
59				knownNames.insert(entry.Name());
60		}
61	}
62}
63
64
65int32
66FilterList::CountInfos() const
67{
68	return fList.size();
69}
70
71
72const FilterInfo&
73FilterList::InfoAt(int32 index) const
74{
75	return fList[index];
76}
77
78
79int32
80FilterList::InfoIndexFor(const entry_ref& ref) const
81{
82	for (size_t i = 0; i < fList.size(); i++) {
83		const FilterInfo& info = fList[i];
84		if (info.ref == ref)
85			return i;
86	}
87	return -1;
88}
89
90
91BString
92FilterList::SimpleName(int32 index,
93	const BMailAccountSettings& accountSettings) const
94{
95	return DescriptiveName(index, accountSettings, NULL);
96}
97
98
99BString
100FilterList::SimpleName(const entry_ref& ref,
101	const BMailAccountSettings& accountSettings) const
102{
103	return DescriptiveName(InfoIndexFor(ref), accountSettings, NULL);
104}
105
106
107BString
108FilterList::DescriptiveName(int32 index,
109	const BMailAccountSettings& accountSettings,
110	const BMailAddOnSettings* settings) const
111{
112	if (index < 0 || index >= CountInfos())
113		return "-";
114
115	const FilterInfo& info = InfoAt(index);
116	return info.name(accountSettings, settings);
117}
118
119
120BString
121FilterList::DescriptiveName(const entry_ref& ref,
122	const BMailAccountSettings& accountSettings,
123	const BMailAddOnSettings* settings) const
124{
125	return DescriptiveName(InfoIndexFor(ref), accountSettings, settings);
126}
127
128
129BMailSettingsView*
130FilterList::CreateSettingsView(const BMailAccountSettings& accountSettings,
131	const BMailAddOnSettings& settings)
132{
133	const entry_ref& ref = settings.AddOnRef();
134	int32 index = InfoIndexFor(ref);
135	if (index < 0)
136		return NULL;
137
138	const FilterInfo& info = InfoAt(index);
139	return info.instantiateSettingsView(accountSettings, settings);
140}
141
142
143void
144FilterList::_MakeEmpty()
145{
146	for (size_t i = 0; i < fList.size(); i++) {
147		FilterInfo& info = fList[i];
148		unload_add_on(info.image);
149	}
150	fList.clear();
151}
152
153
154status_t
155FilterList::_LoadAddOn(BEntry& entry)
156{
157	FilterInfo info;
158
159	BPath path(&entry);
160	info.image = load_add_on(path.Path());
161	if (info.image < 0)
162		return info.image;
163
164	status_t status = get_image_symbol(info.image,
165		"instantiate_filter_settings_view", B_SYMBOL_TYPE_TEXT,
166		(void**)&info.instantiateSettingsView);
167	if (status == B_OK) {
168		status = get_image_symbol(info.image, "filter_name", B_SYMBOL_TYPE_TEXT,
169			(void**)&info.name);
170	}
171	if (status != B_OK) {
172		fprintf(stderr, "Filter \"%s\" misses required hooks!\n", path.Path());
173		unload_add_on(info.image);
174		return B_NAME_NOT_FOUND;
175	}
176
177	entry.GetRef(&info.ref);
178	fList.push_back(info);
179	return B_OK;
180}
181