mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-09-19 19:50:18 +02:00
552 lines
14 KiB
C
552 lines
14 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
* March 31, 1998.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998-1999
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
/*
|
|
* Copyright (c) 1993 Regents of the University of Michigan.
|
|
* All rights reserved.
|
|
*/
|
|
/*
|
|
* getfilter.c -- optional add-on to libldap
|
|
*/
|
|
|
|
#if 0
|
|
#ifndef lint
|
|
static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
|
|
#endif
|
|
#endif
|
|
|
|
#include "ldap-int.h"
|
|
#include "regex.h"
|
|
#include <stdio.h> /* sprintf */
|
|
|
|
static int break_into_words( char *str, char *delims, char ***wordsp );
|
|
int nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp );
|
|
void nsldapi_free_strarray( char **sap );
|
|
|
|
#if !defined( macintosh ) && !defined( DOS )
|
|
extern char * LDAP_CALL re_comp();
|
|
#endif
|
|
|
|
#define FILT_MAX_LINE_LEN 1024
|
|
|
|
LDAPFiltDesc *
|
|
LDAP_CALL
|
|
ldap_init_getfilter( char *fname )
|
|
{
|
|
FILE *fp;
|
|
char *buf;
|
|
long rlen, len;
|
|
int eof;
|
|
LDAPFiltDesc *lfdp;
|
|
|
|
if (( fp = fopen( fname, "r" )) == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
|
|
fclose( fp );
|
|
return( NULL );
|
|
}
|
|
|
|
len = ftell( fp );
|
|
|
|
if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
|
|
fclose( fp );
|
|
return( NULL );
|
|
}
|
|
|
|
if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) {
|
|
fclose( fp );
|
|
return( NULL );
|
|
}
|
|
|
|
rlen = fread( buf, 1, (size_t)len, fp );
|
|
eof = feof( fp );
|
|
fclose( fp );
|
|
|
|
if ( rlen != len && !eof ) { /* error: didn't get the whole file */
|
|
NSLDAPI_FREE( buf );
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
lfdp = ldap_init_getfilter_buf( buf, rlen );
|
|
NSLDAPI_FREE( buf );
|
|
|
|
return( lfdp );
|
|
}
|
|
|
|
|
|
LDAPFiltDesc *
|
|
LDAP_CALL
|
|
ldap_init_getfilter_buf( char *buf, long buflen )
|
|
{
|
|
LDAPFiltDesc *lfdp;
|
|
LDAPFiltList *flp, *nextflp;
|
|
LDAPFiltInfo *fip, *nextfip;
|
|
char *tag, **tok;
|
|
int tokcnt, i;
|
|
|
|
if ( (buf == NULL) || (buflen < 0) ||
|
|
( lfdp = (LDAPFiltDesc *)NSLDAPI_CALLOC(1, sizeof( LDAPFiltDesc)))
|
|
== NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
flp = nextflp = NULL;
|
|
fip = NULL;
|
|
tag = NULL;
|
|
|
|
while ( buflen > 0 && ( tokcnt = nsldapi_next_line_tokens( &buf, &buflen,
|
|
&tok )) > 0 ) {
|
|
switch( tokcnt ) {
|
|
case 1: /* tag line */
|
|
if ( tag != NULL ) {
|
|
NSLDAPI_FREE( tag );
|
|
}
|
|
tag = tok[ 0 ];
|
|
NSLDAPI_FREE( tok );
|
|
break;
|
|
case 4:
|
|
case 5: /* start of filter info. list */
|
|
if (( nextflp = (LDAPFiltList *)NSLDAPI_CALLOC( 1,
|
|
sizeof( LDAPFiltList ))) == NULL ) {
|
|
ldap_getfilter_free( lfdp );
|
|
return( NULL );
|
|
}
|
|
nextflp->lfl_tag = nsldapi_strdup( tag );
|
|
nextflp->lfl_pattern = tok[ 0 ];
|
|
if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
|
|
char msg[256];
|
|
ldap_getfilter_free( lfdp );
|
|
sprintf( msg, "bad regular expresssion %s\n",
|
|
nextflp->lfl_pattern );
|
|
ber_err_print( msg );
|
|
nsldapi_free_strarray( tok );
|
|
return( NULL );
|
|
}
|
|
|
|
nextflp->lfl_delims = tok[ 1 ];
|
|
nextflp->lfl_ilist = NULL;
|
|
nextflp->lfl_next = NULL;
|
|
if ( flp == NULL ) { /* first one */
|
|
lfdp->lfd_filtlist = nextflp;
|
|
} else {
|
|
flp->lfl_next = nextflp;
|
|
}
|
|
flp = nextflp;
|
|
fip = NULL;
|
|
for ( i = 2; i < 5; ++i ) {
|
|
tok[ i - 2 ] = tok[ i ];
|
|
}
|
|
/* fall through */
|
|
|
|
case 2:
|
|
case 3: /* filter, desc, and optional search scope */
|
|
if ( nextflp != NULL ) { /* add to info list */
|
|
if (( nextfip = (LDAPFiltInfo *)NSLDAPI_CALLOC( 1,
|
|
sizeof( LDAPFiltInfo ))) == NULL ) {
|
|
ldap_getfilter_free( lfdp );
|
|
nsldapi_free_strarray( tok );
|
|
return( NULL );
|
|
}
|
|
if ( fip == NULL ) { /* first one */
|
|
nextflp->lfl_ilist = nextfip;
|
|
} else {
|
|
fip->lfi_next = nextfip;
|
|
}
|
|
fip = nextfip;
|
|
nextfip->lfi_next = NULL;
|
|
nextfip->lfi_filter = tok[ 0 ];
|
|
nextfip->lfi_desc = tok[ 1 ];
|
|
if ( tok[ 2 ] != NULL ) {
|
|
if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
|
|
nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
|
|
} else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
|
|
nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
|
|
} else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
|
|
nextfip->lfi_scope = LDAP_SCOPE_BASE;
|
|
} else {
|
|
nsldapi_free_strarray( tok );
|
|
ldap_getfilter_free( lfdp );
|
|
return( NULL );
|
|
}
|
|
NSLDAPI_FREE( tok[ 2 ] );
|
|
tok[ 2 ] = NULL;
|
|
} else {
|
|
nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */
|
|
}
|
|
nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
|
|
strchr( tok[ 0 ], '~' ) == NULL );
|
|
NSLDAPI_FREE( tok );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
nsldapi_free_strarray( tok );
|
|
ldap_getfilter_free( lfdp );
|
|
return( NULL );
|
|
}
|
|
}
|
|
|
|
if ( tag != NULL ) {
|
|
NSLDAPI_FREE( tag );
|
|
}
|
|
|
|
return( lfdp );
|
|
}
|
|
|
|
|
|
int
|
|
LDAP_CALL
|
|
ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
|
|
{
|
|
if ( lfdp == NULL ) {
|
|
return( LDAP_PARAM_ERROR );
|
|
}
|
|
|
|
if ( lfdp->lfd_filtprefix != NULL ) {
|
|
NSLDAPI_FREE( lfdp->lfd_filtprefix );
|
|
}
|
|
lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : nsldapi_strdup( prefix );
|
|
|
|
if ( lfdp->lfd_filtsuffix != NULL ) {
|
|
NSLDAPI_FREE( lfdp->lfd_filtsuffix );
|
|
}
|
|
lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : nsldapi_strdup( suffix );
|
|
|
|
return( LDAP_SUCCESS );
|
|
}
|
|
|
|
|
|
/*
|
|
* ldap_setfilteraffixes() is deprecated -- use ldap_set_filter_additions()
|
|
*/
|
|
void
|
|
LDAP_CALL
|
|
ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
|
|
{
|
|
(void)ldap_set_filter_additions( lfdp, prefix, suffix );
|
|
}
|
|
|
|
|
|
LDAPFiltInfo *
|
|
LDAP_CALL
|
|
ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
|
|
{
|
|
LDAPFiltList *flp;
|
|
|
|
if ( lfdp == NULL || tagpat == NULL || value == NULL ) {
|
|
return( NULL ); /* punt */
|
|
}
|
|
|
|
if ( lfdp->lfd_curvalcopy != NULL ) {
|
|
NSLDAPI_FREE( lfdp->lfd_curvalcopy );
|
|
NSLDAPI_FREE( lfdp->lfd_curvalwords );
|
|
}
|
|
|
|
lfdp->lfd_curval = value;
|
|
lfdp->lfd_curfip = NULL;
|
|
|
|
for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
|
|
if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
|
|
&& re_comp( flp->lfl_pattern ) == NULL
|
|
&& re_exec( lfdp->lfd_curval ) == 1 ) {
|
|
lfdp->lfd_curfip = flp->lfl_ilist;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( lfdp->lfd_curfip == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if (( lfdp->lfd_curvalcopy = nsldapi_strdup( value )) == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
|
|
&lfdp->lfd_curvalwords ) < 0 ) {
|
|
NSLDAPI_FREE( lfdp->lfd_curvalcopy );
|
|
lfdp->lfd_curvalcopy = NULL;
|
|
return( NULL );
|
|
}
|
|
|
|
return( ldap_getnextfilter( lfdp ));
|
|
}
|
|
|
|
|
|
LDAPFiltInfo *
|
|
LDAP_CALL
|
|
ldap_getnextfilter( LDAPFiltDesc *lfdp )
|
|
{
|
|
LDAPFiltInfo *fip;
|
|
|
|
if ( lfdp == NULL || ( fip = lfdp->lfd_curfip ) == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
lfdp->lfd_curfip = fip->lfi_next;
|
|
|
|
ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter,
|
|
lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
|
|
lfdp->lfd_curval, lfdp->lfd_curvalwords );
|
|
lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
|
|
lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
|
|
lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
|
|
lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
|
|
|
|
return( &lfdp->lfd_retfi );
|
|
}
|
|
|
|
|
|
static char*
|
|
filter_add_strn( char *f, char *flimit, char *v, size_t vlen )
|
|
/* Copy v into f. If flimit is too small, return NULL;
|
|
* otherwise return (f + vlen).
|
|
*/
|
|
{
|
|
auto size_t flen = flimit - f;
|
|
if ( vlen > flen ) { /* flimit is too small */
|
|
if ( flen > 0 ) SAFEMEMCPY( f, v, flen );
|
|
return NULL;
|
|
}
|
|
if ( vlen > 0 ) SAFEMEMCPY( f, v, vlen );
|
|
return f + vlen;
|
|
}
|
|
|
|
static char*
|
|
filter_add_value( char *f, char *flimit, char *v, int escape_all )
|
|
/* Copy v into f, but with parentheses escaped. But only escape * and \
|
|
* if escape_all is non-zero so that either "*" or "\2a" can be used in
|
|
* v, with different meanings.
|
|
* If flimit is too small, return NULL; otherwise
|
|
* return (f + the number of bytes copied).
|
|
*/
|
|
{
|
|
auto char x[4];
|
|
auto size_t slen;
|
|
while ( f && *v ) {
|
|
switch ( *v ) {
|
|
case '*':
|
|
if ( escape_all ) {
|
|
f = filter_add_strn( f, flimit, "\\2a", 3 );
|
|
v++;
|
|
} else {
|
|
if ( f < flimit ) {
|
|
*f++ = *v++;
|
|
} else {
|
|
f = NULL; /* overflow */
|
|
}
|
|
}
|
|
break;
|
|
|
|
case '(':
|
|
case ')':
|
|
sprintf( x, "\\%02x", (unsigned)*v );
|
|
f = filter_add_strn( f, flimit, x, 3 );
|
|
v++;
|
|
break;
|
|
|
|
case '\\':
|
|
if ( escape_all ) {
|
|
f = filter_add_strn( f, flimit, "\\5c", 3 );
|
|
v++;
|
|
} else {
|
|
slen = (ldap_utf8isxdigit( v+1 ) &&
|
|
ldap_utf8isxdigit( v+2 )) ? 3 : (v[1] ? 2 : 1);
|
|
f = filter_add_strn( f, flimit, v, slen );
|
|
v += slen;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if ( f < flimit ) {
|
|
*f++ = *v++;
|
|
} else {
|
|
f = NULL; /* overflow */
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return f;
|
|
}
|
|
|
|
int
|
|
LDAP_CALL
|
|
ldap_create_filter( char *filtbuf, unsigned long buflen, char *pattern,
|
|
char *prefix, char *suffix, char *attr, char *value, char **valwords )
|
|
{
|
|
char *p, *f, *flimit;
|
|
int i, wordcount, wordnum, endwordnum, escape_all;
|
|
|
|
/*
|
|
* there is some confusion on what to create for a filter if
|
|
* attr or value are null pointers. For now we just leave them
|
|
* as TO BE DEALT with
|
|
*/
|
|
|
|
if ( filtbuf == NULL || buflen == 0 || pattern == NULL ){
|
|
return( LDAP_PARAM_ERROR );
|
|
}
|
|
|
|
if ( valwords == NULL ) {
|
|
wordcount = 0;
|
|
} else {
|
|
for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
|
|
;
|
|
}
|
|
}
|
|
|
|
f = filtbuf;
|
|
flimit = filtbuf + buflen - 1;
|
|
|
|
if ( prefix != NULL ) {
|
|
f = filter_add_strn( f, flimit, prefix, strlen( prefix ));
|
|
}
|
|
|
|
for ( p = pattern; f != NULL && *p != '\0'; ++p ) {
|
|
if ( *p == '%' ) {
|
|
++p;
|
|
if ( *p == 'v' || *p == 'e' ) {
|
|
escape_all = ( *p == 'e' );
|
|
if ( ldap_utf8isdigit( p+1 )) {
|
|
++p;
|
|
wordnum = *p - '1';
|
|
if ( *(p+1) == '-' ) {
|
|
++p;
|
|
if ( ldap_utf8isdigit( p+1 )) {
|
|
++p;
|
|
endwordnum = *p - '1'; /* e.g., "%v2-4" */
|
|
if ( endwordnum > wordcount - 1 ) {
|
|
endwordnum = wordcount - 1;
|
|
}
|
|
} else {
|
|
endwordnum = wordcount - 1; /* e.g., "%v2-" */
|
|
}
|
|
} else {
|
|
endwordnum = wordnum; /* e.g., "%v2" */
|
|
}
|
|
|
|
if ( wordcount > 0 ) {
|
|
for ( i = wordnum; i <= endwordnum; ++i ) {
|
|
if ( i > wordnum ) { /* add blank btw words */
|
|
f = filter_add_strn( f, flimit, " ", 1 );
|
|
if ( f == NULL ) break;
|
|
}
|
|
f = filter_add_value( f, flimit, valwords[ i ],
|
|
escape_all );
|
|
if ( f == NULL ) break;
|
|
}
|
|
}
|
|
} else if ( *(p+1) == '$' ) {
|
|
++p;
|
|
if ( wordcount > 0 ) {
|
|
wordnum = wordcount - 1;
|
|
f = filter_add_value( f, flimit,
|
|
valwords[ wordnum ], escape_all );
|
|
}
|
|
} else if ( value != NULL ) {
|
|
f = filter_add_value( f, flimit, value, escape_all );
|
|
}
|
|
} else if ( *p == 'a' && attr != NULL ) {
|
|
f = filter_add_strn( f, flimit, attr, strlen( attr ));
|
|
} else {
|
|
*f++ = *p;
|
|
}
|
|
} else {
|
|
*f++ = *p;
|
|
}
|
|
if ( f > flimit ) { /* overflow */
|
|
f = NULL;
|
|
}
|
|
}
|
|
|
|
if ( suffix != NULL && f != NULL) {
|
|
f = filter_add_strn( f, flimit, suffix, strlen( suffix ));
|
|
}
|
|
|
|
if ( f == NULL ) {
|
|
*flimit = '\0';
|
|
return( LDAP_SIZELIMIT_EXCEEDED );
|
|
}
|
|
*f = '\0';
|
|
return( LDAP_SUCCESS );
|
|
}
|
|
|
|
|
|
/*
|
|
* ldap_build_filter() is deprecated -- use ldap_create_filter() instead
|
|
*/
|
|
void
|
|
LDAP_CALL
|
|
ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern,
|
|
char *prefix, char *suffix, char *attr, char *value, char **valwords )
|
|
{
|
|
(void)ldap_create_filter( filtbuf, buflen, pattern, prefix, suffix, attr,
|
|
value, valwords );
|
|
}
|
|
|
|
|
|
static int
|
|
break_into_words( char *str, char *delims, char ***wordsp )
|
|
{
|
|
char *word, **words;
|
|
int count;
|
|
char *lasts;
|
|
|
|
if (( words = (char **)NSLDAPI_CALLOC( 1, sizeof( char * ))) == NULL ) {
|
|
return( -1 );
|
|
}
|
|
count = 0;
|
|
words[ count ] = NULL;
|
|
|
|
word = ldap_utf8strtok_r( str, delims, &lasts );
|
|
while ( word != NULL ) {
|
|
if (( words = (char **)NSLDAPI_REALLOC( words,
|
|
( count + 2 ) * sizeof( char * ))) == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
words[ count ] = word;
|
|
words[ ++count ] = NULL;
|
|
word = ldap_utf8strtok_r( NULL, delims, &lasts );
|
|
}
|
|
|
|
*wordsp = words;
|
|
return( count );
|
|
}
|