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