~ubuntu-branches/ubuntu/trusty/ejabberd/trusty-proposed

« back to all changes in this revision

Viewing changes to src/eldap/eldap_filter.erl

  • Committer: Bazaar Package Importer
  • Author(s): Konstantin Khomoutov, Konstantin Khomoutov
  • Date: 2010-07-26 20:36:14 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20100726203614-s3asj0k5ym3bxhdw
Tags: 2.1.4-1
[ Konstantin Khomoutov ]
* Do not prevent ejabberd_debug from being installed and used
  as this was implemented upstream as the default behavior.
* Add build dependency on erlang-parsetools.
* Add 'sharedscripts' option to logrotate config.
* Update VCS references in control file to point to git.deb.at.
* Add group sticky bit to permissions on the log directory --
  this should make log files owned by the group "adm".
* Explicitly set umask to 027 before starting erl.
* Add patch with fix for EJAB-953 (closes: #590389).
* Fix call to setup_ejabberd in postinst.
* Fix owner/permissions for log files when upgrading.
* Minor fixes and clarifications in ejabberdctl.8 manual page.
* Refresh reopen-log.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
%%% Purpose: Converts String Representation of
4
4
%%%            LDAP Search Filter (RFC 2254)
5
5
%%%            to eldap's representation of filter
6
 
%%% Author:  Evgeniy Khramtsov <xramtsov@gmail.com>
 
6
%%% Author:  Evgeniy Khramtsov <ekhramtsov@process-one.net>
7
7
%%%
8
8
%%%
9
9
%%% ejabberd, Copyright (C) 2002-2010   ProcessOne
24
24
%%% 02111-1307 USA
25
25
%%%
26
26
%%%----------------------------------------------------------------------
27
 
 
28
27
-module(eldap_filter).
29
28
 
30
 
%%%======================
31
 
%%% Export functions
32
 
%%%======================
33
 
 
34
 
-export([parse/1,
35
 
         parse/2,
36
 
         do_sub/2
37
 
        ]).
38
 
 
39
 
%%%-------------------------------------------------------------------------
 
29
%% TODO: remove this when new regexp module will be used
 
30
-compile({nowarn_deprecated_function, {regexp, sub, 3}}).
 
31
 
 
32
-export([parse/1, parse/2, do_sub/2]).
 
33
 
 
34
%%====================================================================
 
35
%% API
 
36
%%====================================================================
 
37
%%%-------------------------------------------------------------------
40
38
%%% Arity: parse/1
41
39
%%% Function: parse(RFC2254_Filter) -> {ok, EldapFilter}   |
42
40
%%%                                    {error, bad_filter}
47
45
%%%              to eldap's representation of filter.
48
46
%%%
49
47
%%% Example:
50
 
%%%    > eldap_filter:parse("(&(!(uid<=100))(mail=*))").
 
48
%%%   > eldap_filter:parse("(&(!(uid<=100))(mail=*))").
51
49
%%%
52
 
%%%    {ok,{'and',[{'not',{lessOrEqual,{'AttributeValueAssertion',"uid","100"}}},
53
 
%%%            {present,"mail"}]}}
54
 
%%%-------------------------------------------------------------------------
55
 
parse(RFC2254_Filter) ->
56
 
    parse(RFC2254_Filter, []).
 
50
%%%   {ok,{'and',[{'not',{lessOrEqual,{'AttributeValueAssertion',"uid","100"}}},
 
51
%%%           {present,"mail"}]}}
 
52
%%%-------------------------------------------------------------------
 
53
parse(L) when is_list(L) ->
 
54
    parse(L, []).
57
55
 
58
 
%%%-------------------------------------------------------------------------
 
56
%%%-------------------------------------------------------------------
59
57
%%% Arity: parse/2
60
58
%%% Function: parse(RFC2254_Filter, [SubstValue |...]) ->
61
59
%%%                                  {ok, EldapFilter}                 |
81
79
%%%           {equalityMatch,{'AttributeValueAssertion',
82
80
%%%                              "jid",
83
81
%%%                              "xramtsov@gmail.com"}}]}}
84
 
%%%--------------------------------------------------------------------------
85
 
parse(RFC2254_Filter, ListOfSubValues) ->
86
 
    case catch convert_filter(parse_filter(RFC2254_Filter), ListOfSubValues) of
87
 
        [EldapFilter] when is_tuple(EldapFilter) ->
88
 
            {ok, EldapFilter};
89
 
        {regexp, Error} ->
90
 
            {error, Error};
91
 
        _ ->
92
 
            {error, bad_filter}
93
 
    end.
94
 
 
95
 
%%%==========================
96
 
%%% Internal functions
97
 
%%%==========================
98
 
 
99
 
%%%----------------------
100
 
%%% split/1,4
101
 
%%%----------------------
102
 
split(Filter) ->
103
 
    split(Filter, 0, [], []).
104
 
 
105
 
split([], _, _, Result) ->
106
 
    Result;
107
 
 
108
 
split([H|T], Num, Rest, Result) ->
109
 
    NewNum = case H of
110
 
                 $( -> Num + 1;
111
 
                    $) -> Num - 1;
112
 
                 _ -> Num
113
 
             end,
114
 
    if
115
 
        NewNum == 0 ->
116
 
            X = Rest++[H],
117
 
            LenX = length(X),
118
 
            if
119
 
                LenX > 2 ->
120
 
                    split(T, 0, [], Result ++ [lists:sublist(X, 2, LenX-2)]);
121
 
                true ->
122
 
                    split(T, 0, Rest, Result)
123
 
            end;
124
 
        true ->
125
 
            split(T, NewNum, Rest++[H], Result)
126
 
    end.
127
 
 
128
 
%%%-----------------------
129
 
%%% parse_filter/1
130
 
%%%-----------------------
131
 
parse_filter(Filter) ->
132
 
    case Filter of
133
 
        [$! | T] ->
134
 
            {'not', parse_filter(T)};
135
 
        [$| | T] ->
136
 
            {'or', parse_filter(T)};
137
 
        [$& | T] ->
138
 
            {'and', parse_filter(T)};
139
 
        [$( | _] ->
140
 
                parse_filter(split(Filter));
141
 
        [List | _] when is_list(List) ->
142
 
            [parse_filter(X) || X <- Filter];
143
 
        _ ->
144
 
            Filter
145
 
    end.
146
 
 
147
 
%%%--------------------
148
 
%%% convert_filter/2
149
 
%%%--------------------
150
 
convert_filter({'not', [Val | _]}, Replace) ->
151
 
    eldap:'not'(convert_filter(Val, Replace));
152
 
 
153
 
convert_filter({'or', Vals}, Replace) ->
154
 
    eldap:'or'([convert_filter(X, Replace) || X <- Vals]);
155
 
 
156
 
convert_filter({'and', Vals}, Replace) ->
157
 
    eldap:'and'([convert_filter(X, Replace) || X <- Vals]);
158
 
 
159
 
convert_filter([H|_] = Filter, Replace) when is_integer(H) ->
160
 
    parse_attr(Filter, Replace);
161
 
 
162
 
convert_filter(Filter, Replace) when is_list(Filter) ->
163
 
    [convert_filter(X, Replace) || X <- Filter].
164
 
 
165
 
%%%-----------------
166
 
%%% parse_attr/2,3
167
 
%%%-----------------
168
 
parse_attr(Attr, ListOfSubValues) ->
169
 
    {Action, [_|_] = Name, [_|_] = Value} = split_attribute(Attr),
170
 
    parse_attr(Action, {Name, Value}, ListOfSubValues).
171
 
 
172
 
parse_attr(approx, {Name, Value}, ListOfSubValues) ->
173
 
    NewValue = do_sub(Value, ListOfSubValues),
174
 
    eldap:approxMatch(Name, NewValue);
175
 
 
176
 
parse_attr(greater, {Name, Value}, ListOfSubValues) ->
177
 
    NewValue = do_sub(Value, ListOfSubValues),
178
 
    eldap:greaterOrEqual(Name, NewValue);
179
 
 
180
 
parse_attr(less, {Name, Value}, ListOfSubValues) ->
181
 
    NewValue = do_sub(Value, ListOfSubValues),
182
 
    eldap:lessOrEqual(Name, NewValue);
183
 
 
184
 
parse_attr(equal, {Name, Value}, ListOfSubValues) ->
185
 
    {ok, RegSList} = regexp:split(remove_extra_asterisks(Value), "[*]"),
186
 
    Pattern = case [do_sub(X, ListOfSubValues) || X <- RegSList] of
187
 
                  [Head | Tail] when Tail /= [] ->
188
 
                      {Head, lists:sublist(Tail, length(Tail)-1), lists:last(Tail)};
189
 
                  R ->
190
 
                      R
191
 
              end,
192
 
    case Pattern of
193
 
        [V] ->
194
 
            eldap:equalityMatch(Name, V);
195
 
        {[], [], []} ->
196
 
            eldap:present(Name);
197
 
        {"", Any, ""} ->
198
 
            eldap:substrings(Name, [{any, X} || X<-Any]);
199
 
        {H, Any, ""} ->
200
 
            eldap:substrings(Name, [{initial, H}]++[{any, X} || X<-Any]);
201
 
        {"", Any, T} ->
202
 
            eldap:substrings(Name, [{any, X} || X<-Any]++[{final, T}]);
203
 
        {H, Any, T} ->
204
 
            eldap:substrings(Name, [{initial, H}]++[{any, X} || X<-Any]++[{final, T}])
205
 
    end;
206
 
 
207
 
parse_attr(_, _, _) ->
208
 
    false.
209
 
 
210
 
%%%--------------------
211
 
%%% do_sub/2,3
212
 
%%%--------------------
 
82
%%%-------------------------------------------------------------------
 
83
parse(L, SList) when is_list(L), is_list(SList) ->
 
84
    case catch eldap_filter_yecc:parse(scan(L, SList)) of
 
85
        {error, {_, _, Msg}} ->
 
86
            {error, Msg};
 
87
        {ok, Result} ->
 
88
            {ok, Result};
 
89
        {regexp, Err} ->
 
90
            {error, Err}
 
91
    end.
 
92
 
 
93
%%====================================================================
 
94
%% Internal functions
 
95
%%====================================================================
 
96
-define(do_scan(L), scan(Rest, [], [{L, 1} | check(Buf, S) ++ Result], L, S)).
 
97
 
 
98
scan(L, SList) ->
 
99
    scan(L, "", [], undefined, SList).
 
100
 
 
101
scan("=*)" ++ Rest, Buf, Result, '(', S) ->
 
102
    scan(Rest, [], [{')', 1}, {'=*', 1} | check(Buf, S) ++ Result], ')', S);
 
103
scan(":dn" ++ Rest, Buf, Result, '(', S) -> ?do_scan(':dn');
 
104
scan(":=" ++ Rest, Buf, Result, '(', S) -> ?do_scan(':=');
 
105
scan(":=" ++ Rest, Buf, Result, ':dn', S) -> ?do_scan(':=');
 
106
scan(":=" ++ Rest, Buf, Result, ':', S) -> ?do_scan(':=');
 
107
scan("~=" ++ Rest, Buf, Result, '(', S) -> ?do_scan('~=');
 
108
scan(">=" ++ Rest, Buf, Result, '(', S) -> ?do_scan('>=');
 
109
scan("<=" ++ Rest, Buf, Result, '(', S) -> ?do_scan('<=');
 
110
scan("="  ++ Rest, Buf, Result, '(', S) -> ?do_scan('=');
 
111
scan(":"  ++ Rest, Buf, Result, '(', S) -> ?do_scan(':');
 
112
scan(":"  ++ Rest, Buf, Result, ':dn', S) -> ?do_scan(':');
 
113
scan("&"  ++ Rest, Buf, Result, '(', S) when Buf=="" -> ?do_scan('&');
 
114
scan("|"  ++ Rest, Buf, Result, '(', S) when Buf=="" -> ?do_scan('|');
 
115
scan("!"  ++ Rest, Buf, Result, '(', S) when Buf=="" -> ?do_scan('!');
 
116
scan("*"  ++ Rest, Buf, Result, '*', S) -> ?do_scan('*');
 
117
scan("*"  ++ Rest, Buf, Result, '=', S) -> ?do_scan('*');
 
118
scan("("  ++ Rest, Buf, Result, _, S) -> ?do_scan('(');
 
119
scan(")"  ++ Rest, Buf, Result, _, S) -> ?do_scan(')');
 
120
scan([Letter | Rest], Buf, Result, PreviosAtom, S) ->
 
121
    scan(Rest, [Letter|Buf], Result, PreviosAtom, S);
 
122
scan([], Buf, Result, _, S) ->
 
123
    lists:reverse(check(Buf, S) ++ Result).
 
124
 
 
125
check([], _) ->
 
126
    [];
 
127
check(Buf, S) ->
 
128
    [{str, 1, do_sub(lists:reverse(Buf), S)}].
213
129
 
214
130
-define(MAX_RECURSION, 100).
215
131
 
234
150
        {ok, NewS, _} when Iter =< ?MAX_RECURSION ->
235
151
            do_sub(NewS, {RegExp, New}, Iter+1);
236
152
        {ok, _, _} when Iter > ?MAX_RECURSION ->
237
 
            throw({regexp, max_substitute_recursion});
 
153
            erlang:error(max_substitute_recursion);
238
154
        _ ->
239
 
            throw({regexp, bad_regexp})
 
155
            erlang:error(bad_regexp)
240
156
    end;
241
157
 
242
158
do_sub(S, {_, _, N}, _) when N<1 ->
251
167
        {ok, NewS, _} ->
252
168
            NewS;
253
169
        _ ->
254
 
            throw({regexp, bad_regexp})
 
170
            erlang:error(bad_regexp)
255
171
    end.
256
172
 
257
 
remove_extra_asterisks(String) ->
258
 
    {Res, _} = lists:foldl(
259
 
                 fun(X, {Acc, Last}) ->
260
 
                         case X of
261
 
                             $* when Last==$* ->
262
 
                                 {Acc, X};
263
 
                             _ ->
264
 
                                 {Acc ++ [X], X}
265
 
                         end
266
 
                 end,
267
 
                 {"", ""}, String),
268
 
    Res.
269
 
 
270
173
replace_amps(String) ->
271
 
        lists:foldl(
272
 
                fun(X, Acc) ->
273
 
                        if
274
 
                                X == $& ->
275
 
                                        Acc ++ "\\&";
276
 
                                true ->
277
 
                                        Acc ++ [X]
278
 
                        end
279
 
                end,
280
 
        "", String).
281
 
 
282
 
split_attribute(String) ->
283
 
    split_attribute(String, "", $0).
284
 
 
285
 
split_attribute([], _, _) ->
286
 
    {error, "", ""};
287
 
 
288
 
split_attribute([H|Tail], Acc, Last) ->
289
 
    case H of
290
 
        $= when Last==$> ->
291
 
            {greater, lists:sublist(Acc, 1, length(Acc)-1), Tail};
292
 
        $= when Last==$< ->
293
 
            {less, lists:sublist(Acc, 1, length(Acc)-1), Tail};
294
 
        $= when Last==$~ ->
295
 
            {approx, lists:sublist(Acc, 1, length(Acc)-1), Tail};
296
 
        $= when Last==$: ->
297
 
            {equal, lists:sublist(Acc, 1, length(Acc)-1), Tail};
298
 
        $= ->
299
 
            {equal, Acc, Tail};
300
 
        _ ->
301
 
            split_attribute(Tail, Acc++[H], H)
302
 
    end.
 
174
    lists:map(
 
175
      fun($&) -> "\\&";
 
176
         (Chr) -> Chr
 
177
      end, String).