From f0d3f3afdfa314e1e8cd7d8da790878008a46aad Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 24 Jun 2009 12:59:33 -0400 Subject: Radically reorganize source code. - Collect all shell modules into a new top-level 'modules' directory: $(top_srcdir)/modules/addressbook $(top_srcdir)/modules/calendar $(top_srcdir)/modules/mail Nothing is allowed to link to these, not plugins nor other modules. THIS SOLVES BUG #571275 AND OPENS THE DOOR TO PORTING TO MAC OS X. - Mimic the libevolution-mail-shared library from master (except drop the "shared" suffix) and have libevolution-mail-importers and all mail-related plugins link to it. - Discard the a11y subdirectories and have the files live alongside their counterpart widgets. --- addressbook/gui/component/openldap-extract.h | 1427 -------------------------- 1 file changed, 1427 deletions(-) delete mode 100644 addressbook/gui/component/openldap-extract.h (limited to 'addressbook/gui/component/openldap-extract.h') diff --git a/addressbook/gui/component/openldap-extract.h b/addressbook/gui/component/openldap-extract.h deleted file mode 100644 index 996bf370a8..0000000000 --- a/addressbook/gui/component/openldap-extract.h +++ /dev/null @@ -1,1427 +0,0 @@ -/* This is extracted from the OpenLDAP sources. - * - * Stuff that isn't used in e-book-backend-ldap.c was dropped, like - * the LDAPSchemaExtensionItem stuff. - * - * This file basically has three parts: - * - * - some general macros from OpenLDAP that work as such on all - * implementations. - * - * - ldap_str2objectclass() - * - * - ldap_url_parse() - */ - -/* This work is part of OpenLDAP Software . - * - * Copyright 1998-2005 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in file COPYING.OPENLDAP in - * the top-level directory of the distribution or, alternatively, at - * . - */ - -#include -#include - -/* from various header files */ - -#define LDAP_CONST const - -#define LDAP_PORT 389 /* ldap:/// default LDAP port */ -#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ - -#define LDAP_ROOT_DSE "" - -#define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') -#define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') - -#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 2830 */ - -#define LDAP_MALLOC(n) malloc((n)) -#define LDAP_CALLOC(n,s) calloc((n),(s)) -#define LDAP_REALLOC(p,s) realloc((p),(s)) -#define LDAP_FREE(p) free((p)) -#define LDAP_VFREE(p) vfree((gpointer *)(p)) -#define LDAP_STRDUP(s) strdup((s)) - -#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) -#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ - -#define ldap_msgtype(lm) (lm)->lm_msgtype -#define ldap_msgid(lm) (lm)->lm_msgid - -#define LDAP_SCHERR_OUTOFMEM 1 -#define LDAP_SCHERR_UNEXPTOKEN 2 -#define LDAP_SCHERR_NOLEFTPAREN 3 -#define LDAP_SCHERR_NORIGHTPAREN 4 -#define LDAP_SCHERR_NODIGIT 5 -#define LDAP_SCHERR_BADNAME 6 -#define LDAP_SCHERR_BADDESC 7 -#define LDAP_SCHERR_BADSUP 8 -#define LDAP_SCHERR_DUPOPT 9 -#define LDAP_SCHERR_EMPTY 10 -#define LDAP_SCHERR_MISSING 11 -#define LDAP_SCHERR_OUT_OF_ORDER 12 - -#define LDAP_SCHEMA_YES 1 - -#define LDAP_SCHEMA_ABSTRACT 0 -#define LDAP_SCHEMA_STRUCTURAL 1 -#define LDAP_SCHEMA_AUXILIARY 2 - -#define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ -#define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ -#define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ -#define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ -#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ -#define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ -#define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ -#define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ -#define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ - -typedef struct ldap_objectclass { - gchar *oc_oid; /* REQUIRED */ - gchar **oc_names; /* OPTIONAL */ - gchar *oc_desc; /* OPTIONAL */ - gint oc_obsolete; /* 0=no, 1=yes */ - gchar **oc_sup_oids; /* OPTIONAL */ - gint oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ - gchar **oc_at_oids_must; /* OPTIONAL */ - gchar **oc_at_oids_may; /* OPTIONAL */ -} LDAPObjectClass; - - -static void -vfree(gpointer *vec) -{ - gint i; - - for (i = 0; vec[i] != NULL; i++) - free(vec[i]); -} - -/* from schema.c */ - -/* - * Now come the parsers. There is one parser for each entity type: - * objectclasses, attributetypes, etc. - * - * Each of them is written as a recursive-descent parser, except that - * none of them is really recursive. But the idea is kept: there - * is one routine per non-terminal that eithers gobbles lexical tokens - * or calls lower-level routines, etc. - * - * The scanner is implemented in the routine get_token. Actually, - * get_token is more than a scanner and will return tokens that are - * in fact non-terminals in the grammar. So you can see the whole - * approach as the combination of a low-level bottom-up recognizer - * combined with a scanner and a number of top-down parsers. Or just - * consider that the real grammars recognized by the parsers are not - * those of the standards. As a matter of fact, our parsers are more - * liberal than the spec when there is no ambiguity. - * - * The difference is pretty academic (modulo bugs or incorrect - * interpretation of the specs). - */ - -#define TK_NOENDQUOTE -2 -#define TK_OUTOFMEM -1 -#define TK_EOS 0 -#define TK_UNEXPCHAR 1 -#define TK_BAREWORD 2 -#define TK_QDSTRING 3 -#define TK_LEFTPAREN 4 -#define TK_RIGHTPAREN 5 -#define TK_DOLLAR 6 -#define TK_QDESCR TK_QDSTRING - -struct token { - gint type; - gchar *sval; -}; - -static gint -get_token( const gchar ** sp, gchar ** token_val ) -{ - gint kind; - const gchar * p; - const gchar * q; - gchar * res; - - *token_val = NULL; - switch (**sp) { - case '\0': - kind = TK_EOS; - (*sp)++; - break; - case '(': - kind = TK_LEFTPAREN; - (*sp)++; - break; - case ')': - kind = TK_RIGHTPAREN; - (*sp)++; - break; - case '$': - kind = TK_DOLLAR; - (*sp)++; - break; - case '\'': - kind = TK_QDSTRING; - (*sp)++; - p = *sp; - while ( **sp != '\'' && **sp != '\0' ) - (*sp)++; - if ( **sp == '\'' ) { - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - (*sp)++; - } else { - kind = TK_NOENDQUOTE; - } - break; - default: - kind = TK_BAREWORD; - p = *sp; - while ( !LDAP_SPACE(**sp) && - **sp != '(' && - **sp != ')' && - **sp != '$' && - **sp != '\'' && - **sp != '\0' ) - (*sp)++; - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - break; -/* kind = TK_UNEXPCHAR; */ -/* break; */ - } - - return kind; -} - -/* Gobble optional whitespace */ -static void -parse_whsp(const gchar **sp) -{ - while (LDAP_SPACE(**sp)) - (*sp)++; -} - -/* Parse a sequence of dot-separated decimal strings */ -static gchar * -ldap_int_parse_numericoid(const gchar **sp, gint *code, const gint flags) -{ - gchar * res = NULL; - const gchar * start = *sp; - gint len; - gint quoted = 0; - - /* Netscape puts the SYNTAX value in quotes (incorrectly) */ - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { - quoted = 1; - (*sp)++; - start++; - } - /* Each iteration of this loop gets one decimal string */ - while (**sp) { - if ( !LDAP_DIGIT(**sp) ) { - /* - * Initial gchar is not a digit or gchar after dot is - * not a digit - */ - *code = LDAP_SCHERR_NODIGIT; - return NULL; - } - (*sp)++; - while ( LDAP_DIGIT(**sp) ) - (*sp)++; - if ( **sp != '.' ) - break; - /* Otherwise, gobble the dot and loop again */ - (*sp)++; - } - /* Now *sp points at the gchar past the numericoid. Perfect. */ - len = *sp - start; - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { - if ( **sp == '\'' ) { - (*sp)++; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - return NULL; - } - } - if (flags & LDAP_SCHEMA_SKIP) { - res = (gchar *)start; - } else { - res = LDAP_MALLOC(len+1); - if (!res) { - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - strncpy(res,start,len); - res[len] = '\0'; - } - return(res); -} - -/* Parse a qdescr or a list of them enclosed in () */ -static gchar ** -parse_qdescrs(const gchar **sp, gint *code) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - while (1) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_QDESCR ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - parse_whsp(sp); - } else { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_UNEXPTOKEN; - return(NULL); - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_QDESCR ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -/* Parse a woid or a $-separated list of them enclosed in () */ -static gchar ** -parse_oids(const gchar **sp, gint *code, const gint allow_quoted) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - /* - * Strictly speaking, doing this here accepts whsp before the - * ( at the begining of an oidlist, but this is harmless. Also, - * we are very liberal in what we accept as an OID. Maybe - * refine later. - */ - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - while (1) { - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_DOLLAR ) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && - kind == TK_QDSTRING ) ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_FREE(sval); - LDAP_VFREE(res); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -static void -ldap_objectclass_free(LDAPObjectClass * oc) -{ - LDAP_FREE(oc->oc_oid); - if (oc->oc_names) LDAP_VFREE(oc->oc_names); - if (oc->oc_desc) LDAP_FREE(oc->oc_desc); - if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); - if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); - if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); - LDAP_FREE(oc); -} - -static LDAPObjectClass * -ldap_str2objectclass( LDAP_CONST gchar * s, - gint * code, - LDAP_CONST gchar ** errp, - LDAP_CONST unsigned flags ) -{ - gint kind; - const gchar * ss = s; - gchar * sval; - gint seen_name = 0; - gint seen_desc = 0; - gint seen_obsolete = 0; - gint seen_sup = 0; - gint seen_kind = 0; - gint seen_must = 0; - gint seen_may = 0; - LDAPObjectClass * oc; - gchar ** ext_vals; - const gchar * savepos; - - if ( !s ) { - *code = LDAP_SCHERR_EMPTY; - *errp = ""; - return NULL; - } - - *errp = s; - oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); - - if ( !oc ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - - kind = get_token(&ss,&sval); - if ( kind != TK_LEFTPAREN ) { - *code = LDAP_SCHERR_NOLEFTPAREN; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - - /* - * Definitions MUST begin with an OID in the numericoid format. - * However, this routine is used by clients to parse the response - * from servers and very well known servers will provide an OID - * in the wrong format or even no OID at all. We do our best to - * extract info from those servers. - */ - parse_whsp(&ss); - savepos = ss; - oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); - if ( !oc->oc_oid ) { - if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { - /* Backtracking */ - ss = savepos; - kind = get_token(&ss,&sval); - if ( kind == TK_BAREWORD ) { - if ( !strcasecmp(sval, "NAME") || - !strcasecmp(sval, "DESC") || - !strcasecmp(sval, "OBSOLETE") || - !strcasecmp(sval, "SUP") || - !strcasecmp(sval, "ABSTRACT") || - !strcasecmp(sval, "STRUCTURAL") || - !strcasecmp(sval, "AUXILIARY") || - !strcasecmp(sval, "MUST") || - !strcasecmp(sval, "MAY") || - !strncasecmp(sval, "X-", 2) ) { - /* Missing OID, backtrack */ - ss = savepos; - } else if ( flags & - LDAP_SCHEMA_ALLOW_OID_MACRO ) { - /* Non-numerical OID, ignore */ - gint len = ss-savepos; - oc->oc_oid = LDAP_MALLOC(len+1); - strncpy(oc->oc_oid, savepos, len); - oc->oc_oid[len] = 0; - } - } - LDAP_FREE(sval); - } else { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } - parse_whsp(&ss); - - /* - * Beyond this point we will be liberal an accept the items - * in any order. - */ - while (1) { - kind = get_token(&ss,&sval); - switch (kind) { - case TK_EOS: - *code = LDAP_SCHERR_NORIGHTPAREN; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - case TK_RIGHTPAREN: - return oc; - case TK_BAREWORD: - if ( !strcasecmp(sval,"NAME") ) { - LDAP_FREE(sval); - if ( seen_name ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_name = 1; - oc->oc_names = parse_qdescrs(&ss,code); - if ( !oc->oc_names ) { - if ( *code != LDAP_SCHERR_OUTOFMEM ) - *code = LDAP_SCHERR_BADNAME; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"DESC") ) { - LDAP_FREE(sval); - if ( seen_desc ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_desc = 1; - parse_whsp(&ss); - kind = get_token(&ss,&sval); - if ( kind != TK_QDSTRING ) { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - oc->oc_desc = sval; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"OBSOLETE") ) { - LDAP_FREE(sval); - if ( seen_obsolete ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_obsolete = 1; - oc->oc_obsolete = LDAP_SCHEMA_YES; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"SUP") ) { - LDAP_FREE(sval); - if ( seen_sup ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_sup = 1; - oc->oc_sup_oids = parse_oids(&ss, - code, - flags); - if ( !oc->oc_sup_oids ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"ABSTRACT") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_ABSTRACT; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"STRUCTURAL") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"AUXILIARY") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_AUXILIARY; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MUST") ) { - LDAP_FREE(sval); - if ( seen_must ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_must = 1; - oc->oc_at_oids_must = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_must ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MAY") ) { - LDAP_FREE(sval); - if ( seen_may ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_may = 1; - oc->oc_at_oids_may = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_may ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( sval[0] == 'X' && sval[1] == '-' ) { - /* Should be parse_qdstrings */ - ext_vals = parse_qdescrs(&ss, code); - if ( !ext_vals ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } -#if 0 - if ( add_extension(&oc->oc_extensions, - sval, ext_vals) ) { - *code = LDAP_SCHERR_OUTOFMEM; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } -#endif - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - break; - default: - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - } -} - -/* from utf-8.c */ - -#define LDAP_UTF8_NEXT(p) g_utf8_next_char((p)) -#define LDAP_UTF8_INCR(p) ((p)=LDAP_UTF8_NEXT((p))) -#define ldap_x_utf8_to_ucs4(str) g_utf8_get_char(str) - -static gchar *ldap_utf8_strchr( const gchar *str, const gchar *chr ) -{ - for(; *str != '\0'; LDAP_UTF8_INCR(str) ) { - if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { - return (gchar *) str; - } - } - - return NULL; -} - -static gsize ldap_utf8_strcspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { - if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - return cstr - str; - } - } - } - - return cstr - str; -} - -static gsize ldap_utf8_strspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for( cset = set; ; LDAP_UTF8_INCR(cset) ) { - if( *cset == '\0' ) { - return cstr - str; - } - - if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - break; - } - } - } - - return cstr - str; -} - -static gchar *ldap_utf8_strtok(gchar *str, const gchar *sep, gchar **last) -{ - gchar *begin; - gchar *end; - - if( last == NULL ) return NULL; - - begin = str ? str : *last; - - begin += ldap_utf8_strspn( begin, sep ); - - if( *begin == '\0' ) { - *last = NULL; - return NULL; - } - - end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; - - if( *end != '\0' ) { - gchar *next = LDAP_UTF8_NEXT( end ); - *end = '\0'; - end = next; - } - - *last = end; - return begin; -} - -/* from ldap.h */ - -#define LDAP_URL_SUCCESS 0x00 /* Success */ -#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ -#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ - -#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ -#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ -#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ -#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ -#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ -#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ -#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ -#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ - -#define LDAP_URL_PREFIX "ldap://" -#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1) -#define LDAPS_URL_PREFIX "ldaps://" -#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1) -#define LDAPI_URL_PREFIX "ldapi://" -#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1) - -#define LDAP_URL_URLCOLON "URL:" -#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1) - -typedef struct ldap_url_desc { - struct ldap_url_desc *lud_next; - gchar *lud_scheme; - gchar *lud_host; - gint lud_port; - gchar *lud_dn; - gchar **lud_attrs; - gint lud_scope; - gchar *lud_filter; - gchar **lud_exts; - gint lud_crit_exts; -} LDAPURLDesc; - -/* from url.c */ - -static const gchar * -skip_url_prefix( - const gchar *url, - gint *enclosedp, - const gchar **scheme ) -{ - /* - * return non-zero if this looks like a LDAP URL; zero if not - * if non-zero returned, *urlp will be moved past "ldap://" part of URL - */ - const gchar *p; - - if ( url == NULL ) { - return( NULL ); - } - - p = url; - - /* skip leading '<' (if any) */ - if ( *p == '<' ) { - *enclosedp = 1; - ++p; - } else { - *enclosedp = 0; - } - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { - p += LDAP_URL_URLCOLON_LEN; - } - - /* check for "ldap://" prefix */ - if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldap://" prefix and return success */ - p += LDAP_URL_PREFIX_LEN; - *scheme = "ldap"; - return( p ); - } - - /* check for "ldaps://" prefix */ - if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldaps://" prefix and return success */ - p += LDAPS_URL_PREFIX_LEN; - *scheme = "ldaps"; - return( p ); - } - - /* check for "ldapi://" prefix */ - if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldapi://" prefix and return success */ - p += LDAPI_URL_PREFIX_LEN; - *scheme = "ldapi"; - return( p ); - } - -#ifdef LDAP_CONNECTIONLESS - /* check for "cldap://" prefix */ - if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { - /* skip over "cldap://" prefix and return success */ - p += LDAPC_URL_PREFIX_LEN; - *scheme = "cldap"; - return( p ); - } -#endif - - return( NULL ); -} - -static gint str2scope( const gchar *p ) -{ - if ( strcasecmp( p, "one" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "onelevel" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "base" ) == 0 ) { - return LDAP_SCOPE_BASE; - - } else if ( strcasecmp( p, "sub" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - - } else if ( strcasecmp( p, "subtree" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - } - - return( -1 ); -} - -static void -ldap_free_urldesc( LDAPURLDesc *ludp ) -{ - if ( ludp == NULL ) { - return; - } - - if ( ludp->lud_scheme != NULL ) { - LDAP_FREE( ludp->lud_scheme ); - } - - if ( ludp->lud_host != NULL ) { - LDAP_FREE( ludp->lud_host ); - } - - if ( ludp->lud_dn != NULL ) { - LDAP_FREE( ludp->lud_dn ); - } - - if ( ludp->lud_filter != NULL ) { - LDAP_FREE( ludp->lud_filter); - } - - if ( ludp->lud_attrs != NULL ) { - LDAP_VFREE( ludp->lud_attrs ); - } - - if ( ludp->lud_exts != NULL ) { - LDAP_VFREE( ludp->lud_exts ); - } - - LDAP_FREE( ludp ); -} - -static gint -ldap_int_unhex( gint c ) -{ - return( c >= '0' && c <= '9' ? c - '0' - : c >= 'A' && c <= 'F' ? c - 'A' + 10 - : c - 'a' + 10 ); -} - -static void -ldap_pvt_hex_unescape( gchar *s ) -{ - /* - * Remove URL hex escapes from s... done in place. The basic concept for - * this routine is borrowed from the WWW library HTUnEscape() routine. - */ - gchar *p; - - for ( p = s; *s != '\0'; ++s ) { - if ( *s == '%' ) { - if ( *++s == '\0' ) { - break; - } - *p = ldap_int_unhex( *s ) << 4; - if ( *++s == '\0' ) { - break; - } - *p++ += ldap_int_unhex( *s ); - } else { - *p++ = *s; - } - } - - *p = '\0'; -} - -static gchar ** -ldap_str2charray( const gchar *str_in, const gchar *brkstr ) -{ - gchar **res; - gchar *str, *s; - gchar *lasts; - gint i; - - /* protect the input string from strtok */ - str = LDAP_STRDUP( str_in ); - if( str == NULL ) { - return NULL; - } - - i = 1; - for ( s = str; *s; s++ ) { - if ( ldap_utf8_strchr( brkstr, s ) != NULL ) { - i++; - } - } - - res = (gchar **) LDAP_MALLOC( (i + 1) * sizeof(gchar *) ); - - if( res == NULL ) { - LDAP_FREE( str ); - return NULL; - } - - i = 0; - - for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); - s != NULL; - s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) - { - res[i] = LDAP_STRDUP( s ); - - if(res[i] == NULL) { - for( --i; i >= 0; i-- ) { - LDAP_FREE( res[i] ); - } - LDAP_FREE( res ); - LDAP_FREE( str ); - return NULL; - } - - i++; - } - - res[i] = NULL; - - LDAP_FREE( str ); - return( res ); -} - -static gint -ldap_url_parse_ext( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ -/* - * Pick apart the pieces of an LDAP URL. - */ - - LDAPURLDesc *ludp; - gchar *p, *q, *r; - gint i, enclosed; - const gchar *scheme = NULL; - const gchar *url_tmp; - gchar *url; - - if( url_in == NULL || ludpp == NULL ) { - return LDAP_URL_ERR_PARAM; - } - - *ludpp = NULL; /* pessimistic */ - - url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); - - if ( url_tmp == NULL ) { - return LDAP_URL_ERR_BADSCHEME; - } - - assert( scheme ); - - /* make working copy of the remainder of the URL */ - url = LDAP_STRDUP( url_tmp ); - if ( url == NULL ) { - return LDAP_URL_ERR_MEM; - } - - if ( enclosed ) { - p = &url[strlen(url)-1]; - - if( *p != '>' ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_BADENCLOSURE; - } - - *p = '\0'; - } - - /* allocate return struct */ - ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); - - if ( ludp == NULL ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_MEM; - } - - ludp->lud_next = NULL; - ludp->lud_host = NULL; - ludp->lud_port = 0; - ludp->lud_dn = NULL; - ludp->lud_attrs = NULL; - ludp->lud_filter = NULL; - ludp->lud_scope = LDAP_SCOPE_DEFAULT; - ludp->lud_filter = NULL; - ludp->lud_exts = NULL; - - ludp->lud_scheme = LDAP_STRDUP( scheme ); - - if ( ludp->lud_scheme == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* scan forward for '/' that marks end of hostport and begin. of dn */ - p = strchr( url, '/' ); - - if( p != NULL ) { - /* terminate hostport; point to start of dn */ - *p++ = '\0'; - } - - /* IPv6 syntax with [ip address]:port */ - if ( *url == '[' ) { - r = strchr( url, ']' ); - if ( r == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - *r++ = '\0'; - q = strchr( r, ':' ); - } else { - q = strchr( url, ':' ); - } - - if ( q != NULL ) { - gchar *next; - - *q++ = '\0'; - ldap_pvt_hex_unescape( q ); - - if( *q == '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - ludp->lud_port = strtol( q, &next, 10 ); - if ( next == NULL || next[0] != '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - } - - ldap_pvt_hex_unescape( url ); - - /* If [ip address]:port syntax, url is [ip and we skip the [ */ - ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); - - if( ludp->lud_host == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* - * Kludge. ldap://111.222.333.444:389??cn=abc,o=company - * - * On early Novell releases, search references/referrals were returned - * in this format, i.e., the dn was kind of in the scope position, - * but the required slash is missing. The whole thing is illegal syntax, - * but we need to account for it. Fortunately it can't be confused with - * anything real. - */ - if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { - q++; - /* ? immediately followed by question */ - if( *q == '?') { - q++; - if( *q != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( q ); - ludp->lud_dn = LDAP_STRDUP( q ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - } - - if( p == NULL ) { - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of dn */ - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate dn part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( p ); - ludp->lud_dn = LDAP_STRDUP( p ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - if( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of attributes */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate attributes part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse attributes */ - ldap_pvt_hex_unescape( p ); - ludp->lud_attrs = ldap_str2charray( p, "," ); - - if( ludp->lud_attrs == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADATTRS; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of scope */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate the scope part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse the scope */ - ldap_pvt_hex_unescape( p ); - ludp->lud_scope = str2scope( p ); - - if( ludp->lud_scope == -1 ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADSCOPE; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of filter */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate the filter part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse the filter */ - ldap_pvt_hex_unescape( p ); - - if( ! *p ) { - /* missing filter */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADFILTER; - } - - LDAP_FREE( ludp->lud_filter ); - ludp->lud_filter = LDAP_STRDUP( p ); - - if( ludp->lud_filter == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of extensions */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* extra '?' */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - /* parse the extensions */ - ludp->lud_exts = ldap_str2charray( p, "," ); - - if( ludp->lud_exts == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - for( i=0; ludp->lud_exts[i] != NULL; i++ ) { - ldap_pvt_hex_unescape( ludp->lud_exts[i] ); - - if( *ludp->lud_exts[i] == '!' ) { - /* count the number of critical extensions */ - ludp->lud_crit_exts++; - } - } - - if( i == 0 ) { - /* must have 1 or more */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - /* no more */ - *ludpp = ludp; - LDAP_FREE( url ); - return LDAP_URL_SUCCESS; -} - -static gint -ldap_url_parse( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ - gint rc = ldap_url_parse_ext( url_in, ludpp ); - - if( rc != LDAP_URL_SUCCESS ) { - return rc; - } - - if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) { - (*ludpp)->lud_scope = LDAP_SCOPE_BASE; - } - - if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { - LDAP_FREE( (*ludpp)->lud_host ); - (*ludpp)->lud_host = NULL; - } - - if ((*ludpp)->lud_port == 0) { - if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#ifdef LDAP_CONNECTIONLESS - } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#endif - } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) { - (*ludpp)->lud_port = LDAPS_PORT; - } - } - - return rc; -} - -- cgit v1.2.3