1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2002-2012 Match Grun and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 /*
21  * Address list item selection objects.
22  */
23 
24 #include <stdio.h>
25 #include <glib.h>
26 
27 #include "addrselect.h"
28 #include "addressitem.h"
29 #include "mgutils.h"
30 
31 static AddrSelectItem *addrselect_create_item	( AddrItemObject *aio );
32 
33 /**
34  * Create a selection record from an address cache item.
35  * \param  aio Item object.
36  * \return Address select item.
37  */
addrselect_create_item(AddrItemObject * aio)38 static AddrSelectItem *addrselect_create_item( AddrItemObject *aio ) {
39 	AddrSelectItem *item = NULL;
40 
41 	if( aio ) {
42 		item = g_new0( AddrSelectItem, 1 );
43 		item->objectType = aio->type;
44 		item->addressItem = aio;
45 		item->uid = g_strdup( aio->uid );
46 		item->cacheID = NULL;
47 	}
48 	return item;
49 }
50 
51 /**
52  * Create a selection record from an address object (in tree node).
53  * \param obj Address object.
54  * \return Address select item.
55  */
addrselect_create_node(AddressObject * obj)56 AddrSelectItem *addrselect_create_node( AddressObject *obj ) {
57 	AddrSelectItem *item = NULL;
58 
59 	if( obj ) {
60 		item = g_new0( AddrSelectItem, 1 );
61 		item->objectType = addressbook_type2item( obj->type );
62 		item->addressItem = NULL;
63 		item->uid = NULL;
64 		item->cacheID = NULL;
65 	}
66 	return item;
67 }
68 
69 /**
70  * Create a copy of a selection record.
71  * Enter: item Address entry to copy.
72  * \return Address select item.
73  */
addrselect_item_copy(AddrSelectItem * item)74 AddrSelectItem *addrselect_item_copy( AddrSelectItem *item ) {
75 	AddrSelectItem *copy = NULL;
76 
77 	if( item ) {
78 		copy = g_new0( AddrSelectItem, 1 );
79 		copy->objectType = item->objectType;
80 		copy->addressItem = item->addressItem;
81 		copy->uid = g_strdup( item->uid );
82 		copy->cacheID = g_strdup( item->cacheID );
83 	}
84 	return copy;
85 }
86 
87 /**
88  * Free selection record.
89  * \return Address select item.
90  */
addrselect_item_free(AddrSelectItem * item)91 void addrselect_item_free( AddrSelectItem *item ) {
92 	if( item ) {
93 		g_free( item->uid );
94 		g_free( item->cacheID );
95 		item->objectType = ITEMTYPE_NONE;
96 		item->addressItem = NULL;
97 		item->uid = NULL;
98 		item->cacheID = NULL;
99 	}
100 	g_free( item );
101 }
102 
103 /**
104  * Print address selection item.
105  * \param item   Address select item.
106  * \param stream Output stream.
107  */
addrselect_item_print(AddrSelectItem * item,FILE * stream)108 void addrselect_item_print( AddrSelectItem *item, FILE *stream ) {
109 	fprintf( stream, "Select Record\n" );
110 	fprintf( stream, "obj type: %d\n", item->objectType );
111 	fprintf( stream, "     uid: %s\n", item->uid );
112 	fprintf( stream, "cache id: %s\n", item->cacheID );
113 	fprintf( stream, "---\n" );
114 }
115 
116 /**
117  * Create a new address selection object.
118  * \return Initialized object.
119  */
addrselect_list_create()120 AddrSelectList *addrselect_list_create() {
121 	AddrSelectList *asl;
122 
123 	asl = g_new0( AddrSelectList, 1 );
124 	asl->listSelect = NULL;
125 	return asl;
126 }
127 
128 /**
129  * Clear list of selection records.
130  * \param asl  List to process.
131  */
addrselect_list_clear(AddrSelectList * asl)132 void addrselect_list_clear( AddrSelectList *asl ) {
133 	GList *node;
134 
135 	cm_return_if_fail( asl != NULL );
136 	node = asl->listSelect;
137 	while( node ) {
138 		AddrSelectItem *item;
139 
140 		item = node->data;
141 		addrselect_item_free( item );
142 		node->data = NULL;
143 		node = g_list_next( node );
144 	}
145 	g_list_free( asl->listSelect );
146 	asl->listSelect = NULL;
147 }
148 
149 /**
150  * Free selection list.
151  * \param asl  List to free.
152  */
addrselect_list_free(AddrSelectList * asl)153 void addrselect_list_free( AddrSelectList *asl ) {
154 	cm_return_if_fail( asl != NULL );
155 
156 	addrselect_list_clear( asl );
157 	g_list_free( asl->listSelect );
158 	asl->listSelect = NULL;
159 	g_free( asl );
160 }
161 
162 /**
163  * Test whether selection is empty.
164  * \param  asl List to test.
165  * \return <i>TRUE</i> if list is empty.
166  */
addrselect_test_empty(AddrSelectList * asl)167 gboolean addrselect_test_empty( AddrSelectList *asl ) {
168 	cm_return_val_if_fail( asl != NULL, TRUE );
169 	return ( asl->listSelect == NULL );
170 }
171 
172 /**
173  * Return list of AddrSelectItem objects.
174  * \param  asl  List to process.
175  * \return List of selection items. The list should should be freed with
176  *         <code>g_list_free()</code> when done. Items contained in the
177  *         list should <b>not</b> be freed!!!
178  */
addrselect_get_list(AddrSelectList * asl)179 GList *addrselect_get_list( AddrSelectList *asl ) {
180 	GList *node, *list;
181 
182 	cm_return_val_if_fail(asl != NULL, NULL);
183 	list = NULL;
184 	node = asl->listSelect;
185 	while( node ) {
186 		list = g_list_append( list, node->data );
187 		node = g_list_next( node );
188 	}
189 	return list;
190 }
191 
192 /**
193  * Format address item.
194  * \param  aio Item.
195  * \return Formatted address.
196  */
addrselect_format_address(AddrItemObject * aio)197 static gchar *addrselect_format_address( AddrItemObject * aio ) {
198 	gchar *buf = NULL;
199 	gchar *name = NULL;
200 	gchar *address = NULL;
201 
202 	if( aio->type == ITEMTYPE_EMAIL ) {
203 		ItemPerson *person = NULL;
204 		ItemEMail *email = ( ItemEMail * ) aio;
205 
206 		person = ( ItemPerson * ) ADDRITEM_PARENT(email);
207 		if( email->address ) {
208 			if( ADDRITEM_NAME(email) ) {
209 				name = ADDRITEM_NAME(email);
210 				if( *name == '\0' ) {
211 					name = ADDRITEM_NAME(person);
212 				}
213 			}
214 			else if( ADDRITEM_NAME(person) ) {
215 				name = ADDRITEM_NAME(person);
216 			}
217 			else {
218 				buf = g_strdup( email->address );
219 			}
220 			address = email->address;
221 		}
222 	}
223 	else if( aio->type == ITEMTYPE_PERSON ) {
224 		ItemPerson *person = ( ItemPerson * ) aio;
225 		GList *node = person->listEMail;
226 
227 		name = ADDRITEM_NAME(person);
228 		if( node ) {
229 			ItemEMail *email = ( ItemEMail * ) node->data;
230 			address = email->address;
231 		}
232 	}
233 	if( address ) {
234 		if( name && name[0] != '\0' ) {
235 			if( strchr_with_skip_quote( name, '"', ',' ) )
236 				buf = g_strdup_printf( "\"%s\" <%s>", name, address );
237 			else
238 				buf = g_strdup_printf( "%s <%s>", name, address );
239 		}
240 		else {
241 			buf = g_strdup( address );
242 		}
243 	}
244 	return buf;
245 }
246 
247 /**
248  * Test whether specified object is in list.
249  * \param list List to check.
250  * \param aio  Object to test.
251  * \param item found, or <i>NULL</i> if not in list.
252  */
addrselect_list_find(GList * list,AddrItemObject * aio)253 static AddrSelectItem *addrselect_list_find( GList *list, AddrItemObject *aio ) {
254 	GList *node;
255 
256 	node = list;
257 	while( node ) {
258 		AddrSelectItem *item;
259 
260 		item = node->data;
261 		if( item->addressItem == aio ) return item;
262 		node = g_list_next( node );
263 	}
264 	return NULL;
265 }
266 
267 /**
268  * Add a single object into the list.
269  * \param asl     Address selection object.
270  * \param aio     Address object.
271  * \param cacheID Cache ID. Should be freed after calling function.
272  */
addrselect_list_add_obj(AddrSelectList * asl,AddrItemObject * aio,gchar * cacheID)273 void addrselect_list_add_obj( AddrSelectList *asl, AddrItemObject *aio, gchar *cacheID ) {
274 	AddrSelectItem *item;
275 
276 	cm_return_if_fail( asl != NULL );
277 	if( aio == NULL ) return;
278 
279 	/* Check whether object is in list */
280 	if( addrselect_list_find( asl->listSelect, aio ) ) return;
281 
282 	if( aio->type == ITEMTYPE_PERSON ||
283 	    aio->type == ITEMTYPE_EMAIL ||
284 	    aio->type == ITEMTYPE_GROUP ) {
285 		item = addrselect_create_item( aio );
286 		item->cacheID = g_strdup( cacheID );
287 		asl->listSelect = g_list_append( asl->listSelect, item );
288 	}
289 	/* addrselect_list_show( asl, stdout ); */
290 }
291 
292 /**
293  * Add a single item into the list.
294  * \param  asl     Address selection object.
295  * \param  item    Address select item.
296  * \param  cacheID Cache ID. Should be g_free() after calling function.
297  */
addrselect_list_add(AddrSelectList * asl,AddrSelectItem * item,gchar * cacheID)298 void addrselect_list_add( AddrSelectList *asl, AddrSelectItem *item, gchar *cacheID ) {
299 	cm_return_if_fail( asl != NULL );
300 	if( item == NULL ) return;
301 
302 	/* Check whether object is in list */
303 	if( g_list_find( asl->listSelect, item ) ) return;
304 
305 	item->cacheID = g_strdup( cacheID );
306 	asl->listSelect = g_list_append( asl->listSelect, item );
307 }
308 
309 /**
310  * Remove specified object from list.
311  * \param asl  Address selection object.
312  * \param aio  Object to remove.
313  */
addrselect_list_remove(AddrSelectList * asl,AddrItemObject * aio)314 void addrselect_list_remove( AddrSelectList *asl, AddrItemObject *aio ) {
315 	GList *node;
316 	AddrSelectItem *item;
317 
318 	cm_return_if_fail( asl != NULL );
319 	if( aio == NULL ) return;
320 	node = asl->listSelect;
321 	while( node ) {
322 		item = node->data;
323 		if( item->addressItem == aio ) {
324 			addrselect_item_free( item );
325 			node->data = NULL;
326 			asl->listSelect = g_list_remove_link( asl->listSelect, node );
327 			break;
328 		}
329 		node = g_list_next( node );
330 	}
331 	/* addrselect_list_show( list, stdout ); */
332 }
333 
334 /**
335  * Build list of formatted addresses.
336  * \param  asl List to process.
337  * \return List of addresses, formatted as character strings. List should be
338  *         freed when no longer required.
339  */
addrselect_build_list(AddrSelectList * asl)340 GList *addrselect_build_list( AddrSelectList *asl ) {
341 	GList *list;
342 	GList *node;
343 
344 	cm_return_val_if_fail(asl != NULL, NULL);
345 	list = NULL;
346 	node = asl->listSelect;
347 	while( node != NULL ) {
348 		AddrSelectItem *item;
349 		AddrItemObject *aio;
350 		gchar *addr;
351 
352 		item = node->data;
353 		aio = ( AddrItemObject * ) item->addressItem;
354 		if( aio ) {
355 			if( aio->type == ITEMTYPE_GROUP ) {
356 				ItemGroup *group = ( ItemGroup * ) aio;
357 				GList *node = group->listEMail;
358 				while( node ) {
359 					ItemEMail *email = node->data;
360 					addr = addrselect_format_address(
361 						( AddrItemObject * ) email );
362 					if( addr ) {
363 						list = g_list_append( list, addr );
364 					}
365 					node = g_list_next( node );
366 				}
367 			}
368 			else {
369 				addr = addrselect_format_address( aio );
370 				if( addr ) {
371 					list = g_list_append( list, addr );
372 				}
373 			}
374 		}
375 		node = g_list_next( node );
376 	}
377 	return list;
378 }
379 
380 /*
381 * End of Source.
382 */
383 
384 
385