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