package ldap

  1. Overview
  2. Docs

Source file ldap_filter.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
(* Ldap filter parser driver.

   Copyright (C) 2004 Eric Stokes, and The California State University at
   Northridge

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*)

open Ldap_types
open Ldap_filterparser
open Ldap_filterlexer
open Str

exception Invalid_filter of int * string

(* escape a string to be put in a string representation of a search
   filter *)
let star_rex = Pcre.regexp ~study:true "\\*"
let lparen_rex = Pcre.regexp ~study:true "\\("
let rparen_rex = Pcre.regexp ~study:true "\\)"
let backslash_rex = Pcre.regexp ~study:true "\\Q\\\\E"
let null_rex = Pcre.regexp ~study:true "\\000"
let escape_filterstring s =
  (Pcre.qreplace ~rex:star_rex ~templ:"\\2a"
     (Pcre.qreplace ~rex:lparen_rex ~templ:"\\28"
        (Pcre.qreplace ~rex:rparen_rex ~templ:"\\29"
           (Pcre.qreplace ~rex:null_rex ~templ:"\\00"
              (Pcre.qreplace ~rex:backslash_rex ~templ:"\\5c" s)))))

let of_string f =
  let lxbuf = Lexing.from_string f in
    try filter_and_eof lexfilter lxbuf
    with
        Parsing.Parse_error ->
          raise (Invalid_filter (lxbuf.Lexing.lex_curr_pos, "parse error"))
      | Failure msg ->
          raise (Invalid_filter (lxbuf.Lexing.lex_curr_pos, msg))

let double_star_rex = regexp "\\*\\*"
let to_string (f:filter) =
  let rec to_string' buf f =
    match f with
        `And lst ->
          Buffer.add_string buf "(&";
          List.iter
            (fun f_component -> to_string' buf f_component)
            lst;
          Buffer.add_char buf ')'
      | `Or lst ->
          Buffer.add_string buf "(|";
          List.iter
            (fun f_component -> to_string' buf f_component)
            lst;
          Buffer.add_char buf ')'
      | `Not f_component ->
          Buffer.add_string buf "(!";
          to_string' buf f_component;
          Buffer.add_char buf ')'
      | `EqualityMatch {attributeDesc=attrname;assertionValue=valu} ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attrname;
          Buffer.add_char buf '=';
          Buffer.add_string buf (escape_filterstring valu);
          Buffer.add_char buf ')'
      | `Substrings {attrtype=attrname;
                     substrings={substr_initial=initial;
                                 substr_any=any;
                                 substr_final=final}} ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attrname;
          Buffer.add_char buf '=';
          Buffer.add_string buf
            (global_replace double_star_rex "*"
               ((match initial with
                     [s] -> (escape_filterstring s) ^ "*"
                   | [] -> ""
                   | _ ->
                       raise
                         (Invalid_filter
                            (0, "multiple substring components cannot be represented"))) ^
                  (match any with
                       [] -> ""
                     | lst ->
                         List.fold_left
                           (fun f s -> f ^ "*" ^ (escape_filterstring s) ^ "*")
                           "" lst) ^
                     (match final with
                          [s] -> "*" ^ (escape_filterstring s)
                        | [] -> ""
                        | _ ->
                            raise
                              (Invalid_filter
                                 (0, "multiple substring components cannot be represented")))));
          Buffer.add_char buf ')';
      | `GreaterOrEqual {attributeDesc=attrname;assertionValue=valu} ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attrname;
          Buffer.add_string buf ">=";
          Buffer.add_string buf (escape_filterstring valu);
          Buffer.add_char buf ')'
      | `LessOrEqual {attributeDesc=attrname;assertionValue=valu} ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attrname;
          Buffer.add_string buf "<=";
          Buffer.add_string buf (escape_filterstring valu);
          Buffer.add_char buf ')'
      | `ApproxMatch {attributeDesc=attrname;assertionValue=valu} ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attrname;
          Buffer.add_string buf "~=";
          Buffer.add_string buf (escape_filterstring valu);
          Buffer.add_char buf ')'
      | `Present attr ->
          Buffer.add_char buf '(';
          Buffer.add_string buf attr;
          Buffer.add_string buf "=*";
          Buffer.add_char buf ')'
      | `ExtensibleMatch {matchingRule=rul;ruletype=rtype;
                          matchValue=matchval;dnAttributes=dnattrs} ->
          Buffer.add_char buf '(';
          (match rtype with
               Some attrname ->
                 Buffer.add_string buf attrname;
                 (if dnattrs then
                    Buffer.add_string buf ":dn");
                 (match rul with
                      Some r ->
                        Buffer.add_char buf ':';
                        Buffer.add_string buf r
                    | None -> ());
                 Buffer.add_string buf ":=";
                 Buffer.add_string buf (escape_filterstring matchval)
             | None ->
                 ((if dnattrs then
                     Buffer.add_string buf ":dn");
                  (match rul with
                       Some r ->
                         Buffer.add_char buf ':';
                         Buffer.add_string buf r;
                         Buffer.add_string buf ":=";
                         Buffer.add_string buf (escape_filterstring matchval)
                     | None ->
                         raise
                           (Invalid_filter
                              (0, "matchingRule is required if type is unspecified")))));
          Buffer.add_char buf ')'
  in
  let buf = Buffer.create 100 in
    to_string' buf f;
    Buffer.contents buf