diff --git a/Ldap-Asn1-FromAsn1.html b/Ldap-Asn1-FromAsn1.html new file mode 100644 index 0000000..1375283 --- /dev/null +++ b/Ldap-Asn1-FromAsn1.html @@ -0,0 +1,93 @@ +Ldap.Asn1.FromAsn1

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Asn1.FromAsn1

Documentation

class FromAsn1 a where Source

Methods

fromAsn1 :: Parser [ASN1] a Source

Instances

FromAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+
FromAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded,
+
FromAsn1 Uri Source
URI ::= LDAPString
+
FromAsn1 ReferralUris Source
Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+
FromAsn1 LdapDn Source
LDAPDN ::= LDAPString
+
FromAsn1 PartialAttribute Source
PartialAttribute ::= SEQUENCE {
+     type       AttributeDescription,
+     vals       SET OF value AttributeValue }
+
FromAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
+
FromAsn1 AttributeDescription Source
AttributeDescription ::= LDAPString
+
FromAsn1 LdapResult Source
LDAPResult ::= SEQUENCE {
+     resultCode         ENUMERATED {
+          success                      (0),
+          operationsError              (1),
+          protocolError                (2),
+          timeLimitExceeded            (3),
+          sizeLimitExceeded            (4),
+          compareFalse                 (5),
+          compareTrue                  (6),
+          authMethodNotSupported       (7),
+          strongerAuthRequired         (8),
+          -- 9 reserved --
+          referral                     (10),
+          adminLimitExceeded           (11),
+          unavailableCriticalExtension (12),
+          confidentialityRequired      (13),
+          saslBindInProgress           (14),
+          noSuchAttribute              (16),
+          undefinedAttributeType       (17),
+          inappropriateMatching        (18),
+          constraintViolation          (19),
+          attributeOrValueExists       (20),
+          invalidAttributeSyntax       (21),
+          -- 22-31 unused --
+          noSuchObject                 (32),
+          aliasProblem                 (33),
+          invalidDNSyntax              (34),
+          -- 35 reserved for undefined isLeaf --
+          aliasDereferencingProblem    (36),
+          -- 37-47 unused --
+          inappropriateAuthentication  (48),
+          invalidCredentials           (49),
+          insufficientAccessRights     (50),
+          busy                         (51),
+          unavailable                  (52),
+          unwillingToPerform           (53),
+          loopDetect                   (54),
+          -- 55-63 unused --
+          namingViolation              (64),
+          objectClassViolation         (65),
+          notAllowedOnNonLeaf          (66),
+          notAllowedOnRDN              (67),
+          entryAlreadyExists           (68),
+          objectClassModsProhibited    (69),
+          -- 70 reserved for CLDAP --
+          affectsMultipleDSAs          (71),
+          -- 72-79 unused --
+          other                        (80),
+          ...  },
+     matchedDN          LDAPDN,
+     diagnosticMessage  LDAPString,
+     referral           [3] Referral OPTIONAL }
+
FromAsn1 PartialAttributeList Source
PartialAttributeList ::= SEQUENCE OF partialAttribute PartialAttribute
+
FromAsn1 ProtocolServerOp Source
BindResponse ::= [APPLICATION 1] SEQUENCE {
+     COMPONENTS OF LDAPResult,
+     serverSaslCreds    [7] OCTET STRING OPTIONAL }
+
SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+     objectName      LDAPDN,
+     attributes      PartialAttributeList }
+
SearchResultDone ::= [APPLICATION 5] LDAPResult
+
ModifyResponse ::= [APPLICATION 7] LDAPResult
+
AddResponse ::= [APPLICATION 9] LDAPResult
+
DelResponse ::= [APPLICATION 11] LDAPResult
+
CompareResponse ::= [APPLICATION 15] LDAPResult
+
FromAsn1 Id Source
MessageID ::= INTEGER (0 ..  maxInt)
+
FromAsn1 op => FromAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+     messageID       MessageID,
+     protocolOp      CHOICE {
+          bindRequest           BindRequest,
+          bindResponse          BindResponse,
+          unbindRequest         UnbindRequest,
+          searchRequest         SearchRequest,
+          searchResEntry        SearchResultEntry,
+          searchResDone         SearchResultDone,
+          searchResRef          SearchResultReference,
+          addRequest            AddRequest,
+          addResponse           AddResponse,
+          ... },
+     controls       [0] Controls OPTIONAL }
+
(FromAsn1 a, FromAsn1 b) => FromAsn1 (a, b) Source 

parseAsn1 :: FromAsn1 a => [ASN1] -> Maybe ([ASN1], a) Source

parse :: Parser s a -> s -> Maybe (s, a) Source

next :: Parser [s] s Source

\ No newline at end of file diff --git a/Ldap-Asn1-ToAsn1.html b/Ldap-Asn1-ToAsn1.html new file mode 100644 index 0000000..a5742e0 --- /dev/null +++ b/Ldap-Asn1-ToAsn1.html @@ -0,0 +1,116 @@ +Ldap.Asn1.ToAsn1

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Asn1.ToAsn1

Documentation

class ToAsn1 a where Source

Methods

toAsn1 :: a -> Endo [ASN1] Source

Instances

ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
+
ToAsn1 RelativeLdapDn Source
RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+
ToAsn1 LdapDn Source
LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
+
ToAsn1 PartialAttribute Source
PartialAttribute ::= SEQUENCE {
+     type       AttributeDescription,
+     vals       SET OF value AttributeValue }
+
ToAsn1 Attribute Source
Attribute ::= PartialAttribute(WITH COMPONENTS {
+     ...,
+     vals (SIZE(1..MAX))})
+
ToAsn1 AssertionValue Source
AssertionValue ::= OCTET STRING
+
ToAsn1 AttributeValueAssertion Source
AttributeValueAssertion ::= SEQUENCE {
+     attributeDesc   AttributeDescription,
+     assertionValue  AssertionValue }
+
ToAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
+
ToAsn1 AttributeDescription Source
AttributeDescription ::= LDAPString
+
ToAsn1 Control Source
Control ::= SEQUENCE {
+     controlType             LDAPOID,
+     criticality             BOOLEAN DEFAULT FALSE,
+     controlValue            OCTET STRING OPTIONAL }
+
ToAsn1 Controls Source
Controls ::= SEQUENCE OF control Control
+
ToAsn1 AttributeList Source
AttributeList ::= SEQUENCE OF attribute Attribute
+
ToAsn1 AttributeSelection Source
AttributeSelection ::= SEQUENCE OF selector LDAPString
+
ToAsn1 MatchingRuleId Source
MatchingRuleId ::= LDAPString
+
ToAsn1 MatchingRuleAssertion Source
MatchingRuleAssertion ::= SEQUENCE {
+     matchingRule    [1] MatchingRuleId OPTIONAL,
+     type            [2] AttributeDescription OPTIONAL,
+     matchValue      [3] AssertionValue,
+     dnAttributes    [4] BOOLEAN DEFAULT FALSE }
+
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
+     }
+
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,
+     equalityMatch   [3] AttributeValueAssertion,
+     substrings      [4] SubstringFilter,
+     greaterOrEqual  [5] AttributeValueAssertion,
+     lessOrEqual     [6] AttributeValueAssertion,
+     present         [7] AttributeDescription,
+     approxMatch     [8] AttributeValueAssertion,
+     extensibleMatch [9] MatchingRuleAssertion,
+     ...  }
+
ToAsn1 AuthenticationChoice Source
AuthenticationChoice ::= CHOICE {
+     simple                  [0] OCTET STRING,
+     ...  }
+
ToAsn1 ProtocolClientOp Source
BindRequest ::= [APPLICATION 0] SEQUENCE {
+     version                 INTEGER (1 ..  127),
+     name                    LDAPDN,
+     authentication          AuthenticationChoice }
+
UnbindRequest ::= [APPLICATION 2] NULL
+
SearchRequest ::= [APPLICATION 3] SEQUENCE {
+     baseObject      LDAPDN,
+     scope           ENUMERATED {
+          baseObject              (0),
+          singleLevel             (1),
+          wholeSubtree            (2),
+          ...  },
+     derefAliases    ENUMERATED {
+          neverDerefAliases       (0),
+          derefInSearching        (1),
+          derefFindingBaseObj     (2),
+          derefAlways             (3) },
+     sizeLimit       INTEGER (0 ..  maxInt),
+     timeLimit       INTEGER (0 ..  maxInt),
+     typesOnly       BOOLEAN,
+     filter          Filter,
+     attributes      AttributeSelection }
+
ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+     object          LDAPDN,
+     changes         SEQUENCE OF change SEQUENCE {
+          operation       ENUMERATED {
+               add     (0),
+               delete  (1),
+               replace (2),
+               ...  },
+          modification    PartialAttribute } }
+
AddRequest ::= [APPLICATION 8] SEQUENCE {
+     entry           LDAPDN,
+     attributes      AttributeList }
+
DelRequest ::= [APPLICATION 10] LDAPDN
+
ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+     entry           LDAPDN,
+     newrdn          RelativeLDAPDN,
+     deleteoldrdn    BOOLEAN,
+     newSuperior     [0] LDAPDN OPTIONAL }
+
CompareRequest ::= [APPLICATION 14] SEQUENCE {
+     entry           LDAPDN,
+     ava             AttributeValueAssertion }
+
ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+     requestName      [0] LDAPOID,
+     requestValue     [1] OCTET STRING OPTIONAL }
+
ToAsn1 Id Source
MessageID ::= INTEGER (0 ..  maxInt)
+
ToAsn1 a => ToAsn1 [a] Source 
ToAsn1 a => ToAsn1 (NonEmpty a) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+     messageID       MessageID,
+     protocolOp      CHOICE {
+          bindRequest           BindRequest,
+          bindResponse          BindResponse,
+          unbindRequest         UnbindRequest,
+          searchRequest         SearchRequest,
+          searchResEntry        SearchResultEntry,
+          searchResDone         SearchResultDone,
+          searchResRef          SearchResultReference,
+          addRequest            AddRequest,
+          addResponse           AddResponse,
+          ... },
+     controls       [0] Controls OPTIONAL }
+
\ No newline at end of file diff --git a/Ldap-Asn1-Type.html b/Ldap-Asn1-Type.html new file mode 100644 index 0000000..00408d8 --- /dev/null +++ b/Ldap-Asn1-Type.html @@ -0,0 +1,208 @@ +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

Instances

Eq op => Eq (LdapMessage op) Source 
Ord op => Ord (LdapMessage op) Source 
Show op => Show (LdapMessage op) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+     messageID       MessageID,
+     protocolOp      CHOICE {
+          bindRequest           BindRequest,
+          bindResponse          BindResponse,
+          unbindRequest         UnbindRequest,
+          searchRequest         SearchRequest,
+          searchResEntry        SearchResultEntry,
+          searchResDone         SearchResultDone,
+          searchResRef          SearchResultReference,
+          addRequest            AddRequest,
+          addResponse           AddResponse,
+          ... },
+     controls       [0] Controls OPTIONAL }
+
FromAsn1 op => FromAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+     messageID       MessageID,
+     protocolOp      CHOICE {
+          bindRequest           BindRequest,
+          bindResponse          BindResponse,
+          unbindRequest         UnbindRequest,
+          searchRequest         SearchRequest,
+          searchResEntry        SearchResultEntry,
+          searchResDone         SearchResultDone,
+          searchResRef          SearchResultReference,
+          addRequest            AddRequest,
+          addResponse           AddResponse,
+          ... },
+     controls       [0] Controls OPTIONAL }
+

newtype Id Source

Constructors

Id 

Fields

unId :: Int32
 

Instances

Eq Id Source 
Ord Id Source 
Show Id Source 
ToAsn1 Id Source
MessageID ::= INTEGER (0 ..  maxInt)
+
FromAsn1 Id Source
MessageID ::= INTEGER (0 ..  maxInt)
+

data ProtocolClientOp Source

Instances

Eq ProtocolClientOp Source 
Ord ProtocolClientOp Source 
Show ProtocolClientOp Source 
ToAsn1 ProtocolClientOp Source
BindRequest ::= [APPLICATION 0] SEQUENCE {
+     version                 INTEGER (1 ..  127),
+     name                    LDAPDN,
+     authentication          AuthenticationChoice }
+
UnbindRequest ::= [APPLICATION 2] NULL
+
SearchRequest ::= [APPLICATION 3] SEQUENCE {
+     baseObject      LDAPDN,
+     scope           ENUMERATED {
+          baseObject              (0),
+          singleLevel             (1),
+          wholeSubtree            (2),
+          ...  },
+     derefAliases    ENUMERATED {
+          neverDerefAliases       (0),
+          derefInSearching        (1),
+          derefFindingBaseObj     (2),
+          derefAlways             (3) },
+     sizeLimit       INTEGER (0 ..  maxInt),
+     timeLimit       INTEGER (0 ..  maxInt),
+     typesOnly       BOOLEAN,
+     filter          Filter,
+     attributes      AttributeSelection }
+
ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+     object          LDAPDN,
+     changes         SEQUENCE OF change SEQUENCE {
+          operation       ENUMERATED {
+               add     (0),
+               delete  (1),
+               replace (2),
+               ...  },
+          modification    PartialAttribute } }
+
AddRequest ::= [APPLICATION 8] SEQUENCE {
+     entry           LDAPDN,
+     attributes      AttributeList }
+
DelRequest ::= [APPLICATION 10] LDAPDN
+
ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+     entry           LDAPDN,
+     newrdn          RelativeLDAPDN,
+     deleteoldrdn    BOOLEAN,
+     newSuperior     [0] LDAPDN OPTIONAL }
+
CompareRequest ::= [APPLICATION 14] SEQUENCE {
+     entry           LDAPDN,
+     ava             AttributeValueAssertion }
+
ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+     requestName      [0] LDAPOID,
+     requestValue     [1] OCTET STRING OPTIONAL }
+

data ProtocolServerOp Source

Instances

Eq ProtocolServerOp Source 
Ord ProtocolServerOp Source 
Show ProtocolServerOp Source 
FromAsn1 ProtocolServerOp Source
BindResponse ::= [APPLICATION 1] SEQUENCE {
+     COMPONENTS OF LDAPResult,
+     serverSaslCreds    [7] OCTET STRING OPTIONAL }
+
SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+     objectName      LDAPDN,
+     attributes      PartialAttributeList }
+
SearchResultDone ::= [APPLICATION 5] LDAPResult
+
ModifyResponse ::= [APPLICATION 7] LDAPResult
+
AddResponse ::= [APPLICATION 9] LDAPResult
+
DelResponse ::= [APPLICATION 11] LDAPResult
+
CompareResponse ::= [APPLICATION 15] LDAPResult
+

data AuthenticationChoice Source

Constructors

Simple ByteString 

Instances

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

data Filter Source

Instances

Eq Filter Source 
Ord 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,
+     equalityMatch   [3] AttributeValueAssertion,
+     substrings      [4] SubstringFilter,
+     greaterOrEqual  [5] AttributeValueAssertion,
+     lessOrEqual     [6] AttributeValueAssertion,
+     present         [7] AttributeDescription,
+     approxMatch     [8] AttributeValueAssertion,
+     extensibleMatch [9] MatchingRuleAssertion,
+     ...  }
+

data SubstringFilter Source

Instances

Eq SubstringFilter Source 
Ord 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 
Ord MatchingRuleAssertion Source 
Show MatchingRuleAssertion Source 
ToAsn1 MatchingRuleAssertion Source
MatchingRuleAssertion ::= SEQUENCE {
+     matchingRule    [1] MatchingRuleId OPTIONAL,
+     type            [2] AttributeDescription OPTIONAL,
+     matchValue      [3] AssertionValue,
+     dnAttributes    [4] BOOLEAN DEFAULT FALSE }
+

newtype AttributeList Source

Constructors

AttributeList [Attribute] 

Instances

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

newtype Controls Source

Constructors

Controls [Control] 

Instances

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

data Control Source

Instances

Eq Control Source 
Ord 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 
Ord LdapResult Source 
Show LdapResult Source 
FromAsn1 LdapResult Source
LDAPResult ::= SEQUENCE {
+     resultCode         ENUMERATED {
+          success                      (0),
+          operationsError              (1),
+          protocolError                (2),
+          timeLimitExceeded            (3),
+          sizeLimitExceeded            (4),
+          compareFalse                 (5),
+          compareTrue                  (6),
+          authMethodNotSupported       (7),
+          strongerAuthRequired         (8),
+          -- 9 reserved --
+          referral                     (10),
+          adminLimitExceeded           (11),
+          unavailableCriticalExtension (12),
+          confidentialityRequired      (13),
+          saslBindInProgress           (14),
+          noSuchAttribute              (16),
+          undefinedAttributeType       (17),
+          inappropriateMatching        (18),
+          constraintViolation          (19),
+          attributeOrValueExists       (20),
+          invalidAttributeSyntax       (21),
+          -- 22-31 unused --
+          noSuchObject                 (32),
+          aliasProblem                 (33),
+          invalidDNSyntax              (34),
+          -- 35 reserved for undefined isLeaf --
+          aliasDereferencingProblem    (36),
+          -- 37-47 unused --
+          inappropriateAuthentication  (48),
+          invalidCredentials           (49),
+          insufficientAccessRights     (50),
+          busy                         (51),
+          unavailable                  (52),
+          unwillingToPerform           (53),
+          loopDetect                   (54),
+          -- 55-63 unused --
+          namingViolation              (64),
+          objectClassViolation         (65),
+          notAllowedOnNonLeaf          (66),
+          notAllowedOnRDN              (67),
+          entryAlreadyExists           (68),
+          objectClassModsProhibited    (69),
+          -- 70 reserved for CLDAP --
+          affectsMultipleDSAs          (71),
+          -- 72-79 unused --
+          other                        (80),
+          ...  },
+     matchedDN          LDAPDN,
+     diagnosticMessage  LDAPString,
+     referral           [3] Referral OPTIONAL }
+

newtype AttributeValue Source

Instances

Eq AttributeValue Source 
Ord AttributeValue Source 
Show AttributeValue Source 
ToAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
+
FromAsn1 AttributeValue Source
AttributeValue ::= OCTET STRING
+

data AttributeValueAssertion Source

Instances

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

data Attribute Source

Instances

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

data PartialAttribute Source

Instances

Eq PartialAttribute Source 
Ord 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

Constructors

LdapDn LdapString 

Instances

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

newtype RelativeLdapDn Source

Instances

Eq RelativeLdapDn Source 
Ord 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 
Ord ReferralUris Source 
Show ReferralUris Source 
FromAsn1 ReferralUris Source
Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+

newtype Uri Source

Constructors

Uri LdapString 

Instances

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.

Constructors

LdapString Text 

Instances

Eq LdapString Source 
Ord 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

Constructors

LdapOid ByteString 

Instances

Eq LdapOid Source 
Ord 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-Add.html b/Ldap-Client-Add.html new file mode 100644 index 0000000..ad51456 --- /dev/null +++ b/Ldap-Client-Add.html @@ -0,0 +1,4 @@ +Ldap.Client.Add

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Add

Documentation

\ No newline at end of file diff --git a/Ldap-Client-Bind.html b/Ldap-Client-Bind.html new file mode 100644 index 0000000..df16968 --- /dev/null +++ b/Ldap-Client-Bind.html @@ -0,0 +1,10 @@ +Ldap.Client.Bind

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Bind

Synopsis

Documentation

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

unbindAsync :: Ldap -> IO () Source

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, + because LDAP server never responds to UnbindRequests, hence + a call to wait on a hypothetical Async would have resulted + in an exception anyway.

\ No newline at end of file diff --git a/Ldap-Client-Compare.html b/Ldap-Client-Compare.html new file mode 100644 index 0000000..b20272c --- /dev/null +++ b/Ldap-Client-Compare.html @@ -0,0 +1,4 @@ +Ldap.Client.Compare

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Compare

Documentation

\ No newline at end of file diff --git a/Ldap-Client-Delete.html b/Ldap-Client-Delete.html new file mode 100644 index 0000000..375d5b8 --- /dev/null +++ b/Ldap-Client-Delete.html @@ -0,0 +1,4 @@ +Ldap.Client.Delete

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Delete

Documentation

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

\ No newline at end of file diff --git a/Ldap-Client-Extended.html b/Ldap-Client-Extended.html new file mode 100644 index 0000000..a44b004 --- /dev/null +++ b/Ldap-Client-Extended.html @@ -0,0 +1,4 @@ +Ldap.Client.Extended

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Extended

Documentation

\ No newline at end of file diff --git a/Ldap-Client-Internal.html b/Ldap-Client-Internal.html new file mode 100644 index 0000000..7418adb --- /dev/null +++ b/Ldap-Client-Internal.html @@ -0,0 +1,4 @@ +Ldap.Client.Internal

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Internal

Contents

Synopsis

Documentation

data Ldap Source

Constructors

Ldap 

Fields

client :: TQueue ClientMessage
 

Instances

data Async a Source

Instances

newtype Oid Source

Constructors

Oid ByteString 

Instances

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

Waiting for Request Completion

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 diff --git a/Ldap-Client-Modify.html b/Ldap-Client-Modify.html new file mode 100644 index 0000000..82abc30 --- /dev/null +++ b/Ldap-Client-Modify.html @@ -0,0 +1,4 @@ +Ldap.Client.Modify

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Modify

Documentation

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

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

\ No newline at end of file diff --git a/Ldap-Client-Search.html b/Ldap-Client-Search.html new file mode 100644 index 0000000..8fd4ef9 --- /dev/null +++ b/Ldap-Client-Search.html @@ -0,0 +1,4 @@ +Ldap.Client.Search

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Search

Documentation

data Mod a Source

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 
\ No newline at end of file diff --git a/Ldap-Client.html b/Ldap-Client.html new file mode 100644 index 0000000..f7035dd --- /dev/null +++ b/Ldap-Client.html @@ -0,0 +1,4 @@ +Ldap.Client

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client

Contents

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

Search

Search modifiers

data Mod a Source

Instances

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

Modify

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

Add

Delete

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

ModifyDn

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

Compare

Extended

Waiting for completion

Miscellanous

newtype Dn Source

Constructors

Dn Text 

Instances

newtype RelativeDn Source

Constructors

RelativeDn Text 

newtype Oid Source

Constructors

Oid ByteString 

Instances

type AttrList f = [(Attr, f ByteString)] 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 diff --git a/doc-index-58.html b/doc-index-58.html new file mode 100644 index 0000000..eb8a855 --- /dev/null +++ b/doc-index-58.html @@ -0,0 +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
\ No newline at end of file diff --git a/doc-index-A.html b/doc-index-A.html new file mode 100644 index 0000000..83b816b --- /dev/null +++ b/doc-index-A.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - A)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - A

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
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
\ No newline at end of file diff --git a/doc-index-All.html b/doc-index-All.html new file mode 100644 index 0000000..200d2cc --- /dev/null +++ b/doc-index-All.html @@ -0,0 +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
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
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
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
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
nextLdap.Asn1.FromAsn1
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
parseLdap.Asn1.FromAsn1
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
ParserLdap.Asn1.FromAsn1
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.Bind
unbindAsyncSTMLdap.Client.Bind
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-B.html b/doc-index-B.html new file mode 100644 index 0000000..e0f2bac --- /dev/null +++ b/doc-index-B.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - B)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - B

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
\ No newline at end of file diff --git a/doc-index-C.html b/doc-index-C.html new file mode 100644 index 0000000..2130975 --- /dev/null +++ b/doc-index-C.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - C)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - C

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
\ No newline at end of file diff --git a/doc-index-D.html b/doc-index-D.html new file mode 100644 index 0000000..47b33ad --- /dev/null +++ b/doc-index-D.html @@ -0,0 +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
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
\ No newline at end of file diff --git a/doc-index-E.html b/doc-index-E.html new file mode 100644 index 0000000..e86ffd9 --- /dev/null +++ b/doc-index-E.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - E)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - E

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
\ No newline at end of file diff --git a/doc-index-F.html b/doc-index-F.html new file mode 100644 index 0000000..c2364f2 --- /dev/null +++ b/doc-index-F.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - F)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - F

Filter 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Search, Ldap.Client
FinalLdap.Asn1.Type
FromAsn1Ldap.Asn1.FromAsn1
fromAsn1Ldap.Asn1.FromAsn1
\ No newline at end of file diff --git a/doc-index-G.html b/doc-index-G.html new file mode 100644 index 0000000..4cd5007 --- /dev/null +++ b/doc-index-G.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - G)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - G

GreaterOrEqualLdap.Asn1.Type
\ No newline at end of file diff --git a/doc-index-H.html b/doc-index-H.html new file mode 100644 index 0000000..1fe8663 --- /dev/null +++ b/doc-index-H.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - H)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - H

HostLdap.Client.Internal, Ldap.Client
\ No newline at end of file diff --git a/doc-index-I.html b/doc-index-I.html new file mode 100644 index 0000000..4ca0f6e --- /dev/null +++ b/doc-index-I.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - I)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - I

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
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
\ No newline at end of file diff --git a/doc-index-L.html b/doc-index-L.html new file mode 100644 index 0000000..2731ae8 --- /dev/null +++ b/doc-index-L.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - L)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - L

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
\ No newline at end of file diff --git a/doc-index-M.html b/doc-index-M.html new file mode 100644 index 0000000..14377b0 --- /dev/null +++ b/doc-index-M.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - M)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - M

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
\ No newline at end of file diff --git a/doc-index-N.html b/doc-index-N.html new file mode 100644 index 0000000..95f5559 --- /dev/null +++ b/doc-index-N.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - N)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - N

NamingViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NeverDerefAliasesLdap.Asn1.Type
NewLdap.Client.Internal
nextLdap.Asn1.FromAsn1
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
\ No newline at end of file diff --git a/doc-index-O.html b/doc-index-O.html new file mode 100644 index 0000000..1ee8e79 --- /dev/null +++ b/doc-index-O.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - O)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - O

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
\ No newline at end of file diff --git a/doc-index-P.html b/doc-index-P.html new file mode 100644 index 0000000..09bd77b --- /dev/null +++ b/doc-index-P.html @@ -0,0 +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

parseLdap.Asn1.FromAsn1
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
ParserLdap.Asn1.FromAsn1
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 diff --git a/doc-index-R.html b/doc-index-R.html new file mode 100644 index 0000000..80f5829 --- /dev/null +++ b/doc-index-R.html @@ -0,0 +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 diff --git a/doc-index-S.html b/doc-index-S.html new file mode 100644 index 0000000..603b37f --- /dev/null +++ b/doc-index-S.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - S)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - S

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
\ No newline at end of file diff --git a/doc-index-T.html b/doc-index-T.html new file mode 100644 index 0000000..2c86a6f --- /dev/null +++ b/doc-index-T.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - T)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - T

timeLdap.Client.Search, Ldap.Client
TimeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ToAsn1Ldap.Asn1.ToAsn1
toAsn1Ldap.Asn1.ToAsn1
typesOnlyLdap.Client.Search, Ldap.Client
\ No newline at end of file diff --git a/doc-index-U.html b/doc-index-U.html new file mode 100644 index 0000000..0961a58 --- /dev/null +++ b/doc-index-U.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - U)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - U

unAttrLdap.Client.Internal
UnavailableLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
UnavailableCriticalExtensionLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unbindAsyncLdap.Client.Bind
unbindAsyncSTMLdap.Client.Bind
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
\ No newline at end of file diff --git a/doc-index-W.html b/doc-index-W.html new file mode 100644 index 0000000..686aea4 --- /dev/null +++ b/doc-index-W.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - W)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - W

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.html b/doc-index.html new file mode 100644 index 0000000..48a73ea --- /dev/null +++ b/doc-index.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file diff --git a/frames.html b/frames.html new file mode 100644 index 0000000..1b4e38d --- /dev/null +++ b/frames.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + diff --git a/haddock-util.js b/haddock-util.js new file mode 100644 index 0000000..9a6fccf --- /dev/null +++ b/haddock-util.js @@ -0,0 +1,344 @@ +// Haddock JavaScript utilities + +var rspace = /\s\s+/g, + rtrim = /^\s+|\s+$/g; + +function spaced(s) { return (" " + s + " ").replace(rspace, " "); } +function trim(s) { return s.replace(rtrim, ""); } + +function hasClass(elem, value) { + var className = spaced(elem.className || ""); + return className.indexOf( " " + value + " " ) >= 0; +} + +function addClass(elem, value) { + var className = spaced(elem.className || ""); + if ( className.indexOf( " " + value + " " ) < 0 ) { + elem.className = trim(className + " " + value); + } +} + +function removeClass(elem, value) { + var className = spaced(elem.className || ""); + className = className.replace(" " + value + " ", " "); + elem.className = trim(className); +} + +function toggleClass(elem, valueOn, valueOff, bool) { + if (bool == null) { bool = ! hasClass(elem, valueOn); } + if (bool) { + removeClass(elem, valueOff); + addClass(elem, valueOn); + } + else { + removeClass(elem, valueOn); + addClass(elem, valueOff); + } + return bool; +} + + +function makeClassToggle(valueOn, valueOff) +{ + return function(elem, bool) { + return toggleClass(elem, valueOn, valueOff, bool); + } +} + +toggleShow = makeClassToggle("show", "hide"); +toggleCollapser = makeClassToggle("collapser", "expander"); + +function toggleSection(id) +{ + var b = toggleShow(document.getElementById("section." + id)); + toggleCollapser(document.getElementById("control." + id), b); + rememberCollapsed(id, b); + return b; +} + +var collapsed = {}; +function rememberCollapsed(id, b) +{ + if(b) + delete collapsed[id] + else + collapsed[id] = null; + + var sections = []; + for(var i in collapsed) + { + if(collapsed.hasOwnProperty(i)) + sections.push(i); + } + // cookie specific to this page; don't use setCookie which sets path=/ + document.cookie = "collapsed=" + escape(sections.join('+')); +} + +function restoreCollapsed() +{ + var cookie = getCookie("collapsed"); + if(!cookie) + return; + + var ids = cookie.split('+'); + for(var i in ids) + { + if(document.getElementById("section." + ids[i])) + toggleSection(ids[i]); + } +} + +function setCookie(name, value) { + document.cookie = name + "=" + escape(value) + ";path=/;"; +} + +function clearCookie(name) { + document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"; +} + +function getCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) { + return unescape(c.substring(nameEQ.length,c.length)); + } + } + return null; +} + + + +var max_results = 75; // 50 is not enough to search for map in the base libraries +var shown_range = null; +var last_search = null; + +function quick_search() +{ + perform_search(false); +} + +function full_search() +{ + perform_search(true); +} + + +function perform_search(full) +{ + var text = document.getElementById("searchbox").value.toLowerCase(); + if (text == last_search && !full) return; + last_search = text; + + var table = document.getElementById("indexlist"); + var status = document.getElementById("searchmsg"); + var children = table.firstChild.childNodes; + + // first figure out the first node with the prefix + var first = bisect(-1); + var last = (first == -1 ? -1 : bisect(1)); + + if (first == -1) + { + table.className = ""; + status.innerHTML = "No results found, displaying all"; + } + else if (first == 0 && last == children.length - 1) + { + table.className = ""; + status.innerHTML = ""; + } + else if (last - first >= max_results && !full) + { + table.className = ""; + status.innerHTML = "More than " + max_results + ", press Search to display"; + } + else + { + // decide what you need to clear/show + if (shown_range) + setclass(shown_range[0], shown_range[1], "indexrow"); + setclass(first, last, "indexshow"); + shown_range = [first, last]; + table.className = "indexsearch"; + status.innerHTML = ""; + } + + + function setclass(first, last, status) + { + for (var i = first; i <= last; i++) + { + children[i].className = status; + } + } + + + // do a binary search, treating 0 as ... + // return either -1 (no 0's found) or location of most far match + function bisect(dir) + { + var first = 0, finish = children.length - 1; + var mid, success = false; + + while (finish - first > 3) + { + mid = Math.floor((finish + first) / 2); + + var i = checkitem(mid); + if (i == 0) i = dir; + if (i == -1) + finish = mid; + else + first = mid; + } + var a = (dir == 1 ? first : finish); + var b = (dir == 1 ? finish : first); + for (var i = b; i != a - dir; i -= dir) + { + if (checkitem(i) == 0) return i; + } + return -1; + } + + + // from an index, decide what the result is + // 0 = match, -1 is lower, 1 is higher + function checkitem(i) + { + var s = getitem(i).toLowerCase().substr(0, text.length); + if (s == text) return 0; + else return (s > text ? -1 : 1); + } + + + // from an index, get its string + // this abstracts over alternates + function getitem(i) + { + for ( ; i >= 0; i--) + { + var s = children[i].firstChild.firstChild.data; + if (s.indexOf(' ') == -1) + return s; + } + return ""; // should never be reached + } +} + +function setSynopsis(filename) { + if (parent.window.synopsis) { + if (parent.window.synopsis.location.replace) { + // In Firefox this avoids adding the change to the history. + parent.window.synopsis.location.replace(filename); + } else { + parent.window.synopsis.location = filename; + } + } +} + +function addMenuItem(html) { + var menu = document.getElementById("page-menu"); + if (menu) { + var btn = menu.firstChild.cloneNode(false); + btn.innerHTML = html; + menu.appendChild(btn); + } +} + +function adjustForFrames() { + var bodyCls; + + if (parent.location.href == window.location.href) { + // not in frames, so add Frames button + addMenuItem("Frames"); + bodyCls = "no-frame"; + } + else { + bodyCls = "in-frame"; + } + addClass(document.body, bodyCls); +} + +function reframe() { + setCookie("haddock-reframe", document.URL); + window.location = "frames.html"; +} + +function postReframe() { + var s = getCookie("haddock-reframe"); + if (s) { + parent.window.main.location = s; + clearCookie("haddock-reframe"); + } +} + +function styles() { + var i, a, es = document.getElementsByTagName("link"), rs = []; + for (i = 0; a = es[i]; i++) { + if(a.rel.indexOf("style") != -1 && a.title) { + rs.push(a); + } + } + return rs; +} + +function addStyleMenu() { + var as = styles(); + var i, a, btns = ""; + for(i=0; a = as[i]; i++) { + btns += "
  • " + + a.title + "
  • " + } + if (as.length > 1) { + var h = "
    " + + "Style ▾" + + "" + + "
    "; + addMenuItem(h); + } +} + +function setActiveStyleSheet(title) { + var as = styles(); + var i, a, found; + for(i=0; a = as[i]; i++) { + a.disabled = true; + // need to do this always, some browsers are edge triggered + if(a.title == title) { + found = a; + } + } + if (found) { + found.disabled = false; + setCookie("haddock-style", title); + } + else { + as[0].disabled = false; + clearCookie("haddock-style"); + } + styleMenu(false); +} + +function resetStyle() { + var s = getCookie("haddock-style"); + if (s) setActiveStyleSheet(s); +} + + +function styleMenu(show) { + var m = document.getElementById('style-menu'); + if (m) toggleShow(m, show); +} + + +function pageLoad() { + addStyleMenu(); + adjustForFrames(); + resetStyle(); + restoreCollapsed(); +} + diff --git a/hslogo-16.png b/hslogo-16.png new file mode 100644 index 0000000..0ff8579 Binary files /dev/null and b/hslogo-16.png differ diff --git a/index-frames.html b/index-frames.html new file mode 100644 index 0000000..c95cef5 --- /dev/null +++ b/index-frames.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library

    Modules

    \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..edcd5a8 --- /dev/null +++ b/index.html @@ -0,0 +1,4 @@ +ldap-client-0.1.0: Pure Haskell LDAP Client Library

    ldap-client-0.1.0: Pure Haskell LDAP Client Library

    ldap-client-0.1.0: Pure Haskell LDAP Client Library

    Pure Haskell LDAP client library implementing (the parts of) RFC 4511.

    Modules

    \ No newline at end of file diff --git a/ldap-client.haddock b/ldap-client.haddock new file mode 100644 index 0000000..df2ff38 Binary files /dev/null and b/ldap-client.haddock differ diff --git a/mini_Ldap-Asn1-FromAsn1.html b/mini_Ldap-Asn1-FromAsn1.html new file mode 100644 index 0000000..5a1b897 --- /dev/null +++ b/mini_Ldap-Asn1-FromAsn1.html @@ -0,0 +1,4 @@ +Ldap.Asn1.FromAsn1

    Ldap.Asn1.FromAsn1

    class FromAsn1 a

    data Parser s a

    parseAsn1

    parse

    next

    \ No newline at end of file diff --git a/mini_Ldap-Asn1-ToAsn1.html b/mini_Ldap-Asn1-ToAsn1.html new file mode 100644 index 0000000..4f67251 --- /dev/null +++ b/mini_Ldap-Asn1-ToAsn1.html @@ -0,0 +1,4 @@ +Ldap.Asn1.ToAsn1

    Ldap.Asn1.ToAsn1

    class ToAsn1 a

    \ No newline at end of file diff --git a/mini_Ldap-Asn1-Type.html b/mini_Ldap-Asn1-Type.html new file mode 100644 index 0000000..8868af8 --- /dev/null +++ b/mini_Ldap-Asn1-Type.html @@ -0,0 +1,4 @@ +Ldap.Asn1.Type

    Ldap.Asn1.Type

    data LdapMessage op

    data Id

    data ProtocolClientOp

    data ProtocolServerOp

    data AuthenticationChoice

    data Scope

    data DerefAliases

    data Filter

    data SubstringFilter

    data Substring

    data MatchingRuleAssertion

    data MatchingRuleId

    data AttributeSelection

    data AttributeList

    data PartialAttributeList

    data Controls

    data Control

    data LdapResult

    data ResultCode

    data AttributeDescription

    data AttributeValue

    data AttributeValueAssertion

    data AssertionValue

    data Attribute

    data PartialAttribute

    data LdapDn

    data RelativeLdapDn

    data ReferralUris

    data Uri

    data Operation

    data LdapString

    data LdapOid

    \ No newline at end of file diff --git a/mini_Ldap-Client-Add.html b/mini_Ldap-Client-Add.html new file mode 100644 index 0000000..3e317aa --- /dev/null +++ b/mini_Ldap-Client-Add.html @@ -0,0 +1,4 @@ +Ldap.Client.Add

    Ldap.Client.Add

    add

    addEither

    addAsync

    addAsyncSTM

    \ No newline at end of file diff --git a/mini_Ldap-Client-Bind.html b/mini_Ldap-Client-Bind.html new file mode 100644 index 0000000..7ed621a --- /dev/null +++ b/mini_Ldap-Client-Bind.html @@ -0,0 +1,4 @@ +Ldap.Client.Bind

    Ldap.Client.Bind

    bind

    bindEither

    bindAsync

    bindAsyncSTM

    unbindAsync

    unbindAsyncSTM

    \ No newline at end of file diff --git a/mini_Ldap-Client-Compare.html b/mini_Ldap-Client-Compare.html new file mode 100644 index 0000000..432a0ba --- /dev/null +++ b/mini_Ldap-Client-Compare.html @@ -0,0 +1,4 @@ +Ldap.Client.Compare

    Ldap.Client.Compare

    compare

    compareEither

    compareAsync

    compareAsyncSTM

    \ No newline at end of file diff --git a/mini_Ldap-Client-Delete.html b/mini_Ldap-Client-Delete.html new file mode 100644 index 0000000..f046436 --- /dev/null +++ b/mini_Ldap-Client-Delete.html @@ -0,0 +1,4 @@ +Ldap.Client.Delete

    Ldap.Client.Delete

    delete

    deleteEither

    deleteAsync

    deleteAsyncSTM

    \ No newline at end of file diff --git a/mini_Ldap-Client-Extended.html b/mini_Ldap-Client-Extended.html new file mode 100644 index 0000000..ebf2d85 --- /dev/null +++ b/mini_Ldap-Client-Extended.html @@ -0,0 +1,4 @@ +Ldap.Client.Extended

    Ldap.Client.Extended

    extended

    extendedEither

    extendedAsync

    extendedAsyncSTM

    startTls

    startTlsEither

    startTlsAsync

    startTlsAsyncSTM

    \ No newline at end of file diff --git a/mini_Ldap-Client-Internal.html b/mini_Ldap-Client-Internal.html new file mode 100644 index 0000000..9229263 --- /dev/null +++ b/mini_Ldap-Client-Internal.html @@ -0,0 +1,4 @@ +Ldap.Client.Internal

    Ldap.Client.Internal

    data Host

    data PortNumber

    data Ldap

    data ClientMessage

    data ResultCode

    data Async a

    data Oid

    type AttrList f

    Waiting for Request Completion

    wait

    waitSTM

    Misc

    type Response

    data ResponseError

    type Request

    raise

    sendRequest

    data Dn

    data RelativeDn

    data Password

    data Attr

    unAttr

    \ No newline at end of file diff --git a/mini_Ldap-Client-Modify.html b/mini_Ldap-Client-Modify.html new file mode 100644 index 0000000..06ccf0f --- /dev/null +++ b/mini_Ldap-Client-Modify.html @@ -0,0 +1,4 @@ +Ldap.Client.Modify

    Ldap.Client.Modify

    data Operation

    modify

    modifyEither

    modifyAsync

    modifyAsyncSTM

    modifyDn

    modifyDnEither

    modifyDnAsync

    modifyDnAsyncSTM

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

    Ldap.Client.Search

    search

    searchEither

    searchAsync

    searchAsyncSTM

    data Search

    data Mod a

    data Scope

    scope

    size

    time

    typesOnly

    derefAliases

    data Filter

    data SearchEntry

    \ No newline at end of file diff --git a/mini_Ldap-Client.html b/mini_Ldap-Client.html new file mode 100644 index 0000000..7165334 --- /dev/null +++ b/mini_Ldap-Client.html @@ -0,0 +1,4 @@ +Ldap.Client

    Ldap.Client

    data Host

    data Ldap

    data LdapError

    data ResponseError

    data ResultCode

    data Async a

    with

    Bind

    bind

    Search

    search

    data SearchEntry

    Search modifiers

    data Search

    data Mod a

    scope

    data Scope

    size

    time

    typesOnly

    derefAliases

    data Filter

    Modify

    modify

    data Operation

    Add

    add

    Delete

    delete

    ModifyDn

    modifyDn

    Compare

    compare

    Extended

    extended

    Waiting for completion

    wait

    Miscellanous

    data Dn

    data RelativeDn

    data Oid

    data Password

    type AttrList f

    data Attr

    Re-exports

    data NonEmpty a

    data PortNumber

    \ No newline at end of file diff --git a/minus.gif b/minus.gif new file mode 100644 index 0000000..1deac2f Binary files /dev/null and b/minus.gif differ diff --git a/ocean.css b/ocean.css new file mode 100644 index 0000000..ef652a2 --- /dev/null +++ b/ocean.css @@ -0,0 +1,587 @@ +/* @group Fundamentals */ + +* { margin: 0; padding: 0 } + +/* Is this portable? */ +html { + background-color: white; + width: 100%; + height: 100%; +} + +body { + background: white; + color: black; + text-align: left; + min-height: 100%; + position: relative; +} + +p { + margin: 0.8em 0; +} + +ul, ol { + margin: 0.8em 0 0.8em 2em; +} + +dl { + margin: 0.8em 0; +} + +dt { + font-weight: bold; +} +dd { + margin-left: 2em; +} + +a { text-decoration: none; } +a[href]:link { color: rgb(196,69,29); } +a[href]:visited { color: rgb(171,105,84); } +a[href]:hover { text-decoration:underline; } + +/* @end */ + +/* @group Fonts & Sizes */ + +/* Basic technique & IE workarounds from YUI 3 + For reasons, see: + http://yui.yahooapis.com/3.1.1/build/cssfonts/fonts.css + */ + +body { + font:13px/1.4 sans-serif; + *font-size:small; /* for IE */ + *font:x-small; /* for IE in quirks mode */ +} + +h1 { font-size: 146.5%; /* 19pt */ } +h2 { font-size: 131%; /* 17pt */ } +h3 { font-size: 116%; /* 15pt */ } +h4 { font-size: 100%; /* 13pt */ } +h5 { font-size: 100%; /* 13pt */ } + +select, input, button, textarea { + font:99% sans-serif; +} + +table { + font-size:inherit; + font:100%; +} + +pre, code, kbd, samp, tt, .src { + font-family:monospace; + *font-size:108%; + line-height: 124%; +} + +.links, .link { + font-size: 85%; /* 11pt */ +} + +#module-header .caption { + font-size: 182%; /* 24pt */ +} + +.info { + font-size: 85%; /* 11pt */ +} + +#table-of-contents, #synopsis { + /* font-size: 85%; /* 11pt */ +} + + +/* @end */ + +/* @group Common */ + +.caption, h1, h2, h3, h4, h5, h6 { + font-weight: bold; + color: rgb(78,98,114); + margin: 0.8em 0 0.4em; +} + +* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 { + margin-top: 2em; +} + +h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 { + margin-top: inherit; +} + +ul.links { + list-style: none; + text-align: left; + float: right; + display: inline-table; + margin: 0 0 0 1em; +} + +ul.links li { + display: inline; + border-left: 1px solid #d5d5d5; + white-space: nowrap; + padding: 0; +} + +ul.links li a { + padding: 0.2em 0.5em; +} + +.hide { display: none; } +.show { display: inherit; } +.clear { clear: both; } + +.collapser { + background-image: url(minus.gif); + background-repeat: no-repeat; +} +.expander { + background-image: url(plus.gif); + background-repeat: no-repeat; +} +p.caption.collapser, +p.caption.expander { + background-position: 0 0.4em; +} +.collapser, .expander { + padding-left: 14px; + margin-left: -14px; + cursor: pointer; +} + +pre { + padding: 0.25em; + margin: 0.8em 0; + background: rgb(229,237,244); + overflow: auto; + border-bottom: 0.25em solid white; + /* white border adds some space below the box to compensate + for visual extra space that paragraphs have between baseline + and the bounding box */ +} + +.src { + background: #f0f0f0; + padding: 0.2em 0.5em; +} + +.keyword { font-weight: normal; } +.def { font-weight: bold; } + + +/* @end */ + +/* @group Page Structure */ + +#content { + margin: 0 auto; + padding: 0 2em 6em; +} + +#package-header { + background: rgb(41,56,69); + border-top: 5px solid rgb(78,98,114); + color: #ddd; + padding: 0.2em; + position: relative; + text-align: left; +} + +#package-header .caption { + background: url(hslogo-16.png) no-repeat 0em; + color: white; + margin: 0 2em; + font-weight: normal; + font-style: normal; + padding-left: 2em; +} + +#package-header a:link, #package-header a:visited { color: white; } +#package-header a:hover { background: rgb(78,98,114); } + +#module-header .caption { + color: rgb(78,98,114); + font-weight: bold; + border-bottom: 1px solid #ddd; +} + +table.info { + float: right; + padding: 0.5em 1em; + border: 1px solid #ddd; + color: rgb(78,98,114); + background-color: #fff; + max-width: 40%; + border-spacing: 0; + position: relative; + top: -0.5em; + margin: 0 0 0 2em; +} + +.info th { + padding: 0 1em 0 0; +} + +div#style-menu-holder { + position: relative; + z-index: 2; + display: inline; +} + +#style-menu { + position: absolute; + z-index: 1; + overflow: visible; + background: #374c5e; + margin: 0; + text-align: center; + right: 0; + padding: 0; + top: 1.25em; +} + +#style-menu li { + display: list-item; + border-style: none; + margin: 0; + padding: 0; + color: #000; + list-style-type: none; +} + +#style-menu li + li { + border-top: 1px solid #919191; +} + +#style-menu a { + width: 6em; + padding: 3px; + display: block; +} + +#footer { + background: #ddd; + border-top: 1px solid #aaa; + padding: 0.5em 0; + color: #666; + text-align: center; + position: absolute; + bottom: 0; + width: 100%; + height: 3em; +} + +/* @end */ + +/* @group Front Matter */ + +#table-of-contents { + float: right; + clear: right; + background: #faf9dc; + border: 1px solid #d8d7ad; + padding: 0.5em 1em; + max-width: 20em; + margin: 0.5em 0 1em 1em; +} + +#table-of-contents .caption { + text-align: center; + margin: 0; +} + +#table-of-contents ul { + list-style: none; + margin: 0; +} + +#table-of-contents ul ul { + margin-left: 2em; +} + +#description .caption { + display: none; +} + +#synopsis { + display: none; +} + +.no-frame #synopsis { + display: block; + position: fixed; + right: 0; + height: 80%; + top: 10%; + padding: 0; + max-width: 75%; +} + +#synopsis .caption { + float: left; + width: 29px; + color: rgba(255,255,255,0); + height: 110px; + margin: 0; + font-size: 1px; + padding: 0; +} + +#synopsis p.caption.collapser { + background: url(synopsis.png) no-repeat -64px -8px; +} + +#synopsis p.caption.expander { + background: url(synopsis.png) no-repeat 0px -8px; +} + +#synopsis ul { + height: 100%; + overflow: auto; + padding: 0.5em; + margin: 0; +} + +#synopsis ul ul { + overflow: hidden; +} + +#synopsis ul, +#synopsis ul li.src { + background-color: #faf9dc; + white-space: nowrap; + list-style: none; + margin-left: 0; +} + +/* @end */ + +/* @group Main Content */ + +#interface div.top { margin: 2em 0; } +#interface h1 + div.top, +#interface h2 + div.top, +#interface h3 + div.top, +#interface h4 + div.top, +#interface h5 + div.top { + margin-top: 1em; +} +#interface p.src .link { + float: right; + color: #919191; + border-left: 1px solid #919191; + background: #f0f0f0; + padding: 0 0.5em 0.2em; + margin: 0 -0.5em 0 0.5em; +} + +#interface td.src .link { + float: right; + color: #919191; + border-left: 1px solid #919191; + background: #f0f0f0; + padding: 0 0.5em 0.2em; + margin: 0 -0.5em 0 0.5em; +} + +#interface span.fixity { + color: #919191; + border-left: 1px solid #919191; + padding: 0.2em 0.5em 0.2em 0.5em; + margin: 0 -1em 0 1em; +} + +#interface span.rightedge { + border-left: 1px solid #919191; + padding: 0.2em 0 0.2em 0; + margin: 0 0 0 1em; +} + +#interface table { border-spacing: 2px; } +#interface td { + vertical-align: top; + padding-left: 0.5em; +} +#interface td.src { + white-space: nowrap; +} +#interface td.doc p { + margin: 0; +} +#interface td.doc p + p { + margin-top: 0.8em; +} + +.subs dl { + margin: 0; +} + +.subs dt { + float: left; + clear: left; + display: block; + margin: 1px 0; +} + +.subs dd { + float: right; + width: 90%; + display: block; + padding-left: 0.5em; + margin-bottom: 0.5em; +} + +.subs dd.empty { + display: none; +} + +.subs dd p { + margin: 0; +} + +/* Render short-style data instances */ +.inst ul { + height: 100%; + padding: 0.5em; + margin: 0; +} + +.inst, .inst li { + list-style: none; + margin-left: 1em; +} + +.top p.src { + border-top: 1px solid #ccc; +} + +.subs, .doc { + /* use this selector for one level of indent */ + padding-left: 2em; +} + +.warning { + color: red; +} + +.arguments { + margin-top: -0.4em; +} +.arguments .caption { + display: none; +} + +.fields { padding-left: 1em; } + +.fields .caption { display: none; } + +.fields p { margin: 0 0; } + +/* this seems bulky to me +.methods, .constructors { + background: #f8f8f8; + border: 1px solid #eee; +} +*/ + +/* @end */ + +/* @group Auxillary Pages */ + + +.extension-list { + list-style-type: none; + margin-left: 0; +} + +#mini { + margin: 0 auto; + padding: 0 1em 1em; +} + +#mini > * { + font-size: 93%; /* 12pt */ +} + +#mini #module-list .caption, +#mini #module-header .caption { + font-size: 125%; /* 15pt */ +} + +#mini #interface h1, +#mini #interface h2, +#mini #interface h3, +#mini #interface h4 { + font-size: 109%; /* 13pt */ + margin: 1em 0 0; +} + +#mini #interface .top, +#mini #interface .src { + margin: 0; +} + +#mini #module-list ul { + list-style: none; + margin: 0; +} + +#alphabet ul { + list-style: none; + padding: 0; + margin: 0.5em 0 0; + text-align: center; +} + +#alphabet li { + display: inline; + margin: 0 0.25em; +} + +#alphabet a { + font-weight: bold; +} + +#index .caption, +#module-list .caption { font-size: 131%; /* 17pt */ } + +#index table { + margin-left: 2em; +} + +#index .src { + font-weight: bold; +} +#index .alt { + font-size: 77%; /* 10pt */ + font-style: italic; + padding-left: 2em; +} + +#index td + td { + padding-left: 1em; +} + +#module-list ul { + list-style: none; + margin: 0 0 0 2em; +} + +#module-list li { + clear: right; +} + +#module-list span.collapser, +#module-list span.expander { + background-position: 0 0.3em; +} + +#module-list .package { + float: right; +} + +/* @end */ diff --git a/plus.gif b/plus.gif new file mode 100644 index 0000000..2d15c14 Binary files /dev/null and b/plus.gif differ diff --git a/src/Ldap-Asn1-FromAsn1.html b/src/Ldap-Asn1-FromAsn1.html new file mode 100644 index 0000000..b526d8a --- /dev/null +++ b/src/Ldap-Asn1-FromAsn1.html @@ -0,0 +1,389 @@ + + + + + +src/Ldap/Asn1/FromAsn1.hs + + + +
    {-# LANGUAGE CPP #-}
    +module Ldap.Asn1.FromAsn1
    +  ( FromAsn1(..)
    +  , Parser
    +  , parseAsn1
    +  , parse
    +  , next
    +  ) where
    +
    +#if __GLASGOW_HASKELL__ >= 710
    +import           Control.Applicative (Alternative(..), liftA2, optional)
    +#else
    +import           Control.Applicative (Applicative(..), Alternative(..), liftA2, optional)
    +#endif
    +import           Control.Monad (MonadPlus(..), (>=>), guard)
    +import           Data.ASN1.Types (ASN1)
    +import qualified Data.ASN1.Types as Asn1
    +import           Data.Foldable (asum)
    +import           Data.List.NonEmpty (some1)
    +import qualified Data.Text.Encoding as Text
    +
    +import           Ldap.Asn1.Type
    +
    +{-# ANN module "HLint: ignore Use const" #-}
    +{-# ANN module "HLint: ignore Avoid lambda" #-}
    +
    +
    +class FromAsn1 a where
    +  fromAsn1 :: Parser [ASN1] a
    +
    +{- |
    +@
    +LDAPMessage ::= SEQUENCE {
    +     messageID       MessageID,
    +     protocolOp      CHOICE {
    +          bindRequest           BindRequest,
    +          bindResponse          BindResponse,
    +          unbindRequest         UnbindRequest,
    +          searchRequest         SearchRequest,
    +          searchResEntry        SearchResultEntry,
    +          searchResDone         SearchResultDone,
    +          searchResRef          SearchResultReference,
    +          addRequest            AddRequest,
    +          addResponse           AddResponse,
    +          ... },
    +     controls       [0] Controls OPTIONAL }
    +@
    +-}
    +instance FromAsn1 op =>  FromAsn1 (LdapMessage op) where
    +  fromAsn1 = do
    +    Asn1.Start Asn1.Sequence <- next
    +    i  <- fromAsn1
    +    op <- fromAsn1
    +    Asn1.End Asn1.Sequence <- next
    +    return (LdapMessage i op Nothing)
    +
    +{- |
    +@
    +MessageID ::= INTEGER (0 ..  maxInt)
    +@
    +-}
    +instance FromAsn1 Id where
    +  fromAsn1 = do
    +    Asn1.IntVal i <- next
    +    return (Id (fromIntegral i))
    +
    +{- |
    +@
    +LDAPString ::= OCTET STRING -- UTF-8 encoded,
    +@
    +-}
    +instance FromAsn1 LdapString where
    +  fromAsn1 = do
    +    Asn1.OctetString s <- next
    +    case Text.decodeUtf8' s of
    +      Right t -> return (LdapString t)
    +      Left  _ -> empty
    +
    +{- |
    +@
    +LDAPOID ::= OCTET STRING -- Constrained to \<numericoid\>
    +@
    +-}
    +instance FromAsn1 LdapOid where
    +  fromAsn1 = do
    +    Asn1.OctetString s <- next
    +    return (LdapOid s)
    +
    +{- |
    +@
    +LDAPDN ::= LDAPString
    +@
    +-}
    +instance FromAsn1 LdapDn where
    +  fromAsn1 = fmap LdapDn fromAsn1
    +
    +{- |
    +@
    +AttributeDescription ::= LDAPString
    +@
    +-}
    +instance FromAsn1 AttributeDescription where
    +  fromAsn1 = fmap AttributeDescription fromAsn1
    +
    +{- |
    +@
    +AttributeValue ::= OCTET STRING
    +@
    +-}
    +instance FromAsn1 AttributeValue where
    +  fromAsn1 = do
    +    Asn1.OctetString s <- next
    +    return (AttributeValue s)
    +
    +{- |
    +@
    +PartialAttribute ::= SEQUENCE {
    +     type       AttributeDescription,
    +     vals       SET OF value AttributeValue }
    +@
    +-}
    +instance FromAsn1 PartialAttribute where
    +  fromAsn1 = do
    +    Asn1.Start Asn1.Sequence <- next
    +    d  <- fromAsn1
    +    Asn1.Start Asn1.Set <- next
    +    vs <- many fromAsn1
    +    Asn1.End Asn1.Set <- next
    +    Asn1.End Asn1.Sequence <- next
    +    return (PartialAttribute d vs)
    +
    +{- |
    +@
    +LDAPResult ::= SEQUENCE {
    +     resultCode         ENUMERATED {
    +          success                      (0),
    +          operationsError              (1),
    +          protocolError                (2),
    +          timeLimitExceeded            (3),
    +          sizeLimitExceeded            (4),
    +          compareFalse                 (5),
    +          compareTrue                  (6),
    +          authMethodNotSupported       (7),
    +          strongerAuthRequired         (8),
    +          -- 9 reserved --
    +          referral                     (10),
    +          adminLimitExceeded           (11),
    +          unavailableCriticalExtension (12),
    +          confidentialityRequired      (13),
    +          saslBindInProgress           (14),
    +          noSuchAttribute              (16),
    +          undefinedAttributeType       (17),
    +          inappropriateMatching        (18),
    +          constraintViolation          (19),
    +          attributeOrValueExists       (20),
    +          invalidAttributeSyntax       (21),
    +          -- 22-31 unused --
    +          noSuchObject                 (32),
    +          aliasProblem                 (33),
    +          invalidDNSyntax              (34),
    +          -- 35 reserved for undefined isLeaf --
    +          aliasDereferencingProblem    (36),
    +          -- 37-47 unused --
    +          inappropriateAuthentication  (48),
    +          invalidCredentials           (49),
    +          insufficientAccessRights     (50),
    +          busy                         (51),
    +          unavailable                  (52),
    +          unwillingToPerform           (53),
    +          loopDetect                   (54),
    +          -- 55-63 unused --
    +          namingViolation              (64),
    +          objectClassViolation         (65),
    +          notAllowedOnNonLeaf          (66),
    +          notAllowedOnRDN              (67),
    +          entryAlreadyExists           (68),
    +          objectClassModsProhibited    (69),
    +          -- 70 reserved for CLDAP --
    +          affectsMultipleDSAs          (71),
    +          -- 72-79 unused --
    +          other                        (80),
    +          ...  },
    +     matchedDN          LDAPDN,
    +     diagnosticMessage  LDAPString,
    +     referral           [3] Referral OPTIONAL }
    +@
    +-}
    +instance FromAsn1 LdapResult where
    +  fromAsn1 = do
    +    resultCode <- do
    +      Asn1.Enumerated x <- next
    +      case x of
    +        0  -> pure Success
    +        1  -> pure OperationError
    +        2  -> pure ProtocolError
    +        3  -> pure TimeLimitExceeded
    +        4  -> pure SizeLimitExceeded
    +        5  -> pure CompareFalse
    +        6  -> pure CompareTrue
    +        7  -> pure AuthMethodNotSupported
    +        8  -> pure StrongerAuthRequired
    +        10 -> pure Referral
    +        11 -> pure AdminLimitExceeded
    +        12 -> pure UnavailableCriticalExtension
    +        13 -> pure ConfidentialityRequired
    +        14 -> pure SaslBindInProgress
    +        16 -> pure NoSuchAttribute
    +        17 -> pure UndefinedAttributeType
    +        18 -> pure InappropriateMatching
    +        19 -> pure ConstraintViolation
    +        20 -> pure AttributeOrValueExists
    +        21 -> pure InvalidAttributeSyntax
    +        32 -> pure NoSuchObject
    +        33 -> pure AliasProblem
    +        34 -> pure InvalidDNSyntax
    +        36 -> pure AliasDereferencingProblem
    +        48 -> pure InappropriateAuthentication
    +        49 -> pure InvalidCredentials
    +        50 -> pure InsufficientAccessRights
    +        51 -> pure Busy
    +        52 -> pure Unavailable
    +        53 -> pure UnwillingToPerform
    +        54 -> pure LoopDetect
    +        64 -> pure NamingViolation
    +        65 -> pure ObjectClassViolation
    +        66 -> pure NotAllowedOnNonLeaf
    +        67 -> pure NotAllowedOnRDN
    +        68 -> pure EntryAlreadyExists
    +        69 -> pure ObjectClassModsProhibited
    +        71 -> pure AffectsMultipleDSAs
    +        80 -> pure Other
    +        _  -> empty
    +    matchedDn  <- fromAsn1
    +    diagnosticMessage
    +               <- fromAsn1
    +    referral   <- optional $ do
    +      Asn1.Start (Asn1.Container Asn1.Context 0) <- next
    +      x <- fromAsn1
    +      Asn1.End (Asn1.Container Asn1.Context 0) <- next
    +      return x
    +    return (LdapResult resultCode matchedDn diagnosticMessage referral)
    +
    +{- |
    +@
    +Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
    +@
    +-}
    +instance FromAsn1 ReferralUris where
    +  fromAsn1 = do
    +    Asn1.Start Asn1.Sequence <- next
    +    xs <- some1 fromAsn1
    +    Asn1.End Asn1.Sequence <- next
    +    return (ReferralUris xs)
    +
    +{- |
    +@
    +URI ::= LDAPString
    +@
    +-}
    +instance FromAsn1 Uri where
    +  fromAsn1 = fmap Uri fromAsn1
    +
    +{- |
    +@
    +BindResponse ::= [APPLICATION 1] SEQUENCE {
    +     COMPONENTS OF LDAPResult,
    +     serverSaslCreds    [7] OCTET STRING OPTIONAL }
    +@
    +
    +@
    +SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
    +     objectName      LDAPDN,
    +     attributes      PartialAttributeList }
    +@
    +
    +@
    +SearchResultDone ::= [APPLICATION 5] LDAPResult
    +@
    +
    +@
    +ModifyResponse ::= [APPLICATION 7] LDAPResult
    +@
    +
    +@
    +AddResponse ::= [APPLICATION 9] LDAPResult
    +@
    +
    +@
    +DelResponse ::= [APPLICATION 11] LDAPResult
    +@
    +
    +@
    +CompareResponse ::= [APPLICATION 15] LDAPResult
    +@
    +-}
    +instance FromAsn1 ProtocolServerOp where
    +  fromAsn1 = asum
    +    [ fmap (\res -> BindResponse res Nothing) (app 1)
    +    , fmap (uncurry SearchResultEntry) (app 4)
    +    , fmap SearchResultDone (app 5)
    +    , fmap ModifyResponse (app 7)
    +    , fmap AddResponse (app 9)
    +    , fmap DeleteResponse (app 11)
    +    , fmap ModifyDnResponse (app 13)
    +    , fmap CompareResponse (app 15)
    +    , do
    +      Asn1.Start (Asn1.Container Asn1.Application 24) <- next
    +      res <- fromAsn1
    +      name <- optional $ do
    +        Asn1.Other Asn1.Context 0 s <- next
    +        return s
    +      value <- optional $ do
    +        Asn1.Other Asn1.Context 1 s <- next
    +        return s
    +      Asn1.End (Asn1.Container Asn1.Application 24) <- next
    +      return (ExtendedResponse res (fmap LdapOid name) value)
    +    ]
    +   where
    +    app l = do
    +      Asn1.Start (Asn1.Container Asn1.Application x) <- next
    +      guard (x == l)
    +      res <- fromAsn1
    +      Asn1.End (Asn1.Container Asn1.Application y) <- next
    +      guard (y == l)
    +      return res
    +
    +{- |
    +@
    +PartialAttributeList ::= SEQUENCE OF partialAttribute PartialAttribute
    +@
    +-}
    +instance FromAsn1 PartialAttributeList where
    +  fromAsn1 = do
    +    Asn1.Start Asn1.Sequence <- next
    +    xs <- many fromAsn1
    +    Asn1.End Asn1.Sequence <- next
    +    return (PartialAttributeList xs)
    +
    +instance (FromAsn1 a, FromAsn1 b) => FromAsn1 (a, b) where
    +  fromAsn1 = liftA2 (,) fromAsn1 fromAsn1
    +
    +
    +newtype Parser s a = Parser { unParser :: s -> Maybe (s, a) }
    +
    +instance Functor (Parser s) where
    +  fmap f (Parser g) = Parser (fmap (fmap f) . g)
    +
    +instance Applicative (Parser s) where
    +  pure x = Parser (\s -> pure (s, x))
    +  Parser mf <*> Parser mx = Parser $ \s -> do
    +    (s', f)  <- mf s
    +    (s'', x) <- mx s'
    +    pure (s'', f x)
    +
    +instance Alternative (Parser s) where
    +  empty = Parser (\_ -> empty)
    +  Parser ma <|> Parser mb =
    +    Parser (\s -> ma s <|> mb s)
    +
    +instance Monad (Parser s) where
    +  return x = Parser (\s -> return (s, x))
    +  Parser mx >>= k =
    +    Parser (mx >=> \(s', x) -> unParser (k x) s')
    +  fail _ = empty
    +
    +instance MonadPlus (Parser s) where
    +  mzero = Parser (\_ -> mzero)
    +  Parser ma `mplus` Parser mb =
    +    Parser (\s -> ma s `mplus` mb s)
    +
    +parseAsn1 :: FromAsn1 a => [ASN1] -> Maybe ([ASN1], a)
    +parseAsn1 = parse fromAsn1
    +
    +parse :: Parser s a -> s -> Maybe (s, a)
    +parse = unParser
    +
    +next :: Parser [s] s
    +next = Parser (\s -> case s of [] -> Nothing; x : xs -> Just (xs, x))
    +
    + diff --git a/src/Ldap-Asn1-ToAsn1.html b/src/Ldap-Asn1-ToAsn1.html new file mode 100644 index 0000000..90e7770 --- /dev/null +++ b/src/Ldap-Asn1-ToAsn1.html @@ -0,0 +1,432 @@ + + + + + +src/Ldap/Asn1/ToAsn1.hs + + + +
    module Ldap.Asn1.ToAsn1
    +  ( ToAsn1(toAsn1)
    +  ) where
    +
    +import           Data.ASN1.Types (ASN1, ASN1Class, ASN1Tag, ASN1ConstructionType)
    +import qualified Data.ASN1.Types as Asn1
    +import           Data.ByteString (ByteString)
    +import           Data.Foldable (fold, foldMap)
    +import           Data.List.NonEmpty (NonEmpty)
    +import           Data.Maybe (Maybe, maybe)
    +import           Data.Monoid (Endo(Endo), (<>), mempty)
    +import qualified Data.Text.Encoding as Text
    +import           Prelude (Integer, (.), fromIntegral)
    +
    +import           Ldap.Asn1.Type
    +
    +
    +class ToAsn1 a where
    +  toAsn1 :: a -> Endo [ASN1]
    +
    +{- |
    +@
    +LDAPMessage ::= SEQUENCE {
    +     messageID       MessageID,
    +     protocolOp      CHOICE {
    +          bindRequest           BindRequest,
    +          bindResponse          BindResponse,
    +          unbindRequest         UnbindRequest,
    +          searchRequest         SearchRequest,
    +          searchResEntry        SearchResultEntry,
    +          searchResDone         SearchResultDone,
    +          searchResRef          SearchResultReference,
    +          addRequest            AddRequest,
    +          addResponse           AddResponse,
    +          ... },
    +     controls       [0] Controls OPTIONAL }
    +@
    +-}
    +instance ToAsn1 op => ToAsn1 (LdapMessage op) where
    +  toAsn1 (LdapMessage i op mc) =
    +    sequence (toAsn1 i <> toAsn1 op <> maybe mempty (context 0 . toAsn1) mc)
    +
    +{- |
    +@
    +MessageID ::= INTEGER (0 ..  maxInt)
    +@
    +-}
    +instance ToAsn1 Id where
    +  toAsn1 (Id i) = single (Asn1.IntVal (fromIntegral i))
    +
    +{- |
    +@
    +LDAPString ::= OCTET STRING -- UTF-8 encoded
    +@
    +-}
    +instance ToAsn1 LdapString where
    +  toAsn1 (LdapString s) = single (Asn1.OctetString (Text.encodeUtf8 s))
    +
    +{- |
    +@
    +LDAPOID ::= OCTET STRING -- Constrained to \<numericoid\>
    +@
    +-}
    +instance ToAsn1 LdapOid where
    +  toAsn1 (LdapOid s) = single (Asn1.OctetString s)
    +
    +{- |
    +@
    +LDAPDN ::= LDAPString -- Constrained to \<distinguishedName\>
    +@
    +-}
    +instance ToAsn1 LdapDn where
    +  toAsn1 (LdapDn s) = toAsn1 s
    +
    +{- |
    +@
    +RelativeLDAPDN ::= LDAPString -- Constrained to \<name-component\>
    +@
    +-}
    +instance ToAsn1 RelativeLdapDn where
    +  toAsn1 (RelativeLdapDn s) = toAsn1 s
    +
    +{- |
    +@
    +AttributeDescription ::= LDAPString
    +@
    +-}
    +instance ToAsn1 AttributeDescription where
    +  toAsn1 (AttributeDescription s) = toAsn1 s
    +
    +{- |
    +@
    +AttributeValue ::= OCTET STRING
    +@
    +-}
    +instance ToAsn1 AttributeValue where
    +  toAsn1 (AttributeValue s) = single (Asn1.OctetString s)
    +
    +{- |
    +@
    +AttributeValueAssertion ::= SEQUENCE {
    +     attributeDesc   AttributeDescription,
    +     assertionValue  AssertionValue }
    +@
    +-}
    +instance ToAsn1 AttributeValueAssertion where
    +  toAsn1 (AttributeValueAssertion d v) = toAsn1 d <> toAsn1 v
    +
    +{- |
    +@
    +AssertionValue ::= OCTET STRING
    +@
    +-}
    +instance ToAsn1 AssertionValue where
    +  toAsn1 (AssertionValue s) = single (Asn1.OctetString s)
    +
    +
    +{- |
    +@
    +PartialAttribute ::= SEQUENCE {
    +     type       AttributeDescription,
    +     vals       SET OF value AttributeValue }
    +@
    +-}
    +instance ToAsn1 PartialAttribute where
    +  toAsn1 (PartialAttribute d xs) = sequence (toAsn1 d <> set (toAsn1 xs))
    +
    +{- |
    +@
    +Attribute ::= PartialAttribute(WITH COMPONENTS {
    +     ...,
    +     vals (SIZE(1..MAX))})
    +@
    +-}
    +instance ToAsn1 Attribute where
    +  toAsn1 (Attribute d xs) = sequence (toAsn1 d <> set (toAsn1 xs))
    +
    +{- |
    +@
    +MatchingRuleId ::= LDAPString
    +@
    +-}
    +instance ToAsn1 MatchingRuleId where
    +  toAsn1 (MatchingRuleId s) = toAsn1 s
    +
    +{- |
    +@
    +Controls ::= SEQUENCE OF control Control
    +@
    +-}
    +instance ToAsn1 Controls where
    +  toAsn1 (Controls cs) = sequence (toAsn1 cs)
    +
    +{- |
    +@
    +Control ::= SEQUENCE {
    +     controlType             LDAPOID,
    +     criticality             BOOLEAN DEFAULT FALSE,
    +     controlValue            OCTET STRING OPTIONAL }
    +@
    +-}
    +instance ToAsn1 Control where
    +  toAsn1 (Control t c v) =
    +    sequence (fold
    +      [ toAsn1 t
    +      , single (Asn1.Boolean c)
    +      , maybe mempty (single . Asn1.OctetString) v
    +      ])
    +
    +{- |
    +@
    +BindRequest ::= [APPLICATION 0] SEQUENCE {
    +     version                 INTEGER (1 ..  127),
    +     name                    LDAPDN,
    +     authentication          AuthenticationChoice }
    +@
    +
    +@
    +UnbindRequest ::= [APPLICATION 2] NULL
    +@
    +
    +@
    +SearchRequest ::= [APPLICATION 3] SEQUENCE {
    +     baseObject      LDAPDN,
    +     scope           ENUMERATED {
    +          baseObject              (0),
    +          singleLevel             (1),
    +          wholeSubtree            (2),
    +          ...  },
    +     derefAliases    ENUMERATED {
    +          neverDerefAliases       (0),
    +          derefInSearching        (1),
    +          derefFindingBaseObj     (2),
    +          derefAlways             (3) },
    +     sizeLimit       INTEGER (0 ..  maxInt),
    +     timeLimit       INTEGER (0 ..  maxInt),
    +     typesOnly       BOOLEAN,
    +     filter          Filter,
    +     attributes      AttributeSelection }
    +@
    +
    +@
    +ModifyRequest ::= [APPLICATION 6] SEQUENCE {
    +     object          LDAPDN,
    +     changes         SEQUENCE OF change SEQUENCE {
    +          operation       ENUMERATED {
    +               add     (0),
    +               delete  (1),
    +               replace (2),
    +               ...  },
    +          modification    PartialAttribute } }
    +@
    +
    +@
    +AddRequest ::= [APPLICATION 8] SEQUENCE {
    +     entry           LDAPDN,
    +     attributes      AttributeList }
    +@
    +
    +@
    +DelRequest ::= [APPLICATION 10] LDAPDN
    +@
    +
    +@
    +ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
    +     entry           LDAPDN,
    +     newrdn          RelativeLDAPDN,
    +     deleteoldrdn    BOOLEAN,
    +     newSuperior     [0] LDAPDN OPTIONAL }
    +@
    +
    +@
    +CompareRequest ::= [APPLICATION 14] SEQUENCE {
    +     entry           LDAPDN,
    +     ava             AttributeValueAssertion }
    +@
    +
    +@
    +ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
    +     requestName      [0] LDAPOID,
    +     requestValue     [1] OCTET STRING OPTIONAL }
    +@
    +-}
    +instance ToAsn1 ProtocolClientOp where
    +  toAsn1 (BindRequest v n a) =
    +    application 0 (single (Asn1.IntVal (fromIntegral v)) <> toAsn1 n <> toAsn1 a)
    +  toAsn1 UnbindRequest =
    +    other Asn1.Application 2 mempty
    +  toAsn1 (SearchRequest bo s da sl tl to f a) =
    +    application 3 (fold
    +      [ toAsn1 bo
    +      , enum s'
    +      , enum da'
    +      , single (Asn1.IntVal (fromIntegral sl))
    +      , single (Asn1.IntVal (fromIntegral tl))
    +      , single (Asn1.Boolean to)
    +      , toAsn1 f
    +      , toAsn1 a
    +      ])
    +   where
    +    s' = case s of
    +      BaseObject   -> 0
    +      SingleLevel  -> 1
    +      WholeSubtree -> 2
    +    da' = case da of
    +      NeverDerefAliases      -> 0
    +      DerefInSearching       -> 1
    +      DerefFindingBaseObject -> 2
    +      DerefAlways            -> 3
    +  toAsn1 (ModifyRequest dn xs) =
    +    application 6 (fold
    +      [ toAsn1 dn
    +      , sequence (foldMap (\(op, pa) -> sequence (enum (case op of
    +          Add     -> 0
    +          Delete  -> 1
    +          Replace -> 2) <> toAsn1 pa)) xs)
    +      ])
    +  toAsn1 (AddRequest dn as) =
    +    application 8 (toAsn1 dn <> toAsn1 as)
    +  toAsn1 (DeleteRequest (LdapDn (LdapString dn))) =
    +    other Asn1.Application 10 (Text.encodeUtf8 dn)
    +  toAsn1 (ModifyDnRequest dn rdn del new) =
    +    application 12 (fold
    +      [ toAsn1 dn
    +      , toAsn1 rdn
    +      , single (Asn1.Boolean del)
    +      , maybe mempty
    +              (\(LdapDn (LdapString dn')) -> other Asn1.Context 0 (Text.encodeUtf8 dn'))
    +              new
    +      ])
    +  toAsn1 (CompareRequest dn av) =
    +    application 14 (toAsn1 dn <> sequence (toAsn1 av))
    +  toAsn1 (ExtendedRequest (LdapOid oid) mv) =
    +    application 23 (fold
    +     [ other Asn1.Context 0 oid
    +     , maybe mempty (other Asn1.Context 1) mv
    +     ])
    +
    +{- |
    +@
    +AuthenticationChoice ::= CHOICE {
    +     simple                  [0] OCTET STRING,
    +     ...  }
    +@
    +-}
    +instance ToAsn1 AuthenticationChoice where
    +  toAsn1 (Simple s) = other Asn1.Context 0 s
    +
    +{- |
    +@
    +AttributeSelection ::= SEQUENCE OF selector LDAPString
    +@
    +-}
    +instance ToAsn1 AttributeSelection where
    +  toAsn1 (AttributeSelection as) = sequence (toAsn1 as)
    +
    +{- |
    +@
    +Filter ::= CHOICE {
    +     and             [0] SET SIZE (1..MAX) OF filter Filter,
    +     or              [1] SET SIZE (1..MAX) OF filter Filter,
    +     not             [2] Filter,
    +     equalityMatch   [3] AttributeValueAssertion,
    +     substrings      [4] SubstringFilter,
    +     greaterOrEqual  [5] AttributeValueAssertion,
    +     lessOrEqual     [6] AttributeValueAssertion,
    +     present         [7] AttributeDescription,
    +     approxMatch     [8] AttributeValueAssertion,
    +     extensibleMatch [9] MatchingRuleAssertion,
    +     ...  }
    +@
    +-}
    +instance ToAsn1 Filter where
    +  toAsn1 f = case f of
    +    And xs            -> context 0 (toAsn1 xs)
    +    Or xs             -> context 1 (toAsn1 xs)
    +    Not x             -> context 2 (toAsn1 x)
    +    EqualityMatch x   -> context 3 (toAsn1 x)
    +    Substrings x      -> context 4 (toAsn1 x)
    +    GreaterOrEqual x  -> context 5 (toAsn1 x)
    +    LessOrEqual x     -> context 6 (toAsn1 x)
    +    Present (AttributeDescription (LdapString x))
    +                      -> other Asn1.Context 7 (Text.encodeUtf8 x)
    +    ApproxMatch x     -> context 8 (toAsn1 x)
    +    ExtensibleMatch x -> context 9 (toAsn1 x)
    +
    +{- |
    +@
    +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
    +     }
    +@
    +-}
    +instance ToAsn1 SubstringFilter where
    +  toAsn1 (SubstringFilter ad ss) =
    +    toAsn1 ad <> sequence (foldMap (\s -> case s of
    +      Initial (AssertionValue v) -> other Asn1.Context 0 v
    +      Any (AssertionValue v)     -> other Asn1.Context 1 v
    +      Final (AssertionValue v)   -> other Asn1.Context 2 v) ss)
    +
    +{- |
    +@
    +MatchingRuleAssertion ::= SEQUENCE {
    +     matchingRule    [1] MatchingRuleId OPTIONAL,
    +     type            [2] AttributeDescription OPTIONAL,
    +     matchValue      [3] AssertionValue,
    +     dnAttributes    [4] BOOLEAN DEFAULT FALSE }
    +@
    +-}
    +instance ToAsn1 MatchingRuleAssertion where
    +  toAsn1 (MatchingRuleAssertion mmr mad av b) = sequence (fold
    +    [ context 1 (optional mmr)
    +    , context 2 (optional mad)
    +    , context 3 (toAsn1 av)
    +    , context 4 (single (Asn1.Boolean b))
    +    ])
    +
    +{- |
    +@
    +AttributeList ::= SEQUENCE OF attribute Attribute
    +@
    +-}
    +instance ToAsn1 AttributeList where
    +  toAsn1 (AttributeList xs) = sequence (toAsn1 xs)
    +
    +instance ToAsn1 a => ToAsn1 [a] where
    +  toAsn1 = foldMap toAsn1
    +
    +instance ToAsn1 a => ToAsn1 (NonEmpty a) where
    +  toAsn1 = foldMap toAsn1
    +
    +sequence :: Endo [ASN1] -> Endo [ASN1]
    +sequence = construction Asn1.Sequence
    +
    +set :: Endo [ASN1] -> Endo [ASN1]
    +set = construction Asn1.Set
    +
    +application :: ASN1Tag -> Endo [ASN1] -> Endo [ASN1]
    +application = construction . Asn1.Container Asn1.Application
    +
    +context :: ASN1Tag -> Endo [ASN1] -> Endo [ASN1]
    +context = construction . Asn1.Container Asn1.Context
    +
    +construction :: ASN1ConstructionType -> Endo [ASN1] -> Endo [ASN1]
    +construction t x = single (Asn1.Start t) <> x <> single (Asn1.End t)
    +
    +other :: ASN1Class -> ASN1Tag -> ByteString -> Endo [ASN1]
    +other c t = single . Asn1.Other c t
    +
    +optional :: ToAsn1 a => Maybe a -> Endo [ASN1]
    +optional = maybe mempty toAsn1
    +
    +enum :: Integer -> Endo [ASN1]
    +enum = single . Asn1.Enumerated
    +
    +single :: a -> Endo [a]
    +single x = Endo (x :)
    +
    + diff --git a/src/Ldap-Asn1-Type.html b/src/Ldap-Asn1-Type.html new file mode 100644 index 0000000..26e7fb2 --- /dev/null +++ b/src/Ldap-Asn1-Type.html @@ -0,0 +1,202 @@ + + + + + +src/Ldap/Asn1/Type.hs + + + +
    module Ldap.Asn1.Type where
    +
    +import Data.ByteString (ByteString)
    +import Data.Int (Int8, Int32)
    +import Data.List.NonEmpty (NonEmpty)
    +import Data.Text (Text)
    +
    +
    +data LdapMessage op = LdapMessage
    +  { ldapMessageId       :: !Id
    +  , ldapMessageOp       :: !op
    +  , ldapMessageControls :: !(Maybe Controls)
    +  } deriving (Show, Eq, Ord)
    +
    +newtype Id = Id { unId :: Int32 }
    +    deriving (Show, Eq, Ord)
    +
    +data ProtocolClientOp =
    +    BindRequest Int8 LdapDn AuthenticationChoice
    +  | UnbindRequest
    +  | SearchRequest LdapDn Scope DerefAliases Int32 Int32 Bool Filter AttributeSelection
    +  | ModifyRequest LdapDn [(Operation, PartialAttribute)]
    +  | AddRequest LdapDn AttributeList
    +  | DeleteRequest LdapDn
    +  | ModifyDnRequest LdapDn RelativeLdapDn Bool (Maybe LdapDn)
    +  | CompareRequest LdapDn AttributeValueAssertion
    +  | ExtendedRequest LdapOid (Maybe ByteString)
    +    deriving (Show, Eq, Ord)
    +
    +data ProtocolServerOp =
    +    BindResponse LdapResult (Maybe ByteString)
    +  | SearchResultEntry LdapDn PartialAttributeList
    +  | SearchResultReference (NonEmpty Uri)
    +  | SearchResultDone (LdapResult)
    +  | ModifyResponse LdapResult
    +  | AddResponse LdapResult
    +  | DeleteResponse LdapResult
    +  | ModifyDnResponse LdapResult
    +  | CompareResponse LdapResult
    +  | ExtendedResponse LdapResult (Maybe LdapOid) (Maybe ByteString)
    +    deriving (Show, Eq, Ord)
    +
    +data AuthenticationChoice = Simple ByteString
    +    deriving (Show, Eq, Ord)
    +
    +data Scope =
    +    BaseObject
    +  | SingleLevel
    +  | WholeSubtree
    +    deriving (Show, Eq, Ord)
    +
    +data DerefAliases =
    +    NeverDerefAliases
    +  | DerefInSearching
    +  | DerefFindingBaseObject
    +  | DerefAlways
    +    deriving (Show, Eq, Ord)
    +
    +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, Ord)
    +
    +data SubstringFilter = SubstringFilter AttributeDescription (NonEmpty Substring)
    +    deriving (Show, Eq, Ord)
    +
    +data Substring =
    +    Initial AssertionValue
    +  | Any AssertionValue
    +  | Final AssertionValue
    +    deriving (Show, Eq, Ord)
    +
    +data MatchingRuleAssertion = MatchingRuleAssertion (Maybe MatchingRuleId) (Maybe AttributeDescription) AssertionValue Bool
    +    deriving (Show, Eq, Ord)
    +
    +newtype MatchingRuleId = MatchingRuleId LdapString
    +    deriving (Show, Eq, Ord)
    +
    +newtype AttributeSelection = AttributeSelection [LdapString]
    +    deriving (Show, Eq, Ord)
    +
    +newtype AttributeList = AttributeList [Attribute]
    +    deriving (Show, Eq, Ord)
    +
    +newtype PartialAttributeList = PartialAttributeList [PartialAttribute]
    +    deriving (Show, Eq, Ord)
    +
    +newtype Controls = Controls [Control]
    +    deriving (Show, Eq, Ord)
    +
    +data Control = Control LdapOid Bool (Maybe ByteString)
    +    deriving (Show, Eq, Ord)
    +
    +data LdapResult = LdapResult ResultCode LdapDn LdapString (Maybe ReferralUris)
    +    deriving (Show, Eq, Ord)
    +
    +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, Ord)
    +
    +newtype AttributeDescription = AttributeDescription LdapString
    +    deriving (Show, Eq, Ord)
    +
    +newtype AttributeValue = AttributeValue ByteString
    +    deriving (Show, Eq, Ord)
    +
    +data AttributeValueAssertion = AttributeValueAssertion AttributeDescription AssertionValue
    +    deriving (Show, Eq, Ord)
    +
    +newtype AssertionValue = AssertionValue ByteString
    +    deriving (Show, Eq, Ord)
    +
    +data Attribute = Attribute AttributeDescription (NonEmpty AttributeValue)
    +    deriving (Show, Eq, Ord)
    +
    +data PartialAttribute = PartialAttribute AttributeDescription [AttributeValue]
    +    deriving (Show, Eq, Ord)
    +
    +newtype LdapDn = LdapDn LdapString
    +    deriving (Show, Eq, Ord)
    +
    +newtype RelativeLdapDn = RelativeLdapDn LdapString
    +    deriving (Show, Eq, Ord)
    +
    +newtype ReferralUris = ReferralUris (NonEmpty Uri)
    +    deriving (Show, Eq, Ord)
    +
    +newtype Uri = Uri LdapString
    +    deriving (Show, Eq, Ord)
    +
    +data Operation =
    +    Add
    +  | Delete
    +  | Replace
    +    deriving (Show, Eq, Ord)
    +
    +-- | 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.
    +newtype LdapString = LdapString Text
    +    deriving (Show, Eq, Ord)
    +
    +newtype LdapOid = LdapOid ByteString
    +    deriving (Show, Eq, Ord)
    +
    + diff --git a/src/Ldap-Client-Add.html b/src/Ldap-Client-Add.html new file mode 100644 index 0000000..4337346 --- /dev/null +++ b/src/Ldap-Client-Add.html @@ -0,0 +1,55 @@ + + + + + +src/Ldap/Client/Add.hs + + + +
    module Ldap.Client.Add
    +  ( add
    +  , addEither
    +  , addAsync
    +  , addAsyncSTM
    +  ) where
    +
    +import           Control.Monad.STM (STM, atomically)
    +import           Data.List.NonEmpty (NonEmpty((:|)))
    +
    +import qualified Ldap.Asn1.Type as Type
    +import           Ldap.Client.Internal
    +
    +
    +add :: Ldap -> Dn -> AttrList NonEmpty -> IO ()
    +add l dn as =
    +  raise =<< addEither l dn as
    +
    +addEither :: Ldap -> Dn -> AttrList NonEmpty -> IO (Either ResponseError ())
    +addEither l dn as =
    +  wait =<< addAsync l dn as
    +
    +addAsync :: Ldap -> Dn -> AttrList NonEmpty -> IO (Async ())
    +addAsync l dn as =
    +  atomically (addAsyncSTM l dn as)
    +
    +addAsyncSTM :: Ldap -> Dn -> AttrList NonEmpty -> STM (Async ())
    +addAsyncSTM l dn as =
    +  let req = addRequest dn as in sendRequest l (addResult req) req
    +
    +addRequest :: Dn -> AttrList NonEmpty -> Request
    +addRequest (Dn dn) as =
    +  Type.AddRequest (Type.LdapDn (Type.LdapString dn))
    +                  (Type.AttributeList (map f as))
    + where
    +  f (Attr x, xs) = Type.Attribute (Type.AttributeDescription (Type.LdapString x))
    +                                  (fmap Type.AttributeValue xs)
    +
    +addResult :: Request -> Response -> Either ResponseError ()
    +addResult req (Type.AddResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn))
    +                                                      (Type.LdapString msg) _) :| [])
    +  | Type.Success <- code = Right ()
    +  | otherwise = Left (ResponseErrorCode req code (Dn dn) msg)
    +addResult req res = Left (ResponseInvalid req res)
    +
    + diff --git a/src/Ldap-Client-Bind.html b/src/Ldap-Client-Bind.html new file mode 100644 index 0000000..af963cd --- /dev/null +++ b/src/Ldap-Client-Bind.html @@ -0,0 +1,77 @@ + + + + + +src/Ldap/Client/Bind.hs + + + +
    module Ldap.Client.Bind
    +  ( bind
    +  , bindEither
    +  , bindAsync
    +  , bindAsyncSTM
    +  , unbindAsync
    +  , unbindAsyncSTM
    +  ) where
    +
    +import           Control.Monad (void)
    +import           Control.Monad.STM (STM, atomically)
    +import           Data.List.NonEmpty (NonEmpty((:|)))
    +
    +import qualified Ldap.Asn1.Type as Type
    +import           Ldap.Client.Internal
    +
    +
    +bind :: Ldap -> Dn -> Password -> IO ()
    +bind l username password =
    +  raise =<< bindEither l username password
    +
    +bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ())
    +bindEither l username password =
    +  wait =<< bindAsync l username password
    +
    +bindAsync :: Ldap -> Dn -> Password -> IO (Async ())
    +bindAsync l username password =
    +  atomically (bindAsyncSTM l username password)
    +
    +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)
    +
    +
    +-- | 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',
    +-- 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-Compare.html b/src/Ldap-Client-Compare.html new file mode 100644 index 0000000..a883caf --- /dev/null +++ b/src/Ldap-Client-Compare.html @@ -0,0 +1,57 @@ + + + + + +src/Ldap/Client/Compare.hs + + + +
    module Ldap.Client.Compare
    +  ( compare
    +  , compareEither
    +  , compareAsync
    +  , compareAsyncSTM
    +  ) where
    +
    +import           Control.Monad.STM (STM, atomically)
    +import           Data.ByteString (ByteString)
    +import           Data.List.NonEmpty (NonEmpty((:|)))
    +import           Prelude hiding (compare)
    +
    +import           Ldap.Client.Internal
    +import qualified Ldap.Asn1.Type as Type
    +
    +
    +compare :: Ldap -> Dn -> Attr -> ByteString -> IO Bool
    +compare l dn k v =
    +  raise =<< compareEither l dn k v
    +
    +compareEither :: Ldap -> Dn -> Attr -> ByteString -> IO (Either ResponseError Bool)
    +compareEither l dn k v =
    +  wait =<< compareAsync l dn k v
    +
    +compareAsync :: Ldap -> Dn -> Attr -> ByteString -> IO (Async Bool)
    +compareAsync l dn k v =
    +  atomically (compareAsyncSTM l dn k v)
    +
    +compareAsyncSTM :: Ldap -> Dn -> Attr -> ByteString -> STM (Async Bool)
    +compareAsyncSTM l dn k v =
    +  let req = compareRequest dn k v in sendRequest l (compareResult req) req
    +
    +compareRequest :: Dn -> Attr -> ByteString -> Request
    +compareRequest (Dn dn) (Attr k) v =
    +  Type.CompareRequest (Type.LdapDn (Type.LdapString dn))
    +                      (Type.AttributeValueAssertion
    +                        (Type.AttributeDescription (Type.LdapString k))
    +                        (Type.AssertionValue v))
    +
    +compareResult :: Request -> Response -> Either ResponseError Bool
    +compareResult req (Type.CompareResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn))
    +                                                              (Type.LdapString msg) _) :| [])
    +  | Type.CompareTrue  <- code = Right True
    +  | Type.CompareFalse <- code = Right False
    +  | otherwise = Left (ResponseErrorCode req code (Dn dn) msg)
    +compareResult req res = Left (ResponseInvalid req res)
    +
    + diff --git a/src/Ldap-Client-Delete.html b/src/Ldap-Client-Delete.html new file mode 100644 index 0000000..c10197e --- /dev/null +++ b/src/Ldap-Client-Delete.html @@ -0,0 +1,51 @@ + + + + + +src/Ldap/Client/Delete.hs + + + +
    module Ldap.Client.Delete
    +  ( delete
    +  , deleteEither
    +  , deleteAsync
    +  , deleteAsyncSTM
    +  ) where
    +
    +import           Control.Concurrent.STM (STM, atomically)
    +import           Data.List.NonEmpty (NonEmpty((:|)))
    +
    +import qualified Ldap.Asn1.Type as Type
    +import           Ldap.Client.Internal
    +
    +
    +delete :: Ldap -> Dn -> IO ()
    +delete l dn =
    +  raise =<< deleteEither l dn
    +
    +deleteEither :: Ldap -> Dn -> IO (Either ResponseError ())
    +deleteEither l dn =
    +  wait =<< deleteAsync l dn
    +
    +deleteAsync :: Ldap -> Dn -> IO (Async ())
    +deleteAsync l dn =
    +  atomically (deleteAsyncSTM l dn)
    +
    +deleteAsyncSTM :: Ldap -> Dn -> STM (Async ())
    +deleteAsyncSTM l dn =
    +  let req = deleteRequest dn in sendRequest l (deleteResult req) req
    +
    +deleteRequest :: Dn -> Request
    +deleteRequest (Dn dn) =
    +  Type.DeleteRequest (Type.LdapDn (Type.LdapString dn))
    +
    +deleteResult :: Request -> Response -> Either ResponseError ()
    +deleteResult req (Type.DeleteResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn))
    +                                                            (Type.LdapString msg) _) :| [])
    +  | Type.Success <- code = Right ()
    +  | otherwise = Left (ResponseErrorCode req code (Dn dn) msg)
    +deleteResult req res = Left (ResponseInvalid req res)
    +
    + diff --git a/src/Ldap-Client-Extended.html b/src/Ldap-Client-Extended.html new file mode 100644 index 0000000..ca12d31 --- /dev/null +++ b/src/Ldap-Client-Extended.html @@ -0,0 +1,75 @@ + + + + + +src/Ldap/Client/Extended.hs + + + +
    {-# LANGUAGE OverloadedStrings #-}
    +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
    +
    +
    +extended :: Ldap -> Oid -> Maybe ByteString -> IO ()
    +extended l oid mv =
    +  raise =<< extendedEither l oid mv
    +
    +extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ())
    +extendedEither l oid mv =
    +  wait =<< extendedAsync l oid mv
    +
    +extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ())
    +extendedAsync l oid mv =
    +  atomically (extendedAsyncSTM l oid mv)
    +
    +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)
    +
    +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)
    +
    +
    +startTls :: Ldap -> IO ()
    +startTls =
    +  raise <=< startTlsEither
    +
    +startTlsEither :: Ldap -> IO (Either ResponseError ())
    +startTlsEither =
    +  wait <=< startTlsAsync
    +
    +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
    +
    + diff --git a/src/Ldap-Client-Internal.html b/src/Ldap-Client-Internal.html new file mode 100644 index 0000000..733dde5 --- /dev/null +++ b/src/Ldap-Client-Internal.html @@ -0,0 +1,123 @@ + + + + + +src/Ldap/Client/Internal.hs + + + +
    {-# LANGUAGE DeriveDataTypeable #-}
    +{-# LANGUAGE NamedFieldPuns #-}
    +module Ldap.Client.Internal
    +  ( Host(..)
    +  , PortNumber
    +  , Ldap(..)
    +  , ClientMessage(..)
    +  , Type.ResultCode(..)
    +  , Async
    +  , Oid(..)
    +  , AttrList
    +    -- * Waiting for Request Completion
    +  , wait
    +  , waitSTM
    +    -- * Misc
    +  , Response
    +  , ResponseError(..)
    +  , Request
    +  , raise
    +  , sendRequest
    +  , Dn(..)
    +  , RelativeDn(..)
    +  , Password(..)
    +  , Attr(..)
    +  , 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           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
    +
    +
    +data Host =
    +    Plain String
    +  | Secure String
    +  | Insecure String
    +    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
    +    deriving (Show, Eq)
    +
    +newtype Oid = Oid ByteString
    +    deriving (Show, Eq)
    +
    +newtype Password = Password ByteString
    +    deriving (Show, Eq)
    +
    +
    +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 AttrList f = [(Attr, f ByteString)]
    +
    +-- '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)
    +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)))
    +
    +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
    +
    + diff --git a/src/Ldap-Client-Modify.html b/src/Ldap-Client-Modify.html new file mode 100644 index 0000000..9c4e286 --- /dev/null +++ b/src/Ldap-Client-Modify.html @@ -0,0 +1,102 @@ + + + + + +src/Ldap/Client/Modify.hs + + + +
    module Ldap.Client.Modify
    +  ( Operation(..)
    +  , modify
    +  , modifyEither
    +  , modifyAsync
    +  , modifyAsyncSTM
    +  , modifyDn
    +  , modifyDnEither
    +  , modifyDnAsync
    +  , modifyDnAsyncSTM
    +  ) 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
    +
    +
    +data Operation =
    +    Delete Attr [ByteString]
    +  | Add Attr [ByteString]
    +  | Replace Attr [ByteString]
    +    deriving (Show, Eq)
    +
    +modify :: Ldap -> Dn -> [Operation] -> IO ()
    +modify l dn as =
    +  raise =<< modifyEither l dn as
    +
    +modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ())
    +modifyEither l dn as =
    +  wait =<< modifyAsync l dn as
    +
    +modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ())
    +modifyAsync l dn as =
    +  atomically (modifyAsyncSTM l dn as)
    +
    +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)
    +
    +
    +modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO ()
    +modifyDn l dn rdn del new =
    +  raise =<< modifyDnEither l dn rdn del new
    +
    +modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ())
    +modifyDnEither l dn rdn del new =
    +  wait =<< modifyDnAsync l dn rdn del new
    +
    +modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ())
    +modifyDnAsync l dn rdn del new =
    +  atomically (modifyDnAsyncSTM l dn rdn del new)
    +
    +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 new file mode 100644 index 0000000..adced5e --- /dev/null +++ b/src/Ldap-Client-Search.html @@ -0,0 +1,189 @@ + + + + + +src/Ldap/Client/Search.hs + + + +
    {-# LANGUAGE CPP #-}
    +{-# LANGUAGE NamedFieldPuns #-}
    +module Ldap.Client.Search
    +  ( search
    +  , searchEither
    +  , searchAsync
    +  , searchAsyncSTM
    +  , Search
    +  , Mod
    +  , Type.Scope(..)
    +  , scope
    +  , size
    +  , time
    +  , typesOnly
    +  , derefAliases
    +  , Filter(..)
    +  , SearchEntry(..)
    +  ) where
    +
    +import           Control.Monad.STM (STM, atomically)
    +import           Data.ByteString (ByteString)
    +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
    +
    +
    +search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry]
    +search l base opts flt attributes =
    +  raise =<< searchEither l base opts flt attributes
    +
    +searchEither
    +  :: Ldap
    +  -> Dn
    +  -> Mod Search
    +  -> Filter
    +  -> [Attr]
    +  -> IO (Either ResponseError [SearchEntry])
    +searchEither l base opts flt attributes =
    +  wait =<< searchAsync l base opts flt attributes
    +
    +searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry])
    +searchAsync l base opts flt attributes =
    +  atomically (searchAsyncSTM l base opts flt attributes)
    +
    +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 })
    +
    +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 := ByteString
    +  | Attr :>= ByteString
    +  | Attr :<= ByteString
    +  | Attr :~= ByteString
    +  | Attr :=* (Maybe ByteString, [ByteString], Maybe ByteString)
    +  | (Maybe Attr, Maybe Attr, Bool) ::= ByteString
    +
    +data SearchEntry = SearchEntry Dn (AttrList [])
    +    deriving (Show, Eq)
    +
    + diff --git a/src/Ldap-Client.html b/src/Ldap-Client.html new file mode 100644 index 0000000..af6edfb --- /dev/null +++ b/src/Ldap-Client.html @@ -0,0 +1,216 @@ + + + + + +src/Ldap/Client.hs + + + +
    {-# LANGUAGE CPP #-}
    +{-# LANGUAGE BangPatterns #-}
    +{-# 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(..)
    +    -- * 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)
    +import           Control.Concurrent.STM.TMVar (putTMVar)
    +import           Control.Concurrent.STM.TQueue (TQueue, newTQueueIO, writeTQueue, readTQueue)
    +import           Control.Exception (Handler(..), bracket, throwIO, 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 (traverse_, asum)
    +import           Data.Function (fix)
    +import           Data.List.NonEmpty (NonEmpty((:|)))
    +import qualified Data.Map.Strict as Map
    +import           Data.Monoid (Endo(appEndo))
    +import           Network.Connection (Connection)
    +import qualified Network.Connection as Conn
    +import qualified System.IO.Error as IO
    +import           Prelude hiding (compare)
    +
    +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, unbindAsync)
    +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)
    +
    +
    +newLdap :: IO Ldap
    +newLdap = Ldap
    +  <$> newTQueueIO
    +
    +data LdapError =
    +    IOError IOError
    +  | ParseError Asn1.ASN1Error
    +  | ResponseError ResponseError
    +    deriving (Show, Eq)
    +
    +-- | 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 (return . Left . IOError)
    +  , 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 = 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 = 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, Map.empty, 1) $ \loop (!got, !results, !counter) ->
    +    loop =<< atomically (asum
    +      [ do New new var <- readTQueue client
    +           writeTQueue outq (Type.LdapMessage (Type.Id counter) new Nothing)
    +           return (got, Map.insert (Type.Id counter) var results, counter + 1)
    +      , do Type.LdapMessage mid op _ <- readTQueue inq
    +           case op of
    +             Type.SearchResultEntry {} ->
    +               return (Map.insertWith (++) mid [op] got, results, counter)
    +             Type.SearchResultReference {} ->
    +               return (got, results, counter)
    +             Type.SearchResultDone {} -> do
    +               let stack = Map.findWithDefault [] mid got
    +               traverse_ (\var -> putTMVar var (op :| stack)) (Map.lookup mid results)
    +               return (Map.delete mid got, Map.delete mid results, counter)
    +             _ -> do
    +               traverse_ (\var -> putTMVar var (op :| [])) (Map.lookup mid results)
    +               return (Map.delete mid got, Map.delete mid results, counter)
    +      ])
    +
    + diff --git a/src/hscolour.css b/src/hscolour.css new file mode 100644 index 0000000..c15919e --- /dev/null +++ b/src/hscolour.css @@ -0,0 +1,5 @@ +.hs-keyglyph, .hs-layout {color: red;} +.hs-keyword {color: blue;} +.hs-comment, .hs-comment a {color: green;} +.hs-str, .hs-chr {color: teal;} +.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/synopsis.png b/synopsis.png new file mode 100644 index 0000000..85fb86e Binary files /dev/null and b/synopsis.png differ