From f27a82b4761cc081f0c2486fea1262797edaf0c0 Mon Sep 17 00:00:00 2001 From: Matvey Aksenov Date: Sat, 11 Apr 2015 16:20:48 +0000 Subject: [PATCH] Update haddock documentation --- Ldap-Asn1-Type.html | 52 ++-- Ldap-Client-Bind.html | 6 +- Ldap-Client-Extended.html | 8 +- Ldap-Client-Internal.html | 11 +- Ldap-Client-Modify.html | 8 +- Ldap-Client-Search.html | 9 +- Ldap-Client.html | 9 +- doc-index-All.html | 2 +- doc-index-D.html | 2 +- doc-index-N.html | 2 +- doc-index-O.html | 2 +- doc-index-P.html | 2 +- doc-index-R.html | 2 +- ldap-client.haddock | Bin 78863 -> 94042 bytes mini_Ldap-Client-Bind.html | 2 +- mini_Ldap-Client-Extended.html | 2 +- mini_Ldap-Client-Internal.html | 2 +- mini_Ldap-Client-Modify.html | 2 +- mini_Ldap-Client-Search.html | 2 +- mini_Ldap-Client.html | 2 +- src/Ldap-Asn1-Type.html | 303 ++++++++++---------- src/Ldap-Client-Bind.html | 106 +++---- src/Ldap-Client-Extended.html | 178 ++++++------ src/Ldap-Client-Internal.html | 228 ++++++++------- src/Ldap-Client-Modify.html | 208 +++++++------- src/Ldap-Client-Search.html | 367 ++++++++++++------------ src/Ldap-Client.html | 510 +++++++++++++++++---------------- 27 files changed, 1057 insertions(+), 970 deletions(-) diff --git a/Ldap-Asn1-Type.html b/Ldap-Asn1-Type.html index a122659..efef296 100644 --- a/Ldap-Asn1-Type.html +++ b/Ldap-Asn1-Type.html @@ -1,7 +1,7 @@ Ldap.Asn1.Type

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellSafe
LanguageHaskell2010

Ldap.Asn1.Type

Synopsis

Documentation

data LdapMessage op Source

Message envelope. (Section 4.1.1.)

Instances

Eq op => Eq (LdapMessage op) Source 
Show op => Show (LdapMessage op) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellSafe
LanguageHaskell2010

Ldap.Asn1.Type

Synopsis

Documentation

data LdapMessage op Source

Message envelope. (Section 4.1.1.)

Instances

Eq op => Eq (LdapMessage op) Source 
Show op => Show (LdapMessage op) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
      messageID       MessageID,
      protocolOp      CHOICE {
           bindRequest           BindRequest,
@@ -100,10 +100,12 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-Type.html");
 
IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
      responseName     [0] LDAPOID OPTIONAL,
      responseValue    [1] OCTET STRING OPTIONAL }
-

newtype AuthenticationChoice Source

Not really a choice until SASL is supported.

Constructors

Simple ByteString 

Instances

Eq AuthenticationChoice Source 
Show AuthenticationChoice Source 
ToAsn1 AuthenticationChoice Source
AuthenticationChoice ::= CHOICE {
      simple                  [0] OCTET STRING,
      ...  }
-

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

data DerefAliases Source

An indicator as to whether or not alias entries (as defined in + [RFC4512]) are to be dereferenced during stages of the Search + operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

And !(NonEmpty Filter)

All filters evaluate to TRUE

Or !(NonEmpty Filter)

Any filter evaluates to TRUE

Not Filter

Filter evaluates to FALSE

EqualityMatch AttributeValueAssertion

EQUALITY rule returns TRUE

Substrings SubstringFilter

SUBSTR rule returns TRUE

GreaterOrEqual AttributeValueAssertion

ORDERING rule returns FALSE

LessOrEqual AttributeValueAssertion

ORDERING or EQUALITY rule returns TRUE

Present AttributeDescription

Attribute is present in the entry

ApproxMatch AttributeValueAssertion

Same as EqualityMatch for most servers

ExtensibleMatch MatchingRuleAssertion 

Instances

Eq Filter Source 
Show Filter Source 
ToAsn1 Filter Source
Filter ::= CHOICE {
      and             [0] SET SIZE (1..MAX) OF filter Filter,
      or              [1] SET SIZE (1..MAX) OF filter Filter,
      not             [2] Filter,
@@ -115,14 +117,14 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-Type.html");
      approxMatch     [8] AttributeValueAssertion,
      extensibleMatch [9] MatchingRuleAssertion,
      ...  }
-

data SubstringFilter Source

Instances

Eq SubstringFilter Source 
Show SubstringFilter Source 
ToAsn1 SubstringFilter Source
SubstringFilter ::= SEQUENCE {
      type           AttributeDescription,
      substrings     SEQUENCE SIZE (1..MAX) OF substring CHOICE {
           initial [0] AssertionValue,  -- can occur at most once
           any     [1] AssertionValue,
           final   [2] AssertionValue } -- can occur at most once
      }
-

data MatchingRuleAssertion Source

Instances

Eq MatchingRuleAssertion Source 
Show MatchingRuleAssertion Source 
ToAsn1 MatchingRuleAssertion Source
MatchingRuleAssertion ::= SEQUENCE {
      matchingRule    [1] MatchingRuleId OPTIONAL,
      type            [2] AttributeDescription OPTIONAL,
      matchValue      [3] AssertionValue,
@@ -130,16 +132,16 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-Type.html");
 

newtype MatchingRuleId Source

Matching rules are defined in Section 4.1.3 of [RFC4512]. A matching rule is identified in the protocol by the printable representation of either its numericoid or one of its short name descriptors - [RFC4512], e.g., caseIgnoreMatch or '2.5.13.2'. (Section 4.1.8.)

Instances

newtype AttributeSelection Source

Instances

Eq AttributeSelection Source 
Show AttributeSelection Source 
ToAsn1 AttributeSelection Source
AttributeSelection ::= SEQUENCE OF selector LDAPString
-

newtype AttributeList Source

Constructors

AttributeList [Attribute] 

Instances

Eq AttributeList Source 
Show AttributeList Source 
ToAsn1 AttributeList Source
AttributeList ::= SEQUENCE OF attribute Attribute
-

newtype PartialAttributeList Source

Instances

Eq PartialAttributeList Source 
Show PartialAttributeList Source 
FromAsn1 PartialAttributeList Source
PartialAttributeList ::= SEQUENCE OF partialAttribute PartialAttribute
-

newtype Controls Source

Constructors

Controls [Control] 

Instances

Eq Controls Source 
Show Controls Source 
ToAsn1 Controls Source
Controls ::= SEQUENCE OF control Control
-

data Control Source

Instances

Eq Control Source 
Show Control Source 
ToAsn1 Control Source
Control ::= SEQUENCE {
+ [RFC4512], e.g., caseIgnoreMatch or '2.5.13.2'. (Section 4.1.8.)

Instances

newtype AttributeSelection Source

Instances

Eq AttributeSelection Source 
Show AttributeSelection Source 
ToAsn1 AttributeSelection Source
AttributeSelection ::= SEQUENCE OF selector LDAPString
+

newtype AttributeList Source

Constructors

AttributeList [Attribute] 

Instances

Eq AttributeList Source 
Show AttributeList Source 
ToAsn1 AttributeList Source
AttributeList ::= SEQUENCE OF attribute Attribute
+

newtype PartialAttributeList Source

Instances

Eq PartialAttributeList Source 
Show PartialAttributeList Source 
FromAsn1 PartialAttributeList Source
PartialAttributeList ::= SEQUENCE OF partialAttribute PartialAttribute
+

newtype Controls Source

Constructors

Controls [Control] 

Instances

Eq Controls Source 
Show Controls Source 
ToAsn1 Controls Source
Controls ::= SEQUENCE OF control Control
+

data Control Source

Constructors

Control !LdapOid !Bool !(Maybe ByteString) 

Instances

Eq Control Source 
Show Control Source 
ToAsn1 Control Source
Control ::= SEQUENCE {
      controlType             LDAPOID,
      criticality             BOOLEAN DEFAULT FALSE,
      controlValue            OCTET STRING OPTIONAL }
-

data LdapResult Source

Instances

Eq LdapResult Source 
Show LdapResult Source 
FromAsn1 LdapResult Source
LDAPResult ::= SEQUENCE {
      resultCode         ENUMERATED {
           success                      (0),
           operationsError              (1),
@@ -191,40 +193,40 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-Type.html");
      matchedDN          LDAPDN,
      diagnosticMessage  LDAPString,
      referral           [3] Referral OPTIONAL }
-

newtype AttributeValue Source

Instances

Eq AttributeValue Source 
Show AttributeValue Source 
ToAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
 
FromAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
-

data AttributeValueAssertion Source

Instances

Eq AttributeValueAssertion Source 
Show AttributeValueAssertion Source 
ToAsn1 AttributeValueAssertion Source
AttributeValueAssertion ::= SEQUENCE {
      attributeDesc   AttributeDescription,
      assertionValue  AssertionValue }
-

data Attribute Source

Instances

Eq Attribute Source 
Show Attribute Source 
ToAsn1 Attribute Source
Attribute ::= PartialAttribute(WITH COMPONENTS {
+

data Attribute Source

Instances

Eq Attribute Source 
Show Attribute Source 
ToAsn1 Attribute Source
Attribute ::= PartialAttribute(WITH COMPONENTS {
      ...,
      vals (SIZE(1..MAX))})
-

data PartialAttribute Source

Instances

Eq PartialAttribute Source 
Show PartialAttribute Source 
ToAsn1 PartialAttribute Source
PartialAttribute ::= SEQUENCE {
      type       AttributeDescription,
      vals       SET OF value AttributeValue }
 
FromAsn1 PartialAttribute Source
PartialAttribute ::= SEQUENCE {
      type       AttributeDescription,
      vals       SET OF value AttributeValue }
 

newtype LdapDn Source

An LDAPDN is defined to be the representation of a Distinguished Name - (DN) after encoding according to the specification in [RFC4514].

Constructors

LdapDn LdapString 

Instances

Eq LdapDn Source 
Show LdapDn Source 
ToAsn1 LdapDn Source
LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
+ (DN) after encoding according to the specification in [RFC4514].

Constructors

LdapDn LdapString 

Instances

Eq LdapDn Source 
Show LdapDn Source 
ToAsn1 LdapDn Source
LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
 
FromAsn1 LdapDn Source
LDAPDN ::= LDAPString
 

newtype RelativeLdapDn Source

A RelativeLDAPDN is defined to be the representation of a Relative Distinguished Name (RDN) after encoding according to the - specification in [RFC4514].

Instances

Eq RelativeLdapDn Source 
Show RelativeLdapDn Source 
ToAsn1 RelativeLdapDn Source
RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
-

newtype ReferralUris Source

Constructors

ReferralUris (NonEmpty Uri) 

Instances

Eq ReferralUris Source 
Show ReferralUris Source 
FromAsn1 ReferralUris Source
Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
-

newtype Uri Source

Constructors

Uri LdapString 

Instances

Eq Uri Source 
Show Uri Source 
FromAsn1 Uri Source
URI ::= LDAPString
-

newtype LdapString Source

The LDAPString is a notational convenience to indicate that, although + specification in [RFC4514].

Instances

Eq RelativeLdapDn Source 
Show RelativeLdapDn Source 
ToAsn1 RelativeLdapDn Source
RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+

newtype ReferralUris Source

Constructors

ReferralUris (NonEmpty Uri) 

Instances

Eq ReferralUris Source 
Show ReferralUris Source 
FromAsn1 ReferralUris Source
Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+

newtype Uri Source

Constructors

Uri LdapString 

Instances

Eq Uri Source 
Show Uri Source 
FromAsn1 Uri Source
URI ::= LDAPString
+

newtype LdapString Source

The LDAPString is a notational convenience to indicate that, although strings of LDAPString type encode as ASN.1 OCTET STRING types, the [ISO10646] character set (a superset of [Unicode]) is used, encoded - following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.)

Constructors

LdapString Text 

Instances

Eq LdapString Source 
Show LdapString Source 
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
+ following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.)

Constructors

LdapString Text 

Instances

Eq LdapString Source 
Show LdapString Source 
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
 
FromAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded,
 

newtype LdapOid Source

The LDAPOID is a notational convenience to indicate that the permitted value of this string is a (UTF-8 encoded) dotted-decimal representation of an OBJECT IDENTIFIER. Although an LDAPOID is encoded as an OCTET STRING, values are limited to the definition of - <numericoid> given in Section 1.4 of [RFC4512].

Constructors

LdapOid Text 

Instances

Eq LdapOid Source 
Show LdapOid Source 
ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+ <numericoid> given in Section 1.4 of [RFC4512].

Constructors

LdapOid Text 

Instances

Eq LdapOid Source 
Show LdapOid Source 
ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
FromAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
\ No newline at end of file diff --git a/Ldap-Client-Bind.html b/Ldap-Client-Bind.html index f42491d..9a8fb01 100644 --- a/Ldap-Client-Bind.html +++ b/Ldap-Client-Bind.html @@ -1,7 +1,7 @@ Ldap.Client.Bind

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Bind

Description

Bind operation.

This operation comes in four flavours:

Of those, the first one (bind) is probably the most useful for the typical usecase.

Synopsis

Documentation

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) Source

Perform the Bind operation synchronously. Returns Left e where - e is a ResponseError on failures.

bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) Source

Perform the Bind operation asynchronously. Call wait to wait - for its completion.

bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) Source

Perform the Bind operation asynchronously.

Don't wait for its completion (with waitSTM) in the +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Bind

Description

Bind operation.

This operation comes in four flavours:

Of those, the first one (bind) is probably the most useful for the typical usecase.

Synopsis

Documentation

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) Source

Perform the Bind operation synchronously. Returns Left e where + e is a ResponseError on failures.

bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) Source

Perform the Bind operation asynchronously. Call wait to wait + for its completion.

bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) Source

Perform the Bind operation asynchronously.

Don't wait for its completion (with waitSTM) in the same transaction you've performed it in.

\ No newline at end of file diff --git a/Ldap-Client-Extended.html b/Ldap-Client-Extended.html index e30031b..2fccba2 100644 --- a/Ldap-Client-Extended.html +++ b/Ldap-Client-Extended.html @@ -1,7 +1,7 @@ Ldap.Client.Extended

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Extended

Description

Extended operation.

This operation comes in four flavours:

Of those, the first one (extended) is probably the most useful for the typical usecase.

Documentation

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) Source

Perform the Extended operation synchronously. Returns Left e where - e is a ResponseError on failures.

extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) Source

Perform the Extended operation asynchronously. Call wait to wait - for its completion.

extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) Source

Perform the Extended operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Extended

Description

Extended operation.

This operation comes in four flavours:

Of those, the first one (extended) is probably the most useful for the typical usecase.

Extended Operation

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) Source

Perform the Extended operation synchronously. Returns Left e where + e is a ResponseError on failures.

extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) Source

Perform the Extended operation asynchronously. Call wait to wait + for its completion.

extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) Source

Perform the Extended operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

StartTLS Operation

startTls :: Ldap -> IO () Source

An example of Extended Operation, cf. extended.

startTlsEither :: Ldap -> IO (Either ResponseError ()) Source

An example of Extended Operation, cf. extendedEither.

startTlsAsync :: Ldap -> IO (Async ()) Source

An example of Extended Operation, cf. extendedAsync.

startTlsAsyncSTM :: Ldap -> STM (Async ()) Source

An example of Extended Operation, cf. extendedAsyncSTM.

\ No newline at end of file diff --git a/Ldap-Client-Internal.html b/Ldap-Client-Internal.html index 830532a..e92d5ff 100644 --- a/Ldap-Client-Internal.html +++ b/Ldap-Client-Internal.html @@ -1,10 +1,15 @@ Ldap.Client.Internal

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Internal

Synopsis

Documentation

data Ldap Source

Constructors

Ldap 

Fields

client :: TQueue ClientMessage
 

Instances

data Async a Source

Instances

newtype Oid Source

Constructors

Oid Text 

Instances

type AttrList f = [(Attr, f AttrValue)] Source

Waiting for Request Completion

unbindAsync :: Ldap -> IO () Source

Note that unbindAsync does not return an Async, +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Internal

Synopsis

Documentation

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. + Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Constructors

Ldap 

Fields

client :: TQueue ClientMessage
 

Instances

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these + values are in, e.g. NonEmpty.

Waiting for Request Completion

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

Misc

type Response = NonEmpty InMessage Source

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

raise :: Exception e => Either e a -> IO a Source

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

unAttr :: Attr -> Text Source

Unbind operation

unbindAsync :: Ldap -> IO () Source

Terminate the connection to the Directory.

Note that unbindAsync does not return an Async, because LDAP server never responds to UnbindRequests, hence a call to wait on a hypothetical Async would have resulted - in an exception anyway.

unbindAsyncSTM :: Ldap -> STM () Source

Note that unbindAsyncSTM does not return an Async, + in an exception anyway.

unbindAsyncSTM :: Ldap -> STM () Source

Terminate the connection to the Directory.

Note that unbindAsyncSTM does not return an Async, because LDAP server never responds to UnbindRequests, hence a call to wait on a hypothetical Async would have resulted - in an exception anyway.

Misc

type Response = NonEmpty InMessage Source

raise :: Exception e => Either e a -> IO a Source

newtype Dn Source

Constructors

Dn Text 

Instances

newtype RelativeDn Source

Constructors

RelativeDn Text 

newtype Attr Source

Constructors

Attr Text 

unAttr :: Attr -> Text Source

\ No newline at end of file + in an exception anyway.

\ No newline at end of file diff --git a/Ldap-Client-Modify.html b/Ldap-Client-Modify.html index 7f47c6e..228acc1 100644 --- a/Ldap-Client-Modify.html +++ b/Ldap-Client-Modify.html @@ -4,10 +4,10 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Client-Modify.htm

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Modify

Description

Modify and Modify DN operations.

These operations come in four flavours:

Of those, the first one (modify / modifyDn) is probably the most - useful for the typical usecase.

Documentation

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) Source

Perform the Modify operation synchronously. Returns Left e where + useful for the typical usecase.

Documentation

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) Source

Perform the Modify operation synchronously. Returns Left e where e is a ResponseError on failures.

modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) Source

Perform the Modify operation asynchronously. Call wait to wait for its completion.

modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) Source

Perform the Modify operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) Source

Perform the Modify DN operation synchronously. Returns Left e where - e is a ResponseError on failures.

modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) Source

Perform the Modify DN operation asynchronously. Call wait to wait - for its completion.

modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) Source

Perform the Modify DN operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) Source

Perform the Modify DN operation synchronously. Returns Left e where + e is a ResponseError on failures.

modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) Source

Perform the Modify DN operation asynchronously. Call wait to wait + for its completion.

modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) Source

Perform the Modify DN operation asynchronously.

Don't wait for its completion (with waitSTM) in the same transaction you've performed it in.

\ No newline at end of file diff --git a/Ldap-Client-Search.html b/Ldap-Client-Search.html index 62c9739..5452b22 100644 --- a/Ldap-Client-Search.html +++ b/Ldap-Client-Search.html @@ -1,7 +1,12 @@ Ldap.Client.Search

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Search

Description

Search operation.

This operation comes in four flavours:

Of those, the first one (search) is probably the most useful for the typical usecase.

Documentation

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

searchEither :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Either ResponseError [SearchEntry]) Source

Perform the Search operation synchronously. Returns Left e where +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Search

Description

Search operation.

This operation comes in four flavours:

Of those, the first one (search) is probably the most useful for the typical usecase.

Documentation

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

searchEither :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Either ResponseError [SearchEntry]) Source

Perform the Search operation synchronously. Returns Left e where e is a ResponseError on failures.

searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) Source

Perform the Search operation asynchronously. Call wait to wait for its completion.

searchAsyncSTM :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> STM (Async [SearchEntry]) Source

Perform the Search operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

data Mod a Source

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 
\ No newline at end of file + same transaction you've performed it in.

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. + No limit if the value is 0 (default: 0).

time :: Int32 -> Mod Search Source

Maximum time (in seconds) allowed for the Search. No limit if the value + is 0 (default: 0).

typesOnly :: Bool -> Mod Search Source

Whether Search results are to contain just attribute descriptions, or + both attribute descriptions and values (default: False).

data DerefAliases Source

An indicator as to whether or not alias entries (as defined in + [RFC4512]) are to be dereferenced during stages of the Search + operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 
\ No newline at end of file diff --git a/Ldap-Client.html b/Ldap-Client.html index 2c52051..3ef285b 100644 --- a/Ldap-Client.html +++ b/Ldap-Client.html @@ -1,4 +1,11 @@ Ldap.Client

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client

Synopsis

Documentation

data Ldap Source

Instances

data Async a Source

Instances

with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) Source

The entrypoint into LDAP.

Bind

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

Search

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

Search modifiers

data Mod a Source

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 

Modify

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

Add

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

Delete

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

ModifyDn

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

Compare

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

Extended

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

Waiting for completion

Miscellanous

newtype Dn Source

Constructors

Dn Text 

Instances

newtype RelativeDn Source

Constructors

RelativeDn Text 

newtype Oid Source

Constructors

Oid Text 

Instances

type AttrList f = [(Attr, f AttrValue)] Source

newtype Attr Source

Constructors

Attr Text 

Re-exports

data NonEmpty a :: * -> *

Instances

Monad NonEmpty 
Functor NonEmpty 
MonadFix NonEmpty 
Applicative NonEmpty 
Foldable NonEmpty 
Traversable NonEmpty 
Generic1 NonEmpty 
MonadZip NonEmpty 
IsList (NonEmpty a) 
Eq a => Eq (NonEmpty a) 
Data a => Data (NonEmpty a) 
Ord a => Ord (NonEmpty a) 
Read a => Read (NonEmpty a) 
Show a => Show (NonEmpty a) 
Generic (NonEmpty a) 
NFData a => NFData (NonEmpty a) 
Hashable a => Hashable (NonEmpty a) 
ToAsn1 a => ToAsn1 (NonEmpty a) 
Semigroup (NonEmpty a) 
type Rep1 NonEmpty = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector Par1) (S1 NoSelector (Rec1 [])))) 
type Rep (NonEmpty a) = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector (Rec0 a)) (S1 NoSelector (Rec0 [a])))) 
type Item (NonEmpty a) = a 
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client

Description

Pure Haskell LDAP client library.

Synopsis

Documentation

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. + Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Instances

data LdapError Source

Various failures that can happen when working with LDAP.

Constructors

IOError IOError

Network failure.

ParseError ASN1Error

Invalid ASN.1 data received from the server.

ResponseError ResponseError

An LDAP operation failed.

DisconnectError Disconnect

Notice of Disconnection has been received.

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) Source

The entrypoint into LDAP.

It catches all LDAP-related exceptions.

Bind

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

Search

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 

Search modifiers

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. + No limit if the value is 0 (default: 0).

time :: Int32 -> Mod Search Source

Maximum time (in seconds) allowed for the Search. No limit if the value + is 0 (default: 0).

typesOnly :: Bool -> Mod Search Source

Whether Search results are to contain just attribute descriptions, or + both attribute descriptions and values (default: False).

data DerefAliases Source

An indicator as to whether or not alias entries (as defined in + [RFC4512]) are to be dereferenced during stages of the Search + operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

Modify

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

Add

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

Delete

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

ModifyDn

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

Compare

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

Extended

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

Waiting for completion

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

Miscellanous

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these + values are in, e.g. NonEmpty.

Re-exports

data NonEmpty a :: * -> *

Instances

Monad NonEmpty 
Functor NonEmpty 
MonadFix NonEmpty 
Applicative NonEmpty 
Foldable NonEmpty 
Traversable NonEmpty 
Generic1 NonEmpty 
MonadZip NonEmpty 
IsList (NonEmpty a) 
Eq a => Eq (NonEmpty a) 
Data a => Data (NonEmpty a) 
Ord a => Ord (NonEmpty a) 
Read a => Read (NonEmpty a) 
Show a => Show (NonEmpty a) 
Generic (NonEmpty a) 
NFData a => NFData (NonEmpty a) 
Hashable a => Hashable (NonEmpty a) 
ToAsn1 a => ToAsn1 (NonEmpty a) 
Semigroup (NonEmpty a) 
type Rep1 NonEmpty = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector Par1) (S1 NoSelector (Rec1 [])))) 
type Rep (NonEmpty a) = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector (Rec0 a)) (S1 NoSelector (Rec0 [a])))) 
type Item (NonEmpty a) = a 
\ No newline at end of file diff --git a/doc-index-All.html b/doc-index-All.html index 3a297d7..feb22e6 100644 --- a/doc-index-All.html +++ b/doc-index-All.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index

::=Ldap.Client.Search, Ldap.Client
:<=Ldap.Client.Search, Ldap.Client
:=Ldap.Client.Search, Ldap.Client
:=*Ldap.Client.Search, Ldap.Client
:>=Ldap.Client.Search, Ldap.Client
:~=Ldap.Client.Search, Ldap.Client
Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
BaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
bindLdap.Client.Bind, Ldap.Client
bindAsyncLdap.Client.Bind
bindAsyncSTMLdap.Client.Bind
bindEitherLdap.Client.Bind
BindRequestLdap.Asn1.Type
BindResponseLdap.Asn1.Type
BusyLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
clientLdap.Client.Internal
ClientMessageLdap.Client.Internal
compareLdap.Client.Compare, Ldap.Client
compareAsyncLdap.Client.Compare
compareAsyncSTMLdap.Client.Compare
compareEitherLdap.Client.Compare
CompareFalseLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
CompareRequestLdap.Asn1.Type
CompareResponseLdap.Asn1.Type
CompareTrueLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConfidentialityRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConstraintViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Control 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Controls 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Delete 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
deleteLdap.Client.Delete, Ldap.Client
deleteAsyncLdap.Client.Delete
deleteAsyncSTMLdap.Client.Delete
deleteEitherLdap.Client.Delete
DeleteRequestLdap.Asn1.Type
DeleteResponseLdap.Asn1.Type
DerefAliasesLdap.Asn1.Type
derefAliasesLdap.Client.Search, Ldap.Client
DerefAlwaysLdap.Asn1.Type
DerefFindingBaseObjectLdap.Asn1.Type
DerefInSearchingLdap.Asn1.Type
DisconnectErrorLdap.Client
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
EntryAlreadyExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
EqualityMatchLdap.Asn1.Type
extendedLdap.Client.Extended, Ldap.Client
extendedAsyncLdap.Client.Extended
extendedAsyncSTMLdap.Client.Extended
extendedEitherLdap.Client.Extended
ExtendedRequestLdap.Asn1.Type
ExtendedResponseLdap.Asn1.Type
ExtensibleMatchLdap.Asn1.Type
Filter 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Search, Ldap.Client
FinalLdap.Asn1.Type
FromAsn1Ldap.Asn1.FromAsn1
GreaterOrEqualLdap.Asn1.Type
HostLdap.Client.Internal, Ldap.Client
Id 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
InappropriateAuthenticationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InappropriateMatchingLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InitialLdap.Asn1.Type
InsecureLdap.Client.Internal, Ldap.Client
InsufficientAccessRightsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IntermediateResponseLdap.Asn1.Type
InvalidAttributeSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidCredentialsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidDNSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IOErrorLdap.Client
Ldap 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal
LdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapErrorLdap.Client
LdapMessage 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ldapMessageControlsLdap.Asn1.Type
ldapMessageIdLdap.Asn1.Type
ldapMessageOpLdap.Asn1.Type
LdapOid 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapResult 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapString 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LessOrEqualLdap.Asn1.Type
LoopDetectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
MatchingRuleAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
MatchingRuleId 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ModLdap.Client.Search, Ldap.Client
modifyLdap.Client.Modify, Ldap.Client
modifyAsyncLdap.Client.Modify
modifyAsyncSTMLdap.Client.Modify
modifyDnLdap.Client.Modify, Ldap.Client
modifyDnAsyncLdap.Client.Modify
modifyDnAsyncSTMLdap.Client.Modify
modifyDnEitherLdap.Client.Modify
ModifyDnRequestLdap.Asn1.Type
ModifyDnResponseLdap.Asn1.Type
modifyEitherLdap.Client.Modify
ModifyRequestLdap.Asn1.Type
ModifyResponseLdap.Asn1.Type
NamingViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NeverDerefAliasesLdap.Asn1.Type
NewLdap.Client.Internal
NonEmptyLdap.Client
NoSuchAttributeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NoSuchObjectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Not 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
NotAllowedOnNonLeafLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NotAllowedOnRDNLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassModsProhibitedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Oid 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Operation 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Modify, Ldap.Client
OperationErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Or 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
OtherLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SaslBindInProgressLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ScopeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
scopeLdap.Client.Search, Ldap.Client
SearchLdap.Client.Search, Ldap.Client
searchLdap.Client.Search, Ldap.Client
searchAsyncLdap.Client.Search
searchAsyncSTMLdap.Client.Search
searchEitherLdap.Client.Search
SearchEntry 
1 (Type/Class)Ldap.Client.Search, Ldap.Client
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
SearchRequestLdap.Asn1.Type
SearchResultDoneLdap.Asn1.Type
SearchResultEntryLdap.Asn1.Type
SearchResultReferenceLdap.Asn1.Type
SecureLdap.Client.Internal, Ldap.Client
sendRequestLdap.Client.Internal
SimpleLdap.Asn1.Type
SingleLevelLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
sizeLdap.Client.Search, Ldap.Client
SizeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
startTlsLdap.Client.Extended
startTlsAsyncLdap.Client.Extended
startTlsAsyncSTMLdap.Client.Extended
startTlsEitherLdap.Client.Extended
StrongerAuthRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SubstringLdap.Asn1.Type
SubstringFilter 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
SubstringsLdap.Asn1.Type
SuccessLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
timeLdap.Client.Search, Ldap.Client
TimeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ToAsn1Ldap.Asn1.ToAsn1
toAsn1Ldap.Asn1.ToAsn1
typesOnlyLdap.Client.Search, Ldap.Client
unAttrLdap.Client.Internal
UnavailableLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
UnavailableCriticalExtensionLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unbindAsyncLdap.Client.Internal
unbindAsyncSTMLdap.Client.Internal
UnbindRequestLdap.Asn1.Type
UndefinedAttributeTypeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unIdLdap.Asn1.Type
UnwillingToPerformLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Uri 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
waitLdap.Client.Internal, Ldap.Client
waitSTMLdap.Client.Internal
WholeSubtreeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
withLdap.Client
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index

::=Ldap.Client.Search, Ldap.Client
:<=Ldap.Client.Search, Ldap.Client
:=Ldap.Client.Search, Ldap.Client
:=*Ldap.Client.Search, Ldap.Client
:>=Ldap.Client.Search, Ldap.Client
:~=Ldap.Client.Search, Ldap.Client
Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
BaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
bindLdap.Client.Bind, Ldap.Client
bindAsyncLdap.Client.Bind
bindAsyncSTMLdap.Client.Bind
bindEitherLdap.Client.Bind
BindRequestLdap.Asn1.Type
BindResponseLdap.Asn1.Type
BusyLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
clientLdap.Client.Internal
ClientMessageLdap.Client.Internal
compareLdap.Client.Compare, Ldap.Client
compareAsyncLdap.Client.Compare
compareAsyncSTMLdap.Client.Compare
compareEitherLdap.Client.Compare
CompareFalseLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
CompareRequestLdap.Asn1.Type
CompareResponseLdap.Asn1.Type
CompareTrueLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConfidentialityRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConstraintViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Control 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Controls 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Delete 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
deleteLdap.Client.Delete, Ldap.Client
deleteAsyncLdap.Client.Delete
deleteAsyncSTMLdap.Client.Delete
deleteEitherLdap.Client.Delete
DeleteRequestLdap.Asn1.Type
DeleteResponseLdap.Asn1.Type
DerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
derefAliasesLdap.Client.Search, Ldap.Client
DerefAlwaysLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefFindingBaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefInSearchingLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DisconnectErrorLdap.Client
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
EntryAlreadyExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
EqualityMatchLdap.Asn1.Type
extendedLdap.Client.Extended, Ldap.Client
extendedAsyncLdap.Client.Extended
extendedAsyncSTMLdap.Client.Extended
extendedEitherLdap.Client.Extended
ExtendedRequestLdap.Asn1.Type
ExtendedResponseLdap.Asn1.Type
ExtensibleMatchLdap.Asn1.Type
Filter 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Search, Ldap.Client
FinalLdap.Asn1.Type
FromAsn1Ldap.Asn1.FromAsn1
GreaterOrEqualLdap.Asn1.Type
HostLdap.Client.Internal, Ldap.Client
Id 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
InappropriateAuthenticationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InappropriateMatchingLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InitialLdap.Asn1.Type
InsecureLdap.Client.Internal, Ldap.Client
InsufficientAccessRightsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IntermediateResponseLdap.Asn1.Type
InvalidAttributeSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidCredentialsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidDNSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IOErrorLdap.Client
Ldap 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal
LdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapErrorLdap.Client
LdapMessage 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ldapMessageControlsLdap.Asn1.Type
ldapMessageIdLdap.Asn1.Type
ldapMessageOpLdap.Asn1.Type
LdapOid 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapResult 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapString 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LessOrEqualLdap.Asn1.Type
LoopDetectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
MatchingRuleAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
MatchingRuleId 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ModLdap.Client.Search, Ldap.Client
modifyLdap.Client.Modify, Ldap.Client
modifyAsyncLdap.Client.Modify
modifyAsyncSTMLdap.Client.Modify
modifyDnLdap.Client.Modify, Ldap.Client
modifyDnAsyncLdap.Client.Modify
modifyDnAsyncSTMLdap.Client.Modify
modifyDnEitherLdap.Client.Modify
ModifyDnRequestLdap.Asn1.Type
ModifyDnResponseLdap.Asn1.Type
modifyEitherLdap.Client.Modify
ModifyRequestLdap.Asn1.Type
ModifyResponseLdap.Asn1.Type
NamingViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NeverDerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
NewLdap.Client.Internal
NonEmptyLdap.Client
NoSuchAttributeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NoSuchObjectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Not 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
NotAllowedOnNonLeafLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NotAllowedOnRDNLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassModsProhibitedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Oid 
1 (Type/Class)Ldap.Client.Extended, Ldap.Client
2 (Data Constructor)Ldap.Client.Extended, Ldap.Client
Operation 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Modify, Ldap.Client
OperationErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Or 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
OtherLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Bind, Ldap.Client
2 (Data Constructor)Ldap.Client.Bind, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Modify, Ldap.Client
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SaslBindInProgressLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ScopeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
scopeLdap.Client.Search, Ldap.Client
SearchLdap.Client.Search, Ldap.Client
searchLdap.Client.Search, Ldap.Client
searchAsyncLdap.Client.Search
searchAsyncSTMLdap.Client.Search
searchEitherLdap.Client.Search
SearchEntry 
1 (Type/Class)Ldap.Client.Search, Ldap.Client
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
SearchRequestLdap.Asn1.Type
SearchResultDoneLdap.Asn1.Type
SearchResultEntryLdap.Asn1.Type
SearchResultReferenceLdap.Asn1.Type
SecureLdap.Client.Internal, Ldap.Client
sendRequestLdap.Client.Internal
SimpleLdap.Asn1.Type
SingleLevelLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
sizeLdap.Client.Search, Ldap.Client
SizeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
startTlsLdap.Client.Extended
startTlsAsyncLdap.Client.Extended
startTlsAsyncSTMLdap.Client.Extended
startTlsEitherLdap.Client.Extended
StrongerAuthRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SubstringLdap.Asn1.Type
SubstringFilter 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
SubstringsLdap.Asn1.Type
SuccessLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
timeLdap.Client.Search, Ldap.Client
TimeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ToAsn1Ldap.Asn1.ToAsn1
toAsn1Ldap.Asn1.ToAsn1
typesOnlyLdap.Client.Search, Ldap.Client
unAttrLdap.Client.Internal
UnavailableLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
UnavailableCriticalExtensionLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unbindAsyncLdap.Client.Internal
unbindAsyncSTMLdap.Client.Internal
UnbindRequestLdap.Asn1.Type
UndefinedAttributeTypeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unIdLdap.Asn1.Type
UnwillingToPerformLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Uri 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
waitLdap.Client.Internal, Ldap.Client
waitSTMLdap.Client.Internal
WholeSubtreeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
withLdap.Client
\ No newline at end of file diff --git a/doc-index-D.html b/doc-index-D.html index aef5395..c973edf 100644 --- a/doc-index-D.html +++ b/doc-index-D.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - D)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - D

Delete 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
deleteLdap.Client.Delete, Ldap.Client
deleteAsyncLdap.Client.Delete
deleteAsyncSTMLdap.Client.Delete
deleteEitherLdap.Client.Delete
DeleteRequestLdap.Asn1.Type
DeleteResponseLdap.Asn1.Type
DerefAliasesLdap.Asn1.Type
derefAliasesLdap.Client.Search, Ldap.Client
DerefAlwaysLdap.Asn1.Type
DerefFindingBaseObjectLdap.Asn1.Type
DerefInSearchingLdap.Asn1.Type
DisconnectErrorLdap.Client
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file diff --git a/doc-index-N.html b/doc-index-N.html index fc2f894..c775063 100644 --- a/doc-index-N.html +++ b/doc-index-N.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - N)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file diff --git a/doc-index-O.html b/doc-index-O.html index 1ee8e79..734202b 100644 --- a/doc-index-O.html +++ b/doc-index-O.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - O)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file diff --git a/doc-index-P.html b/doc-index-P.html index b12db76..c7d139f 100644 --- a/doc-index-P.html +++ b/doc-index-P.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - P)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - P

parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - P

parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Bind, Ldap.Client
2 (Data Constructor)Ldap.Client.Bind, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
\ No newline at end of file diff --git a/doc-index-R.html b/doc-index-R.html index 80f5829..23d6779 100644 --- a/doc-index-R.html +++ b/doc-index-R.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - R)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - R

raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - R

raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Modify, Ldap.Client
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
\ No newline at end of file diff --git a/ldap-client.haddock b/ldap-client.haddock index da7f89974cc574d5b9e476712e62d2a1e260294e..9a8f92db74ad815352b28ca5e5add6d3ae9bfb7f 100644 GIT binary patch delta 11140 zcmd5?33!uLy8cf{LeeH}LQ<02C4VSTu+ZWLsE8CO%YYyPgDV(H!3q?IO-n~WaV|Oo z7s@C8j(8D75EKOsTHHa!4cXLjS3q$Yoe_7v&YkPL?@9g=P#9*O>+{_IdERrr?>pyw z+gbi4S@f~<&39cne%}u}jRHfBc-m0C|9oH0sh-I$!!R}gyhv}w8?i1b|=kV_i8Js_A2%mAhV(*YA03)H0P@u=B82_RjYrYFhP z`62l+-xH+jslYgZqozvb!iZeIpp#rBKACqy*kwYRkZysP)!wPXt;@k)Y_w30D2Pgc zx+lp^XT&a{7bZYGGl2xaR(e319@?IfrfsvO!-;AHa2_xcr~)p@w7}5oVWA}NXEjTF zNhE#@U8AWhEX%vcjz0d9^mrFc^#d5#U|={vf5t#ZO9$tl9Os3e+PwyXW&{@~M-D0z zU{3AK*T|NuV#9QHem>euwRWyp+N0*)Xu^b|3KYI2H=yR+*U2JZ ziN850ND?wxA~JW4GkzJk8h{JkrgiAx^$6K`RYaaS5VqQ2TjkMJcGvEr?f@jDPhOeq zp6_&V2V{vAC{rCJ2m`yFw^x6sc04PQy0xMs0p(0#xmJ; zLsVrgxus0@t#SG%AQG-Mu8Jwzo3uK)t=J=jZ}iB{13s5_O5!*!`u#mBpS&AzrM!p4 z%gs%$TAr5z$$28+=iy`Luto+AE0M8V3Td{e94(i@;uzGUG=1nes*$t*9;0qAUFNnK zD|@36mB7{x$*ngQ{zPv~b&~Ca3K+ch*3~V*Tq;xcKN6DgvZ$VAdc1LgQ@-sV_R@YW z?Dv${4wU_Tg#SuBTHoc+H{wWr`I*zmd@w_L6=Y^nUN82`_xZX1icOuviLlug8ixbb zY3)~_u91tjl*+IE9@Y`_@a6(}`+>GHx6$dEgi)R4liIW8@!UZ3>X)g7Vfmj2JTAIf zFAe=GbXb$od63=N#g#c(ter8x3F;^l^v_h*LFGVO<8UciJe3fJl?5dwvOPbbRo2Pg z!h$?gpIwGlN%ex%1b80G+Q!sAxDk?EEty#u&{KXBB<*G2_ENdYXVO*dz1x~1^7X@A zcviSAM$`$>fl!V)SlFJk^pfSKWT@Z1<-fF8dOR>@f2f>dgpaFzOM2K6E9pqttRZ zaKO?yjnR-jbqPLh;mjD*DuTERTDa2T>_2@2HTk8lrsQV_r`-Asq?mP*A7l zZmrS}MQqfjn;X_S3gtHv!VM-Miys+G6;&(X4v+9k_5!$2IBFtbXNq2!0Q)eXgbC1b z=D1FNGr#%4Qr?)Kolh+~9MlQGUV=Pe!*bgCNO}#|RYp|3d=`sH@!P(96Fq60N#|k3Gs0E|OZ{xU1FaF%=K}PKw)8Z~=M52^ZW9v5m%2qoV?J*j+-i&)Lal0w zRMv<5oN>8w+GbWB44sj?u!J9@!@Yd)qf{(#$2j z<-@(1fuW!oD?P85U@RnNy;BA(47hauqkP%SL9=<6SBiHNpIuyl(BLo zHJE9dacPY*t2`zH<_EnzS5#Cv7E0x^ZZdeKPv2zUUf02YCHf}P{j;zdO62MJfjBiV z5))v=oDtF!09uG904fJ_ZWv5%wj-gja77`jI`1f^9Df-^Nb*X~$)H>1H}ea|wQnjf(zq2+C&<~e3mwMoGGTUEkt(44ZWilV z+ykgW7DYx?a>wkj>R1JC6>tZz8dw7~0xN)(!0o_t;5OMYdsW9}pq2n@fpq{)-UL{{ z&A@*FGq3I$#jXTv{h}^ zxC`7df|Iwe>2!_@eeT6x51`IG1GpAS0eeq!&2njxC%EVI;zT_T;DXwi^k3^y>OM)_ z+&wvDURR~=mx@*0Wyri9SOHF1ync^LCU^a=wc|t&y59?=KDKNmbsvlSStJ3)!$-vo zx9p!2Rk}RcXbIW9OvMJ^7=zHNFSjJt#pR0YgMJ?Jo6<*Gm25aaQpD}a0JxdCv>Ak% zuK5B}AU(rAzB}YIvdo%n$_#UF4o|@oWj2{?eW?iwCvWyB@tfdy-0@6KNae~% zvzo`Cru)&=@WYW-gW3d`k{Vzdo_Rxf?#xv6I8>c>gsP5b7v}RU=0TYN>?59f>UC0k zEj1ZW-V+$j)44yuR$3j)9G)9Ne zJ8nm=LldyqAU)t<`_90ACcqWVEo#drfKJ_vO?+&SJ;kBC3W%DMpl_^kJSCk`UYbQC zPtpgx$!Q;a;%NxPsn52bc}%2kSz8_X`oXa4d4>9AiK_7>!XMKg_&Aonar{%V^8W7F zRoBVhRU_2X65QB5x$B0WN^Rqzfrh@#C&e?#OBWP7iZJL|`or^JI8Y5xKM$nC-a0#X zfP}l4wz#`FJIn=>%UL=D;7frI^(fgsu+u09Pt%S7U3-pJMuRv9;Ml7Gd#0&}`8I(% zz~-5Mdw$qP&&FFZr;4arsl{grz6L*gRaCNa3uWHbg)(}J$wMVbi}tO12nWg^atq`y zcm-ID53G1qnqxvr^Gu)pj@Cu#R~j}QZ?p=1yBrqi^9*z_#K#QuVsv2E>l>2cj@-D%&%4hxr69} z-Geh|zk(c}>6Q+DZx|xo2K9;^@}Mnbn}F00Ao`b&CPU`@=c$twoxDy|vhDHcz&*v8@+K%K~dd0th)b`Ik#-ZoFh1^G zu1xy%06?#rfX%=|vVT#9G%U(LJr0hhX_p#j?_f^G*9a<&{mMvkJKBBr!2NY z+a`rV8|Na(v~JEplTOZ)ZV<=~Q^U+KG0clj%l|=EU|3%*Q1kc2ZvZdz1|X0mds=OjdL@~-d6-gvl1mq8Df)Hb z{UEt-!E){DtFpa`EeG7M(a~<0D#F9F8OEM8$jHOJ=$d-L+> zQv9pp>dj=uDyLF!iT~Q}QgkPtfHwc2-cH`Ox=OjAU=vb%*Zq z`}JI>C3>D^?gr<@@4`mvr_Ft&_5 zSh?SCUNcg$X@Jhzf#k~jM=JLR%voohvx-fhsf*u(mDEqG2S|MYsBSE}YmeCcKETEg z=+R*U?a|RSNd1FlCmLRi`VdIY2o$&z%4h zs0P@n97r7kA2%NYfBnU5{JGi2XTO+@PnvBU{C91f{LgarY08EV$@>t%@9|RkSfuUg zAQhiVF-^Gs%HlH?2lZnDyM83G$4oEp7d98q$|k3DBeb|vT9Tt5>(Rn>rjhOFFXwI> zB}4iJq`snyblrNr>XCe6YbaNpB`@zD?&^sy6|!$zMDG16Al9?&)>a0d)>kT?EyBW8 zXD2`1^JCoA3;m`;RUetV)G2@48j#v9y^{a&br0pLM3c$aBKho_i&bwK^sVLU16gZ) zV+_f`r#-Up@*Z?r^@X&%md@D`kcAVsxT+v2*OIHpMrEHkW%Tz8R6qIj`(@t#X#3GH z9DUiIy#2qG_k;lmQw?PCD-_1(qy~}t!rJ3d(ZIPB@Wou6$6~nE*g|#b1-oFXSoCAj z-*BMf;4esgp_wQe27sk{t^IT4R4YH0?%+>!TaUL;gWI{G^Gj^r?x=qaBmizjZcE-h zX8_aiqeiI=SnA^+DCjwN6+7A+^RhI51!{sD)o!~IG~17qQ8^7wls)(~f8ddzeBBUg z$9?)0+zFr_0&vuHfLacXxUDJmo5I)V$(=q>p4e9)FLjP~G{KDn=pDzgHUV0qE_%+o zRyG`r$a9UR{)L)Wzk#lN)RjOTKBE`tkH?o@7Z}O@)X84oqSuM2=^Oo_4W`Q0Yl5bH zJV2Tg%62|vvk%+q2!4N`VO0jHV}N*%&j7}_xt zb+uG{8PUK0kV^oQ2>wn`)EShmo>I0lAgx-qTwRt=$I63PUL!!Lku11K)F|r@PF2+Y ze9*>s6kNdKLKYXX;7gdggvDrMinY_J?vy?q!`2L!>T&uCh*tr30IPvDz*^v5U<0rb z*aSQPJP0%an*l!VmdU(DajUCa<>tK#5pVdsU%m%?2z+E+=vIY!O!AQyR#>CmDq`L4 zR_m*lp`Bi5T6_w;ZS_geTY-P`(fRb3Fm@-f3)l_tk;!)TMbP%+R1mz5%{P!*R_7`tnj^n(963>z3B6fbti#fW*>r z!*G(h*=CgWXh7u;hh5_qTgIB{4Z(J6-CfO*k(V}&&|sM=?( zB#p~ySUrQPs0$YaFBiSw%HZXq-e!gpt`}Y|>t<*Px!L~ zZ*^*=dURml`)oOx`)!7GvYD|Kw^HLnE!pGIw6G;rKWceHs+W4qIxD2cDvz}yq)t&@ z>lId6mM5%E$<5{<&N#1Z)pS-^&2-FB7_A&=Qf%g>bF?%?>s0C&1>J%|x$G7)?o1~A z3S_W{@}yfd;{}roVHWLh@zAJ`4BwGd4vjxhWHQlAh9@g8ZRZ3{!ahSuedq_FnL^!^X7~+_mu@Le(fZW^-`7(Y!&fE>UJPHw zHJN7Gq#4}OQ?IGyHPhBGQUM}O`lXdEMz*yzs!mmg)goVAGlz*gRm%;-$GkN&5bCFT zHu}hPC51~f-BNUl>7L2(k%yP=c1DU$F=u8nJv4*-=zeEqHuX$1Tt@0_o1t^f3|o3- zwlp&ks!F?sOz%vlPbSkh^?w8OVZW-(rhb`B{}iJJG?^!;)jsRX_UeXKo`H4KYN}^U ztx5NE54RSUs%mRndlhKwN zCZ^eA{rv~@Dep6-uDX19eO+~0VT<7-&aw8EtND|1`X;6)%7@oXuAMM-$_zex@bVrh z@K8(dLt5SEOsShvJ1*7R@JzU@y7LuNYbU39FME%uzoKSZTHxxJm^7`XX-tLM===xT C#-Jtu delta 4054 zcmb7H3s6+o89x8AEX%SG3@8sbf)7OH9Wer;fSM*2G(Jdb(?@EEO(juF9GgyO+D)5w z+O$rMp4O8XtcxJ=K^}V1)r`>+qDE>&G~km*M1zhgYBfp6wzmIwb}zZ6)3KhJ@4Nr^ z|L30bpXc2@-4(j>qCG0oee;MIDkw2tkh5xARIYQeT?p|O0|oZm+6vg)EcSMbZCLEa zpdHH39Tt11#rB)Fe9QTd6bGvhgC5vNEOx7D%hvE0Bg0so33|fh6RwewPFCGPk5jH> zPdKaIpeJ1JV~>kfU(n-{S6r7V+&B}lHPYx$m~J;(vee@a8;7@x)oXKTyWF;JKGhh% zTRV~LZ;~xWR@KMIWWQZ@zE(grGQN7Z&CoTCJJ#GusdAPt*Cwjv?|mLO#UqIg3`&p< zzO+eVD;y1=H$ZQK^xR|8DG^dnxt?oGG7SZJM5)Z#P%BkUl`Pv5Kem*en;BaeXc8^1 zV$?HUXKZ5BF*f3@88vLZ#;9hjW}sJeicZi65?sSjj8_=73}k_v)-!yJb&NmBe{F~h zc|#<~q}pt+Zf+gH&sYz`$EaaLk2^4I_UQIR9V%>O)MM(+BsYh!u#V#Yo)+vj^2lAa z>C$)BPK`!Ros(#X%;?UOX`2e=_gZc`c8U2cCSxw`md4C>h(7n=jtuHbpb&eb9aeCBZrXD;YE# zGy*gdGzyd=Uv7#kq0z8YL1UQ2UqFXJ`pD_ChC@bULF0snAI~tJWh`bak(ZigtKSw= z^kjq%GCp7&Vze-j0us9I71rnmy`U5H(JHSsWewiN)^2ex^DeCaZpJ$<+4Y`BEh(mm zR19xFHVj60z`;f`gU5!UVPqH>k84%akgU5Lmt4@C9`5F5kBSgmit3J~IC-o21!^M5l~TTYo`x+F0859ilVFhsVa*C|bJPlXFA|R}&`~lm<$NJPA4lIt{`lM;V|@ z;g%KcV{oe>az?AiOeG@OI*L=%#yG|}&iIHS+Cg{Ml^oiUO=pd=4m(k&G3P`j*}M46 z$fL(5$b!>V`owhO#Eg|qC+qYct>je_XVFzBs0)Pqn6g0G`V1kAD1zOXquU(f4lQtf zUBadB(g=OHd-VGBcLvtyW4%88oxDEhjEwF%M7@T$XM}BT4_^BibPm+Zpd8TsI;$Qw z5k;^US@kdm96Bp_tS!hv9Wm0;n@Z=6%-&d{3vy{&o-FHo7}pDZV(h)}C^`BtK^gi= zDeLQ}Z=Xja7eJqY`WQ4Gl&jM~7*PcKkj8BeoyPxeL9V%!7DfCLN+RCAs8iZ=d4-X6 zxjd9y^1IjLJQFxT51`Jcpud9pL05!RzIr{GG~0x(?FiI1TsI0sLMMs{+e7l!@@cZ@ zpRsb*{Ad;BoIgDX`Wl9E71l$ruEBa3Gz0W?P^qEf80|N-;H;)NlyN;2U?4v5SE_`T%1; z1DE<&FZ%zwFEWtwdWMgoe^2n!{9W=Y+iMxC8Gm5>ks%o< zt3(7(%WN#j9L8K2^Vt74?EmYcP>36Be8%{kBjxU82}= zyROkD3q%G4BFY*W5Qw~DMnY6%DJ6K}!}w5iJJkU@&;w=wMMnk%Jor6@q7%V{q3CKp zZ3ab+RctT?p0!%2eWetpepO0|BkQcujaGrJg<@Bqm(u8rP}taJC|Ya{*usI)G?)Uj z(x9@+Xr@|IM%n7mb0{$iH4L*xi0Ut+@5eZx_n1yR-&Ie~RClp_oGF#6lm^frQa) zBLf9B$Q!2ZpmJITKF%n*o-1Gn1n*Q`bi{2H_;91>NL0WMhHn` zg@U{&Mw>wq8x%;A23y6Dpg_hHXBF{5f%GZCD)iqF!Tn<}`VR=AT6lu>Ff#os7+Q;A z)<}|7BwNLBs~BMwBduZ-3q4%jc8VENm*-M0_8I?f4HP%2=pjL1`46V1XJ+3 zekl-nz#174?4*fi1R~EW@~xu4Dkf=hAHTo`@m-{g7L$Ya6#wCJ+USmT&R(!=+4D=E zdn#BdBsdpCw diff --git a/mini_Ldap-Client-Bind.html b/mini_Ldap-Client-Bind.html index 834210c..196c4a7 100644 --- a/mini_Ldap-Client-Bind.html +++ b/mini_Ldap-Client-Bind.html @@ -1,4 +1,4 @@ Ldap.Client.Bind

Ldap.Client.Bind

\ No newline at end of file +

Ldap.Client.Bind

\ No newline at end of file diff --git a/mini_Ldap-Client-Extended.html b/mini_Ldap-Client-Extended.html index ebf2d85..023931f 100644 --- a/mini_Ldap-Client-Extended.html +++ b/mini_Ldap-Client-Extended.html @@ -1,4 +1,4 @@ Ldap.Client.Extended

Ldap.Client.Extended

\ No newline at end of file +

Ldap.Client.Extended

\ No newline at end of file diff --git a/mini_Ldap-Client-Internal.html b/mini_Ldap-Client-Internal.html index 510ec9f..4619814 100644 --- a/mini_Ldap-Client-Internal.html +++ b/mini_Ldap-Client-Internal.html @@ -1,4 +1,4 @@ Ldap.Client.Internal

Ldap.Client.Internal

data Host

data Ldap

data Async a

data Oid

type AttrList f

Waiting for Request Completion

Misc

type Request

data Dn

data Attr

\ No newline at end of file +

Ldap.Client.Internal

data Host

data Ldap

data Async a

type AttrList f

Waiting for Request Completion

Misc

type Request

data Dn

data Attr

Unbind operation

\ No newline at end of file diff --git a/mini_Ldap-Client-Modify.html b/mini_Ldap-Client-Modify.html index 06ccf0f..3ca044d 100644 --- a/mini_Ldap-Client-Modify.html +++ b/mini_Ldap-Client-Modify.html @@ -1,4 +1,4 @@ Ldap.Client.Modify

Ldap.Client.Modify

\ No newline at end of file +

Ldap.Client.Modify

\ No newline at end of file diff --git a/mini_Ldap-Client-Search.html b/mini_Ldap-Client-Search.html index 9d4bb03..d2af2f7 100644 --- a/mini_Ldap-Client-Search.html +++ b/mini_Ldap-Client-Search.html @@ -1,4 +1,4 @@ Ldap.Client.Search

Ldap.Client.Search

\ No newline at end of file +

Ldap.Client.Search

\ No newline at end of file diff --git a/mini_Ldap-Client.html b/mini_Ldap-Client.html index bcbb978..f6ea8c4 100644 --- a/mini_Ldap-Client.html +++ b/mini_Ldap-Client.html @@ -1,4 +1,4 @@ Ldap.Client

Ldap.Client

data Host

data Ldap

data Async a

Bind

Search

Search modifiers

data Search

data Mod a

data Scope

data Filter

Modify

Add

Delete

ModifyDn

Compare

Extended

Waiting for completion

Miscellanous

data Dn

data Oid

type AttrList f

data Attr

Re-exports

data NonEmpty a

\ No newline at end of file +

Ldap.Client

data Host

data Ldap

data Async a

Bind

Search

Search modifiers

data Search

data Mod a

data Scope

data Filter

Modify

Add

Delete

ModifyDn

Compare

Extended

data Oid

Waiting for completion

Miscellanous

data Dn

data Attr

type AttrList f

Re-exports

data NonEmpty a

\ No newline at end of file diff --git a/src/Ldap-Asn1-Type.html b/src/Ldap-Asn1-Type.html index 2d2cb70..899e6e8 100644 --- a/src/Ldap-Asn1-Type.html +++ b/src/Ldap-Asn1-Type.html @@ -56,170 +56,177 @@ | IntermediateResponse !(Maybe LdapOid) !(Maybe ByteString) deriving (Show, Eq) -newtype AuthenticationChoice = Simple ByteString - deriving (Show, Eq) - -data Scope = - BaseObject - | SingleLevel - | WholeSubtree - deriving (Show, Eq) - -data DerefAliases = - NeverDerefAliases - | DerefInSearching - | DerefFindingBaseObject - | DerefAlways - deriving (Show, Eq) - -data Filter = - And (NonEmpty Filter) - | Or (NonEmpty Filter) - | Not Filter - | EqualityMatch AttributeValueAssertion - | Substrings SubstringFilter - | GreaterOrEqual AttributeValueAssertion - | LessOrEqual AttributeValueAssertion - | Present AttributeDescription - | ApproxMatch AttributeValueAssertion - | ExtensibleMatch MatchingRuleAssertion - deriving (Show, Eq) - -data SubstringFilter = SubstringFilter AttributeDescription (NonEmpty Substring) - deriving (Show, Eq) - -data Substring = - Initial AssertionValue - | Any AssertionValue - | Final AssertionValue +-- | Not really a choice until SASL is supported. +newtype AuthenticationChoice = Simple ByteString + deriving (Show, Eq) + +-- | Scope of the search to be performed. +data Scope = + BaseObject -- ^ Constrained to the entry named by baseObject. + | SingleLevel -- ^ Constrained to the immediate subordinates of the entry named by baseObject. + | WholeSubtree -- ^ Constrained to the entry named by baseObject and to all its subordinates. + deriving (Show, Eq) + +-- | An indicator as to whether or not alias entries (as defined in +-- [RFC4512]) are to be dereferenced during stages of the Search +-- operation. +data DerefAliases = + NeverDerefAliases -- ^ Do not dereference aliases in searching or in locating the base object of the Search. + | DerefInSearching -- ^ While searching subordinates of the base object, dereference any alias within the search scope. + | DerefFindingBaseObject -- ^ Dereference aliases in locating the base object of the Search. + | DerefAlways -- ^ Dereference aliases both in searching and in locating the base object of the Search. + deriving (Show, Eq) + +-- | Conditions that must be fulfilled in order for the Search to match a given entry. +data Filter = + And !(NonEmpty Filter) -- ^ All filters evaluate to @TRUE@ + | Or !(NonEmpty Filter) -- ^ Any filter evaluates to @TRUE@ + | Not Filter -- ^ Filter evaluates to @FALSE@ + | EqualityMatch AttributeValueAssertion -- ^ @EQUALITY@ rule returns @TRUE@ + | Substrings SubstringFilter -- ^ @SUBSTR@ rule returns @TRUE@ + | GreaterOrEqual AttributeValueAssertion -- ^ @ORDERING@ rule returns @FALSE@ + | LessOrEqual AttributeValueAssertion -- ^ @ORDERING@ or @EQUALITY@ rule returns @TRUE@ + | Present AttributeDescription -- ^ Attribute is present in the entry + | ApproxMatch AttributeValueAssertion -- ^ Same as 'EqualityMatch' for most servers + | ExtensibleMatch MatchingRuleAssertion + deriving (Show, Eq) + +data SubstringFilter = SubstringFilter !AttributeDescription !(NonEmpty Substring) deriving (Show, Eq) -data MatchingRuleAssertion = MatchingRuleAssertion (Maybe MatchingRuleId) (Maybe AttributeDescription) AssertionValue Bool - deriving (Show, Eq) - --- | Matching rules are defined in Section 4.1.3 of [RFC4512]. A matching --- rule is identified in the protocol by the printable representation of --- either its <numericoid> or one of its short name descriptors --- [RFC4512], e.g., 'caseIgnoreMatch' or '2.5.13.2'. (Section 4.1.8.) -newtype MatchingRuleId = MatchingRuleId LdapString - deriving (Show, Eq) - -newtype AttributeSelection = AttributeSelection [LdapString] - deriving (Show, Eq) - -newtype AttributeList = AttributeList [Attribute] +data Substring = + Initial !AssertionValue + | Any !AssertionValue + | Final !AssertionValue + deriving (Show, Eq) + +data MatchingRuleAssertion = MatchingRuleAssertion !(Maybe MatchingRuleId) !(Maybe AttributeDescription) !AssertionValue !Bool + deriving (Show, Eq) + +-- | Matching rules are defined in Section 4.1.3 of [RFC4512]. A matching +-- rule is identified in the protocol by the printable representation of +-- either its <numericoid> or one of its short name descriptors +-- [RFC4512], e.g., 'caseIgnoreMatch' or '2.5.13.2'. (Section 4.1.8.) +newtype MatchingRuleId = MatchingRuleId LdapString deriving (Show, Eq) -newtype PartialAttributeList = PartialAttributeList [PartialAttribute] +newtype AttributeSelection = AttributeSelection [LdapString] deriving (Show, Eq) -newtype Controls = Controls [Control] +newtype AttributeList = AttributeList [Attribute] deriving (Show, Eq) -data Control = Control LdapOid Bool (Maybe ByteString) +newtype PartialAttributeList = PartialAttributeList [PartialAttribute] deriving (Show, Eq) -data LdapResult = LdapResult ResultCode LdapDn LdapString (Maybe ReferralUris) +newtype Controls = Controls [Control] deriving (Show, Eq) -data ResultCode = - Success - | OperationError - | ProtocolError - | TimeLimitExceeded - | SizeLimitExceeded - | CompareFalse - | CompareTrue - | AuthMethodNotSupported - | StrongerAuthRequired - | Referral - | AdminLimitExceeded - | UnavailableCriticalExtension - | ConfidentialityRequired - | SaslBindInProgress - | NoSuchAttribute - | UndefinedAttributeType - | InappropriateMatching - | ConstraintViolation - | AttributeOrValueExists - | InvalidAttributeSyntax - | NoSuchObject - | AliasProblem - | InvalidDNSyntax - | AliasDereferencingProblem - | InappropriateAuthentication - | InvalidCredentials - | InsufficientAccessRights - | Busy - | Unavailable - | UnwillingToPerform - | LoopDetect - | NamingViolation - | ObjectClassViolation - | NotAllowedOnNonLeaf - | NotAllowedOnRDN - | EntryAlreadyExists - | ObjectClassModsProhibited - | AffectsMultipleDSAs - | Other - deriving (Show, Eq) - -newtype AttributeDescription = AttributeDescription LdapString - deriving (Show, Eq) - -newtype AttributeValue = AttributeValue ByteString - deriving (Show, Eq) - -data AttributeValueAssertion = AttributeValueAssertion AttributeDescription AssertionValue - deriving (Show, Eq) - -newtype AssertionValue = AssertionValue ByteString - deriving (Show, Eq) - -data Attribute = Attribute AttributeDescription (NonEmpty AttributeValue) - deriving (Show, Eq) - -data PartialAttribute = PartialAttribute AttributeDescription [AttributeValue] - deriving (Show, Eq) - +data Control = Control !LdapOid !Bool !(Maybe ByteString) + deriving (Show, Eq) + +data LdapResult = LdapResult !ResultCode !LdapDn !LdapString !(Maybe ReferralUris) + deriving (Show, Eq) + +-- | LDAP operation's result. +data ResultCode = + Success + | OperationError + | ProtocolError + | TimeLimitExceeded + | SizeLimitExceeded + | CompareFalse + | CompareTrue + | AuthMethodNotSupported + | StrongerAuthRequired + | Referral + | AdminLimitExceeded + | UnavailableCriticalExtension + | ConfidentialityRequired + | SaslBindInProgress + | NoSuchAttribute + | UndefinedAttributeType + | InappropriateMatching + | ConstraintViolation + | AttributeOrValueExists + | InvalidAttributeSyntax + | NoSuchObject + | AliasProblem + | InvalidDNSyntax + | AliasDereferencingProblem + | InappropriateAuthentication + | InvalidCredentials + | InsufficientAccessRights + | Busy + | Unavailable + | UnwillingToPerform + | LoopDetect + | NamingViolation + | ObjectClassViolation + | NotAllowedOnNonLeaf + | NotAllowedOnRDN + | EntryAlreadyExists + | ObjectClassModsProhibited + | AffectsMultipleDSAs + | Other + deriving (Show, Eq) + +newtype AttributeDescription = AttributeDescription LdapString + deriving (Show, Eq) + +newtype AttributeValue = AttributeValue ByteString + deriving (Show, Eq) + +data AttributeValueAssertion = AttributeValueAssertion !AttributeDescription !AssertionValue + deriving (Show, Eq) + +newtype AssertionValue = AssertionValue ByteString + deriving (Show, Eq) - --- | An LDAPDN is defined to be the representation of a Distinguished Name --- (DN) after encoding according to the specification in [RFC4514]. -newtype LdapDn = LdapDn LdapString +data Attribute = Attribute !AttributeDescription !(NonEmpty AttributeValue) + deriving (Show, Eq) + +data PartialAttribute = PartialAttribute !AttributeDescription ![AttributeValue] deriving (Show, Eq) --- | A RelativeLDAPDN is defined to be the representation of a Relative --- Distinguished Name (RDN) after encoding according to the --- specification in [RFC4514]. -newtype RelativeLdapDn = RelativeLdapDn LdapString - deriving (Show, Eq) - -newtype ReferralUris = ReferralUris (NonEmpty Uri) - deriving (Show, Eq) - -newtype Uri = Uri LdapString - deriving (Show, Eq) - -data Operation = - Add - | Delete - | Replace - deriving (Show, Eq) - --- | The LDAPString is a notational convenience to indicate that, although --- strings of LDAPString type encode as ASN.1 OCTET STRING types, the --- [ISO10646] character set (a superset of [Unicode]) is used, encoded --- following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.) -newtype LdapString = LdapString Text + + +-- | An LDAPDN is defined to be the representation of a Distinguished Name +-- (DN) after encoding according to the specification in [RFC4514]. +newtype LdapDn = LdapDn LdapString + deriving (Show, Eq) + +-- | A RelativeLDAPDN is defined to be the representation of a Relative +-- Distinguished Name (RDN) after encoding according to the +-- specification in [RFC4514]. +newtype RelativeLdapDn = RelativeLdapDn LdapString + deriving (Show, Eq) + +newtype ReferralUris = ReferralUris (NonEmpty Uri) + deriving (Show, Eq) + +newtype Uri = Uri LdapString + deriving (Show, Eq) + +data Operation = + Add + | Delete + | Replace deriving (Show, Eq) --- | The LDAPOID is a notational convenience to indicate that the --- permitted value of this string is a (UTF-8 encoded) dotted-decimal --- representation of an OBJECT IDENTIFIER. Although an LDAPOID is --- encoded as an OCTET STRING, values are limited to the definition of --- \<numericoid\> given in Section 1.4 of [RFC4512]. -newtype LdapOid = LdapOid Text - deriving (Show, Eq) +-- | The LDAPString is a notational convenience to indicate that, although +-- strings of LDAPString type encode as ASN.1 OCTET STRING types, the +-- [ISO10646] character set (a superset of [Unicode]) is used, encoded +-- following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.) +newtype LdapString = LdapString Text + deriving (Show, Eq) + +-- | The LDAPOID is a notational convenience to indicate that the +-- permitted value of this string is a (UTF-8 encoded) dotted-decimal +-- representation of an OBJECT IDENTIFIER. Although an LDAPOID is +-- encoded as an OCTET STRING, values are limited to the definition of +-- \<numericoid\> given in Section 1.4 of [RFC4512]. +newtype LdapOid = LdapOid Text + deriving (Show, Eq)
diff --git a/src/Ldap-Client-Bind.html b/src/Ldap-Client-Bind.html index aed3193..f7f5cc1 100644 --- a/src/Ldap-Client-Bind.html +++ b/src/Ldap-Client-Bind.html @@ -21,57 +21,63 @@ -- -- Of those, the first one ('bind') is probably the most useful for the typical usecase. module Ldap.Client.Bind - ( bind - , bindEither - , bindAsync - , bindAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal - - --- | Perform the Bind operation synchronously. Raises 'ResponseError' on failures. -bind :: Ldap -> Dn -> Password -> IO () -bind l username password = - raise =<< bindEither l username password - --- | Perform the Bind operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) -bindEither l username password = - wait =<< bindAsync l username password + ( Password(..) + , bind + , bindEither + , bindAsync + , bindAsyncSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.ByteString (ByteString) +import Data.List.NonEmpty (NonEmpty((:|))) + +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | User's password. +newtype Password = Password ByteString + deriving (Show, Eq) + +-- | Perform the Bind operation synchronously. Raises 'ResponseError' on failures. +bind :: Ldap -> Dn -> Password -> IO () +bind l username password = + raise =<< bindEither l username password --- | Perform the Bind operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) -bindAsync l username password = - atomically (bindAsyncSTM l username password) +-- | Perform the Bind operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) +bindEither l username password = + wait =<< bindAsync l username password --- | Perform the Bind operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) -bindAsyncSTM l username password = - let req = bindRequest username password in sendRequest l (bindResult req) req - -bindRequest :: Dn -> Password -> Request -bindRequest (Dn username) (Password password) = - Type.BindRequest ldapVersion - (Type.LdapDn (Type.LdapString username)) - (Type.Simple password) - where - ldapVersion = 3 - -bindResult :: Request -> Response -> Either ResponseError () -bindResult req (Type.BindResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) _ :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -bindResult req res = Left (ResponseInvalid req res) +-- | Perform the Bind operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) +bindAsync l username password = + atomically (bindAsyncSTM l username password) + +-- | Perform the Bind operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) +bindAsyncSTM l username password = + let req = bindRequest username password in sendRequest l (bindResult req) req + +bindRequest :: Dn -> Password -> Request +bindRequest (Dn username) (Password password) = + Type.BindRequest ldapVersion + (Type.LdapDn (Type.LdapString username)) + (Type.Simple password) + where + ldapVersion = 3 + +bindResult :: Request -> Response -> Either ResponseError () +bindResult req (Type.BindResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) _ :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +bindResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Extended.html b/src/Ldap-Client-Extended.html index d41ef2d..2b5dd47 100644 --- a/src/Ldap-Client-Extended.html +++ b/src/Ldap-Client-Extended.html @@ -7,91 +7,105 @@ -
{-# LANGUAGE OverloadedStrings #-}
--- | <https://tools.ietf.org/html/rfc4511#section-4.12 Extended> operation.
---
--- This operation comes in four flavours:
---
---   * synchronous, exception throwing ('extended')
---
---   * synchronous, returning 'Either' 'ResponseError' @()@ ('extendedEither')
---
---   * asynchronous, 'IO' based ('extendedAsync')
---
---   * asynchronous, 'STM' based ('extendedAsyncSTM')
---
--- Of those, the first one ('extended') is probably the most useful for the typical usecase.
-module Ldap.Client.Extended
-  ( extended
-  , extendedEither
-  , extendedAsync
-  , extendedAsyncSTM
-  , startTls
-  , startTlsEither
-  , startTlsAsync
-  , startTlsAsyncSTM
-  ) where
-
-import           Control.Monad ((<=<))
-import           Control.Monad.STM (STM, atomically)
-import           Data.ByteString (ByteString)
-import           Data.List.NonEmpty (NonEmpty((:|)))
-
-import qualified Ldap.Asn1.Type as Type
-import           Ldap.Client.Internal
-
+
-- | <https://tools.ietf.org/html/rfc4511#section-4.12 Extended> operation.
+--
+-- This operation comes in four flavours:
+--
+--   * synchronous, exception throwing ('extended')
+--
+--   * synchronous, returning 'Either' 'ResponseError' @()@ ('extendedEither')
+--
+--   * asynchronous, 'IO' based ('extendedAsync')
+--
+--   * asynchronous, 'STM' based ('extendedAsyncSTM')
+--
+-- Of those, the first one ('extended') is probably the most useful for the typical usecase.
+module Ldap.Client.Extended
+  ( -- * Extended Operation
+    Oid(..)
+  , extended
+  , extendedEither
+  , extendedAsync
+  , extendedAsyncSTM
+    -- ** StartTLS Operation
+  , startTls
+  , startTlsEither
+  , startTlsAsync
+  , startTlsAsyncSTM
+  ) where
+
+import           Control.Monad ((<=<))
+import           Control.Monad.STM (STM, atomically)
+import           Data.ByteString (ByteString)
+import           Data.List.NonEmpty (NonEmpty((:|)))
+import           Data.String (fromString)
+import           Data.Text (Text)
 
--- | Perform the Extended operation synchronously. Raises 'ResponseError' on failures.
-extended :: Ldap -> Oid -> Maybe ByteString -> IO ()
-extended l oid mv =
-  raise =<< extendedEither l oid mv
-
--- | Perform the Extended operation synchronously. Returns @Left e@ where
--- @e@ is a 'ResponseError' on failures.
-extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ())
-extendedEither l oid mv =
-  wait =<< extendedAsync l oid mv
-
--- | Perform the Extended operation asynchronously. Call 'Ldap.Client.wait' to wait
--- for its completion.
-extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ())
-extendedAsync l oid mv =
-  atomically (extendedAsyncSTM l oid mv)
-
--- | Perform the Extended operation asynchronously.
---
--- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the
--- same transaction you've performed it in.
-extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ())
-extendedAsyncSTM l oid mv =
-  let req = extendedRequest oid mv in sendRequest l (extendedResult req) req
+import qualified Ldap.Asn1.Type as Type
+import           Ldap.Client.Internal
+
+
+-- | Globally unique LDAP object identifier.
+newtype Oid = Oid Text
+    deriving (Show, Eq)
+
+-- | Perform the Extended operation synchronously. Raises 'ResponseError' on failures.
+extended :: Ldap -> Oid -> Maybe ByteString -> IO ()
+extended l oid mv =
+  raise =<< extendedEither l oid mv
+
+-- | Perform the Extended operation synchronously. Returns @Left e@ where
+-- @e@ is a 'ResponseError' on failures.
+extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ())
+extendedEither l oid mv =
+  wait =<< extendedAsync l oid mv
+
+-- | Perform the Extended operation asynchronously. Call 'Ldap.Client.wait' to wait
+-- for its completion.
+extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ())
+extendedAsync l oid mv =
+  atomically (extendedAsyncSTM l oid mv)
 
-extendedRequest :: Oid -> Maybe ByteString -> Request
-extendedRequest (Oid oid) =
-  Type.ExtendedRequest (Type.LdapOid oid)
-
-extendedResult :: Request -> Response -> Either ResponseError ()
-extendedResult req (Type.ExtendedResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn))
-                                                                (Type.LdapString msg) _) _ _ :| [])
-  | Type.Success <- code = Right ()
-  | otherwise = Left (ResponseErrorCode req code (Dn dn) msg)
-extendedResult req res = Left (ResponseInvalid req res)
-
+-- | Perform the Extended operation asynchronously.
+--
+-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the
+-- same transaction you've performed it in.
+extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ())
+extendedAsyncSTM l oid mv =
+  let req = extendedRequest oid mv in sendRequest l (extendedResult req) req
+
+extendedRequest :: Oid -> Maybe ByteString -> Request
+extendedRequest (Oid oid) =
+  Type.ExtendedRequest (Type.LdapOid oid)
 
-startTls :: Ldap -> IO ()
-startTls =
-  raise <=< startTlsEither
-
-startTlsEither :: Ldap -> IO (Either ResponseError ())
-startTlsEither =
-  wait <=< startTlsAsync
+extendedResult :: Request -> Response -> Either ResponseError ()
+extendedResult req (Type.ExtendedResponse
+                     (Type.LdapResult code (Type.LdapDn (Type.LdapString dn))
+                                           (Type.LdapString msg) _) _ _ :| [])
+  | Type.Success <- code = Right ()
+  | otherwise = Left (ResponseErrorCode req code (Dn dn) msg)
+extendedResult req res = Left (ResponseInvalid req res)
 
-startTlsAsync :: Ldap -> IO (Async ())
-startTlsAsync =
-  atomically . startTlsAsyncSTM
-
-startTlsAsyncSTM :: Ldap -> STM (Async ())
-startTlsAsyncSTM l =
-  extendedAsyncSTM l (Oid "1.3.6.1.4.1.1466.20037") Nothing
+
+-- | An example of @Extended Operation@, cf. 'extended'.
+startTls :: Ldap -> IO ()
+startTls =
+  raise <=< startTlsEither
+
+-- | An example of @Extended Operation@, cf. 'extendedEither'.
+startTlsEither :: Ldap -> IO (Either ResponseError ())
+startTlsEither =
+  wait <=< startTlsAsync
+
+-- | An example of @Extended Operation@, cf. 'extendedAsync'.
+startTlsAsync :: Ldap -> IO (Async ())
+startTlsAsync =
+  atomically . startTlsAsyncSTM
+
+-- | An example of @Extended Operation@, cf. 'extendedAsyncSTM'.
+startTlsAsyncSTM :: Ldap -> STM (Async ())
+startTlsAsyncSTM l =
+  extendedAsyncSTM l (Oid (fromString "1.3.6.1.4.1.1466.20037"))
+                     Nothing
 
diff --git a/src/Ldap-Client-Internal.html b/src/Ldap-Client-Internal.html index 4bc9031..3a74cd7 100644 --- a/src/Ldap-Client-Internal.html +++ b/src/Ldap-Client-Internal.html @@ -16,127 +16,137 @@ , ClientMessage(..) , Type.ResultCode(..) , Async - , Oid(..) - , AttrList - -- * Waiting for Request Completion - , wait - , waitSTM - , unbindAsync - , unbindAsyncSTM - -- * Misc - , Response - , ResponseError(..) - , Request - , raise - , sendRequest - , Dn(..) - , RelativeDn(..) - , Password(..) - , Attr(..) - , AttrValue - , unAttr - ) where - -import Control.Concurrent.STM (STM, atomically) -import Control.Concurrent.STM.TMVar (TMVar, newEmptyTMVar, readTMVar) -import Control.Concurrent.STM.TQueue (TQueue, writeTQueue) -import Control.Exception (Exception, throwIO) -import Control.Monad (void) -import Data.ByteString (ByteString) -import Data.List.NonEmpty (NonEmpty) -import Data.Text (Text) -import Data.Typeable (Typeable) -import Network (PortNumber) + , AttrList + -- * Waiting for Request Completion + , wait + , waitSTM + -- * Misc + , Response + , ResponseError(..) + , Request + , raise + , sendRequest + , Dn(..) + , Attr(..) + , AttrValue + , unAttr + -- * Unbind operation + , unbindAsync + , unbindAsyncSTM + ) where + +import Control.Concurrent.STM (STM, atomically) +import Control.Concurrent.STM.TMVar (TMVar, newEmptyTMVar, readTMVar) +import Control.Concurrent.STM.TQueue (TQueue, writeTQueue) +import Control.Exception (Exception, throwIO) +import Control.Monad (void) +import Data.ByteString (ByteString) +import Data.List.NonEmpty (NonEmpty) +import Data.Text (Text) +import Data.Typeable (Typeable) +import Network (PortNumber) + +import qualified Ldap.Asn1.Type as Type -import qualified Ldap.Asn1.Type as Type - - -data Host = - Plain String - | Secure String - | Insecure String + +-- | LDAP host. +data Host = + Plain String -- ^ Plain LDAP. Do not use! + | Insecure String -- ^ LDAP over TLS without the certificate validity check. + -- Only use for testing! + | Secure String -- ^ LDAP over TLS. Use! deriving (Show, Eq, Ord) -data Ldap = Ldap - { client :: TQueue ClientMessage - } deriving (Eq) - -data ClientMessage = New Request (TMVar (NonEmpty Type.ProtocolServerOp)) -type Request = Type.ProtocolClientOp -type InMessage = Type.ProtocolServerOp -type Response = NonEmpty InMessage - -data Async a = Async (STM (Either ResponseError a)) - -instance Functor Async where - fmap f (Async stm) = Async (fmap (fmap f) stm) - -newtype Dn = Dn Text - deriving (Show, Eq) - -newtype RelativeDn = RelativeDn Text +-- | A token. All functions that interact with the Directory require one. +data Ldap = Ldap + { client :: TQueue ClientMessage + } deriving (Eq) + +data ClientMessage = New Request (TMVar (NonEmpty Type.ProtocolServerOp)) +type Request = Type.ProtocolClientOp +type InMessage = Type.ProtocolServerOp +type Response = NonEmpty InMessage + +-- | Asynchronous LDAP operation. Use 'wait' or 'waitSTM' to wait for its completion. +data Async a = Async (STM (Either ResponseError a)) + +instance Functor Async where + fmap f (Async stm) = Async (fmap (fmap f) stm) + +-- | Unique identifier of an LDAP entry. +newtype Dn = Dn Text deriving (Show, Eq) -newtype Oid = Oid Text - deriving (Show, Eq) - -newtype Password = Password ByteString - deriving (Show, Eq) +-- | Response indicates a failed operation. +data ResponseError = + ResponseInvalid Request Response -- ^ LDAP server did not follow the protocol, so @ldap-client@ couldn't make sense of the response. + | ResponseErrorCode Request Type.ResultCode Dn Text -- ^ The response contains a result code indicating failure and an error message. + deriving (Show, Eq, Typeable) -data ResponseError = - ResponseInvalid Request Response - | ResponseErrorCode Request Type.ResultCode Dn Text - deriving (Show, Eq, Typeable) - -instance Exception ResponseError - -newtype Attr = Attr Text - deriving (Show, Eq) - -type AttrValue = ByteString - -type AttrList f = [(Attr, f AttrValue)] - --- 'Attr' unwrapper. This is a separate function not to turn 'Attr''s --- 'Show' instance into complete and utter shit. -unAttr :: Attr -> Text -unAttr (Attr a) = a - -wait :: Async a -> IO (Either ResponseError a) +instance Exception ResponseError + +-- | Attribute name. +newtype Attr = Attr Text + deriving (Show, Eq) + +-- | Attribute value. +type AttrValue = ByteString + +-- | List of attributes and their values. @f@ is the structure these +-- values are in, e.g. 'NonEmpty'. +type AttrList f = [(Attr, f AttrValue)] + +-- 'Attr' unwrapper. This is a separate function not to turn 'Attr''s +-- 'Show' instance into complete and utter shit. +unAttr :: Attr -> Text +unAttr (Attr a) = a + +-- | Wait for operation completion. +wait :: Async a -> IO (Either ResponseError a) wait = atomically . waitSTM -waitSTM :: Async a -> STM (Either ResponseError a) -waitSTM (Async stm) = stm - -sendRequest :: Ldap -> (Response -> Either ResponseError a) -> Request -> STM (Async a) -sendRequest l p msg = - do var <- newEmptyTMVar - writeRequest l var msg - return (Async (fmap p (readTMVar var))) +-- | Wait for operation completion inside 'STM'. +-- +-- Do not use this inside the same 'STM' transaction the operation was +-- requested in! To give LDAP the chance to respond to it that transaction +-- should commit. After that, applying 'waitSTM' to the corresponding 'Async' +-- starts to make sense. +waitSTM :: Async a -> STM (Either ResponseError a) +waitSTM (Async stm) = stm -writeRequest :: Ldap -> TMVar Response -> Request -> STM () -writeRequest Ldap { client } var msg = writeTQueue client (New msg var) - -raise :: Exception e => Either e a -> IO a -raise = either throwIO return +sendRequest :: Ldap -> (Response -> Either ResponseError a) -> Request -> STM (Async a) +sendRequest l p msg = + do var <- newEmptyTMVar + writeRequest l var msg + return (Async (fmap p (readTMVar var))) - --- | Note that 'unbindAsync' does not return an 'Async', --- because LDAP server never responds to @UnbindRequest@s, hence --- a call to 'wait' on a hypothetical 'Async' would have resulted --- in an exception anyway. -unbindAsync :: Ldap -> IO () -unbindAsync = - atomically . unbindAsyncSTM - --- | Note that 'unbindAsyncSTM' does not return an 'Async', +writeRequest :: Ldap -> TMVar Response -> Request -> STM () +writeRequest Ldap { client } var msg = writeTQueue client (New msg var) + +raise :: Exception e => Either e a -> IO a +raise = either throwIO return + + +-- | Terminate the connection to the Directory. +-- +-- Note that 'unbindAsync' does not return an 'Async', -- because LDAP server never responds to @UnbindRequest@s, hence -- a call to 'wait' on a hypothetical 'Async' would have resulted -- in an exception anyway. -unbindAsyncSTM :: Ldap -> STM () -unbindAsyncSTM l = - void (sendRequest l die Type.UnbindRequest) - where - die = error "Ldap.Client: do not wait for the response to UnbindRequest" +unbindAsync :: Ldap -> IO () +unbindAsync = + atomically . unbindAsyncSTM + +-- | Terminate the connection to the Directory. +-- +-- Note that 'unbindAsyncSTM' does not return an 'Async', +-- because LDAP server never responds to @UnbindRequest@s, hence +-- a call to 'wait' on a hypothetical 'Async' would have resulted +-- in an exception anyway. +unbindAsyncSTM :: Ldap -> STM () +unbindAsyncSTM l = + void (sendRequest l die Type.UnbindRequest) + where + die = error "Ldap.Client: do not wait for the response to UnbindRequest"
diff --git a/src/Ldap-Client-Modify.html b/src/Ldap-Client-Modify.html index e88eab1..ee6a204 100644 --- a/src/Ldap-Client-Modify.html +++ b/src/Ldap-Client-Modify.html @@ -29,108 +29,114 @@ , modifyEither , modifyAsync , modifyAsyncSTM - , modifyDn - , modifyDnEither - , modifyDnAsync - , modifyDnAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal - - --- | Type of modification being performed. -data Operation = - Delete Attr [AttrValue] -- ^ Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed. - | Add Attr [AttrValue] -- ^ Add values to the attribute, creating it if necessary. - | Replace Attr [AttrValue] -- ^ Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty. - deriving (Show, Eq) - --- | Perform the Modify operation synchronously. Raises 'ResponseError' on failures. -modify :: Ldap -> Dn -> [Operation] -> IO () -modify l dn as = - raise =<< modifyEither l dn as - --- | Perform the Modify operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) -modifyEither l dn as = - wait =<< modifyAsync l dn as - --- | Perform the Modify operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) -modifyAsync l dn as = - atomically (modifyAsyncSTM l dn as) - --- | Perform the Modify operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) -modifyAsyncSTM l dn xs = - let req = modifyRequest dn xs in sendRequest l (modifyResult req) req - -modifyRequest :: Dn -> [Operation] -> Request -modifyRequest (Dn dn) xs = - Type.ModifyRequest (Type.LdapDn (Type.LdapString dn)) (map f xs) - where - f (Delete (Attr k) vs) = - (Type.Delete, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - f (Add (Attr k) vs) = - (Type.Add, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - f (Replace (Attr k) vs) = - (Type.Replace, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - -modifyResult :: Request -> Response -> Either ResponseError () -modifyResult req (Type.ModifyResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -modifyResult req res = Left (ResponseInvalid req res) - - --- | Perform the Modify DN operation synchronously. Raises 'ResponseError' on failures. -modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () -modifyDn l dn rdn del new = - raise =<< modifyDnEither l dn rdn del new - --- | Perform the Modify DN operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) -modifyDnEither l dn rdn del new = - wait =<< modifyDnAsync l dn rdn del new + , RelativeDn(..) + , modifyDn + , modifyDnEither + , modifyDnAsync + , modifyDnAsyncSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.List.NonEmpty (NonEmpty((:|))) +import Data.Text (Text) + +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Type of modification being performed. +data Operation = + Delete Attr [AttrValue] -- ^ Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed. + | Add Attr [AttrValue] -- ^ Add values to the attribute, creating it if necessary. + | Replace Attr [AttrValue] -- ^ Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty. + deriving (Show, Eq) + +-- | Perform the Modify operation synchronously. Raises 'ResponseError' on failures. +modify :: Ldap -> Dn -> [Operation] -> IO () +modify l dn as = + raise =<< modifyEither l dn as + +-- | Perform the Modify operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) +modifyEither l dn as = + wait =<< modifyAsync l dn as + +-- | Perform the Modify operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) +modifyAsync l dn as = + atomically (modifyAsyncSTM l dn as) + +-- | Perform the Modify operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) +modifyAsyncSTM l dn xs = + let req = modifyRequest dn xs in sendRequest l (modifyResult req) req + +modifyRequest :: Dn -> [Operation] -> Request +modifyRequest (Dn dn) xs = + Type.ModifyRequest (Type.LdapDn (Type.LdapString dn)) (map f xs) + where + f (Delete (Attr k) vs) = + (Type.Delete, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + f (Add (Attr k) vs) = + (Type.Add, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + f (Replace (Attr k) vs) = + (Type.Replace, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + +modifyResult :: Request -> Response -> Either ResponseError () +modifyResult req (Type.ModifyResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +modifyResult req res = Left (ResponseInvalid req res) + + +-- | A component of 'Dn'. +newtype RelativeDn = RelativeDn Text + deriving (Show, Eq) + +-- | Perform the Modify DN operation synchronously. Raises 'ResponseError' on failures. +modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () +modifyDn l dn rdn del new = + raise =<< modifyDnEither l dn rdn del new --- | Perform the Modify DN operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) -modifyDnAsync l dn rdn del new = - atomically (modifyDnAsyncSTM l dn rdn del new) +-- | Perform the Modify DN operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) +modifyDnEither l dn rdn del new = + wait =<< modifyDnAsync l dn rdn del new --- | Perform the Modify DN operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) -modifyDnAsyncSTM l dn rdn del new = - let req = modifyDnRequest dn rdn del new in sendRequest l (modifyDnResult req) req - -modifyDnRequest :: Dn -> RelativeDn -> Bool -> Maybe Dn -> Request -modifyDnRequest (Dn dn) (RelativeDn rdn) del new = - Type.ModifyDnRequest (Type.LdapDn (Type.LdapString dn)) - (Type.RelativeLdapDn (Type.LdapString rdn)) - del - (fmap (\(Dn dn') -> Type.LdapDn (Type.LdapString dn')) new) - -modifyDnResult :: Request -> Response -> Either ResponseError () -modifyDnResult req (Type.ModifyDnResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -modifyDnResult req res = Left (ResponseInvalid req res) +-- | Perform the Modify DN operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) +modifyDnAsync l dn rdn del new = + atomically (modifyDnAsyncSTM l dn rdn del new) + +-- | Perform the Modify DN operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) +modifyDnAsyncSTM l dn rdn del new = + let req = modifyDnRequest dn rdn del new in sendRequest l (modifyDnResult req) req + +modifyDnRequest :: Dn -> RelativeDn -> Bool -> Maybe Dn -> Request +modifyDnRequest (Dn dn) (RelativeDn rdn) del new = + Type.ModifyDnRequest (Type.LdapDn (Type.LdapString dn)) + (Type.RelativeLdapDn (Type.LdapString rdn)) + del + (fmap (\(Dn dn') -> Type.LdapDn (Type.LdapString dn')) new) + +modifyDnResult :: Request -> Response -> Either ResponseError () +modifyDnResult req (Type.ModifyDnResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +modifyDnResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Search.html b/src/Ldap-Client-Search.html index fe98327..65781ea 100644 --- a/src/Ldap-Client-Search.html +++ b/src/Ldap-Client-Search.html @@ -34,183 +34,198 @@ , size , time , typesOnly - , derefAliases - , Filter(..) - , SearchEntry(..) - ) where - -import Control.Monad.STM (STM, atomically) -import Data.Int (Int32) -import Data.List.NonEmpty (NonEmpty((:|))) -import qualified Data.List.NonEmpty as NonEmpty -import Data.Maybe (mapMaybe) -#if __GLASGOW_HASKELL__ >= 710 -import Data.Semigroup (Semigroup(..)) -#else -import Data.Semigroup (Semigroup(..), Monoid(..)) -#endif - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal - + , Type.DerefAliases(..) + , derefAliases + , Filter(..) + , SearchEntry(..) + ) where + +import Control.Monad.STM (STM, atomically) +import Data.Int (Int32) +import Data.List.NonEmpty (NonEmpty((:|))) +import qualified Data.List.NonEmpty as NonEmpty +import Data.Maybe (mapMaybe) +#if __GLASGOW_HASKELL__ >= 710 +import Data.Semigroup (Semigroup(..)) +#else +import Data.Semigroup (Semigroup(..), Monoid(..)) +#endif + +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal --- | Perform the Search operation synchronously. Raises 'ResponseError' on failures. -search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] -search l base opts flt attributes = - raise =<< searchEither l base opts flt attributes - --- | Perform the Search operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -searchEither - :: Ldap - -> Dn - -> Mod Search - -> Filter - -> [Attr] - -> IO (Either ResponseError [SearchEntry]) -searchEither l base opts flt attributes = - wait =<< searchAsync l base opts flt attributes - --- | Perform the Search operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) -searchAsync l base opts flt attributes = - atomically (searchAsyncSTM l base opts flt attributes) - --- | Perform the Search operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -searchAsyncSTM - :: Ldap - -> Dn - -> Mod Search - -> Filter - -> [Attr] - -> STM (Async [SearchEntry]) -searchAsyncSTM l base opts flt attributes = - let req = searchRequest base opts flt attributes in sendRequest l (searchResult req) req - -searchRequest :: Dn -> Mod Search -> Filter -> [Attr] -> Request -searchRequest (Dn base) (Mod m) flt attributes = - Type.SearchRequest (Type.LdapDn (Type.LdapString base)) - _scope - _derefAliases - _size - _time - _typesOnly - (fromFilter flt) - (Type.AttributeSelection (map (Type.LdapString . unAttr) attributes)) - where - Search { _scope, _derefAliases, _size, _time, _typesOnly } = - m defaultSearch - fromFilter (Not x) = Type.Not (fromFilter x) - fromFilter (And xs) = Type.And (fmap fromFilter xs) - fromFilter (Or xs) = Type.Or (fmap fromFilter xs) - fromFilter (Present (Attr x)) = - Type.Present (Type.AttributeDescription (Type.LdapString x)) - fromFilter (Attr x := y) = - Type.EqualityMatch - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :>= y) = - Type.GreaterOrEqual - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :<= y) = - Type.LessOrEqual - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :~= y) = - Type.ApproxMatch - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :=* (mi, xs, mf)) = - Type.Substrings - (Type.SubstringFilter (Type.AttributeDescription (Type.LdapString x)) - (NonEmpty.fromList (concat - [ maybe [] (\i -> [Type.Initial (Type.AssertionValue i)]) mi - , fmap (Type.Any . Type.AssertionValue) xs - , maybe [] (\f -> [Type.Final (Type.AssertionValue f)]) mf - ]))) - fromFilter ((mx, mr, b) ::= y) = - Type.ExtensibleMatch - (Type.MatchingRuleAssertion (fmap (\(Attr r) -> Type.MatchingRuleId (Type.LdapString r)) mr) - (fmap (\(Attr x) -> Type.AttributeDescription (Type.LdapString x)) mx) - (Type.AssertionValue y) - b) - -searchResult :: Request -> Response -> Either ResponseError [SearchEntry] -searchResult req (Type.SearchResultDone (Type.LdapResult code (Type.LdapDn (Type.LdapString dn')) - (Type.LdapString msg) _) :| xs) - | Type.Success <- code = Right (mapMaybe g xs) - | Type.AdminLimitExceeded <- code = Right (mapMaybe g xs) - | Type.SizeLimitExceeded <- code = Right (mapMaybe g xs) - | otherwise = Left (ResponseErrorCode req code (Dn dn') msg) - where - g (Type.SearchResultEntry (Type.LdapDn (Type.LdapString dn)) - (Type.PartialAttributeList ys)) = - Just (SearchEntry (Dn dn) (map h ys)) - g _ = Nothing - h (Type.PartialAttribute (Type.AttributeDescription (Type.LdapString x)) - y) = (Attr x, fmap j y) - j (Type.AttributeValue x) = x -searchResult req res = Left (ResponseInvalid req res) - -data Search = Search - { _scope :: Type.Scope - , _derefAliases :: Type.DerefAliases - , _size :: Int32 - , _time :: Int32 - , _typesOnly :: Bool - } deriving (Show, Eq) - -defaultSearch :: Search -defaultSearch = Search - { _scope = Type.BaseObject - , _size = 0 - , _time = 0 - , _typesOnly = False - , _derefAliases = Type.NeverDerefAliases - } - -scope :: Type.Scope -> Mod Search -scope x = Mod (\y -> y { _scope = x }) - -size :: Int32 -> Mod Search -size x = Mod (\y -> y { _size = x }) + +-- | Perform the Search operation synchronously. Raises 'ResponseError' on failures. +search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] +search l base opts flt attributes = + raise =<< searchEither l base opts flt attributes + +-- | Perform the Search operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +searchEither + :: Ldap + -> Dn + -> Mod Search + -> Filter + -> [Attr] + -> IO (Either ResponseError [SearchEntry]) +searchEither l base opts flt attributes = + wait =<< searchAsync l base opts flt attributes + +-- | Perform the Search operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) +searchAsync l base opts flt attributes = + atomically (searchAsyncSTM l base opts flt attributes) + +-- | Perform the Search operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +searchAsyncSTM + :: Ldap + -> Dn + -> Mod Search + -> Filter + -> [Attr] + -> STM (Async [SearchEntry]) +searchAsyncSTM l base opts flt attributes = + let req = searchRequest base opts flt attributes in sendRequest l (searchResult req) req + +searchRequest :: Dn -> Mod Search -> Filter -> [Attr] -> Request +searchRequest (Dn base) (Mod m) flt attributes = + Type.SearchRequest (Type.LdapDn (Type.LdapString base)) + _scope + _derefAliases + _size + _time + _typesOnly + (fromFilter flt) + (Type.AttributeSelection (map (Type.LdapString . unAttr) attributes)) + where + Search { _scope, _derefAliases, _size, _time, _typesOnly } = + m defaultSearch + fromFilter (Not x) = Type.Not (fromFilter x) + fromFilter (And xs) = Type.And (fmap fromFilter xs) + fromFilter (Or xs) = Type.Or (fmap fromFilter xs) + fromFilter (Present (Attr x)) = + Type.Present (Type.AttributeDescription (Type.LdapString x)) + fromFilter (Attr x := y) = + Type.EqualityMatch + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :>= y) = + Type.GreaterOrEqual + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :<= y) = + Type.LessOrEqual + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :~= y) = + Type.ApproxMatch + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :=* (mi, xs, mf)) = + Type.Substrings + (Type.SubstringFilter (Type.AttributeDescription (Type.LdapString x)) + (NonEmpty.fromList (concat + [ maybe [] (\i -> [Type.Initial (Type.AssertionValue i)]) mi + , fmap (Type.Any . Type.AssertionValue) xs + , maybe [] (\f -> [Type.Final (Type.AssertionValue f)]) mf + ]))) + fromFilter ((mx, mr, b) ::= y) = + Type.ExtensibleMatch + (Type.MatchingRuleAssertion (fmap (\(Attr r) -> Type.MatchingRuleId (Type.LdapString r)) mr) + (fmap (\(Attr x) -> Type.AttributeDescription (Type.LdapString x)) mx) + (Type.AssertionValue y) + b) + +searchResult :: Request -> Response -> Either ResponseError [SearchEntry] +searchResult req (Type.SearchResultDone (Type.LdapResult code (Type.LdapDn (Type.LdapString dn')) + (Type.LdapString msg) _) :| xs) + | Type.Success <- code = Right (mapMaybe g xs) + | Type.AdminLimitExceeded <- code = Right (mapMaybe g xs) + | Type.SizeLimitExceeded <- code = Right (mapMaybe g xs) + | otherwise = Left (ResponseErrorCode req code (Dn dn') msg) + where + g (Type.SearchResultEntry (Type.LdapDn (Type.LdapString dn)) + (Type.PartialAttributeList ys)) = + Just (SearchEntry (Dn dn) (map h ys)) + g _ = Nothing + h (Type.PartialAttribute (Type.AttributeDescription (Type.LdapString x)) + y) = (Attr x, fmap j y) + j (Type.AttributeValue x) = x +searchResult req res = Left (ResponseInvalid req res) + +-- | Search options. Use 'Mod' to change some of those. +data Search = Search + { _scope :: !Type.Scope + , _derefAliases :: !Type.DerefAliases + , _size :: !Int32 + , _time :: !Int32 + , _typesOnly :: !Bool + } deriving (Show, Eq) + +defaultSearch :: Search +defaultSearch = Search + { _scope = Type.WholeSubtree + , _size = 0 + , _time = 0 + , _typesOnly = False + , _derefAliases = Type.NeverDerefAliases + } + +-- | Scope of the search (default: 'WholeSubtree'). +scope :: Type.Scope -> Mod Search +scope x = Mod (\y -> y { _scope = x }) -time :: Int32 -> Mod Search -time x = Mod (\y -> y { _time = x }) - -typesOnly :: Bool -> Mod Search -typesOnly x = Mod (\y -> y { _typesOnly = x }) - -derefAliases :: Type.DerefAliases -> Mod Search -derefAliases x = Mod (\y -> y { _derefAliases = x }) - -newtype Mod a = Mod (a -> a) - -instance Semigroup (Mod a) where - Mod f <> Mod g = Mod (g . f) - -instance Monoid (Mod a) where - mempty = Mod id - mappend = (<>) - -data Filter = - Not Filter - | And (NonEmpty Filter) - | Or (NonEmpty Filter) - | Present Attr - | Attr := AttrValue - | Attr :>= AttrValue - | Attr :<= AttrValue - | Attr :~= AttrValue - | Attr :=* (Maybe AttrValue, [AttrValue], Maybe AttrValue) - | (Maybe Attr, Maybe Attr, Bool) ::= AttrValue - -data SearchEntry = SearchEntry Dn (AttrList []) - deriving (Show, Eq) +-- | Maximum number of entries to be returned as a result of the Search. +-- No limit if the value is @0@ (default: @0@). +size :: Int32 -> Mod Search +size x = Mod (\y -> y { _size = x }) + +-- | Maximum time (in seconds) allowed for the Search. No limit if the value +-- is @0@ (default: @0@). +time :: Int32 -> Mod Search +time x = Mod (\y -> y { _time = x }) + +-- | Whether Search results are to contain just attribute descriptions, or +-- both attribute descriptions and values (default: 'False'). +typesOnly :: Bool -> Mod Search +typesOnly x = Mod (\y -> y { _typesOnly = x }) + +-- | Alias dereference policy (default: 'NeverDerefAliases'). +derefAliases :: Type.DerefAliases -> Mod Search +derefAliases x = Mod (\y -> y { _derefAliases = x }) + +-- | Search modifier. Combine using 'Semigroup' and/or 'Monoid' instance. +newtype Mod a = Mod (a -> a) + +instance Semigroup (Mod a) where + Mod f <> Mod g = Mod (g . f) + +instance Monoid (Mod a) where + mempty = Mod id + mappend = (<>) + +-- | Conditions that must be fulfilled in order for the Search to match a given entry. +data Filter = + Not !Filter -- ^ Filter does not match the entry + | And !(NonEmpty Filter) -- ^ All filters match the entry + | Or !(NonEmpty Filter) -- ^ Any filter matches the entry + | Present !Attr -- ^ Attribute is present in the entry + | !Attr := !AttrValue -- ^ Attribute's value is equal to the assertion + | !Attr :>= !AttrValue -- ^ Attribute's value is equal to or greater than the assertion + | !Attr :<= !AttrValue -- ^ Attribute's value is equal to or less than the assertion + | !Attr :~= !AttrValue -- ^ Attribute's value approximately matches the assertion + | !Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue) + -- ^ Glob match + | (Maybe Attr, Maybe Attr, Bool) ::= AttrValue + -- ^ Extensible match + +-- | Entry found during the Search. +data SearchEntry = SearchEntry !Dn !(AttrList []) + deriving (Show, Eq) diff --git a/src/Ldap-Client.html b/src/Ldap-Client.html index b91e5f0..32b4b9e 100644 --- a/src/Ldap-Client.html +++ b/src/Ldap-Client.html @@ -11,256 +11,266 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE NamedFieldPuns #-} -module Ldap.Client - ( Host(..) - , Ldap - , LdapError(..) - , ResponseError(..) - , Type.ResultCode(..) - , Async - , with - -- * Bind - , bind - -- * Search - , search - , SearchEntry(..) - -- ** Search modifiers - , Search - , Mod - , scope - , Type.Scope(..) - , size - , time - , typesOnly - , derefAliases - , Filter(..) - -- * Modify - , modify - , Operation(..) - -- * Add - , add - -- * Delete - , delete - -- * ModifyDn - , modifyDn - -- * Compare - , compare - -- * Extended - , extended - -- * Waiting for completion - , wait - -- * Miscellanous - , Dn(..) - , RelativeDn(..) - , Oid(..) - , Password(..) - , AttrList - , Attr(..) - , AttrValue - -- * Re-exports - , NonEmpty - , PortNumber - ) where - -#if __GLASGOW_HASKELL__ < 710 -import Control.Applicative ((<$>)) -#endif -import qualified Control.Concurrent.Async as Async -import Control.Concurrent.STM (atomically, throwSTM) -import Control.Concurrent.STM.TMVar (putTMVar) -import Control.Concurrent.STM.TQueue (TQueue, newTQueueIO, writeTQueue, readTQueue) -import Control.Exception (Exception, Handler(..), bracket, throwIO, catch, catches) -import Control.Monad (forever) -import qualified Data.ASN1.BinaryEncoding as Asn1 -import qualified Data.ASN1.Encoding as Asn1 -import qualified Data.ASN1.Error as Asn1 -import qualified Data.ByteString as ByteString -import qualified Data.ByteString.Lazy as ByteString.Lazy -import Data.Foldable (asum) -import Data.Function (fix) -import Data.List.NonEmpty (NonEmpty((:|))) -import qualified Data.Map.Strict as Map -import Data.Monoid (Endo(appEndo)) -import Data.String (fromString) -import Data.Text (Text) -import Data.Typeable (Typeable) -import Network.Connection (Connection) -import qualified Network.Connection as Conn -import Prelude hiding (compare) -import qualified System.IO.Error as IO - -import Ldap.Asn1.ToAsn1 (ToAsn1(toAsn1)) -import Ldap.Asn1.FromAsn1 (FromAsn1, parseAsn1) -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal -import Ldap.Client.Bind (bind) -import Ldap.Client.Search - ( search - , Search - , Mod - , scope - , size - , time - , typesOnly - , derefAliases - , Filter(..) - , SearchEntry(..) - ) -import Ldap.Client.Modify (Operation(..), modify, modifyDn) -import Ldap.Client.Add (add) -import Ldap.Client.Delete (delete) -import Ldap.Client.Compare (compare) -import Ldap.Client.Extended (extended) - -{-# ANN module "HLint: ignore Use first" #-} - - -newLdap :: IO Ldap -newLdap = Ldap - <$> newTQueueIO +-- | Pure Haskell LDAP client library. +module Ldap.Client + ( Host(..) + , Ldap + , LdapError(..) + , ResponseError(..) + , Type.ResultCode(..) + , Async + , with + -- * Bind + , Password(..) + , bind + -- * Search + , search + , SearchEntry(..) + -- ** Search modifiers + , Search + , Mod + , Type.Scope(..) + , scope + , size + , time + , typesOnly + , Type.DerefAliases(..) + , derefAliases + , Filter(..) + -- * Modify + , modify + , Operation(..) + -- * Add + , add + -- * Delete + , delete + -- * ModifyDn + , RelativeDn(..) + , modifyDn + -- * Compare + , compare + -- * Extended + , Oid(..) + , extended + -- * Waiting for completion + , wait + -- * Miscellanous + , Dn(..) + , Attr(..) + , AttrValue + , AttrList + -- * Re-exports + , NonEmpty + , PortNumber + ) where + +#if __GLASGOW_HASKELL__ < 710 +import Control.Applicative ((<$>)) +#endif +import qualified Control.Concurrent.Async as Async +import Control.Concurrent.STM (atomically, throwSTM) +import Control.Concurrent.STM.TMVar (putTMVar) +import Control.Concurrent.STM.TQueue (TQueue, newTQueueIO, writeTQueue, readTQueue) +import Control.Exception (Exception, Handler(..), bracket, throwIO, catch, catches) +import Control.Monad (forever) +import qualified Data.ASN1.BinaryEncoding as Asn1 +import qualified Data.ASN1.Encoding as Asn1 +import qualified Data.ASN1.Error as Asn1 +import qualified Data.ByteString as ByteString +import qualified Data.ByteString.Lazy as ByteString.Lazy +import Data.Foldable (asum) +import Data.Function (fix) +import Data.List.NonEmpty (NonEmpty((:|))) +import qualified Data.Map.Strict as Map +import Data.Monoid (Endo(appEndo)) +import Data.String (fromString) +import Data.Text (Text) +#if __GLASGOW_HASKELL__ < 710 +import Data.Traversable (traverse) +#endif +import Data.Typeable (Typeable) +import Network.Connection (Connection) +import qualified Network.Connection as Conn +import Prelude hiding (compare) +import qualified System.IO.Error as IO + +import Ldap.Asn1.ToAsn1 (ToAsn1(toAsn1)) +import Ldap.Asn1.FromAsn1 (FromAsn1, parseAsn1) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal +import Ldap.Client.Bind (Password(..), bind) +import Ldap.Client.Search + ( search + , Search + , Mod + , scope + , size + , time + , typesOnly + , derefAliases + , Filter(..) + , SearchEntry(..) + ) +import Ldap.Client.Modify (Operation(..), modify, RelativeDn(..), modifyDn) +import Ldap.Client.Add (add) +import Ldap.Client.Delete (delete) +import Ldap.Client.Compare (compare) +import Ldap.Client.Extended (Oid(..), extended) + +{-# ANN module "HLint: ignore Use first" #-} -data LdapError = - IOError IOError - | ParseError Asn1.ASN1Error - | ResponseError ResponseError - | DisconnectError Disconnect - deriving (Show, Eq) - -newtype WrappedIOError = WrappedIOError IOError - deriving (Show, Eq, Typeable) - -instance Exception WrappedIOError - -data Disconnect = Disconnect Type.ResultCode Dn Text - deriving (Show, Eq, Typeable) - -instance Exception Disconnect - --- | The entrypoint into LDAP. -with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) -with host port f = do - context <- Conn.initConnectionContext - bracket (Conn.connectTo context params) Conn.connectionClose (\conn -> - bracket newLdap unbindAsync (\l -> do - inq <- newTQueueIO - outq <- newTQueueIO - Async.withAsync (input inq conn) $ \i -> - Async.withAsync (output outq conn) $ \o -> - Async.withAsync (dispatch l inq outq) $ \d -> - Async.withAsync (f l) $ \u -> - fmap (Right . snd) (Async.waitAnyCancel [i, o, d, u]))) - `catches` - [ Handler (\(WrappedIOError e) -> return (Left (IOError e))) - , Handler (return . Left . ParseError) - , Handler (return . Left . ResponseError) - ] - where - params = Conn.ConnectionParams - { Conn.connectionHostname = - case host of - Plain h -> h - Secure h -> h - Insecure h -> h - , Conn.connectionPort = port - , Conn.connectionUseSecure = - case host of - Plain _ -> Nothing - Secure _ -> Just Conn.TLSSettingsSimple - { Conn.settingDisableCertificateValidation = False - , Conn.settingDisableSession = False - , Conn.settingUseServerName = False - } - Insecure _ -> Just Conn.TLSSettingsSimple - { Conn.settingDisableCertificateValidation = True - , Conn.settingDisableSession = False - , Conn.settingUseServerName = False - } - , Conn.connectionUseSocks = Nothing - } - -input :: FromAsn1 a => TQueue a -> Connection -> IO b -input inq conn = wrap . flip fix [] $ \loop chunks -> do - chunk <- Conn.connectionGet conn 8192 - case ByteString.length chunk of - 0 -> throwIO (IO.mkIOError IO.eofErrorType "Ldap.Client.input" Nothing Nothing) - _ -> do - let chunks' = chunk : chunks - case Asn1.decodeASN1 Asn1.DER (ByteString.Lazy.fromChunks (reverse chunks')) of - Left Asn1.ParsingPartial - -> loop chunks' - Left e -> throwIO e - Right asn1 -> do - flip fix asn1 $ \loop' asn1' -> - case parseAsn1 asn1' of - Nothing -> return () - Just (asn1'', a) -> do - atomically (writeTQueue inq a) - loop' asn1'' - loop [] - -output :: ToAsn1 a => TQueue a -> Connection -> IO b -output out conn = wrap . forever $ do - msg <- atomically (readTQueue out) - Conn.connectionPut conn (encode (toAsn1 msg)) - where - encode x = Asn1.encodeASN1' Asn1.DER (appEndo x []) - -dispatch - :: Ldap - -> TQueue (Type.LdapMessage Type.ProtocolServerOp) - -> TQueue (Type.LdapMessage Request) - -> IO a -dispatch Ldap { client } inq outq = - flip fix (Map.empty, 1) $ \loop (!req, !counter) -> - loop =<< atomically (asum - [ do New new var <- readTQueue client - writeTQueue outq (Type.LdapMessage (Type.Id counter) new Nothing) - return (Map.insert (Type.Id counter) ([], var) req, counter + 1) - , do Type.LdapMessage mid op _ - <- readTQueue inq - res <- case op of - Type.BindResponse {} -> done mid op req - Type.SearchResultEntry {} -> saveUp mid op req - Type.SearchResultReference {} -> return req - Type.SearchResultDone {} -> done mid op req - Type.ModifyResponse {} -> done mid op req - Type.AddResponse {} -> done mid op req - Type.DeleteResponse {} -> done mid op req - Type.ModifyDnResponse {} -> done mid op req - Type.CompareResponse {} -> done mid op req - Type.ExtendedResponse {} -> probablyDisconnect mid op req - Type.IntermediateResponse {} -> saveUp mid op req - return (res, counter) - ]) - where - saveUp mid op res = - return (Map.adjust (\(stack, var) -> (op : stack, var)) mid res) - - done mid op req = - case Map.lookup mid req of - Nothing -> return req - Just (stack, var) -> do - putTMVar var (op :| stack) - return (Map.delete mid req) - - probablyDisconnect (Type.Id 0) - (Type.ExtendedResponse - (Type.LdapResult code - (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString reason) - _) - moid _) - req = - case moid of - Just (Type.LdapOid oid) - | oid == noticeOfDisconnection -> throwSTM (Disconnect code (Dn dn) reason) - _ -> return req - probablyDisconnect mid op req = done mid op req - - noticeOfDisconnection :: Text - noticeOfDisconnection = fromString "1.3.6.1.4.1.1466.20036" - -wrap :: IO a -> IO a -wrap m = m `catch` (throwIO . WrappedIOError) + +newLdap :: IO Ldap +newLdap = Ldap + <$> newTQueueIO + +-- | Various failures that can happen when working with LDAP. +data LdapError = + IOError IOError -- ^ Network failure. + | ParseError Asn1.ASN1Error -- ^ Invalid ASN.1 data received from the server. + | ResponseError ResponseError -- ^ An LDAP operation failed. + | DisconnectError Disconnect -- ^ Notice of Disconnection has been received. + deriving (Show, Eq) + +newtype WrappedIOError = WrappedIOError IOError + deriving (Show, Eq, Typeable) + +instance Exception WrappedIOError + +data Disconnect = Disconnect Type.ResultCode Dn Text + deriving (Show, Eq, Typeable) + +instance Exception Disconnect + +-- | The entrypoint into LDAP. +-- +-- It catches all LDAP-related exceptions. +with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) +with host port f = do + context <- Conn.initConnectionContext + bracket (Conn.connectTo context params) Conn.connectionClose (\conn -> + bracket newLdap unbindAsync (\l -> do + inq <- newTQueueIO + outq <- newTQueueIO + as <- traverse Async.async + [ input inq conn + , output outq conn + , dispatch l inq outq + , f l + ] + fmap (Right . snd) (Async.waitAnyCancel as))) + `catches` + [ Handler (\(WrappedIOError e) -> return (Left (IOError e))) + , Handler (return . Left . ParseError) + , Handler (return . Left . ResponseError) + ] + where + params = Conn.ConnectionParams + { Conn.connectionHostname = + case host of + Plain h -> h + Secure h -> h + Insecure h -> h + , Conn.connectionPort = port + , Conn.connectionUseSecure = + case host of + Plain _ -> Nothing + Secure _ -> Just Conn.TLSSettingsSimple + { Conn.settingDisableCertificateValidation = False + , Conn.settingDisableSession = False + , Conn.settingUseServerName = False + } + Insecure _ -> Just Conn.TLSSettingsSimple + { Conn.settingDisableCertificateValidation = True + , Conn.settingDisableSession = False + , Conn.settingUseServerName = False + } + , Conn.connectionUseSocks = Nothing + } + +input :: FromAsn1 a => TQueue a -> Connection -> IO b +input inq conn = wrap . flip fix [] $ \loop chunks -> do + chunk <- Conn.connectionGet conn 8192 + case ByteString.length chunk of + 0 -> throwIO (IO.mkIOError IO.eofErrorType "Ldap.Client.input" Nothing Nothing) + _ -> do + let chunks' = chunk : chunks + case Asn1.decodeASN1 Asn1.DER (ByteString.Lazy.fromChunks (reverse chunks')) of + Left Asn1.ParsingPartial + -> loop chunks' + Left e -> throwIO e + Right asn1 -> do + flip fix asn1 $ \loop' asn1' -> + case parseAsn1 asn1' of + Nothing -> return () + Just (asn1'', a) -> do + atomically (writeTQueue inq a) + loop' asn1'' + loop [] + +output :: ToAsn1 a => TQueue a -> Connection -> IO b +output out conn = wrap . forever $ do + msg <- atomically (readTQueue out) + Conn.connectionPut conn (encode (toAsn1 msg)) + where + encode x = Asn1.encodeASN1' Asn1.DER (appEndo x []) + +dispatch + :: Ldap + -> TQueue (Type.LdapMessage Type.ProtocolServerOp) + -> TQueue (Type.LdapMessage Request) + -> IO a +dispatch Ldap { client } inq outq = + flip fix (Map.empty, 1) $ \loop (!req, !counter) -> + loop =<< atomically (asum + [ do New new var <- readTQueue client + writeTQueue outq (Type.LdapMessage (Type.Id counter) new Nothing) + return (Map.insert (Type.Id counter) ([], var) req, counter + 1) + , do Type.LdapMessage mid op _ + <- readTQueue inq + res <- case op of + Type.BindResponse {} -> done mid op req + Type.SearchResultEntry {} -> saveUp mid op req + Type.SearchResultReference {} -> return req + Type.SearchResultDone {} -> done mid op req + Type.ModifyResponse {} -> done mid op req + Type.AddResponse {} -> done mid op req + Type.DeleteResponse {} -> done mid op req + Type.ModifyDnResponse {} -> done mid op req + Type.CompareResponse {} -> done mid op req + Type.ExtendedResponse {} -> probablyDisconnect mid op req + Type.IntermediateResponse {} -> saveUp mid op req + return (res, counter) + ]) + where + saveUp mid op res = + return (Map.adjust (\(stack, var) -> (op : stack, var)) mid res) + + done mid op req = + case Map.lookup mid req of + Nothing -> return req + Just (stack, var) -> do + putTMVar var (op :| stack) + return (Map.delete mid req) + + probablyDisconnect (Type.Id 0) + (Type.ExtendedResponse + (Type.LdapResult code + (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString reason) + _) + moid _) + req = + case moid of + Just (Type.LdapOid oid) + | oid == noticeOfDisconnection -> throwSTM (Disconnect code (Dn dn) reason) + _ -> return req + probablyDisconnect mid op req = done mid op req + + noticeOfDisconnection :: Text + noticeOfDisconnection = fromString "1.3.6.1.4.1.1466.20036" + +wrap :: IO a -> IO a +wrap m = m `catch` (throwIO . WrappedIOError)