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