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