]> git.sur5r.net Git - openldap/blob - servers/slapd/sets.c
Fix aci link error.
[openldap] / servers / slapd / sets.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8 #include <ac/string.h>
9
10 #include "sets.h"
11
12 static char **set_join (char **lset, int op, char **rset);
13 static char **set_chase (SET_GATHER gatherer, void *cookie, char **set, char *attr, int attrlen, int closure);
14 static int set_samedn (char *dn1, char *dn2);
15
16 long
17 set_size (char **set)
18 {
19         int i;
20
21         i = 0;
22         if (set != NULL) {
23                 while (set[i])
24                         i++;
25         }
26         return(i);
27 }
28
29 void
30 set_dispose (char **set)
31 {
32         int i;
33
34         if (set != NULL) {
35                 for (i = 0; set[i]; i++)
36                         ch_free(set[i]);
37                 ch_free(set);
38         }
39 }
40
41 static char **
42 set_join (char **lset, int op, char **rset)
43 {
44         char **set;
45         long i, j, last;
46
47         set = NULL;
48         if (op == '|') {
49                 if (lset == NULL || *lset == NULL) {
50                         if (rset == NULL) {
51                                 if (lset == NULL)
52                                         return(ch_calloc(1, sizeof(char *)));
53                                 return(lset);
54                         }
55                         set_dispose(lset);
56                         return(rset);
57                 }
58                 if (rset == NULL || *rset == NULL) {
59                         set_dispose(rset);
60                         return(lset);
61                 }
62
63                 i = set_size(lset) + set_size(rset) + 1;
64                 set = ch_calloc(i, sizeof(char *));
65                 if (set != NULL) {
66                         /* set_chase() depends on this routine to
67                          * keep the first elements of the result
68                          * set the same (and in the same order)
69                          * as the left-set.
70                          */
71                         for (i = 0; lset[i]; i++)
72                                 set[i] = lset[i];
73                         ch_free(lset);
74                         for (i = 0; rset[i]; i++) {
75                                 for (j = 0; set[j]; j++) {
76                                         if (set_samedn(rset[i], set[j])) {
77                                                 ch_free(rset[i]);
78                                                 rset[i] = NULL;
79                                                 break;          
80                                         }       
81                                 }
82                                 if (rset[i])
83                                         set[j] = rset[i];
84                         }
85                         ch_free(rset);
86                 }
87                 return(set);
88         }
89
90         if (op == '&') {
91                 if (lset == NULL || *lset == NULL || rset == NULL || *rset == NULL) {
92                         set = ch_calloc(1, sizeof(char *));
93                 } else {
94                         set = lset;
95                         lset = NULL;
96                         last = set_size(set) - 1;
97                         for (i = 0; set[i]; i++) {
98                                 for (j = 0; rset[j]; j++) {
99                                         if (set_samedn(set[i], rset[j]))
100                                                 break;
101                                 }
102                                 if (rset[j] == NULL) {
103                                         ch_free(set[i]);
104                                         set[i] = set[last];
105                                         set[last] = NULL;
106                                         last--;
107                                         i--;
108                                 }
109                         }
110                 }
111         }
112
113         set_dispose(lset);
114         set_dispose(rset);
115         return(set);
116 }
117
118 static char **
119 set_chase (SET_GATHER gatherer, void *cookie, char **set, char *attr, int attrlen, int closure)
120 {
121         char **vals, **nset;
122         char attrstr[32];
123         int i;
124
125         if (set == NULL)
126                 return(ch_calloc(1, sizeof(char *)));
127
128         if (*set == NULL)
129                 return(set);
130
131         if (attrlen > (sizeof(attrstr) - 1)) {
132                 set_dispose(set);
133                 return(NULL);
134         }
135         memcpy(attrstr, attr, attrlen);
136         attrstr[attrlen] = 0;
137
138         nset = ch_calloc(1, sizeof(char *));
139         if (nset == NULL) {
140                 set_dispose(set);
141                 return(NULL);
142         }
143         for (i = 0; set[i]; i++) {
144                 vals = (gatherer)(cookie, set[i], attrstr);
145                 if (vals != NULL)
146                         nset = set_join(nset, '|', vals);
147         }
148         set_dispose(set);
149
150         if (closure) {
151                 for (i = 0; nset[i]; i++) {
152                         vals = (gatherer)(cookie, nset[i], attrstr);
153                         if (vals != NULL) {
154                                 nset = set_join(nset, '|', vals);
155                                 if (nset == NULL)
156                                         break;
157                         }
158                 }
159         }
160         return(nset);
161 }
162
163 static int
164 set_samedn (char *dn1, char *dn2)
165 {
166         char c1, c2;
167
168         while (*dn1 == ' ') dn1++;
169         while (*dn2 == ' ') dn2++;
170         while (*dn1 || *dn2) {
171                 if (*dn1 != '=' && *dn1 != ','
172                         && *dn2 != '=' && *dn2 != ',')
173                 {
174                         c1 = *dn1++;
175                         c2 = *dn2++;
176                         if (c1 >= 'a' && c1 <= 'z')
177                                 c1 -= 'a' - 'A';
178                         if (c2 >= 'a' && c2 <= 'z')
179                                 c2 -= 'a' - 'A';
180                         if (c1 != c2)
181                                 return(0);
182                 } else {
183                         while (*dn1 == ' ') dn1++;
184                         while (*dn2 == ' ') dn2++;
185                         if (*dn1++ != *dn2++)
186                                 return(0);
187                         while (*dn1 == ' ') dn1++;
188                         while (*dn2 == ' ') dn2++;
189                 }
190         }
191         return(1);
192 }
193
194 int
195 set_filter (SET_GATHER gatherer, void *cookie, char *filter, char *user, char *this, char ***results)
196 {
197         #define IS_SET(x)       ( (long)(x) >= 256 )
198         #define IS_OP(x)        ( (long)(x) < 256 )
199         #define SF_ERROR(x)     { rc = -1; goto _error; }
200         #define SF_TOP()        (char **)( (stp < 0) ? 0 : stack[stp] )
201         #define SF_POP()        (char **)( (stp < 0) ? 0 : stack[stp--] )
202         #define SF_PUSH(x)      { if (stp >= 63) SF_ERROR(overflow); stack[++stp] = (char **)(long)(x); }
203         char c;
204         char **set, **lset;
205         int len, op, rc, stp;
206         char **stack[64];
207
208         if (results)
209                 *results = NULL;
210
211         stp = -1;
212         while (c = *filter++) {
213                 set = NULL;
214                 switch (c) {
215                 case ' ':
216                 case '\t':
217                 case '\x0A':
218                 case '\x0D':
219                         break;
220
221                 case '(':
222                         if (IS_SET(SF_TOP()))
223                                 SF_ERROR(syntax);
224                         SF_PUSH(c);
225                         break;
226
227                 case ')':
228                         set = SF_POP();
229                         if (IS_OP(set))
230                                 SF_ERROR(syntax);
231                         if (SF_TOP() == (void *)'(') {
232                                 SF_POP();
233                                 SF_PUSH(set);
234                                 set = NULL;
235                         } else if (IS_OP(SF_TOP())) {
236                                 op = (long)SF_POP();
237                                 lset = SF_POP();
238                                 SF_POP();
239                                 set = set_join(lset, op, set);
240                                 if (set == NULL)
241                                         SF_ERROR(memory);
242                                 SF_PUSH(set);
243                                 set = NULL;
244                         } else {
245                                 SF_ERROR(syntax);
246                         }
247                         break;
248
249                 case '&':
250                 case '|':
251                         set = SF_POP();
252                         if (IS_OP(set))
253                                 SF_ERROR(syntax);
254                         if (SF_TOP() == 0 || SF_TOP() == (void *)'(') {
255                                 SF_PUSH(set);
256                                 set = NULL;
257                         } else if (IS_OP(SF_TOP())) {
258                                 op = (long)SF_POP();
259                                 lset = SF_POP();
260                                 set = set_join(lset, op, set);
261                                 if (set == NULL)
262                                         SF_ERROR(memory);
263                                 SF_PUSH(set);
264                                 set = NULL;
265                         } else {
266                                 SF_ERROR(syntax);
267                         }
268                         SF_PUSH(c);
269                         break;
270
271                 case '[':
272                         if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
273                                 SF_ERROR(syntax);
274                         for (   len = 0;
275                                         (c = *filter++) && (c != ']');
276                                         len++)
277                         { }
278                         if (c == 0)
279                                 SF_ERROR(syntax);
280                         
281                         set = ch_calloc(2, sizeof(char *));
282                         if (set == NULL)
283                                 SF_ERROR(memory);
284                         *set = ch_calloc(len + 1, sizeof(char));
285                         if (*set == NULL)
286                                 SF_ERROR(memory);
287                         memcpy(*set, &filter[-len - 1], len);
288                         SF_PUSH(set);
289                         set = NULL;
290                         break;
291
292                 case '-':
293                         c = *filter++;
294                         if (c != '>')
295                                 SF_ERROR(syntax);
296                         /* fall through to next case */
297
298                 case '/':
299                         if (IS_OP(SF_TOP()))
300                                 SF_ERROR(syntax);
301                         SF_PUSH('/');
302                         break;
303
304                 default:
305                         if ((c != '_')
306                                 && (c < 'A' || c > 'Z')
307                                 && (c < 'a' || c > 'z'))
308                         {
309                                 SF_ERROR(syntax);
310                         }
311                         filter--;
312                         for (   len = 1;
313                                         (c = filter[len])
314                                                 && ((c >= '0' && c <= '9')
315                                                         || (c >= 'A' && c <= 'Z')
316                                                         || (c >= 'a' && c <= 'z'));
317                                         len++)
318                         { }
319                         if (len == 4
320                                 && memcmp("this", filter, len) == 0)
321                         {
322                                 if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
323                                         SF_ERROR(syntax);
324                                 set = ch_calloc(2, sizeof(char *));
325                                 if (set == NULL)
326                                         SF_ERROR(memory);
327                                 *set = ch_strdup(this);
328                                 if (*set == NULL)
329                                         SF_ERROR(memory);
330                         } else if (len == 4
331                                 && memcmp("user", filter, len) == 0) 
332                         {
333                                 if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
334                                         SF_ERROR(syntax);
335                                 set = ch_calloc(2, sizeof(char *));
336                                 if (set == NULL)
337                                         SF_ERROR(memory);
338                                 *set = ch_strdup(user);
339                                 if (*set == NULL)
340                                         SF_ERROR(memory);
341                         } else if (SF_TOP() != (void *)'/') {
342                                 SF_ERROR(syntax);
343                         } else {
344                                 SF_POP();
345                                 set = set_chase(gatherer, cookie, SF_POP(), filter, len, c == '*');
346                                 if (set == NULL)
347                                         SF_ERROR(memory);
348                                 if (c == '*')
349                                         len++;
350                         }
351                         filter += len;
352                         SF_PUSH(set);
353                         set = NULL;
354                         break;
355                 }
356         }
357
358         set = SF_POP();
359         if (IS_OP(set))
360                 SF_ERROR(syntax);
361         if (SF_TOP() == 0) {
362
363         } else if (IS_OP(SF_TOP())) {
364                 op = (long)SF_POP();
365                 lset = SF_POP();
366                 set = set_join(lset, op, set);
367                 if (set == NULL)
368                         SF_ERROR(memory);
369         } else {
370                 SF_ERROR(syntax);
371         }
372
373         rc = set_size(set);
374         if (results) {
375                 *results = set;
376                 set = NULL;
377         }
378
379 _error:
380         if (IS_SET(set))
381                 set_dispose(set);
382         while (set = SF_POP()) {
383                 if (IS_SET(set))
384                         set_dispose(set);
385         }
386         return(rc);
387 }