Пример #1
0
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 );
    }

    NSLDAPI_FREE(lfdp->lfd_curval);
    if ((lfdp->lfd_curval = nsldapi_strdup(value)) == NULL) {
	return( NULL );
    }

    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 ));
}
Пример #2
0
LDAPFiltInfo *
ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
{
    LDAPFiltList	*flp;

    if ( lfdp->lfd_curvalcopy != NULL ) {
	free( lfdp->lfd_curvalcopy );
	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 = strdup( value )) == NULL ) {
	return( NULL );
    }

    if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
		&lfdp->lfd_curvalwords ) < 0 ) {
	free( lfdp->lfd_curvalcopy );
	lfdp->lfd_curvalcopy = NULL;
	return( NULL );
    }

    return( ldap_getnextfilter( lfdp ));
}
Пример #3
0
int
do_search(
    REQUEST         *r,
    RESPONSE        *resp
)
{
    char            *filtertype, **search_attrs, *search_filter;
    char            *print_filter, *human_filter;
    int             scope, count = 0, rc, i = 0, j, in_home;
    int option_param;
    struct timeval  timeout;
    LDAPFiltInfo    *fi;
    LDAPMessage     *e, *res;
    static char     *def_attrs[] = 
                {"objectClass", "sn", "aliasedObjectName", "labeledURI", 0};
    struct ldap_disptmpl    *tmpl;
    char    **oc;
    char    *result_dn, *doc, *foc, *url_dn;
    char    *base_dn, *base_ufn, *result_ufn, *alias_ufn, *sortstring, *cp, *bp;
    char    **sn, href[10 * BUFSIZ], *temp, **val, *server = NULL;
    int     counter = 0, base_len, isalias = 0;

#ifdef WEB500GW_DEBUG
    Web500gw_debug(WEB500GW_DEBUG_TRACE, "do_search (%s, %s, (",
        r->r_dn, flag2string(r->r_flags), 0, 0);
    while (r->r_attrs && r->r_attrs[i]) {
        Web500gw_debug(WEB500GW_DEBUG_TRACE, "%s ", r->r_attrs[i], 0, 0, 0);
        i++;
    }
    Web500gw_debug(WEB500GW_DEBUG_TRACE, "), %s)\n", 
        (r->r_filter && *r->r_filter) ? r->r_filter : "No filter", 0, 0, 0);
#endif

    if (r->r_ld == (LDAP *)0 &&
        (r->r_ld = web500gw_ldap_init(r, resp, NULL, NULL, 1)) == NULL)
        return NOTOK;

    base_dn = r->r_dn;
    if (strlen(base_dn) > 0) {
        base_ufn = friendly_dn(resp, base_dn);
    } else {
        base_ufn = NULL;
    }
    base_len = base_ufn ? strlen(base_ufn) : 0;


    if (r->r_filter == NULL) {
        return NOTOK;
    }
    print_filter = r->r_filter;
#if defined(OWN_STR_TRANSLATION)
    search_filter = strdup(web500gw_isotot61(r->r_filter));
#else
    search_filter = r->r_filter;
#endif
    if (*search_filter == '\0' || *(search_filter+1) != '=') {
        scope = LDAP_SCOPE_ONELEVEL;
    } else {
        if (*search_filter == 'S') {
            scope = LDAP_SCOPE_SUBTREE;
        } else {
            scope = LDAP_SCOPE_ONELEVEL;
        }
        search_filter += 2;
        print_filter += 2;
    }

    /* make a "human readable filter" - for now, no artistic things are done */
    human_filter = print_filter;
    if ((cp = strchr(print_filter, '=')) != NULL) {
        if ((cp = strchr(cp+1, '=')) != NULL) {
            /* two '=' in it - must be a complex filter - isn't readable... */
            human_filter = MSG_COMPLEX_FILTER;
        }
    }

    if (*search_filter) {   /* not the default filter */
        r->r_flags |= FLAG_FILTER;
                            /* skip leading white spaces */
        while (isspace(*search_filter)) ++search_filter;
    }
    if (r->r_attrs == NULL || *r->r_attrs == NULL) {
        /* No attributes requested - read default attrs for sorting */
        search_attrs = def_attrs;
    } else {
        j = 0;
        while (def_attrs[j]) j++;
        search_attrs = (char **) calloc(r->r_attrnumb + j + 1, sizeof(char *));
        i = j = 0;
        while (r->r_attrs && r->r_attrs[i])  {
            search_attrs[i] = r->r_attrs[i];
            i++;
        }
        while (def_attrs[j]) 
            search_attrs[i++] = def_attrs[j++];    
        search_attrs[i] = NULL;
    }

    if ((in_home = isinhome(base_dn)))
        /* ACCESS sizelimit if searching below HOME DN */
        ldap_set_option(r->r_ld, LDAP_OPT_SIZELIMIT, &(r->r_access->a_sizelimit));
    else
        ldap_set_option(r->r_ld, LDAP_OPT_SIZELIMIT, &sizelimit);

    /* A simple filter (not starting with '(') with a comma in it 
     *  -> UFN assumed */

    /*    if (ufnsearch && search_filter[0] != '(' && 
        strchr(search_filter, ',') != NULL && strlen(search_filter) > 3) {
        if (strlen(base_dn) > 0)
            ldap_ufn_setprefix(r->r_ld, base_dn);
        timeout.tv_sec = timelimit;
        timeout.tv_usec = 0;
        ldap_ufn_timeout((void *) &timeout);

	option_param = LDAP_DEREF_FINDING;
	ldap_set_option(r->r_ld, LDAP_OPT_DEREF, (void *) &option_param);
#ifdef WEB500GW_DEBUG
        Web500gw_debug(WEB500GW_DEBUG_TRACE, "ldap_ufn_search_s (%s)\n", 
            search_filter, 0, 0, 0);
#endif
        if ((rc = ldap_ufn_search_s(r->r_ld, search_filter, search_attrs, 0, &res))
            != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED) {
            do_error(r, resp, rc, 0, get_ldap_result_code(r->r_ld), get_ldap_matched_str(r->r_ld));
            return NOTOK;
        }
        count = ldap_count_entries(r->r_ld, res);
#ifdef WEB500GW_DEBUG
        Web500gw_debug(WEB500GW_DEBUG_TRACE, "UFN ready: %d results!\n",
            count, 0, 0, 0);
#endif
        // Reset DN, because this UFN search was probably not below DN
        base_dn = base_ufn = "";
        in_home = 0;

        friendlyDesc = MSG_UFN;

	} else { */
        /* let's do the search */
        filtertype = (scope == LDAP_SCOPE_ONELEVEL ? "web500gw onelevel" :
            "web500gw subtree");

	option_param = (scope == LDAP_SCOPE_ONELEVEL ? LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS);

	ldap_set_option(r->r_ld, LDAP_OPT_DEREF, 
			(void *) &option_param);
        timeout.tv_sec = timelimit;
        timeout.tv_usec = 0;
    
        friendlyDesc = NULL;

        /* try all filters til we have success */
        for (fi = ldap_getfirstfilter(r->r_access->a_filtd, filtertype, search_filter);
            fi != NULL; fi = ldap_getnextfilter(r->r_access->a_filtd)) {
#ifdef WEB500GW_DEBUG
            Web500gw_debug(WEB500GW_DEBUG_FILTER, "  search %s: %s -- %s\n",
                scope == LDAP_SCOPE_ONELEVEL ? "onelevel" : "subtree",
                fi->lfi_filter, fi->lfi_desc, 0);
#endif
            if ((rc = ldap_search_st(r->r_ld, base_dn, scope, fi->lfi_filter,
                search_attrs, 0, &timeout, &res)) != LDAP_SUCCESS && 
                rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_INSUFFICIENT_ACCESS 
                && rc != LDAP_TIMELIMIT_EXCEEDED && rc != LDAP_TIMEOUT
                && rc != LDAP_PARTIAL_RESULTS) {
                do_error(r, resp, rc, 0, get_ldap_result_code(r->r_ld), get_ldap_matched_str(r->r_ld));
                return NOTOK;
            }
            if ((count = ldap_count_entries(r->r_ld, res)) > 0) {
                /* found something */
                friendlyDesc = friendly_label(resp, fi->lfi_desc);
#ifdef WEB500GW_DEBUG
                Web500gw_debug(WEB500GW_DEBUG_FILTER, 
                    " searched ... and found %d results!\n", count, 0, 0, 0);
#endif
                break;
            }
#ifdef WEB500GW_DEBUG
            Web500gw_debug(WEB500GW_DEBUG_FILTER, 
                " searched ... and found no results!\n", 0, 0, 0, 0);
#endif
        }
	option_param = LDAP_DEREF_ALWAYS;
	ldap_set_option(r->r_ld, LDAP_OPT_DEREF, (void *) &option_param);
	/* }*/

    if (count < 1) {        /* nothing found :-( */
        if (r->r_flags & FLAG_SEARCHACT) {
            /* in a search action we silently ignore this */
            return OK;
        }

        resp->resp_status = NOT_FOUND;
        if (resp->resp_httpheader == 0) {
            if (r->r_httpversion == 1) {
                /* Expires now */
                resp->resp_expires = 0;
                http_header(r, resp);
            }
            if (r->r_method == HEAD) {
                return OK;
            }
        }
        if (resp->resp_htmlheader == 0) {
            msg_fprintf(fp, in_home && *MSG_HTML_START_NO_SEARCH_RESULTS_HOME
            ? MSG_HTML_START_NO_SEARCH_RESULTS_HOME : MSG_HTML_START_NO_SEARCH_RESULTS, 
                "ss", print_filter, base_ufn ? base_ufn : MSG_ROOT);
            resp->resp_htmlheader = 1;

            if (!(r->r_flags & FLAG_ENTRYONLY)) {
                if (in_home && MSG_HOMEBANNER) {
                    msg_fprintf(fp, MSG_HOMEBANNER, "sss", r->r_query,
                        other_lang_select, other_lang_string);
                } else {
                    msg_fprintf(fp, MSG_BANNER, "sss", r->r_query,
                        other_lang_select, other_lang_string);
                }
            }
            if (rc == LDAP_INSUFFICIENT_ACCESS) {
                fputs(MSG_NO_LIST_ACCESS, fp);
            } else if (rc == LDAP_TIMELIMIT_EXCEEDED || rc == LDAP_TIMEOUT) {
                fputs(MSG_TIMELIMIT, fp);
            } else {
                if (print_filter && *print_filter) {
                    msg_fprintf(fp, MSG_NO_SEARCH_RESULTS, "ssss",
                    (scope == LDAP_SCOPE_ONELEVEL ?  MSG_ONELEVEL : MSG_SUBTREE),
                    print_filter, human_filter, base_ufn ? base_ufn : MSG_ROOT);
                } else {
                    fputs(MSG_NOTHING_FOUND_READORSEARCH, fp);
                }
            }
            if (!(r->r_flags & FLAG_ENTRYONLY)) {
                make_upsearch(r->r_ld, r, resp, 1);
                if (in_home && MSG_HOMETRAILER) {
                    fputs(MSG_HOMETRAILER, fp);
                } else {
                    fputs(MSG_TRAILER, fp);
                }
            }
            fputs(MSG_HTML_END, fp);
            fputs("\n", fp);
        } else {        
            /* resp->resp_htmlheader != 0 -> within a document (searchaction) */
            if (rc == LDAP_INSUFFICIENT_ACCESS) {
                fputs(MSG_NO_LIST_ACCESS, fp);
            } else if (rc == LDAP_TIMELIMIT_EXCEEDED || rc == LDAP_TIMEOUT) {
                fputs(MSG_TIMELIMIT, fp);
            } else {
                fputs(MSG_NOTHING_FOUND_READORSEARCH, fp);
                fputs(MSG_HTML_END, fp);
                fputs("\n", fp);
            }
        }
        return OK;
    }
    if (showonematch == 1 && count == 1 && r->r_attrnumb == 0 &&
        !(r->r_flags & FLAG_SEARCHACT)) {
    /* header != 0 ? */
        /* only one result and not searching for special attrs (searchaction) */
        e = ldap_first_entry(r->r_ld, res);
        if (e != NULL) {
            char **oc, **aliasdn;
            oc = ldap_get_values(r->r_ld, e, objectclass_attr);
            aliasdn = ldap_get_values(r->r_ld, e, "aliasedObjectName");
            if (aliasdn && *aliasdn)
                result_dn = *aliasdn;
            else
                result_dn = ldap_get_dn(r->r_ld, e);
            if (result_dn) {
                result_ufn = friendly_dn(resp, result_dn);
                if (gwswitch) {
                    server = gw_switch(r->r_ld, resp, e);
                }
                r->r_flags &= ~FLAG_FILTER;    /* it's not a search anymore */
                url_dn = dn2url(r, result_dn, 
                          server ? r->r_flags & ~FLAG_LANGUAGE : r->r_flags, 
                          0, NULL, server);

                /* Redirect */
#ifdef WEB500GW_DEBUG
                Web500gw_debug(WEB500GW_DEBUG_TRACE, 
                    "do_search: found one entry -> REDIRECT: %s\n",
                         url_dn, 0, 0, 0);
#endif
                resp->resp_status = REDIRECT;
                if (resp->resp_httpheader == 0 && r->r_httpversion == 1) {
                    resp->resp_location = malloc(strlen(url_dn) + 11);
                    strcpy(resp->resp_location, url_dn);

                    http_header(r, resp);
                    /* free(resp->resp_location); */
                }
                if (r->r_method == HEAD) {
                    return OK;
                }
                msg_fprintf(fp, in_home && *MSG_HTML_START_SEARCH_RESULTS_HOME ?
                MSG_HTML_START_SEARCH_RESULTS_HOME : MSG_HTML_START_SEARCH_RESULTS, 
                    "ss", print_filter, result_ufn);
                msg_fprintf(fp, MSG_REDIRECT, "ss", url_dn, result_ufn);
                fputs(MSG_HTML_END, fp);
                fputs("\n", fp);
                return OK;
            }
        }
    }

    /* Found something */
    /* Prepare HTTP + HTML header */
    if (resp->resp_httpheader == 0 && r->r_httpversion == 1) {
        http_header(r, resp);
        if (r->r_method == HEAD)
            return OK;
    }
    if (resp->resp_htmlheader == 0) {
        msg_fprintf(fp, in_home && *MSG_HTML_START_SEARCH_RESULTS_HOME ?
            MSG_HTML_START_SEARCH_RESULTS_HOME : MSG_HTML_START_SEARCH_RESULTS, 
            "ss", print_filter, base_ufn ? base_ufn : MSG_ROOT);
        if (!(r->r_flags & FLAG_ENTRYONLY)) {
            if (in_home && MSG_HOMEBANNER) {
                msg_fprintf(fp, MSG_HOMEBANNER, "sss", r->r_query,
                    other_lang_select, other_lang_string);
            } else {
                msg_fprintf(fp, MSG_BANNER, "sss", r->r_query,
                    other_lang_select, other_lang_string);
            }
        }
        resp->resp_htmlheader = 1;
    }
    if ((!(r->r_flags & FLAG_ENTRYONLY)) && 
        (r->r_browser->b_upsearch & UPSEARCH_ON_TOP)) {
        make_upsearch(r->r_ld, r, resp, 1);
    }
    if (r->r_flags & FLAG_FILTER && 
        (!(r->r_flags & FLAG_ENTRYONLY))) {
        /* Not the default filter and not entryonly */

        msg_fprintf(fp, MSG_SEARCH_RESULTS, "ssssisss",
            (scope == LDAP_SCOPE_ONELEVEL ?  MSG_ONELEVEL : MSG_SUBTREE),
            print_filter, human_filter, 
            base_ufn && *base_ufn ? base_ufn : MSG_ROOT,
            count, count == 1 ? MSG_ENTRY : MSG_ENTRIES, friendlyDesc,
            rc == LDAP_PARTIAL_RESULTS ?
            resp->resp_language->l_conf->c_errmsg[LDAP_PARTIAL_RESULTS] : "");
    }
    if (ldap_result2error(r->r_ld, res, 0) == LDAP_SIZELIMIT_EXCEEDED) {
        fprintf(fp, r->r_flags & FLAG_FILTER && r->r_access->a_sizelimit == 0 ? 
            MSG_SIZELIMIT_1 : MSG_SIZELIMIT_0, count);
    }
    
    /* Now prepare the result for sorting */ 

#ifdef WEB500GW_DEBUG
    Web500gw_debug(WEB500GW_DEBUG_TRACE, 
        "do_search: preparing for sort\n", 0, 0, 0, 0);
#endif

    /* for all the results ... */
    for (e = ldap_first_entry(r->r_ld, res); e != NULL && counter < MAX_LISTSIZE; 
         e = ldap_next_entry(r->r_ld, e)) {

        result_dn = ldap_get_dn(r->r_ld, e);
        result_ufn = friendly_dn(resp, result_dn);
        if ((val = ldap_get_values(r->r_ld, e, "aliasedObjectName"))) {
            /* entry is alias */
            free(result_dn);
            result_dn = strdup(*val);
            alias_ufn = friendly_dn(resp, result_dn);
            ldap_value_free(val);
            isalias = 1;
        } else {
            isalias = 0;
        }
        if (isalias && r->r_flags & FLAG_DEREFALIAS) {
            /* if alias, look for objectClass of real entry */
            oc = deref(r->r_ld, result_dn);
        } else {
            oc = ldap_get_values(r->r_ld, e, objectclass_attr);
        }
            
        /* find template to see the plural name of the objectclass */
        tmpl = ldap_oc2template(oc, r->r_access->a_tmpllist);
        doc = pick_oc(oc);
        if (tmpl && tmpl->dt_pluralname) {
            foc = strdup(friendly_label(resp, tmpl->dt_pluralname));
        } else {
            foc = strdup(friendly_label(resp, doc));
            if (strcmp(foc, doc) == 0) {
            /* "no friendly objectclass" found -> last in the list (a hack) */
                foc = (char *)malloc(strlen(doc)+9);
                sprintf(foc, "&#032;%s", doc);
            }
        }
        if (strncasecmp(result_ufn, "{ASN}", 5) == 0) {
            /* ASNs are not something we want to display! */
            free(result_dn);
            ldap_value_free(oc);
            continue;
        }
        if (base_len > 0) {
            /* strip search base from result */
            result_ufn = strip_ufn_dn(result_ufn, base_ufn);
        }
#ifdef nodef
            cp = result_ufn + strlen(result_ufn) - 1;
            bp = base_ufn + base_len - 1;
            while (bp >= base_ufn && *cp-- && *bp-- && *cp == *bp);
            
            if ((bp+1) == base_ufn && cp != NULL) { /* Complete match on base */
                /* strip trailing whitespaces and ',' */
                while (*cp && isspace(*cp)) cp--;
                if (cp != NULL && *cp == ',')
                    *cp = '\0';
            }
        }
#endif
        
        sortstring = strdup(result_ufn);
        if (strcasecmp(doc, "country") == 0) {  /* a country */
            sn = NULL;
        } else {                                /* not a country */
            /* DNs may have components in '"', ignored  when sorting */
            if (*sortstring == '"') {
                sortstring++;
                cp = strchr(sortstring+1, '"');
            } else {
                cp = sortstring;
            }
            if ((cp = strchr(cp,',')))
                *cp = '\0';
            if (isalias) {      /* aliases don't have surnames */
                if (isoc (oc, "person")) {
                }
            }
            sn = ldap_get_values(r->r_ld, e, "sn");
/*  Delete spaces ???
            if (sn) {
                cp = *sn;
                while ((cp = strchr(cp,' '))) {
                    cp ++;
                    spaces ++;
                }
            }
            while (spaces > 0) {
                if ((cp = strrchr(sortstring,' '))) {
                    *cp = '\0';
                    spaces --;
                } else
                    break;
            }
*/
            if ((cp = strchr(sortstring,'+'))) {
                cp --;
                *cp = '\0';
            }
        }

        if (gwswitch) {
            server = gw_switch(r->r_ld, resp, e);
        }
        /* build the link (HREF) */
        if (isalias) {
            if (isnonleaf(r->r_ld, oc, result_dn)) {
                if (r->r_flags & FLAG_NOHREFDN)
                    msg_snprintf(href, sizeof(href), MSG_DN_ALIAS_TO_NONLEAF, 
                        "sss", result_ufn, alias_ufn, html_encode(result_dn));
                else
                    msg_snprintf(href, sizeof(href), MSG_HREF_ALIAS_TO_NONLEAF,
                        "ssssss",
                        dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE,
                        0, NULL, server), result_ufn,
                        alias_ufn, html_encode(result_dn),
                        string_encode(result_ufn),string_encode(result_dn));
            } else {
                if (r->r_flags & FLAG_NOHREFDN)
                    msg_snprintf(href, sizeof(href), MSG_DN_ALIAS_TO_LEAF, 
                        "sss",
                        result_ufn, alias_ufn, html_encode(result_dn));
                else
                    msg_snprintf(href, sizeof(href), MSG_HREF_ALIAS_TO_LEAF,
                        "ssssss",
                        dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0, NULL,
                        server), result_ufn,
                        alias_ufn, html_encode(result_dn),
                        string_encode(result_ufn),string_encode(result_dn));
            }
        } else if (isnonleaf(r->r_ld, oc, result_dn)) {
            if (r->r_flags & FLAG_NOHREFDN)
                msg_snprintf(href, sizeof(href), MSG_DN_NON_LEAF, "ss",
                    result_ufn, html_encode(result_dn));
            else
                msg_snprintf(href, sizeof(href), MSG_HREF_NON_LEAF, "sssss",
                    dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0,
                    NULL, server), result_ufn,
                    html_encode(result_dn), string_encode(result_ufn),
                    string_encode(result_dn));
        } else {
            if (r->r_flags & FLAG_NOHREFDN)
                msg_snprintf(href, sizeof(href), MSG_DN_LEAF, "ss",
                    result_ufn, html_encode(result_dn));
            else
                msg_snprintf(href, sizeof(href), MSG_HREF_LEAF, "sssss",
                    dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0,
                    NULL, server), result_ufn, 
                    html_encode(result_dn), string_encode(result_ufn),
                    string_encode(result_dn));
        }
        /* build the sortstring:  foc[sn]sortstring */
        if (sn) {
            temp = (char *) malloc(strlen(foc)+strlen(*sn)+strlen(sortstring)+1);
        } else {
            temp = (char *) malloc(strlen(foc)+strlen(sortstring)+1);
        }
        strcpy(temp, foc);
        if (sn) {
            strcat(temp, *sn);
        }
        strcat(temp, sortstring);
        if (!dnlist[counter]) {
            dnlist[counter] = (struct dncompare *) malloc(sizeof(struct dncompare));
        }
        dnlist[counter]->sortstring = temp;
        dnlist[counter]->href = strdup(href);
        dnlist[counter]->friendly_oc = foc;
        dnlist[counter]->oc = doc;
        dnlist[counter]->tmpl = tmpl;
        dnlist[counter]->entry = e;
        dnlist[counter]->dn = strdup(result_dn);
        counter++;
        ldap_value_free(oc);
        free(result_dn);
        if (sn)
            ldap_value_free(sn);
    }