[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-smalltalk] Re: Calling LDAP C API from Smalltalk

From: Stephen
Subject: Re: [Help-smalltalk] Re: Calling LDAP C API from Smalltalk
Date: Sat, 27 Sep 2008 21:53:31 +1200
User-agent: Thunderbird (Macintosh/20080914)


Thanks Paolo. Lots of progress, I have a query mostly running now! Here is the issue...

I've run the script over a number of LDAP entries and it is consistently tripping up at the mail attribute. It isn't as though the mail attribute is always in the nth index of an entry either; at whatever index the mail attribute occurs in the attribute list, the script will crash at that point.

Here is the output of the script attached below:-

... about to run the search.
... search completed
Found results with base DN: ou=Users,dc=example,dc=com
Found first attribute
'givenName'->'Test --'
'displayName'->'Testing email'
Object: nil error: did not understand #value
MessageNotUnderstood(Exception)>>signal (
UndefinedObject(Object)>>doesNotUnderstand: #value (
UndefinedObject>>executeStatements (

For comparison, here is the output from an ldapsearch query on the same record:-

# sw-apple, Users,
dn: uid=sw-apple,ou=Users,dc=example,dc=com
givenName: Test --
sn: email
loginShell: /bin/bash
uidNumber: 2008
gidNumber: 2008
displayName: Testing email
mail: address@hidden
objectClass: top
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: inetmailrecipient
uid: sw-apple
cn: test email
homeDirectory: /home/sw-apple
maildrop: address@hidden
mailacceptinggeneralid: address@hidden

And here is the script below. Some notes first:-
- I have some LDAP entries with _no_ mail attribute and these query just fine with the script. - I haven't used any "free" methods yet. As I see it, by omitting the "free" methods, the script will not release memory from C objects. This doesn't matter in initial testing (or does it?). - You talked about adding an isNull method to Object. I tried inserting the code you gave as you can see at the top of the script. I've obviously done something wrong as it wouldn't compile so I commented it out. This has meant I've had to omit a line "vals isNull ifTrue: [". I'd like to get this working as a null in vals would trigger a crash like what I'm seeing I think (although as you can see the mail attribute does have a value).

Do you know what would be causing the crash or have suggestions for something I can test?

Thank you


stephenw$ cat
#!/usr/local/bin/gst -f
"call LDAP API"

"  CObject extend [ "
        "Will be in 3.1"
"  isNull [ ^address = 0 ]
  ] "

  CObject subclass: BER [
        " -----------------------
        LBER_F( void )
        ber_free LDAP_P((
                BerElement *ber,
                int freebuf ));
        ------------------------- "
      BER class >> free [
        <cCall: 'ber_free' returning: #void args: #(#self #int)>

  CObject subclass: LDAPMessage [
      LDAPMessage class >> free [
        <cCall: 'ldap_msgfree' returning: #int args: #(#self)>

  CObject subclass: LDAP [
      "class variables"
      scopeBase := 0.
      nolimit := 0.

      LDAP class >> openOn: host port: port [
          "Maybe you prefer #open:port: as the selector, of course."
          <cCall: 'ldap_open' returning: #{LDAP} args: #(#string #int)>

      LDAP class >> on: host port: port [
          "Maybe you prefer #init:port: as the selector, of course."
          <cCall: 'ldap_init' returning: #{LDAP} args: #(#string #int)>

      LDAP class >> errorString: resultNum [
          "Utility methods might also go on the class side."
          <cCall: 'ldap_err2string' returning: #string args: #(#int)>

      simpleBindWithDN: who passwd: secret [
<cCall: 'ldap_simple_bind_s' returning: #int args: #(#self #string #string)>

        " ldap_search_ext_s C definition --------------
        LDAP_F( int )
      ldap_search_ext_s LDAP_P((
        LDAP                    *ld,
        LDAP_CONST char *base,
        int                             scope,
        LDAP_CONST char *filter,
        char                    **attrs,
        int                             attrsonly,
        LDAPControl             **serverctrls,
        LDAPControl             **clientctrls,
        struct timeval  *timeout,
        int                             sizelimit,
        LDAPMessage             **res ));
        rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
    ""(objectclass=*)"", NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
    LDAP_NO_LIMIT, &result
                                        --------------- "
"TODO: write a wrapper method which has less parameters and calls this one"
        searchWithBase: baseDN
          scope: aScope
          filter: aFilter
          attributes: theAttribs
          isAttrsOnly: attrsOnly
          serverctrls: serverControl
          clientctrls: clientControl
          timeout: timeval
          sizelimit: numResults
          searchResult: aSearchResult [
<cCall: 'ldap_search_ext_s' returning: #int args: #(#self #string #int #string #cObject #int #cObject #cObject #cObject #int #cObjectPtr)>

        " ldap_first_entry C definition    --------------
        LDAP_F( LDAPMessage * )
        ldap_first_entry LDAP_P((
                LDAP *ld,
                LDAPMessage *chain ));
        firstEntry: searchResult [
<cCall: 'ldap_first_entry' returning: #{LDAPMessage} args: #(#self #cObject)> ]

        "                  -------------
        LDAP_F( char * )
        ldap_first_attribute LDAP_P((
                LDAP *ld,
                LDAPMessage *entry,
                BerElement **ber ));
        firstAttribute: anEntry ber: aBer [
<cCall: 'ldap_first_attribute' returning: #cObject args: #(#self #cObject #cObjectPtr)> ]

        "                  -------------
        LDAP_F( char * )
        ldap_next_attribute LDAP_P((
                LDAP *ld,
                LDAPMessage *entry,
                BerElement *ber ));
        nextAttribute: anEntry ber: aBer [
<cCall: 'ldap_next_attribute' returning: #cObject args: #(#self #cObject #cObject)> ]

        "                  -------------
        LDAP_F( char ** )
        ldap_get_values LDAP_P((        /* deprecated, use ldap_get_values_len 
                LDAP *ld,
                LDAPMessage *entry,
                LDAP_CONST char *target ));
        getValues: anEntry attribute: anAttribute [
<cCall: 'ldap_get_values' returning: #{CString} args: #(#self #cObject #cObject)> ]


| ldapcall ldap resultCode resultCode2 errorMsg hostName baseDN |
Transcript showCr: 'started'.
DLD addLibrary: 'libldap'.
hostName := 'aserver'.
baseDN := 'ou=Users,dc=example,dc=com'.
superviserDN := 'uid=sw,ou=Users,dc=example,dc=com'.
password := 'apwd'.

ldap := LDAP openOn: hostName port: 389.
ldap isNil ifTrue: [ File checkError. ObjectMemory quit: 1 ].
resultCode := ldap simpleBindWithDN: superviserDN passwd: password.
(resultCode > 0) ifTrue: [
        "Transcript showCr: ('%1 is result from bind' % { resultCode })."
        errorCodeMsg := LDAP errorString: resultCode.
Transcript showCr: 'The LDAP Bind failed with the message: ',errorCodeMsg ].

(resultCode = 0) ifTrue: [
        Transcript showCr: '... about to run the search.'.
        resultCode := ldap searchWithBase: superviserDN
          scope: 16r0000
          filter: '(objectclass=*)'
          attributes: nil
          isAttrsOnly: 0
          serverctrls: nil
          clientctrls: nil
          timeout: nil
          sizelimit: 0
          searchResult: (searchResult := LDAPMessage new).
        Transcript showCr: '... search completed'.      

        (resultCode > 0) ifTrue: [
                "Transcript showCr: ('%1 is result from bind' % { resultCode 
                errorCodeMsg := LDAP errorString: resultCode.
Transcript showCr: 'The LDAP search failed with the message: ',errorCodeMsg ].

        entry := ldap firstEntry: searchResult.
        entry isNil ifFalse: [
                ('Found results with base DN: ', baseDN) displayNl.
                aPtr := ldap firstAttribute: entry ber: (ber := BER new).
                ('Found first attribute') displayNl.
                [ aPtr isNil ] whileFalse: [
                        attr := String fromCData: aPtr.
                        "aPtr free."

                        vals := ldap getValues: entry attribute: attr.
                        val := vals.
                        "vals isNull ifTrue: [   ... omitted since isNull method 
won't compile"
                        attr printNl.
                        [ val value isNil ] whileFalse: [
                                (attr->val value) printNl.
                                val incr ].
                        "vals free. "
                        aPtr := ldap nextAttribute: entry ber: ber.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]