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