]> git.sur5r.net Git - openldap/blob - clients/rcpt500/query.c
Protoized, moved extern definitions to .h files, fixed related bugs.
[openldap] / clients / rcpt500 / query.c
1 /*
2  * query.c: for rcpt500 (X.500 email query responder)
3  *
4  * 18 June 1992 by Mark C Smith
5  * Copyright (c) 1992 The Regents of The University of Michigan
6  * All Rights Reserved
7  */
8
9 #include "portable.h"
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14
15 #include <ac/string.h>
16 #include <ac/syslog.h>
17 #include <ac/time.h>
18 extern int strcasecmp(const char *, const char *);
19
20 #include "lber.h"
21 #include "ldap.h"
22
23 #include "disptmpl.h"
24
25 #include "rcpt500.h"
26 #include "ldapconfig.h"
27
28 static char buf[ MAXSIZE ];
29 static char *errpreface = "Your query failed: ";
30
31 static void close_ldap(LDAP *ld);
32 static void append_entry_list(char *rep, char *qu, LDAP *ld, LDAPMessage *msg);
33 static int  append_text(void *reply, char *text, int len);
34 static int  do_read (LDAP *ld, char *dn, char *rep, struct ldap_disptmpl *tmp);
35 static void report_ldap_err (LDAP *ldp, char *reply);
36 static void remove_trailing_space (char *s);
37
38
39 int
40 query_cmd( struct msginfo *msgp, char *reply )
41 {
42     LDAP                        *ldp;
43     LDAPMessage                 *ldmsgp, *entry;
44     char                        *s, *dn;
45     int                         matches, rc, ld_errno, ufn;
46     LDAPFiltDesc                *lfdp;
47     LDAPFiltInfo                *lfi;
48     struct ldap_disptmpl        *tmpllist = NULL;
49     static char *attrs[] = { "cn", "title",
50 #ifdef RCPT500_SORT_ATTR
51                         RCPT500_SORT_ATTR,
52 #endif
53                         NULL };
54
55     ufn = 0;
56
57     if ( msgp->msg_arg == NULL ) {
58         return( help_cmd( msgp, reply ));
59     }
60
61     remove_trailing_space( msgp->msg_arg );
62     if ( *msgp->msg_arg == '\0' ) {
63         return( help_cmd( msgp, reply ));
64     }
65
66     if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
67         strcat( reply, errpreface );
68         strcat( reply, "filter file configuration error.  Try again later." );
69         return( 0 );
70     }
71
72     /*
73      * open connection to LDAP server and bind as dapuser
74      */
75 #ifdef LDAP_CONNECTIONLESS
76     if ( do_cldap )
77         ldp = cldap_open( ldaphost, ldapport );
78     else
79 #endif /* LDAP_CONNECTIONLESS */
80         ldp = ldap_open( ldaphost, ldapport );
81
82     if ( ldp == NULL ) {
83         strcat( reply, errpreface );
84         strcat( reply, "X.500 service unavailable.  Try again later." );
85         ldap_getfilter_free( lfdp );
86         return( 0 );
87     }
88
89 #ifdef LDAP_CONNECTIONLESS
90     if ( !do_cldap )
91 #endif /* LDAP_CONNECTIONLESS */
92         if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
93             report_ldap_err( ldp, reply );
94             close_ldap( ldp );
95             ldap_getfilter_free( lfdp );
96             return( 0 );
97         }
98
99     /*
100      * set options for search and build filter
101      */
102         ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
103         ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
104
105     matches = 0;
106
107 #ifdef RCPT500_UFN
108 #ifdef LDAP_CONNECTIONLESS
109     if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
110 #else /* LDAP_CONNECTIONLESS */
111     if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
112 #endif /* LDAP_CONNECTIONLESS */
113         struct timeval  tv;
114
115         ldap_ufn_setprefix( ldp, searchbase );
116         if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
117                 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
118                 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
119             report_ldap_err( ldp, reply );
120             close_ldap( ldp );
121             ldap_getfilter_free( lfdp );
122             return( 0 );
123         }
124         matches = ldap_count_entries( ldp, ldmsgp );
125         ufn = 1;
126     } else {
127 #endif /* RCPT500_UFN */
128     
129         for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
130                 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
131 #ifdef LDAP_CONNECTIONLESS
132             if ( do_cldap )
133                 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
134                         lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
135             else 
136 #endif /* LDAP_CONNECTIONLESS */
137                 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
138                         lfi->lfi_filter, attrs, 0, &ldmsgp );
139
140             if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
141                     && rc != LDAP_TIMELIMIT_EXCEEDED ) {
142                 report_ldap_err( ldp, reply );
143                 close_ldap( ldp );
144                 ldap_getfilter_free( lfdp );
145                 return( 0 );
146             }
147
148             if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
149                 break;
150             }
151
152             if ( ldmsgp != NULL ) {
153                 ldap_msgfree( ldmsgp );
154             }
155         }
156 #ifdef RCPT500_UFN
157     }
158 #endif /* RCPT500_UFN */
159
160     if ( matches == 0 ) {
161         sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
162         strcat( reply, buf );
163         close_ldap( ldp );
164         ldap_getfilter_free( lfdp );
165         return( 0 );
166     }
167
168         ld_errno = 0;
169         ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
170
171     if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
172             || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
173         strcat( reply, "(Partial results only - a limit was exceeded)\n" );
174     }
175
176     if ( matches <= RCPT500_LISTLIMIT ) {
177         sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
178                 ufn ? "UFN" : lfi->lfi_desc,
179                 ( matches > 1 ) ? "es" : "", msgp->msg_arg );
180         strcat( reply, buf );
181
182         if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
183             sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
184                 errpreface, templatefile, rc );
185             strcat( reply, buf );
186         }
187
188         for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
189             dn = ldap_get_dn( ldp, entry );
190             if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
191                 report_ldap_err( ldp, reply );
192             }
193             free( dn );
194             if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
195                 strcat( reply, "\n-------\n\n" );
196             }
197         }
198
199         if ( tmpllist != NULL ) {
200             ldap_free_templates( tmpllist );
201         }
202         ldap_msgfree( ldmsgp );
203
204     } else {
205         sprintf( buf, "%d %s matches were found for '%s':\n",
206                 matches, ufn ? "UFN" : lfi->lfi_desc, msgp->msg_arg );
207         strcat( reply, buf );
208         append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
209         ldap_msgfree( ldmsgp );
210     }
211
212     close_ldap( ldp );
213     ldap_getfilter_free( lfdp );
214     return( 0 );
215 }
216
217
218 static void
219 close_ldap( LDAP *ld )
220 {
221 #ifdef LDAP_CONNECTIONLESS
222     if ( do_cldap )
223         cldap_close( ld );
224     else
225 #endif /* LDAP_CONNECTIONLESS */
226         ldap_unbind( ld );
227 }
228
229
230 static void
231 append_entry_list( char *reply, char *query, LDAP *ldp, LDAPMessage *ldmsgp )
232 {
233     LDAPMessage *e;
234     char        *dn, *rdn, *s, **title;
235     int         free_rdn = 0;
236
237 #ifdef RCPT500_SORT_ATTR
238     ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
239 #endif
240
241     for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
242                 e = ldap_next_entry( ldp, e )) {
243         dn = ldap_get_dn( ldp, e );
244         if (( s = strchr( dn, ',' )) != NULL ) {
245             *s = '\0';
246         }
247         if (( s = strchr( dn, '=' )) == NULL ) {
248             rdn = dn;
249         } else {
250             rdn = s + 1;
251         }
252
253 #ifdef UOFM
254         /*
255          * if this entry's rdn is an exact match for the thing looked up, we
256          * return the CN that has a digit after it, so that the user is
257          * returned something guaranteed to yield exactly one match if they
258          * pick it from the list and query it
259          */
260
261         if ( strcasecmp( rdn, query ) == 0 ) {
262             char        **cn;
263             int         i;
264
265             if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
266                 for ( i = 0; cn[i] != NULL; i++ ) {
267                     if ( isdigit( *( cn[i] + strlen( cn[i] ) - 1 ))) {
268                         rdn = strdup( cn[i] );
269                         free_rdn = 1;
270                         break;
271                     }
272                 }
273                 ldap_value_free( cn );
274             }
275         }
276 #endif /* UOFM */
277
278         title = ldap_get_values( ldp, e, "title" );
279         sprintf( buf, "  %-20s    %s\n", rdn, title ? title[0] : "" );
280         strcat( reply, buf );
281         if ( title != NULL ) {
282             ldap_value_free( title );
283         }
284         free( dn );
285         if ( free_rdn ) {
286             free( rdn );
287         }
288     }
289 }
290
291
292 static int
293 append_text( void *reply, char *text, int len )
294 {
295     strcat( (char *) reply, text );
296     return( len );
297 }
298     
299
300 static int
301 do_read( LDAP *ldp, char *dn, char *reply, struct ldap_disptmpl *tmpll )
302 {
303     int                         rc;
304     static char *maildefvals[] = { "None registered in this service", NULL };
305     static char *defattrs[] = { "mail", NULL };
306     static char **defvals[] = { maildefvals, NULL };
307
308
309     rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
310             defattrs, defvals, append_text, (void *)reply, "\n",
311             rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
312
313     return( rc );
314 }
315
316
317 static void
318 report_ldap_err( LDAP *ldp, char *reply )
319 {
320         int ld_errno = 0;
321         ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
322
323     strcat( reply, errpreface );
324     strcat( reply, ldap_err2string( ld_errno ));
325     strcat( reply, "\n" );
326 }
327
328
329 static void
330 remove_trailing_space( char *s )
331 {
332     char        *p = s + strlen( s ) - 1;
333
334     while ( isspace( *p ) && p > s ) {
335         --p;
336     }
337     *(++p) = '\0';
338 }