sync with 0.8.11cvs16
[claws.git] / src / ldapserver.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2003 Match Grun
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 2 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Functions necessary to access LDAP servers.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #ifdef USE_LDAP
29
30 #include <glib.h>
31 #include <sys/time.h>
32 #include <string.h>
33 #include <ldap.h>
34 #include <lber.h>
35
36 #include "mgutils.h"
37 #include "addritem.h"
38 #include "addrcache.h"
39 #include "ldapctrl.h"
40 #include "ldapquery.h"
41 #include "ldapserver.h"
42 #include "utils.h"
43 #include "adbookbase.h"
44
45 /**
46  * Create new LDAP server interface object.
47  * \return Initialized LDAP server object.
48  */
49 LdapServer *ldapsvr_create() {
50         LdapServer *server;
51
52         server = g_new0( LdapServer, 1 );
53         server->type = ADBOOKTYPE_LDAP;
54         server->addressCache = addrcache_create();
55         server->retVal = MGU_SUCCESS;
56         server->control = ldapctl_create();
57         server->listQuery = NULL;
58         server->searchFlag = FALSE;
59         return server;
60 }
61
62 /**
63  * Return name of server.
64  * \param  server Server object.
65  * \return Name for server.
66  */
67 gchar *ldapsvr_get_name( LdapServer *server ) {
68         g_return_val_if_fail( server != NULL, NULL );
69         return addrcache_get_name( server->addressCache );
70 }
71
72 /**
73  * Specify name to be used.
74  * \param server Server object.
75  * \param value      Name for server.
76  */
77 void ldapsvr_set_name( LdapServer* server, const gchar *value ) {
78         g_return_if_fail( server != NULL );
79         addrcache_set_name( server->addressCache, value );
80 }
81
82 /**
83  * Refresh internal variables to force a file read.
84  * \param server Server object.
85  */
86 void ldapsvr_force_refresh( LdapServer *server ) {
87         addrcache_refresh( server->addressCache );
88 }
89
90 /**
91  * Return status/error code.
92  * \param  server Server object.
93  * \return Status/error code.
94  */
95 gint ldapsvr_get_status( LdapServer *server ) {
96         g_return_val_if_fail( server != NULL, -1 );
97         return server->retVal;
98 }
99
100 /**
101  * Return reference to root level folder.
102  * \param  server Server object.
103  * \return Root level folder.
104  */
105 ItemFolder *ldapsvr_get_root_folder( LdapServer *server ) {
106         g_return_val_if_fail( server != NULL, NULL );
107         /*
108         printf( "ldapsvr_get_root_folder/start\n" );
109         ldapsvr_print_data( server, stdout );
110         printf( "ldapsvr_get_root_folder/done\n" );
111         */
112         return addrcache_get_root_folder( server->addressCache );
113 }
114
115 /**
116  * Test whether server data has been accessed.
117  * \param  server Server object.
118  * \return <i>TRUE</i> if data was accessed.
119  */
120 gboolean ldapsvr_get_accessed( LdapServer *server ) {
121         g_return_val_if_fail( server != NULL, FALSE );
122         return server->addressCache->accessFlag;
123 }
124
125 /**
126  * Specify that server's data whas beed accessed.
127  * \param server Server object.
128  * \param value      Value for flag.
129  */
130 void ldapsvr_set_accessed( LdapServer *server, const gboolean value ) {
131         g_return_if_fail( server != NULL );
132         server->addressCache->accessFlag = value;
133 }
134
135 /**
136  * Test whether server data has been modified.
137  * \param  server Server object.
138  * \return <i>TRUE</i> if data was modified.
139  */
140 gboolean ldapsvr_get_modified( LdapServer *server ) {
141         g_return_val_if_fail( server != NULL, FALSE );
142         return server->addressCache->modified;
143 }
144
145 /**
146  * Specify modify flag.
147  * \param server Server object.
148  * \param value      Value for flag.
149  */
150 void ldapsvr_set_modified( LdapServer *server, const gboolean value ) {
151         g_return_if_fail( server != NULL );
152         server->addressCache->modified = value;
153 }
154
155 /**
156  * Test whether data was read from server.
157  * \param server Server object.
158  * \return <i>TRUE</i> if data was read.
159  */
160 gboolean ldapsvr_get_read_flag( LdapServer *server ) {
161         g_return_val_if_fail( server != NULL, FALSE );
162         return server->addressCache->dataRead;
163 }
164
165 /**
166  * Test whether server is to be used for dynamic searches.
167  * \param server Server object.
168  * \return <i>TRUE</i> if server is used for dynamic searches.
169  */
170 gboolean ldapsvr_get_search_flag( LdapServer *server ) {
171         g_return_val_if_fail( server != NULL, FALSE );
172         return server->searchFlag;
173 }
174
175 /**
176  * Specify that server is to be used for dynamic searches.
177  * \param server Server object.
178  * \param value      Name for server.
179  */
180 void ldapsvr_set_search_flag( LdapServer *server, const gboolean value ) {
181         g_return_if_fail( server != NULL );
182         server->searchFlag = value;
183 }
184
185 /**
186  * Specify the reference to control data that will be used for the query. The calling
187  * module should be responsible for creating and destroying this control object.
188  * \param server Server object.
189  * \param ctl    Control data.
190  */
191 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl ) {
192         g_return_if_fail( server != NULL );
193         addrcache_refresh( server->addressCache );
194         server->control = ctl;
195 }
196
197 /**
198  * Release LDAP control object.
199  * \param server Server object.
200  */
201 static void ldapsvr_release_control( LdapServer *server ) {
202         g_return_if_fail( server != NULL );
203         ldapctl_free( server->control );
204         server->control = NULL;
205 }
206
207 /**
208  * Free up LDAP server interface object by releasing internal memory.
209  * \param server Server object.
210  */
211 void ldapsvr_free( LdapServer *server ) {
212         g_return_if_fail( server != NULL );
213
214         /* Stop and cancel any queries that may be active */
215         ldapsvr_stop_all_query( server );
216         ldapsvr_cancel_all_query( server );
217
218         /* Clear cache */
219         addrcache_clear( server->addressCache );
220         addrcache_free( server->addressCache );
221
222         /* Free LDAP control block */
223         ldapctl_free( server->control );
224         server->control = NULL;
225
226         /* Clear pointers */
227         server->type = ADBOOKTYPE_NONE;
228         server->addressCache = NULL;
229         server->retVal = MGU_SUCCESS;
230         server->listQuery = NULL;
231         server->searchFlag = FALSE;
232
233         /* Now release LDAP object */
234         g_free( server );
235 }
236
237 /**
238  * Display object to specified stream.
239  * \param server Server object.
240  * \param stream     Output stream.
241  */
242 void ldapsvr_print_data( LdapServer *server, FILE *stream ) {
243         GList *node;
244         gint  i;
245
246         g_return_if_fail( server != NULL );
247
248         fprintf( stream, "LdapServer:\n" );
249         fprintf( stream, "  ret val: %d\n", server->retVal );
250         fprintf( stream, "srch flag: %s\n",
251                         server->searchFlag ? "yes" : "no" );
252         if( server->control ) {
253                 ldapctl_print( server->control, stream );
254         }
255         else {
256                 fprintf( stream, "  control: NULL\n" );
257         }
258         addrcache_print( server->addressCache, stream );
259         addritem_print_item_folder( server->addressCache->rootFolder, stream );
260
261         /* Dump queries */
262         i = 1;
263         node = server->listQuery;
264         while( node ) {
265                 LdapQuery *qry = node->data;
266                 fprintf( stream, "    query: %2d : %s\n", i, qry->queryName );
267                 i++;
268                 node = g_list_next( node );
269         }
270 }
271
272 /**
273  * Add query to server.
274  * \param server Server object.
275  * \param qry    Query object.
276  */
277 void ldapsvr_add_query( LdapServer *server, LdapQuery *qry ) {
278         g_return_if_fail( server != NULL );
279         g_return_if_fail( qry != NULL );
280
281         server->listQuery = g_list_append( server->listQuery, qry );
282         qry->server = server;
283 }
284
285 /**
286  * Free all queries.
287  * \param server Server object.
288  */
289 void ldapsvr_free_all_query( LdapServer *server ) {
290         GList *node;    
291         g_return_if_fail( server != NULL );
292
293         node = server->listQuery;
294         while( node ) {
295                 LdapQuery *qry = node->data;
296                 ldapqry_free( qry );
297                 node->data = NULL;
298                 node = g_list_next( node );
299         }
300         g_list_free( server->listQuery );
301         server->listQuery = NULL;
302 }
303
304 /**
305  * Return link list of persons.
306  * \param server Server object.
307  * \return List of persons.
308  */
309 GList *ldapsvr_get_list_person( LdapServer *server ) {
310         g_return_val_if_fail( server != NULL, NULL );
311         return addrcache_get_list_person( server->addressCache );
312 }
313
314 /**
315  * Return link list of folders. There are no "real" folders that are returned
316  * from the server.
317  * \param  server Server object.
318  * \return List of folders.
319  */
320 GList *ldapsvr_get_list_folder( LdapServer *server ) {
321         g_return_val_if_fail( server != NULL, NULL );
322         /* return addrcache_get_list_folder( server->addressCache ); */
323         return NULL;
324 }
325
326 /**
327  * Execute specified query.
328  * \param server LDAP server.
329  * \param qry    LDAP query.
330  */
331 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry ) {
332         LdapControl *ctlCopy;
333
334         g_return_if_fail( server != NULL );
335         g_return_if_fail( qry != NULL );
336
337         /* Copy server's control data to the query */
338         ctlCopy = ldapctl_create();
339         ldapctl_copy( server->control, ctlCopy );
340         ldapqry_set_control( qry, ctlCopy );
341         ldapqry_initialize();
342
343         /* Perform query */     
344         printf( "ldapsvr_execute_query::reading with thread...\n" );
345         if( ldapqry_check_search( qry ) ) {
346                 ldapqry_read_data_th( qry );
347                 if( qry->retVal == LDAPRC_SUCCESS ) {
348                         printf( "ldapsvr_execute_query::SUCCESS with thread...\n" );
349                 }
350         }
351         printf( "ldapsvr_execute_query... terminated\n" );
352 }
353
354 /**
355  * Stop all queries for specified ID.
356  * \param server Server object.
357  * \param queryID    Query ID to stop.
358  */
359 void ldapsvr_stop_query_id( LdapServer *server, const gint queryID ) {
360         GList *node;    
361         g_return_if_fail( server != NULL );
362
363         node = server->listQuery;
364         while( node ) {
365                 LdapQuery *qry = node->data;
366                 if( qry->queryID == queryID ) {
367                         /* Notify thread to stop */
368                         ldapqry_set_stop_flag( qry, TRUE );
369                 }
370                 node = g_list_next( node );
371         }
372 }
373
374 /**
375  * Stop all queries by notifying each thread to stop.
376  * \param server Server object.
377  */
378 void ldapsvr_stop_all_query( LdapServer *server ) {
379         GList *node;    
380         g_return_if_fail( server != NULL );
381
382         node = server->listQuery;
383         while( node ) {
384                 LdapQuery *qry = node->data;
385                 ldapqry_set_stop_flag( qry, TRUE );
386                 node = g_list_next( node );
387         }
388 }
389
390 /**
391  * Cancel all query threads for server.
392  * \param server Server object.
393  */
394 void ldapsvr_cancel_all_query( LdapServer *server ) {
395         GList *node;    
396         g_return_if_fail( server != NULL );
397
398         node = server->listQuery;
399         while( node ) {
400                 LdapQuery *qry = node->data;
401                 /* Notify thread to stop */
402                 ldapqry_set_stop_flag( qry, TRUE );
403                 /* Now cancel thread */
404                 ldapqry_cancel( qry );
405                 node = g_list_next( node );
406         }
407 }
408
409 /**
410  * Search most recent query for specified search term. The most recent
411  * completed query is returned. If no completed query is found, the most recent
412  * incomplete is returned.
413  * \param server LdapServer.
414  * \param searchTerm Search term to locate.
415  * \return Query object, or <i>NULL</i> if none found.
416  */
417 LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm )
418 {
419         LdapQuery *incomplete = NULL;
420         GList *node;    
421         g_return_if_fail( server != NULL );
422
423         node = server->listQuery;
424         node = g_list_last( node );
425         /* Search backwards for query */
426         while( node ) {
427                 LdapQuery *qry = node->data;
428                 if( g_strcasecmp( qry->searchValue, searchTerm ) == 0 ) {
429                         if( qry->agedFlag ) continue;
430                         if( qry->completed ) {
431                                 /* Found */
432                                 return qry;
433                         }
434                         if( ! incomplete ) {
435                                 incomplete = qry;
436                         }
437                 }
438                 node = g_list_previous( node );
439         }
440         return incomplete;
441 }
442
443 /**
444  * Retire aged queries.
445  * \param server LdapServer.
446  */
447 void ldapsvr_retire_query( LdapServer *server ) {
448         GList *node;
449         GList *listDelete;
450         GList *listQuery;
451         gint maxAge;
452         LdapControl *ctl;
453
454         g_return_if_fail( server != NULL );
455         ctl = server->control;
456         maxAge = ctl->maxQueryAge;
457
458         /* Identify queries to age and move to deletion list */
459         listDelete = NULL;
460         node = server->listQuery;
461         while( node ) {
462                 LdapQuery *qry = node->data;
463
464                 ldapqry_age( qry, maxAge );
465                 if( qry->agedFlag ) {
466                         /* Delete folder associated with query */
467                         ldapqry_delete_folder( qry );
468                         listDelete = g_list_append( listDelete, qry );
469                 }
470                 node = g_list_next( node );
471         }
472
473         /* Delete queries */
474         listQuery = server->listQuery;
475         node = listDelete;
476         while( node ) {
477                 LdapQuery *qry = node->data;
478
479                 listQuery = g_list_remove( listQuery, qry );
480                 ldapqry_free( qry );
481                 node->data = NULL;
482                 node = g_list_next( node );
483         }
484         server->listQuery = listQuery;
485
486         /* Free up deletion list */
487         g_list_free( listDelete );
488 }
489
490 #endif  /* USE_LDAP */
491
492 /*
493  * End of Source.
494  */
495