add case sensitive matching
This commit is contained in:
6
Makefile
6
Makefile
@@ -16,7 +16,8 @@ freefilter.o freeava.o scan_ldapava.o fmt_ldapsearchresultentry.o \
|
||||
fmt_ldapstring.o freepal.o scan_ldapsearchresultentry.o \
|
||||
fmt_ldapresult.o fmt_ldappal.o fmt_ldapadl.o fmt_ldapava.o \
|
||||
fmt_ldapsearchfilter.o fmt_ldapsearchrequest.o matchstring.o \
|
||||
matchprefix.o scan_ldapmodifyrequest.o
|
||||
matchprefix.o byte_case_diff.o matchcasestring.o matchcaseprefix.o \
|
||||
scan_ldapmodifyrequest.o
|
||||
|
||||
ldif.a: ldif_parse.o ldap_match.o ldap_match_mapped.o
|
||||
|
||||
@@ -42,9 +43,8 @@ endif
|
||||
t1 parse: ldif.a storage.a
|
||||
t2: ldap.a asn1.a
|
||||
t3 t4 t5 addindex: storage.a
|
||||
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str: ldap.a asn1.a
|
||||
|
||||
tinyldap tinyldap_standalone tinyldap_debug: ldif.a storage.a
|
||||
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str: ldap.a asn1.a
|
||||
|
||||
tinyldap_standalone: tinyldap.c
|
||||
$(DIET) $(CC) $(CFLAGS) -DSTANDALONE -o $@ $^ -lowfat
|
||||
|
||||
27
addindex.c
27
addindex.c
@@ -2,6 +2,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <string.h>
|
||||
#include "buffer.h"
|
||||
#include "mmap.h"
|
||||
#include "uint32.h"
|
||||
@@ -12,17 +13,21 @@ char* map;
|
||||
|
||||
int compar(const void* a,const void* b) {
|
||||
return strcmp(map+*(uint32*)a,map+*(uint32*)b);
|
||||
// return *(uint32*)b - *(uint32*)a;
|
||||
}
|
||||
|
||||
int compari(const void* a,const void* b) {
|
||||
return strcasecmp(map+*(uint32*)a,map+*(uint32*)b);
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[]) {
|
||||
long filelen;
|
||||
char* filename=argv[1]?argv[1]:"data";
|
||||
char* filename=argv[1];
|
||||
uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
uint32 wanted,dn,objectClass;
|
||||
uint32 wanted,casesensitive,dn,objectClass;
|
||||
|
||||
if (argc<3) {
|
||||
buffer_putsflush(buffer_2,"usage: ./addindex filename attribute\n");
|
||||
buffer_putsflush(buffer_2,"usage: ./addindex filename attribute [i]\n"
|
||||
"if i is present, make index case insensitive.\n");
|
||||
return 1;
|
||||
}
|
||||
map=mmap_read(filename,&filelen);
|
||||
@@ -45,7 +50,13 @@ int main(int argc,char* argv[]) {
|
||||
uint32_unpack(x,&j);
|
||||
if (!strcmp(map+j,argv[2])) {
|
||||
buffer_putsflush(buffer_2,"found attribute!\n");
|
||||
wanted=j;
|
||||
wanted=j; casesensitive=x+attribute_count*4-map;
|
||||
uint32_unpack(map+casesensitive,&j);
|
||||
if (j) {
|
||||
buffer_putsflush(buffer_2,"case sensitivity flag is nonzero?!\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (!strcmp(map+j,"dn"))
|
||||
dn=j;
|
||||
else if (!strcmp(map+j,"objectClass"))
|
||||
@@ -87,7 +98,10 @@ int main(int argc,char* argv[]) {
|
||||
}
|
||||
buffer_putulong(buffer_1,counted);
|
||||
buffer_putsflush(buffer_1," entries to be sorted...");
|
||||
qsort(idx.root,counted,4,compar);
|
||||
if (argc>3)
|
||||
qsort(idx.root,counted,4,compari);
|
||||
else
|
||||
qsort(idx.root,counted,4,compar);
|
||||
buffer_putsflush(buffer_1," done.\n");
|
||||
munmap(map,filelen);
|
||||
{
|
||||
@@ -102,6 +116,7 @@ int main(int argc,char* argv[]) {
|
||||
buffer_putsflush(buffer_2,"could not mmap database file read-write\n");
|
||||
exit(1);
|
||||
}
|
||||
uint32_pack(map+casesensitive,argc>3?1:0);
|
||||
uint32_pack(map+filelen,0);
|
||||
uint32_pack(map+filelen+4,filelen+(counted+3)*4);
|
||||
uint32_pack(map+filelen+8,wanted);
|
||||
|
||||
14
byte_case_diff.c
Normal file
14
byte_case_diff.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <ctype.h>
|
||||
|
||||
int byte_case_diff(const void* a, unsigned int len, const void* b) {
|
||||
register const char* s=a;
|
||||
register const char* t=b;
|
||||
register const char* u=t+len;
|
||||
register int j;
|
||||
j=0;
|
||||
for (;;) {
|
||||
if (t==u) break; if ((j=(tolower(*s)-tolower(*t)))) break; ++s; ++t;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
3
case.h
Normal file
3
case.h
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
int byte_case_diff(const void* a, unsigned int len, const void* b);
|
||||
|
||||
@@ -33,6 +33,8 @@ int main() {
|
||||
uint32 j;
|
||||
uint32_unpack(x,&j);
|
||||
buffer_puts(buffer_1,map+j);
|
||||
uint32_unpack(x+attribute_count*4,&j);
|
||||
if (j&1) buffer_puts(buffer_1," (case insensitive)");
|
||||
buffer_putsflush(buffer_1,"\n");
|
||||
x+=4;
|
||||
}
|
||||
|
||||
8
ldap.h
8
ldap.h
@@ -1,13 +1,17 @@
|
||||
#ifndef _LDAP_H
|
||||
#define _LDAP_H
|
||||
|
||||
#include "uint32.h"
|
||||
|
||||
struct string {
|
||||
unsigned long l;
|
||||
const char* s;
|
||||
};
|
||||
|
||||
int matchstring(struct string* s,const char* c);
|
||||
int matchcasestring(struct string* s,const char* c);
|
||||
int matchprefix(struct string* s,const char* c);
|
||||
int matchcaseprefix(struct string* s,const char* c);
|
||||
|
||||
struct AttributeValueAssertion {
|
||||
struct string desc, value;
|
||||
@@ -35,9 +39,13 @@ struct Filter {
|
||||
AND=0, OR=1, NOT=2, EQUAL=3, SUBSTRING=4, GREATEQUAL=5, LESSEQUAL=6, PRESENT=7, APPROX=8, EXTENSIBLE=9
|
||||
} type;
|
||||
struct AttributeValueAssertion ava;
|
||||
uint32 attrofs; /* offset of attribute name in index */
|
||||
uint32 attrflag; /* "case sensitivity" flag from index */
|
||||
struct Substring* substrings;
|
||||
struct AttributeDescriptionList *a;
|
||||
struct Filter* x,*next;
|
||||
/* x is the subject of this filter (AND, OR and NOT) */
|
||||
/* next is used to form a linked list of subjects */
|
||||
};
|
||||
|
||||
struct SearchRequest {
|
||||
|
||||
@@ -3,28 +3,36 @@
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
#include "uint32.h"
|
||||
#include "case.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern char* map;
|
||||
extern long filelen;
|
||||
extern uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
extern uint32 dn_ofs,objectClass_ofs;
|
||||
|
||||
static int substringmatch(struct Substring* x,const char* attr) {
|
||||
static int substringmatch(struct Substring* x,const char* attr,int ignorecase) {
|
||||
int (*diff)(const void* a, unsigned int len, const void* b);
|
||||
if (ignorecase)
|
||||
diff=byte_case_diff;
|
||||
else
|
||||
diff=byte_diff;
|
||||
while (x) {
|
||||
unsigned int i;
|
||||
if (x->s.l>strlen(attr)) return 0;
|
||||
switch (x->substrtype) {
|
||||
case prefix:
|
||||
if (byte_diff(x->s.s,x->s.l,attr)) return 0;
|
||||
if (diff(x->s.s,x->s.l,attr)) return 0;
|
||||
found:
|
||||
break;
|
||||
case any:
|
||||
if (x->s.l<strlen(attr)) return 0;
|
||||
for (i=0; i<x->s.l-strlen(attr); ++i)
|
||||
if (byte_equal(x->s.s+i,x->s.l,attr)) goto found;
|
||||
if (!diff(x->s.s+i,x->s.l,attr)) goto found;
|
||||
return 0;
|
||||
case suffix:
|
||||
if (byte_diff(x->s.s+x->s.l-strlen(attr),x->s.l,attr)) return 0;
|
||||
if (diff(x->s.s+x->s.l-strlen(attr),x->s.l,attr)) return 0;
|
||||
}
|
||||
x=x->next;
|
||||
}
|
||||
@@ -52,21 +60,35 @@ int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
return !ldap_matchfilter_mapped(ofs,y);
|
||||
case EQUAL:
|
||||
{
|
||||
uint32 i=2,j,k;
|
||||
uint32 i,j,k;
|
||||
uint32_unpack(map+ofs,&j);
|
||||
if (!matchstring(&f->ava.desc,"dn")) {
|
||||
// if (!matchstring(&f->ava.desc,"dn")) {
|
||||
if (f->attrofs==dn_ofs) {
|
||||
uint32_unpack(map+ofs+8,&k);
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
} else if (!matchstring(&f->ava.desc,"objectName")) {
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
// } else if (!matchstring(&f->ava.desc,"objectName")) {
|
||||
} else if (f->attrofs==objectClass_ofs) {
|
||||
uint32_unpack(map+ofs+12,&k);
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
}
|
||||
for (i=2; i<j; ++i) {
|
||||
uint32_unpack(map+ofs+i*8,&k);
|
||||
if (!matchstring(&f->ava.desc,map+k)) {
|
||||
// if (!matchstring(&f->ava.desc,map+k)) {
|
||||
if (f->attrofs==k) {
|
||||
uint32_unpack(map+ofs+i*8+4,&k);
|
||||
if (!matchstring(&f->ava.value,map+k))
|
||||
return 1;
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -74,20 +96,23 @@ int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
break;
|
||||
case SUBSTRING:
|
||||
{
|
||||
uint32 i=2,j,k;
|
||||
uint32 i,j,k;
|
||||
uint32_unpack(map+ofs,&j);
|
||||
if (matchstring(&f->ava.desc,"dn")) {
|
||||
// if (matchstring(&f->ava.desc,"dn")) {
|
||||
if (f->attrofs==dn_ofs) {
|
||||
uint32_unpack(map+ofs+8,&k);
|
||||
if (substringmatch(f->substrings,map+k)) return 1;
|
||||
} else if (matchstring(&f->ava.desc,"objectName")) {
|
||||
if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
|
||||
// } else if (matchstring(&f->ava.desc,"objectName")) {
|
||||
} else if (f->attrofs==objectClass_ofs) {
|
||||
uint32_unpack(map+ofs+12,&k);
|
||||
if (substringmatch(f->substrings,map+k)) return 1;
|
||||
if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
|
||||
}
|
||||
for (i=2; i<j; ++i) {
|
||||
uint32_unpack(map+ofs+i*8,&k);
|
||||
if (!matchstring(&f->ava.desc,map+k)) {
|
||||
// if (!matchstring(&f->ava.desc,map+k)) {
|
||||
if (f->attrofs==k) {
|
||||
uint32_unpack(map+ofs+i*8+4,&k);
|
||||
if (substringmatch(f->substrings,map+k))
|
||||
if (substringmatch(f->substrings,map+k,f->attrflag&1))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
18
matchcaseprefix.c
Normal file
18
matchcaseprefix.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "case.h"
|
||||
#include "ldif.h"
|
||||
|
||||
/* behave like strcmp, but also return 0 if s is a prefix of c. */
|
||||
int matchcaseprefix(struct string* s,const char* c) {
|
||||
unsigned int l,l1,i;
|
||||
if (!c) return -1;
|
||||
l1=l=strlen(c);
|
||||
if (s->l<l1) l1=s->l;
|
||||
i=byte_case_diff(s->s,l1,c);
|
||||
if (i) return i;
|
||||
/* one is a prefix of the other */
|
||||
if (l==s->l) return 0;
|
||||
if (c[l1]) /* is c the longer string? */
|
||||
return 0;
|
||||
return -(int)(s->s[l1]);
|
||||
}
|
||||
|
||||
18
matchcasestring.c
Normal file
18
matchcasestring.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "case.h"
|
||||
#include "ldif.h"
|
||||
|
||||
/* like matchstring, but case insensitively */
|
||||
int matchcasestring(struct string* s,const char* c) {
|
||||
unsigned int l,l1,i;
|
||||
if (!c) return -1;
|
||||
l1=l=strlen(c);
|
||||
if (s->l<l1) l1=s->l;
|
||||
i=byte_case_diff(s->s,l1,c);
|
||||
if (i) return i;
|
||||
/* one is a prefix of the other */
|
||||
if (l==s->l) return 0;
|
||||
if (c[l1]) /* is c the longer string? */
|
||||
return c[l1];
|
||||
return -(int)(s->s[l1]);
|
||||
}
|
||||
|
||||
183
tinyldap.c
183
tinyldap.c
@@ -13,7 +13,8 @@
|
||||
#include <wait.h>
|
||||
#endif
|
||||
|
||||
static int verbose=0;
|
||||
static const int verbose=0;
|
||||
static const int debug=1;
|
||||
char* map;
|
||||
long filelen;
|
||||
uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
@@ -21,8 +22,130 @@ uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
/* how many longs are needed to have one bit for each record? */
|
||||
uint32 record_set_length;
|
||||
|
||||
/* some pre-looked-up attribute offsets to speed up ldap_match_mapped */
|
||||
uint32 dn_ofs,objectClass_ofs;
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
/* debugging support functions, adapted from t2.c */
|
||||
static void printava(struct AttributeValueAssertion* a,const char* rel) {
|
||||
buffer_puts(buffer_2,"[");
|
||||
buffer_put(buffer_2,a->desc.s,a->desc.l);
|
||||
buffer_puts(buffer_2," ");
|
||||
buffer_puts(buffer_2,rel);
|
||||
buffer_puts(buffer_2," ");
|
||||
buffer_put(buffer_2,a->value.s,a->value.l);
|
||||
buffer_puts(buffer_2,"]");
|
||||
}
|
||||
|
||||
static void printal(struct AttributeDescriptionList* a) {
|
||||
while (a) {
|
||||
buffer_put(buffer_2,a->a.s,a->a.l);
|
||||
a=a->next;
|
||||
if (a) buffer_puts(buffer_2,",");
|
||||
}
|
||||
if (a) buffer_puts(buffer_2,"\n");
|
||||
}
|
||||
|
||||
static void printfilter(struct Filter* f) {
|
||||
switch (f->type) {
|
||||
case AND:
|
||||
buffer_puts(buffer_2,"&(");
|
||||
mergesub:
|
||||
printfilter(f->x);
|
||||
buffer_puts(buffer_2,")\n");
|
||||
break;
|
||||
case OR:
|
||||
buffer_puts(buffer_2,"|(");
|
||||
goto mergesub;
|
||||
break;
|
||||
case NOT:
|
||||
buffer_puts(buffer_2,"!(");
|
||||
goto mergesub;
|
||||
case EQUAL:
|
||||
printava(&f->ava,"==");
|
||||
break;
|
||||
case SUBSTRING:
|
||||
{
|
||||
struct Substring* s=f->substrings;
|
||||
int first=1;
|
||||
buffer_put(buffer_2,f->ava.desc.s,f->ava.desc.l);
|
||||
buffer_puts(buffer_2," has ");
|
||||
while (s) {
|
||||
if (!first) buffer_puts(buffer_2," and "); first=0;
|
||||
switch(s->substrtype) {
|
||||
case prefix: buffer_puts(buffer_2,"prefix \""); break;
|
||||
case any: buffer_puts(buffer_2,"substr \""); break;
|
||||
case suffix: buffer_puts(buffer_2,"suffix \""); break;
|
||||
}
|
||||
buffer_put(buffer_2,s->s.s,s->s.l);
|
||||
buffer_puts(buffer_2,"\"");
|
||||
s=s->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GREATEQUAL:
|
||||
printava(&f->ava,">=");
|
||||
break;
|
||||
case LESSEQUAL:
|
||||
printava(&f->ava,"<=");
|
||||
break;
|
||||
case PRESENT:
|
||||
printava(&f->ava,"\\exist");
|
||||
break;
|
||||
case APPROX:
|
||||
printava(&f->ava,"\\approx");
|
||||
break;
|
||||
case EXTENSIBLE:
|
||||
buffer_puts(buffer_2,"[extensible]");
|
||||
break;
|
||||
}
|
||||
if (f->next) {
|
||||
buffer_puts(buffer_2,",");
|
||||
printfilter(f->next);
|
||||
}
|
||||
buffer_flush(buffer_2);
|
||||
}
|
||||
|
||||
/* recursively fill in attrofs and attrflag */
|
||||
static void fixup(struct Filter* f) {
|
||||
if (!f) return;
|
||||
switch (f->type) {
|
||||
case EQUAL:
|
||||
case SUBSTRING:
|
||||
case GREATEQUAL:
|
||||
case LESSEQUAL:
|
||||
case PRESENT:
|
||||
case APPROX:
|
||||
{
|
||||
char* x=map+5*4+size_of_string_table;
|
||||
unsigned int i;
|
||||
f->attrofs=f->attrflag=0;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j;
|
||||
uint32_unpack(x,&j);
|
||||
if (!matchstring(&f->ava.desc,map+j)) {
|
||||
f->attrofs=j;
|
||||
uint32_unpack(x+-attribute_count*4,&f->attrflag);
|
||||
break;
|
||||
}
|
||||
x+=4;
|
||||
}
|
||||
if (!f->attrofs) {
|
||||
buffer_puts(buffer_2,"cannot find attribute \"");
|
||||
buffer_put(buffer_2,f->ava.desc.s,f->ava.desc.l);
|
||||
buffer_putsflush(buffer_2,"\"!\n");
|
||||
}
|
||||
}
|
||||
case AND:
|
||||
case OR:
|
||||
case NOT:
|
||||
if (f->x) fixup(f->x);
|
||||
default:
|
||||
}
|
||||
if (f->next) fixup(f->next);
|
||||
}
|
||||
|
||||
/* find out whether this filter can be accelerated with the indices */
|
||||
static int indexable(struct Filter* f) {
|
||||
struct Filter* y=f->x;
|
||||
@@ -241,7 +364,8 @@ static int useindex(struct Filter* f,unsigned long* bitfield) {
|
||||
uint32_unpack(map+ofs+8,&indexed_attribute);
|
||||
if (index_type==0)
|
||||
if (!matchstring(&f->ava.desc,map+indexed_attribute)) {
|
||||
tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/4,&f->substrings->s,bitfield,matchprefix);
|
||||
tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/4,&f->substrings->s,bitfield,
|
||||
f->attrflag&1?matchcaseprefix:matchprefix);
|
||||
return 1;
|
||||
}
|
||||
ofs=next;
|
||||
@@ -258,7 +382,8 @@ static int useindex(struct Filter* f,unsigned long* bitfield) {
|
||||
uint32_unpack(map+ofs+8,&indexed_attribute);
|
||||
if (index_type==0)
|
||||
if (!matchstring(&f->ava.desc,map+indexed_attribute)) {
|
||||
tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/4,&f->ava.value,bitfield,matchstring);
|
||||
tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/4,&f->ava.value,bitfield,
|
||||
f->attrflag&1?matchcasestring:matchstring);
|
||||
return 1;
|
||||
}
|
||||
ofs=next;
|
||||
@@ -275,7 +400,7 @@ static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int ou
|
||||
struct SearchResultEntry sre;
|
||||
struct PartialAttributeList** pal=&sre.attributes;
|
||||
|
||||
if (0) {
|
||||
if (debug) {
|
||||
char* x=map+ofs;
|
||||
uint32 j,k;
|
||||
uint32_unpack(x,&j);
|
||||
@@ -443,10 +568,31 @@ int handle(int in,int out) {
|
||||
}
|
||||
#endif
|
||||
if ((tmp=scan_ldapsearchrequest(buf+res,buf+res+len,&sr))) {
|
||||
|
||||
if (debug) {
|
||||
const char* scopes[]={"baseObject","singleLevel","wholeSubtree"};
|
||||
const char* alias[]={"neverDerefAliases","derefInSearching","derefFindingBaseObj","derefAlways"};
|
||||
buffer_puts(buffer_2,"search request: baseObject \"");
|
||||
buffer_put(buffer_2,sr.baseObject.s,sr.baseObject.l);
|
||||
buffer_puts(buffer_2,"\", scope ");
|
||||
buffer_puts(buffer_2,scopes[sr.scope]);
|
||||
buffer_puts(buffer_2,", ");
|
||||
buffer_puts(buffer_2,alias[sr.derefAliases]);
|
||||
buffer_puts(buffer_2,"\nsize limit ");
|
||||
buffer_putulong(buffer_2,sr.sizeLimit);
|
||||
buffer_puts(buffer_2,", time limit ");
|
||||
buffer_putulong(buffer_2,sr.timeLimit);
|
||||
buffer_puts(buffer_2,"\n");
|
||||
printfilter(sr.filter);
|
||||
buffer_puts(buffer_2,"attributes: ");
|
||||
printal(sr.attributes);
|
||||
buffer_putsflush(buffer_2,"\n\n");
|
||||
}
|
||||
fixup(sr.filter);
|
||||
if (indexable(sr.filter)) {
|
||||
unsigned long* result;
|
||||
unsigned long i;
|
||||
// buffer_putsflush(buffer_2,"query is indexable!\n");
|
||||
if (debug) buffer_putsflush(buffer_2,"query can be answered with index!\n");
|
||||
record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
|
||||
result=alloca(record_set_length*sizeof(unsigned long));
|
||||
/* Use the index to find matching data. Put the offsets
|
||||
@@ -524,11 +670,15 @@ int handle(int in,int out) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
case AbandonRequest:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
buffer_puts(buffer_2,"unknown request type ");
|
||||
buffer_putulong(buffer_2,op);
|
||||
buffer_putsflush(buffer_2,"\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
// exit(1);
|
||||
}
|
||||
Len+=res;
|
||||
#if 0
|
||||
@@ -563,6 +713,26 @@ int main() {
|
||||
uint32_unpack(map+3*4,&indices_offset);
|
||||
uint32_unpack(map+4*4,&size_of_string_table);
|
||||
|
||||
/* look up "dn" and "objectClass" */
|
||||
{
|
||||
char* x=map+5*4+size_of_string_table;
|
||||
unsigned int i;
|
||||
dn_ofs=objectClass_ofs=0;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j;
|
||||
uint32_unpack(x,&j);
|
||||
if (!strcmp("dn",map+j))
|
||||
dn_ofs=j;
|
||||
else if (!strcmp("objectClass",map+j))
|
||||
objectClass_ofs=j;
|
||||
x+=4;
|
||||
}
|
||||
if (!dn_ofs || !objectClass_ofs) {
|
||||
buffer_putsflush(buffer_2,"can't happen error: dn or objectClass not there?!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
ldif_parse("exp.ldif");
|
||||
if (!first) {
|
||||
@@ -602,7 +772,6 @@ again:
|
||||
}
|
||||
#ifdef DEBUG
|
||||
handle(asock,asock);
|
||||
close(asock);
|
||||
goto again;
|
||||
// exit(0);
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user