aboutsummaryrefslogtreecommitdiff
path: root/src/eldap
diff options
context:
space:
mode:
authorMickaël Rémond <mickael.remond@process-one.net>2006-10-17 12:35:47 +0000
committerMickaël Rémond <mickael.remond@process-one.net>2006-10-17 12:35:47 +0000
commitd5792ed75ec807b01c6f31ff23f7ee183f57dc20 (patch)
treed202e718831c2712ac746e407ed33d64dc358c4e /src/eldap
parent* src/mod_privacy_odbc.erl: Privacy rules support using odbc (diff)
* src/ejabberd_auth_ldap.erl: LDAP authentication now allows to
match on several alternative attributes. * src/mod_vcard_ldap.erl: Likewise. * doc/guide.tex: Updated. * eldap_utils.erl: Refactoring. * src/eldap/Makefile.in: Likewise. SVN Revision: 661
Diffstat (limited to 'src/eldap')
-rw-r--r--src/eldap/Makefile.in3
-rw-r--r--src/eldap/eldap_utils.erl110
2 files changed, 112 insertions, 1 deletions
diff --git a/src/eldap/Makefile.in b/src/eldap/Makefile.in
index 72e7b4632..de7933831 100644
--- a/src/eldap/Makefile.in
+++ b/src/eldap/Makefile.in
@@ -13,7 +13,8 @@ EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)/eldap.beam \
$(OUTDIR)/ELDAPv3.beam \
- $(OUTDIR)/eldap_filter.beam
+ $(OUTDIR)/eldap_filter.beam \
+ $(OUTDIR)/eldap_utils.beam
all: $(OBJS)
diff --git a/src/eldap/eldap_utils.erl b/src/eldap/eldap_utils.erl
new file mode 100644
index 000000000..b4eb67f86
--- /dev/null
+++ b/src/eldap/eldap_utils.erl
@@ -0,0 +1,110 @@
+%%%----------------------------------------------------------------------
+%%% File : eldap_utils.erl
+%%% Author : Mickael Remond <mickael.remond@process-one.net>
+%%% Purpose : ejabberd LDAP helper functions
+%%% Created : 12 Oct 2006 by Mickael Remond <mickael.remond@process-one.net>
+%%% Id : $Id: ejabberd_auth_ldap.erl 623 2006-09-23 09:52:53Z mremond $
+%%%----------------------------------------------------------------------
+
+-module(eldap_utils).
+-author('mickael.remond@process-one.net').
+-svn('$Revision: $ ').
+
+-export([generate_subfilter/1,
+ find_ldap_attrs/2,
+ get_ldap_attr/2,
+ usort_attrs/1,
+ get_user_part/2,
+ make_filter/2]).
+
+%% Generate an 'or' LDAP query on one or several attributes
+%% If there is only one attribute
+generate_subfilter([UID]) ->
+ subfilter(UID);
+%% If there is several attributes
+generate_subfilter(UIDs) ->
+ "(|" ++ [subfilter(UID) || UID <- UIDs] ++ ")".
+%% Subfilter for a single attribute
+subfilter({UIDAttr, UIDAttrFormat}) ->
+ "(" ++ UIDAttr ++ "=" ++ UIDAttrFormat ++ ")";
+%% The default UiDAttrFormat is %u
+subfilter({UIDAttr}) ->
+ "(" ++ UIDAttr ++ "=" ++ "%u)".
+
+%% Not tail-recursive, but it is not very terribly.
+%% It stops finding on the first not empty value.
+find_ldap_attrs([{Attr, Format} | Rest], Attributes) ->
+ case get_ldap_attr(Attr, Attributes) of
+ Value when is_list(Value), Value /= "" ->
+ {Value, Format};
+ _ ->
+ find_ldap_attrs(Rest, Attributes)
+ end;
+find_ldap_attrs([], _) ->
+ "".
+
+get_ldap_attr(LDAPAttr, Attributes) ->
+ Res = lists:filter(
+ fun({Name, _}) ->
+ case_insensitive_match(Name, LDAPAttr)
+ end, Attributes),
+ case Res of
+ [{_, [Value|_]}] -> Value;
+ _ -> ""
+ end.
+
+
+usort_attrs(Attrs) when is_list(Attrs) ->
+ lists:usort(Attrs);
+usort_attrs(_) ->
+ [].
+
+get_user_part(String, Pattern) ->
+ F = fun(S, P) ->
+ First = string:str(P, "%u"),
+ TailLength = length(P) - (First+1),
+ string:sub_string(S, First, length(S) - TailLength)
+ end,
+ case catch F(String, Pattern) of
+ {'EXIT', _} ->
+ {error, badmatch};
+ Result ->
+ case regexp:sub(Pattern, "%u", Result) of
+ {ok, String, _} -> {ok, Result};
+ _ -> {error, badmatch}
+ end
+ end.
+
+make_filter(Data, UIDs) ->
+ NewUIDs = [{U, eldap_filter:do_sub(UF, [{"%u", "*%u*", 1}])} || {U, UF} <- UIDs],
+ Filter = lists:flatmap(
+ fun({Name, [Value | _]}) ->
+ case Name of
+ "%u" when Value /= "" ->
+ case eldap_filter:parse(
+ lists:flatten(generate_subfilter(NewUIDs)),
+ [{"%u", Value}]) of
+ {ok, F} -> [F];
+ _ -> []
+ end;
+ _ when Value /= "" ->
+ [eldap:substrings(Name, [{any, Value}])];
+ _ ->
+ []
+ end
+ end, Data),
+ case Filter of
+ [F] ->
+ F;
+ _ ->
+ eldap:'and'(Filter)
+ end.
+
+case_insensitive_match(X, Y) ->
+ X1 = stringprep:tolower(X),
+ Y1 = stringprep:tolower(Y),
+ if
+ X1 == Y1 -> true;
+ true -> false
+ end.
+