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