home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap / getfilter.c < prev    next >
C/C++ Source or Header  |  2000-07-29  |  10KB  |  445 lines

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