Comments (11)
Since the library is in the ASCII mode, i offer little fix (or hack) to work with Cyrillic and possibly other charcters...
Size of the cyrillic symbols in the "string" - 2 bytes, whereas the latin symbol - 1 byte.
I did these steps:
- I debug the library half a day :)
- Open file gopkg.in/ldap.v1/filter.go
- import "regexp" library
- make regexp
[0-9A-Za-z\ \*\-\_]
for detect ascii symbols (This regexp needs to be expanded) - I added code to function "compileFilter" for detect latin and non-latin symbols. If symbol is non-latin, put to "condition" 2 bytes and additional increment "newPos". If symbol is latin, put to "condition" 1 byte.
diff for gopkg.in/ldap.v1/filter.go
*** filter.go.orig 2015-09-17 10:40:06.000000000 +0300
--- filter.go 2015-09-17 13:31:42.000000000 +0300
***************
*** 8,13 ****
--- 8,14 ----
"errors"
"fmt"
"strings"
+ "regexp"
"gopkg.in/asn1-ber.v1"
)
***************
*** 164,169 ****
--- 165,172 ----
}
}()
+ asciiChechRegexp:=regexp.MustCompile(`[0-9A-Za-z\ \*\-\_]`)
+
newPos := pos
switch filter[pos] {
case '(':
***************
*** 190,196 ****
for newPos < len(filter) && filter[newPos] != ')' {
switch {
case packet != nil:
- condition += fmt.Sprintf("%c", filter[newPos])
case filter[newPos] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
case filter[newPos] == '>' && filter[newPos+1] == '=':
--- 193,207 ----
for newPos < len(filter) && filter[newPos] != ')' {
switch {
case packet != nil:
+ if !asciiChechRegexp.MatchString(fmt.Sprintf("%c", filter[newPos])) {
+ // fmt.Printf("DEBUG RU:%s / %s / %d\n", filter, filter[newPos:newPos+2], newPos)
+ condition += fmt.Sprintf("%s", filter[newPos:newPos+2])
+ newPos++
+ }else{
+ // fmt.Printf("DEBUG EN:%s / %c / %d\n", filter, filter[newPos], newPos)
+ condition += fmt.Sprintf("%c", filter[newPos])
+ }
+ // fmt.Printf("DEBUG TT:%v\n", condition)
case filter[newPos] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
case filter[newPos] == '>' && filter[newPos+1] == '=':
from ldap.
Example for Cyrilic (non-ascii) after path implementation:
Debug by my printf in file gopkg.in/ldap.v1/filter.go, function compileFilter, line number 193:
Victory!:)
from ldap.
Rather than using a hack to guess at non-ascii strings, I'd like to see correct handling of unicode. In my short googling I've found RFC 4518, and a go library for normalizing1 unicode to KC.
I will try to work on this in the next few weeks, anyone else interested in working on this is welcome to also.
from ldap.
+1 for proper escaping instead of regex tests/fixups
from ldap.
This is very good news ;) Unicode - this is very good and versatile! I do not have work experience with unicode, but happy to learn it. For start, i will read the documentation and study the possibility of normalizing library.
from ldap.
This is a slight modification of code using Unicode:
This code works, I tested it with different search terms. While it is good to optimize and improve :)
*** filter.go.orig 2015-09-17 10:40:06.000000000 +0300
--- filter.go 2015-09-21 16:34:04.042139038 +0300
***************
*** 8,13 ****
--- 8,14 ----
"errors"
"fmt"
"strings"
+ "unicode/utf8"
"gopkg.in/asn1-ber.v1"
)
***************
*** 187,211 ****
default:
attribute := ""
condition := ""
! for newPos < len(filter) && filter[newPos] != ')' {
switch {
case packet != nil:
! condition += fmt.Sprintf("%c", filter[newPos])
! case filter[newPos] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
! case filter[newPos] == '>' && filter[newPos+1] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
newPos++
! case filter[newPos] == '<' && filter[newPos+1] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
newPos++
! case filter[newPos] == '~' && filter[newPos+1] == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterLessOrEqual])
newPos++
case packet == nil:
! attribute += fmt.Sprintf("%c", filter[newPos])
}
! newPos++
}
if newPos == len(filter) {
err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
--- 188,239 ----
default:
attribute := ""
condition := ""
! xfilter := filter
! xckl := 0
! xsize := 0
! // fmt.Printf("X1: %v / %v / %d /bytes x: %d /bytes f: %d/rune: %d\n", xfilter, filter, newPos, len(xfilter), len(filter), utf8.RuneCountInString(xfilter))
! for {
! xckl += xsize
! if xckl>newPos-xsize {
! break
! }
! _, xsize = utf8.DecodeRuneInString(xfilter)
! xfilter = xfilter[xsize:len(xfilter)]
! }
! // fmt.Printf("X2: %v / %v / %d /bytes x: %d /bytes f: %d/rune: %d\n", xfilter, filter, newPos, len(xfilter), len(filter), utf8.RuneCountInString(xfilter))
! xsymbol, _ := utf8.DecodeRuneInString("")
! xstop, _ := utf8.DecodeRuneInString(")")
! xpar, _ := utf8.DecodeRuneInString("=")
! xpar_more, _ := utf8.DecodeRuneInString(">")
! xpar_less, _ := utf8.DecodeRuneInString("<")
! xpar_tld, _ := utf8.DecodeRuneInString("~")
! xsymbol, xsize = utf8.DecodeRuneInString(xfilter)
! xfilter = xfilter[xsize:len(xfilter)]
! xsymbol2, _ := utf8.DecodeRuneInString(xfilter)
! for len(xfilter)>0 && xsymbol != xstop {
! // fmt.Printf("X3: %c,%c\n", xsymbol, xsymbol2)
switch {
case packet != nil:
! condition += fmt.Sprintf("%c", xsymbol)
! // fmt.Printf("X4:%c -> %s\n", xsymbol, condition)
! case xsymbol == xpar:
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
! case xsymbol == xpar_more && xsymbol2 == xpar:
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
newPos++
! case xsymbol == xpar_less && xsymbol2 == xpar:
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
newPos++
! case xsymbol == xpar_tld && xsymbol2 == xpar:
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterLessOrEqual])
newPos++
case packet == nil:
! attribute += fmt.Sprintf("%c", xsymbol)
}
! xsymbol, xsize = utf8.DecodeRuneInString(xfilter)
! xfilter = xfilter[xsize:len(xfilter)]
! xsymbol2, _ = utf8.DecodeRuneInString(xfilter)
! newPos += xsize
}
if newPos == len(filter) {
err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
from ldap.
Thanks for the investigation. If you have working code, could you put it in a branch and open a pull request? That would make it easier to review and check out for local testing.
from ldap.
I created a pull request
from ldap.
#31 for reference
from ldap.
#32 for reference
from ldap.
from ldap.
Related Issues (20)
- Memory leak in ParseDN
- reader error: unexpected EOF HOT 2
- 钉钉员工如果有相同拼音名字 或者同名 换成拼音 弄成uid 是不是会有特殊处理呢
- New release HOT 2
- lockOutObservationWindow Attribute
- Binary value not automatically decoded into base64 string HOT 3
- searchAsync checks cancelled context only after receiving an ldap response HOT 5
- CVE-2009-37 67 - Required Fix For this vulnerability HOT 1
- How to pass settings to NewClientWithPassword()?
- Server Side Sorting on OpenLDAP HOT 4
- Connection.Start is deprecated without alternative HOT 5
- Not possible to connect ldap HOT 6
- [req] Implement ExtendedRequest request as a prereq to enable fast bind for AD
- How to keep the password policy clear after calling the PasswordModify method HOT 8
- Admin authenticate mode, how to implement this library? HOT 1
- v3 and root copies of the code desynced HOT 5
- Unable to perform the cross domain forest user search. HOT 3
- DialURL migration problem HOT 1
- Retrieve Schema version (objectVersion) of LDAP server
- saslBindTokenExchange failing with invalid Credentials Error
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ldap.