xref: /haiku/src/preferences/mail/FilterList.cpp (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
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 
FilterList(direction dir)18 FilterList::FilterList(direction dir)
19 	:
20 	fDirection(dir)
21 {
22 }
23 
24 
~FilterList()25 FilterList::~FilterList()
26 {
27 	_MakeEmpty();
28 }
29 
30 
31 void
Reload()32 FilterList::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 
65 int32
CountInfos() const66 FilterList::CountInfos() const
67 {
68 	return fList.size();
69 }
70 
71 
72 const FilterInfo&
InfoAt(int32 index) const73 FilterList::InfoAt(int32 index) const
74 {
75 	return fList[index];
76 }
77 
78 
79 int32
InfoIndexFor(const entry_ref & ref) const80 FilterList::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 
91 BString
SimpleName(int32 index,const BMailAccountSettings & accountSettings) const92 FilterList::SimpleName(int32 index,
93 	const BMailAccountSettings& accountSettings) const
94 {
95 	return DescriptiveName(index, accountSettings, NULL);
96 }
97 
98 
99 BString
SimpleName(const entry_ref & ref,const BMailAccountSettings & accountSettings) const100 FilterList::SimpleName(const entry_ref& ref,
101 	const BMailAccountSettings& accountSettings) const
102 {
103 	return DescriptiveName(InfoIndexFor(ref), accountSettings, NULL);
104 }
105 
106 
107 BString
DescriptiveName(int32 index,const BMailAccountSettings & accountSettings,const BMailAddOnSettings * settings) const108 FilterList::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 
120 BString
DescriptiveName(const entry_ref & ref,const BMailAccountSettings & accountSettings,const BMailAddOnSettings * settings) const121 FilterList::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 
129 BMailSettingsView*
CreateSettingsView(const BMailAccountSettings & accountSettings,const BMailAddOnSettings & settings)130 FilterList::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 
143 void
_MakeEmpty()144 FilterList::_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 
154 status_t
_LoadAddOn(BEntry & entry)155 FilterList::_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