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