1 /*
2 ** Copyright 2002-2011, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "libmail_config.h"
7 #include <cstring>
8 
9 #include "addressbook.H"
10 #include "addressbookadd.H"
11 #include "addressbookget.H"
12 #include "addressbookopen.H"
13 #include "addressbooksearch.H"
14 #include "rfc2047decode.H"
15 #include "misc.H"
16 #include <errno.h>
17 
18 using namespace std;
19 
Entry()20 mail::addressbook::Entry::Entry()
21 {
22 }
23 
~Entry()24 mail::addressbook::Entry::~Entry()
25 {
26 }
27 
addressbook(mail::account * serverArg,mail::folder * folderArg)28 mail::addressbook::addressbook(mail::account *serverArg,
29 			       mail::folder *folderArg)
30 	: server(serverArg),
31 	  folder(folderArg)
32 {
33 }
34 
~addressbook()35 mail::addressbook::~addressbook()
36 {
37 }
38 
addEntry(Entry & newEntry,string olduid,mail::callback & callback)39 void mail::addressbook::addEntry(Entry &newEntry, string olduid,
40 				 mail::callback &callback)
41 {
42 	vector<Index>::iterator b=index.begin(), e=index.end();
43 
44 	while (b != e)
45 	{
46 		Index &i= *b++;
47 
48 		if (olduid.size() > 0 && i.uid == olduid)
49 			continue;
50 
51 		if (newEntry.nickname == i.nickname)
52 		{
53 			callback.fail("Address book entry with the same name already exists.");
54 			return;
55 		}
56 	}
57 
58 	Add *add=new Add(this, newEntry, olduid, callback);
59 
60 	try {
61 		add->go();
62 	} catch (...) {
63 		delete add;
64 	}
65 }
66 
importEntries(std::list<Entry> & newEntries,mail::callback & callback)67 void mail::addressbook::importEntries(std::list<Entry> &newEntries,
68 				      mail::callback &callback)
69 {
70 	Add *add=new Add(this, newEntries, callback);
71 
72 	try {
73 		add->go();
74 	} catch (...) {
75 		delete add;
76 	}
77 }
78 
79 // Delete an address book entry.
80 
del(std::string uid,mail::callback & callback)81 void mail::addressbook::del(std::string uid, mail::callback &callback)
82 {
83 	vector<Index>::iterator b=index.begin(), e=index.end();
84 
85 	while (b != e)
86 	{
87 		if (b->uid == uid)
88 		{
89 			vector<size_t> msgList;
90 
91 			msgList.push_back(b - index.begin());
92 
93 			server->removeMessages(msgList, callback);
94 			return;
95 		}
96 
97 		b++;
98 	}
99 
100 	callback.success("OK");
101 }
102 
open(mail::callback & callback)103 void mail::addressbook::open(mail::callback &callback)
104 {
105 	Open *o=new Open(this, callback);
106 
107 	try {
108 		o->go();
109 	} catch (...) {
110 		delete o;
111 	}
112 }
113 
Index()114 mail::addressbook::Index::Index() : nickname("(corrupted entry)")
115 {
116 }
117 
~Index()118 mail::addressbook::Index::~Index()
119 {
120 }
121 
setIndex(size_t messageNumber,string subject)122 void mail::addressbook::setIndex(size_t messageNumber,
123 				 string subject)
124 {
125 	subject= mail::rfc2047::decoder().decode(subject, "utf-8");
126 
127 	if (messageNumber < index.size())
128 	{
129 		Index newEntry;
130 
131 		size_t i=subject.find('[');
132 
133 		if (i != std::string::npos)
134 		{
135 			subject=subject.substr(i+1);
136 
137 			i=subject.find(']');
138 
139 			if (i != std::string::npos)
140 			{
141 				newEntry.nickname=subject.substr(0, i);
142 				if (newEntry.nickname.size() == 0)
143 					newEntry.nickname="(none)";
144 
145 				char *p=unicode_convert_tobuf(newEntry
146 								.nickname
147 								.c_str(),
148 								"utf-8",
149 								unicode_default_chset(),
150 								NULL);
151 
152 				if (!p)
153 					LIBMAIL_THROW(strerror(errno));
154 
155 				try {
156 					newEntry.nickname=p;
157 					free(p);
158 				} catch (...) {
159 					free(p);
160 					LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
161 				}
162 			}
163 		}
164 
165 		newEntry.uid=server->getFolderIndexInfo(messageNumber).uid;
166 		index[messageNumber]=newEntry;
167 	}
168 }
169 
newMessages()170 void mail::addressbook::newMessages()
171 {
172 }
173 
messagesRemoved(vector<pair<size_t,size_t>> & r)174 void mail::addressbook::messagesRemoved(vector< pair<size_t, size_t> > &r)
175 {
176 	vector< pair<size_t, size_t> >::iterator b=r.begin(), e=r.end();
177 
178 	while (b != e)
179 	{
180 		--e;
181 
182 		size_t from=e->first, to=e->second;
183 
184 		if (from >= index.size())
185 			continue;
186 
187 		if (to > index.size())
188 			to=index.size();
189 
190 		index.erase(index.begin() + from, index.begin() + to + 1);
191 	}
192 }
193 
messageChanged(size_t n)194 void mail::addressbook::messageChanged(size_t n)
195 {
196 }
197 
getIndex(list<pair<string,std::string>> & listArg,mail::callback & callback)198 void mail::addressbook::getIndex( list< pair<string, std::string> > &listArg,
199 	       mail::callback &callback)
200 {
201 	size_t n=index.size();
202 	size_t i;
203 
204 	for (i=0; i<n; i++)
205 	{
206 		string nickname=index[i].nickname;
207 		string uid=index[i].uid;
208 
209 		if (nickname.size() > 0 && uid.size() > 0)
210 			listArg.push_back( make_pair(nickname, uid));
211 	}
212 
213 	callback.success("Address book index retrieved");
214 }
215 
216 template<class T>
searchNickname(string nickname,vector<T> & addrListArg,mail::callback & callback)217 void mail::addressbook::searchNickname( string nickname,
218 					vector<T> &addrListArg,
219 					mail::callback &callback)
220 {
221 	Search<T> *s=new Search<T>(this, addrListArg, callback);
222 
223 	if (!s)
224 	{
225 		callback.fail(strerror(errno));
226 		return;
227 	}
228 
229 	try {
230 		size_t n=index.size();
231 		size_t i;
232 
233 		for (i=0; i<n; i++)
234 			if (index[i].nickname == nickname)
235 				s->uidList.push_back(server->
236 						     getFolderIndexInfo(i)
237 						     .uid);
238 		s->go();
239 	} catch (...) {
240 		delete s;
241 		LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
242 	}
243 }
244 
245 template
246 void mail::addressbook::searchNickname( string nickname,
247 					vector<mail::address> &addrListArg,
248 					mail::callback &callback);
249 template
250 void mail::addressbook::searchNickname( string nickname,
251 					vector<mail::emailAddress> &addrListArg,
252 					mail::callback &callback);
253 
254 template<class T>
getEntry(string uid,vector<T> & addrListArg,mail::callback & callback)255 void mail::addressbook::getEntry( string uid,
256 				  vector<T> &addrListArg,
257 				  mail::callback &callback)
258 {
259 	size_t n=index.size();
260 	size_t i;
261 
262 	for (i=0; i<n; i++)
263 		if (server->getFolderIndexInfo(i).uid == uid)
264 		{
265 			GetAddressList<T> *get=
266 				new GetAddressList<T>(this, i,
267 						      addrListArg,
268 						      callback);
269 
270 			if (!get)
271 			{
272 				callback.fail(strerror(errno));
273 				return;
274 			}
275 
276 			try {
277 				get->go();
278 			} catch (...) {
279 				delete get;
280 				LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
281 			}
282 			return;
283 		}
284 
285 	callback.success("NOT FOUND.");
286 }
287 
288 template
289 void mail::addressbook::getEntry( string uid,
290 				  vector<mail::address> &addrListArg,
291 				  mail::callback &callback);
292 template
293 void mail::addressbook::getEntry( string uid,
294 				  vector<mail::emailAddress>
295 				  &addrListArg,
296 				  mail::callback &callback);
297