From f3ff583c404b62b7a6582aa7a753b4c26d3f3e65 Mon Sep 17 00:00:00 2001 From: Sergey Balalaev Date: Wed, 28 Nov 2018 16:24:51 +0400 Subject: [PATCH 1/5] added real asyncSearch --- Sources/PerfectLDAP/PerfectLDAP.swift | 96 +++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/Sources/PerfectLDAP/PerfectLDAP.swift b/Sources/PerfectLDAP/PerfectLDAP.swift index 19385a7..e821427 100644 --- a/Sources/PerfectLDAP/PerfectLDAP.swift +++ b/Sources/PerfectLDAP/PerfectLDAP.swift @@ -665,6 +665,102 @@ public class LDAP { throw Exception.message(LDAP.error(r)) }//end search + + + + /// asynchronized search with sync result + /// - parameters: + /// - base: String, search base domain (dn), default = "" + /// - filter: String, the filter of query, default = "(objectclass=*)", means all possible results + /// - scope: See Scope, BASE, SINGLE_LEVEL, SUBTREE or CHILDREN + /// - sortedBy: a sorting string, may be generated by LDAP.sortingString() + /// - returns: + /// ResultSet. See ResultSet + /// - throws: + /// Exception.message + public func asyncSearch(base:String = "", filter:String = "(objectclass=*)", scope:Scope = .BASE, attributes: [String] = [], sortedBy: String = "") throws -> [String:[ + String:Any]] + { + + var serverControl = UnsafeMutablePointer(bitPattern: 0) + + if !sortedBy.isEmpty { + var sortKeyList = UnsafeMutablePointer?>(bitPattern: 0) + let sortString = ber_strdup(sortedBy) + var r = ldap_create_sort_keylist(&sortKeyList, sortString) + defer { ber_memfree(sortString) } + guard r == 0 else { + throw Exception.message(LDAP.error(r)) + }//end if + + r = ldap_create_sort_control(self.ldap, sortKeyList, 0, &serverControl) + defer { ldap_free_sort_keylist(sortKeyList) } + guard r == 0 else { + throw Exception.message(LDAP.error(r)) + }//end if + }//end if + + // prepare the return set + var msg = OpaquePointer(bitPattern: 0) + var msgid : Int32 = 0 + var t = timeval(tv_sec: 10, tv_usec: 10) + + let r = withCArrayOfString(array: attributes) { pAttribute -> Int32 in + + // perform the search + let result = ldap_search_ext(self.ldap, base, scope.rawValue, filter, pAttribute, 0, &serverControl, nil, &t, 0, &msgid) + + if serverControl != nil { + ldap_control_free(serverControl) + } + return result + }//end + + var msgtype = LDAP_RES_SEARCH_ENTRY + var msgcount = 0; + while(msgtype != LDAP_RES_SEARCH_RESULT) + { + var res = OpaquePointer(bitPattern: 0) + msgcount += 1 + // retrieves result + var err = ldap_result(ldap, msgid, 0, nil, &res); + switch(err) + { + case -1: + ldap_get_option(ldap, LDAP_OPT_RESULT_CODE, &err) + print(stderr, "ldap_result(): %s\n", ldap_err2string(err)) + throw Exception.message(LDAP.error(err)) + case 0: + print(stderr, "ldap_result(): timeout expired\n") + ldap_abandon_ext(ldap, msgid, nil, nil) + ldap_unbind_ext_s(ldap, nil, nil) + default: + break; + }; + + // determines result type + msgtype = UInt(ldap_msgtype(res)) + if (msgtype != LDAP_RES_SEARCH_ENTRY) { + continue + } else { + print("bingo") + + if let m = res { + // process the result set + let rs = ResultSet(ldap: self, chain: m) + + // release the memory + ldap_msgfree(m) + + return rs.dictionary + } + break + } + } + + throw Exception.message(LDAP.error(r)) + }//end asyncSearch + /// asynchronized search /// - parameters: From 4aced0912de0a5e3c92e39956377460281451872 Mon Sep 17 00:00:00 2001 From: Sergey Balalaev Date: Wed, 28 Nov 2018 16:26:00 +0400 Subject: [PATCH 2/5] fixed description search with completion block --- Sources/PerfectLDAP/PerfectLDAP.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PerfectLDAP/PerfectLDAP.swift b/Sources/PerfectLDAP/PerfectLDAP.swift index e821427..ab569d1 100644 --- a/Sources/PerfectLDAP/PerfectLDAP.swift +++ b/Sources/PerfectLDAP/PerfectLDAP.swift @@ -762,7 +762,7 @@ public class LDAP { }//end asyncSearch - /// asynchronized search + /// synchronized search but in seporated Thread /// - parameters: /// - base: String, search base domain (dn), default = "" /// - filter: String, the filter of query, default = "(objectclass=*)", means all possible results From 332ecc0a26b20754655f46eb5ab98b9a0f364f26 Mon Sep 17 00:00:00 2001 From: Sergey Balalaev Date: Thu, 29 Nov 2018 21:27:36 +0400 Subject: [PATCH 3/5] free all results of async Search and refactoring this method --- Sources/PerfectLDAP/PerfectLDAP.swift | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Sources/PerfectLDAP/PerfectLDAP.swift b/Sources/PerfectLDAP/PerfectLDAP.swift index ab569d1..b494506 100644 --- a/Sources/PerfectLDAP/PerfectLDAP.swift +++ b/Sources/PerfectLDAP/PerfectLDAP.swift @@ -701,12 +701,12 @@ public class LDAP { }//end if // prepare the return set - var msg = OpaquePointer(bitPattern: 0) var msgid : Int32 = 0 - var t = timeval(tv_sec: 10, tv_usec: 10) let r = withCArrayOfString(array: attributes) { pAttribute -> Int32 in + var t = timeval(tv_sec: 10, tv_usec: 10) + // perform the search let result = ldap_search_ext(self.ldap, base, scope.rawValue, filter, pAttribute, 0, &serverControl, nil, &t, 0, &msgid) @@ -738,14 +738,13 @@ public class LDAP { break; }; - // determines result type - msgtype = UInt(ldap_msgtype(res)) - if (msgtype != LDAP_RES_SEARCH_ENTRY) { - continue - } else { - print("bingo") + if let m = res { + // determines result type + msgtype = UInt(ldap_msgtype(m)) - if let m = res { + if (msgtype != LDAP_RES_SEARCH_ENTRY) { + ldap_msgfree(m) + } else { // process the result set let rs = ResultSet(ldap: self, chain: m) @@ -754,7 +753,6 @@ public class LDAP { return rs.dictionary } - break } } From f597829cf0711b8f9d783472720c599657a6e6b1 Mon Sep 17 00:00:00 2001 From: Sergey Balalaev Date: Wed, 26 Dec 2018 18:36:15 +0400 Subject: [PATCH 4/5] fixed async search method as List of result --- Sources/PerfectLDAP/PerfectLDAP.swift | 50 +++++++++++++++++++-------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/Sources/PerfectLDAP/PerfectLDAP.swift b/Sources/PerfectLDAP/PerfectLDAP.swift index b494506..7bd39b2 100644 --- a/Sources/PerfectLDAP/PerfectLDAP.swift +++ b/Sources/PerfectLDAP/PerfectLDAP.swift @@ -670,18 +670,29 @@ public class LDAP { /// asynchronized search with sync result /// - parameters: - /// - base: String, search base domain (dn), default = "" - /// - filter: String, the filter of query, default = "(objectclass=*)", means all possible results - /// - scope: See Scope, BASE, SINGLE_LEVEL, SUBTREE or CHILDREN - /// - sortedBy: a sorting string, may be generated by LDAP.sortingString() + /// - base: String, search base domain (dn), default = "" + /// - filter: String, the filter of query, default = "(objectclass=*)", means all possible results + /// - scope: See Scope, BASE, SINGLE_LEVEL, SUBTREE or CHILDREN + /// - attributes: filter for output attributes + /// - sortedBy: a sorting string, may be generated by LDAP.sortingString() + /// - sizeLimit: max count of result search. Max limit is 1000. /// - returns: - /// ResultSet. See ResultSet + /// ResultSet. See ResultSet /// - throws: - /// Exception.message - public func asyncSearch(base:String = "", filter:String = "(objectclass=*)", scope:Scope = .BASE, attributes: [String] = [], sortedBy: String = "") throws -> [String:[ + /// Exception.message + public func asyncSearch(base:String = "", filter:String = "(objectclass=*)", scope:Scope = .BASE, attributes: [String] = [], sortedBy: String = "", sizeLimit: Int = 1000) throws -> [String:[ String:Any]] { + var realSizeLimit : Int32 = Int32(sizeLimit) + + // This is limit of space + if realSizeLimit > 1000 { + realSizeLimit = 1000 + } + + var result = [String:[String:Any]]() + var serverControl = UnsafeMutablePointer(bitPattern: 0) if !sortedBy.isEmpty { @@ -703,12 +714,14 @@ public class LDAP { // prepare the return set var msgid : Int32 = 0 + var t = timeval(tv_sec: 10, tv_usec: 10) + let r = withCArrayOfString(array: attributes) { pAttribute -> Int32 in - var t = timeval(tv_sec: 10, tv_usec: 10) + // perform the search - let result = ldap_search_ext(self.ldap, base, scope.rawValue, filter, pAttribute, 0, &serverControl, nil, &t, 0, &msgid) + let result = ldap_search_ext(self.ldap, base, scope.rawValue, filter, pAttribute, 0, &serverControl, nil, &t, realSizeLimit, &msgid) if serverControl != nil { ldap_control_free(serverControl) @@ -716,14 +729,14 @@ public class LDAP { return result }//end - var msgtype = LDAP_RES_SEARCH_ENTRY + var msgtype = LDAP_RES_SEARCH_ENTRY var msgcount = 0; - while(msgtype != LDAP_RES_SEARCH_RESULT) + while(msgtype != LDAP_RES_SEARCH_RESULT && realSizeLimit > msgcount) { var res = OpaquePointer(bitPattern: 0) msgcount += 1 // retrieves result - var err = ldap_result(ldap, msgid, 0, nil, &res); + var err = ldap_result(ldap, msgid, 0, &t, &res); switch(err) { case -1: @@ -750,13 +763,20 @@ public class LDAP { // release the memory ldap_msgfree(m) - - return rs.dictionary + let dictionary = rs.dictionary + for key in dictionary.keys { + result[key] = dictionary[key] + } } } } - throw Exception.message(LDAP.error(r)) + if result.count < 1 { + throw Exception.message(LDAP.error(r)) + } + + return result + }//end asyncSearch From 1895549745333e5d4f7a96ecddbc22b67fc22543 Mon Sep 17 00:00:00 2001 From: Sergey Balalaev Date: Wed, 27 Mar 2019 00:31:29 +0400 Subject: [PATCH 5/5] supporting spm4 with our repositories --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index f77da9e..252b730 100644 --- a/Package.swift +++ b/Package.swift @@ -12,8 +12,8 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/PerfectSideRepos/Perfect-ICONV.git", from: "3.0.0"), - .package(url: "https://github.com/PerfectlySoft/Perfect-libSASL.git", from: "1.0.0"), - .package(url: "https://github.com/PerfectlySoft/Perfect-OpenLDAP.git", from: "1.0.0"), + .package(url: "https://github.com/Altarix/Perfect-libSASL.git", from: "1.0.0"), + .package(url: "https://github.com/Altarix/Perfect-OpenLDAP.git", from: "1.0.0"), ], targets: [ .target(