summaryrefslogtreecommitdiffstats
path: root/scan_ldapsearchfilterstring.c
blob: 5c478ba109e684a9de02cadac5321c6912a71917 (plain) (blame)
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
#include <stdlib.h>
#include "ldap.h"
#include <str.h>

size_t scan_ldapsearchfilterstring(const char* src,struct Filter** f) {
  char* s=(char*)src;
  if (!(*f=calloc(sizeof(struct Filter),1))) goto error;
  if (s[0]=='*' && (s[1]==0 || s[1]=='(')) {
    size_t i=scan_ldapsearchfilterstring("(objectClass=*)",f);
    if (i) return 1;
  }
  if (*s!='(') goto error;
  switch (*(++s)) {
  case '&': ++s; (*f)->type=AND;
scan_filterlist:
    {
      struct Filter** n;
      s+=scan_ldapsearchfilterstring(s,&(*f)->x);
      n=&(*f)->x->next;
      while (*s!=')') {
	size_t l=scan_ldapsearchfilterstring(s,n);
	if (!l) return 0;
	s+=l;
	n=&(*n)->next;
      }
    }
    break;
  case '|': ++s; (*f)->type=OR;
    goto scan_filterlist;
    break;
  case '!':
    (*f)->type=NOT;
    ++s;
    s+=scan_ldapsearchfilterstring(s,&(*f)->x);
    break;
  default:
    (*f)->ava.desc.s=s;
    (*f)->ava.desc.l=str_chr(s,'=')-1;
    s+=(*f)->ava.desc.l+1;
    switch (*(s-1)) {
      case '~': (*f)->type=APPROX; break;
      case '>': (*f)->type=GREATEQUAL; break;
      case '<': (*f)->type=LESSEQUAL; break;
      default:
	++(*f)->ava.desc.l;
	if (*(++s)=='*') {
	  if (*(++s)==')') {
	    (*f)->type=PRESENT;
	    return s-src;
	  }
	 (*f)->type=SUBSTRING;
substring:
	  while (*s!=')') {
	    size_t i,j;
	    struct Substring* substring=malloc(sizeof(struct Substring));
	    if (!substring) goto error;
	    substring->s.s=s;
	    i=str_chr(s,')');
	    j=str_chr(s,'*');
	    if (i>j) {
	      substring->substrtype=any;
	      s+=substring->s.l=j;
	      ++s;
	    } else {
	      substring->substrtype=suffix;
	      s+=substring->s.l=i;
	    }
	    substring->next=(*f)->substrings;
	    (*f)->substrings=substring;
	    if (*s==0) goto error;
	  }
	} else {
	  size_t i,j;
	  i=str_chr(s,')');
	  j=str_chr(s,'*');
	  if (i>j) {
	    struct Substring* substring=malloc(sizeof(struct Substring));
	    if (!substring) goto error;
	    (*f)->type=SUBSTRING;
	    substring->substrtype=prefix;
	    substring->s.s=s;
	    s+=substring->s.l=j;
	    ++s;
	    substring->next=(*f)->substrings;
	    (*f)->substrings=substring;
	    goto substring;
	  } else {
	    (*f)->type=EQUAL;
	  }
	}
    }
    if (*s=='=') ++s;
    (*f)->ava.value.s=s;
    s+=(*f)->ava.value.l=str_chr(s,')');
    if (*s!=')') return 0;
  }
  return s-src+1;
error:
  return 0;
}