]> git.sur5r.net Git - openldap/blob - libraries/libldap/getfilter.c
Merged LDAPworldCurrent (P1-10,13,15,16,19-22)
[openldap] / libraries / libldap / getfilter.c
1 /*
2  *  Copyright (c) 1993 Regents of the University of Michigan.
3  *  All rights reserved.
4  *
5  *  getfilter.c -- optional add-on to libldap
6  */
7
8 #ifndef lint 
9 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
10 #endif
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #if defined(NeXT)
16 #include <regex.h>
17 #endif
18 #ifdef MACOS
19 #include <stdlib.h>
20 #include "macos.h"
21 #else /* MACOS */
22 #ifdef DOS
23 #include <malloc.h>
24 #include "msdos.h"
25 #else /* DOS */
26 #include <sys/types.h>
27 #include <sys/file.h>
28 #include <stdlib.h>
29 #include <sys/errno.h>
30 #ifndef VMS
31 #include <unistd.h>
32 #endif /* VMS */
33 #endif /* DOS */
34 #endif /* MACOS */
35
36 #include "lber.h"
37 #include "ldap.h"
38 #include "regex.h"
39
40 #ifdef NEEDPROTOS
41 static int break_into_words( char *str, char *delims, char ***wordsp );
42 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
43 void free_strarray( char **sap );
44 #else /* NEEDPROTOS */
45 static int break_into_words();
46 int next_line_tokens();
47 void free_strarray();
48 #endif /* NEEDPROTOS */
49
50 #if !defined( MACOS ) && !defined( DOS )
51 extern int      errno;
52 extern char     *re_comp();
53 #endif
54
55 #define FILT_MAX_LINE_LEN       1024
56
57 LDAPFiltDesc *
58 ldap_init_getfilter( char *fname )
59 {
60     FILE                *fp;
61     char                *buf;
62     long                rlen, len;
63     int                 eof;
64     LDAPFiltDesc        *lfdp;
65
66     if (( fp = fopen( fname, "r" )) == NULL ) {
67         return( NULL );
68     }
69
70     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {     /* move to end to get len */
71         fclose( fp );
72         return( NULL );
73     }
74
75     len = ftell( fp );
76
77     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {     /* back to start of file */
78         fclose( fp );
79         return( NULL );
80     }
81
82     if (( buf = malloc( (size_t)len )) == NULL ) {
83         fclose( fp );
84         return( NULL );
85     }
86
87     rlen = fread( buf, 1, (size_t)len, fp );
88     eof = feof( fp );
89     fclose( fp );
90
91     if ( rlen != len && !eof ) {        /* error:  didn't get the whole file */
92         free( buf );
93         return( NULL );
94     }
95
96
97     lfdp = ldap_init_getfilter_buf( buf, rlen );
98     free( buf );
99
100     return( lfdp );
101 }
102
103
104 LDAPFiltDesc *
105 ldap_init_getfilter_buf( char *buf, long buflen )
106 {
107     LDAPFiltDesc        *lfdp;
108     LDAPFiltList        *flp, *nextflp;
109     LDAPFiltInfo        *fip, *nextfip;
110     char                *tag, **tok;
111     int                 tokcnt, i;
112
113     if (( lfdp = (LDAPFiltDesc *)calloc( 1, sizeof( LDAPFiltDesc))) == NULL ) {
114         return( NULL );
115     }
116
117     flp = nextflp = NULL;
118     fip = NULL;
119     tag = NULL;
120
121     while ( buflen > 0 && ( tokcnt = next_line_tokens( &buf, &buflen, &tok ))
122             > 0 ) {
123
124         switch( tokcnt ) {
125         case 1:         /* tag line */
126             if ( tag != NULL ) {
127                 free( tag );
128             }
129             tag = tok[ 0 ];
130             free( tok );
131             break;
132         case 4:
133         case 5:         /* start of filter info. list */
134             if (( nextflp = (LDAPFiltList *)calloc( 1, sizeof( LDAPFiltList )))
135                     == NULL ) {
136                 ldap_getfilter_free( lfdp );
137                 return( NULL );
138             }
139             nextflp->lfl_tag = strdup( tag );
140             nextflp->lfl_pattern = tok[ 0 ];
141             if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
142 #ifndef NO_USERINTERFACE
143                 ldap_getfilter_free( lfdp );
144                 fprintf( stderr, "bad regular expresssion %s\n",
145                         nextflp->lfl_pattern );
146 #if !defined( MACOS ) && !defined( DOS )
147                 errno = EINVAL;
148 #endif
149 #endif /* NO_USERINTERFACE */
150                 free_strarray( tok );
151                 return( NULL );
152             }
153                 
154             nextflp->lfl_delims = tok[ 1 ];
155             nextflp->lfl_ilist = NULL;
156             nextflp->lfl_next = NULL;
157             if ( flp == NULL ) {        /* first one */
158                 lfdp->lfd_filtlist = nextflp;
159             } else {
160                 flp->lfl_next = nextflp;
161             }
162             flp = nextflp;
163             fip = NULL;
164             for ( i = 2; i < 5; ++i ) {
165                 tok[ i - 2 ] = tok[ i ];
166             }
167             /* fall through */
168
169         case 2:
170         case 3:         /* filter, desc, and optional search scope */
171             if ( nextflp != NULL ) { /* add to info list */
172                 if (( nextfip = (LDAPFiltInfo *)calloc( 1,
173                         sizeof( LDAPFiltInfo ))) == NULL ) {
174                     ldap_getfilter_free( lfdp );
175                     free_strarray( tok );
176                     return( NULL );
177                 }
178                 if ( fip == NULL ) {    /* first one */
179                     nextflp->lfl_ilist = nextfip;
180                 } else {
181                     fip->lfi_next = nextfip;
182                 }
183                 fip = nextfip;
184                 nextfip->lfi_next = NULL;
185                 nextfip->lfi_filter = tok[ 0 ];
186                 nextfip->lfi_desc = tok[ 1 ];
187                 if ( tok[ 2 ] != NULL ) {
188                     if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
189                         nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
190                     } else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
191                         nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
192                     } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
193                         nextfip->lfi_scope = LDAP_SCOPE_BASE;
194                     } else {
195                         free_strarray( tok );
196                         ldap_getfilter_free( lfdp );
197 #if !defined( MACOS ) && !defined( DOS )
198                         errno = EINVAL;
199 #endif
200                         return( NULL );
201                     }
202                     free( tok[ 2 ] );
203                     tok[ 2 ] = NULL;
204                 } else {
205                     nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;    /* default */
206                 }
207                 nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
208                         strchr( tok[ 0 ], '~' ) == NULL );
209                 free( tok );
210             }
211             break;
212
213         default:
214             free_strarray( tok );
215             ldap_getfilter_free( lfdp );
216 #if !defined( MACOS ) && !defined( DOS )
217             errno = EINVAL;
218 #endif
219             return( NULL );
220         }
221     }
222
223     if ( tag != NULL ) {
224         free( tag );
225     }
226
227     return( lfdp );
228 }
229
230
231 void
232 ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
233 {
234     if ( lfdp->lfd_filtprefix != NULL ) {
235         free( lfdp->lfd_filtprefix );
236     }
237     lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : strdup( prefix );
238
239     if ( lfdp->lfd_filtsuffix != NULL ) {
240         free( lfdp->lfd_filtsuffix );
241     }
242     lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : strdup( suffix );
243 }
244
245
246 LDAPFiltInfo *
247 ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
248 {
249     LDAPFiltList        *flp;
250
251     if ( lfdp->lfd_curvalcopy != NULL ) {
252         free( lfdp->lfd_curvalcopy );
253         free( lfdp->lfd_curvalwords );
254     }
255
256     lfdp->lfd_curval = value;
257     lfdp->lfd_curfip = NULL;
258
259     for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
260         if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
261                 && re_comp( flp->lfl_pattern ) == NULL
262                 && re_exec( lfdp->lfd_curval ) == 1 ) {
263             lfdp->lfd_curfip = flp->lfl_ilist;
264             break;
265         }
266     }
267
268     if ( lfdp->lfd_curfip == NULL ) {
269         return( NULL );
270     }
271
272     if (( lfdp->lfd_curvalcopy = strdup( value )) == NULL ) {
273         return( NULL );
274     }
275
276     if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
277                 &lfdp->lfd_curvalwords ) < 0 ) {
278         free( lfdp->lfd_curvalcopy );
279         lfdp->lfd_curvalcopy = NULL;
280         return( NULL );
281     }
282
283     return( ldap_getnextfilter( lfdp ));
284 }
285
286
287 LDAPFiltInfo *
288 ldap_getnextfilter( LDAPFiltDesc *lfdp )
289 {
290     LDAPFiltInfo        *fip;
291
292     fip = lfdp->lfd_curfip;
293
294     if ( fip == NULL ) {
295         return( NULL );
296     }
297
298     lfdp->lfd_curfip = fip->lfi_next;
299
300     ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter,
301             lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
302             lfdp->lfd_curval, lfdp->lfd_curvalwords );
303     lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
304     lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
305     lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
306     lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
307
308     return( &lfdp->lfd_retfi );
309 }
310
311
312 void
313 ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern,
314         char *prefix, char *suffix, char *attr, char *value, char **valwords )
315 {
316         char    *p, *f;
317         size_t  slen;
318         int     i, wordcount, wordnum, endwordnum;
319         
320         if ( valwords == NULL ) {
321             wordcount = 0;
322         } else {
323             for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
324                 ;
325             }
326         }
327
328         f = filtbuf;
329
330         if ( prefix != NULL ) {
331             strcpy( f, prefix );
332             f += strlen( prefix );
333         }
334
335         for ( p = pattern; *p != '\0'; ++p ) {
336             if ( *p == '%' ) {
337                 ++p;
338                 if ( *p == 'v' ) {
339                     if ( isdigit( *(p+1))) {
340                         ++p;
341                         wordnum = *p - '1';
342                         if ( *(p+1) == '-' ) {
343                             ++p;
344                             if ( isdigit( *(p+1))) {
345                                 ++p;
346                                 endwordnum = *p - '1';  /* e.g., "%v2-4" */
347                                 if ( endwordnum > wordcount - 1 ) {
348                                     endwordnum = wordcount - 1;
349                                 }
350                             } else {
351                                 endwordnum = wordcount - 1;  /* e.g., "%v2-" */
352                             }
353                         } else {
354                             endwordnum = wordnum;       /* e.g., "%v2" */
355                         }
356
357                         if ( wordcount > 0 ) {
358                             for ( i = wordnum; i <= endwordnum; ++i ) {
359                                 if ( i > wordnum ) {  /* add blank btw words */
360                                     *f++ = ' ';
361                                 }
362                                 slen = strlen( valwords[ i ] );
363                                 SAFEMEMCPY( f, valwords[ i ], slen );
364                                 f += slen;
365                             }
366                         }
367                     } else if ( *(p+1) == '$' ) {
368                         ++p;
369                         if ( wordcount > 0 ) {
370                             wordnum = wordcount - 1;
371                             slen = strlen( valwords[ wordnum ] );
372                             SAFEMEMCPY( f, valwords[ wordnum ], slen );
373                             f += slen;
374                         }
375                     } else if ( value != NULL ) {
376                         slen = strlen( value );
377                         SAFEMEMCPY( f, value, slen );
378                         f += slen;
379                     }
380                 } else if ( *p == 'a' && attr != NULL ) {
381                     slen = strlen( attr );
382                     SAFEMEMCPY( f, attr, slen );
383                     f += slen;
384                 } else {
385                     *f++ = *p;
386                 }
387             } else {
388                 *f++ = *p;
389             }
390                 
391             if ( f - filtbuf > buflen ) {
392                 /* sanity check */
393                 --f;
394                 break;
395             }
396         }
397
398         if ( suffix != NULL && ( f - filtbuf ) < buflen ) {
399             strcpy( f, suffix );
400         } else {
401             *f = '\0';
402         }
403 }
404
405
406 static int
407 break_into_words( char *str, char *delims, char ***wordsp )
408 {
409     char        *word, **words;
410     int         count;
411         
412     if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
413         return( -1 );
414     }
415     count = 0;
416     words[ count ] = NULL;
417
418     word = strtok( str, delims );
419     while ( word != NULL ) {
420         if (( words = (char **)realloc( words,
421                 ( count + 2 ) * sizeof( char * ))) == NULL ) {
422             return( -1 );
423         }
424
425         words[ count ] = word;
426         words[ ++count ] = NULL;
427         word = strtok( NULL, delims );
428     }
429         
430     *wordsp = words;
431     return( count );
432 }