LDAP/LDIF Parsing

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Cruelemort

    #1

    LDAP/LDIF Parsing

    All,

    I am hoping someone would be able to help me with a problem. I have an
    LDAP server running on a linux box, this LDAP server contains a
    telephone list in various groupings, the ldif file of which is -

    dn: dc=example,dc=c om
    objectClass: top
    objectClass: dcObject
    objectClass: organization
    dc: example
    o: Example Organisation

    dn: ou=groupa,dc=ex ample,dc=com
    ou: groupa
    objectClass: top
    objectClass: organizationalU nit
    description: Group A

    dn: cn=johnsmith,ou =groupa,dc=exam ple,dc=com
    cn: johnsmith
    objectClass: top
    objectClass: person
    sn: Smith
    telephoneNumber : 112

    dn: cn=davesteel,ou =groupa,dc=exam ple,dc=com
    cn: davesteel
    objectClass: top
    objectClass: person
    sn: Steel
    telephoneNumber : 113

    dn: ou=groupb,dc=ex ample,dc=com
    ou: groupb
    objectClass: top
    objectClass: organizationalU nit
    description: Group B

    dn: cn=williamdavis ,ou=groupb,dc=e xample,dc=com
    cn: williamdavis
    objectClass: top
    objectClass: person
    sn: Davis
    telephoneNumber : 122

    dn: cn=jamesjarvis, ou=groupb,dc=ex ample,dc=com
    cn: jamesjarvis
    objectClass: top
    objectClass: person
    sn: Jarvis
    telephoneNumber : 123

    I am creating a python client program that will display the telephone
    list in the same directory structure as is on the LDAP server (i.e. it
    starts with buttons of all the groups, when you click on a group it
    comes up with buttons of all the numbers or groups available, and you
    can continually drill down).

    I was wondering the best way to do this? I have installed and used the
    python-ldap libraries and these allow me to access and search the
    server, but the searches always return a horrible nesting of lists,
    tuples and dictionaries, below is an example of returning just one
    record -

    ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
    'organization'], 'dc': ['example'], 'o': ['Example Organisation']})

    Basically i think i need to parse the search results to create objects
    and build the python buttons around this, but i was hoping someone
    would be able to point me in the correct direction of how to do this?
    Is there a parser available? (there is an ldif library available but
    it is not obvious how this works, i cannot see much documentation, and
    it seems to be deprecated...).

    Many thanks.

    Ian

  • Diez B. Roggisch

    #2
    Re: LDAP/LDIF Parsing

    >
    I was wondering the best way to do this? I have installed and used the
    python-ldap libraries and these allow me to access and search the
    server, but the searches always return a horrible nesting of lists,
    tuples and dictionaries, below is an example of returning just one
    record -
    >
    ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
    'organization'], 'dc': ['example'], 'o': ['Example Organisation']})

    But this is exactly what your LDAP-record contains. What else should there
    be? And no, you don't need a parser, as the above _is_ the parsed result.
    No parser can possibly give you anything else.

    You can of course create wrapper-objects, that you instantiate based on the
    values in 'objectClass', and that allow convenient access to certain
    properties. Yet this is entirely up to you, as there is no one else who can
    forsee how things should look and work like in _your_ application.

    Diez

    Comment

    • Bruno Desthuilliers

      #3
      Re: LDAP/LDIF Parsing

      Cruelemort a écrit :
      All,
      >
      I am hoping someone would be able to help me with a problem. I have an
      LDAP server running on a linux box, this LDAP server contains a
      telephone list in various groupings, the ldif file of which is -
      >
      (snip)
      >
      I am creating a python client program that will display the telephone
      list in the same directory structure as is on the LDAP server (i.e. it
      starts with buttons of all the groups, when you click on a group it
      comes up with buttons of all the numbers or groups available, and you
      can continually drill down).
      >
      I was wondering the best way to do this? I have installed and used the
      python-ldap libraries and these allow me to access and search the
      server, but the searches always return a horrible nesting of lists,
      tuples and dictionaries, below is an example of returning just one
      record -
      >
      ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
      'organization'], 'dc': ['example'], 'o': ['Example Organisation']})
      What's your problem ? That's exactly what your ldap record should look
      like. A (base_dn, record) tuple, where the record is a dict of
      attribute_name:[values, ...]
      Basically i think i need to parse the search results to create objects
      Q&D wrapper:

      class LdapObject(obje ct):
      def __init__(self, ldapentry):
      self.dn, self._record = ldapentry

      def __getattr__(sel f, name):
      try:
      data = self._record[name]
      except KeyError:
      raise AttributeError(
      "object %s has no attribute %s" % (self, name)
      )
      else:
      # all LDAP attribs are multivalued by default,
      # even when the schema says they are monovalued
      if len(data) == 1:
      return data[0]
      else:
      return data[:]

      def isa(self, objectClass):
      return objectClass in self.objectClas s:

      root = LdapObject(
      ('dc=example,dc =com',
      {'objectClass': ['top', 'dcObject','org anization'],
      'dc': ['example'],
      'o': ['Example Organisation']}
      ))

      root.o
      ='Example Organisation'
      root.objectClas s
      =['top', 'dcObject','org anization']
      root.isa('organ ization')
      =True

      FWIW, I once started writing an higher-level LDAP api (kind of an
      Object-LDAP Mapper...) using descriptors for ldap attribute access, but
      I never finished the damned thing, and it's in a very sorry state. I'll
      have to get back to it one day...
      and build the python buttons around this, but i was hoping someone
      would be able to point me in the correct direction of how to do this?
      Is there a parser available?
      cf above.

      Comment

      • aspineux

        #4
        Re: LDAP/LDIF Parsing


        The tree hierarchy is defined by the DN of each object, the types of
        the object is specified by its objectClass.
        Just collect all items (or do it dynamically by tunning the scope and
        the base of your search request)


        On 1 fév, 18:22, "Cruelemort " <ian.ing...@gma il.comwrote:
        All,
        >
        I am hoping someone would be able to help me with a problem. I have an
        LDAP server running on a linux box, this LDAP server contains a
        telephone list in various groupings, the ldif file of which is -
        >
        dn: dc=example,dc=c om
        objectClass: top
        objectClass: dcObject
        objectClass: organization
        dc: example
        o: Example Organisation
        >
        dn: ou=groupa,dc=ex ample,dc=com
        ou: groupa
        objectClass: top
        objectClass: organizationalU nit
        description: Group A
        >
        dn: cn=johnsmith,ou =groupa,dc=exam ple,dc=com
        cn: johnsmith
        objectClass: top
        objectClass: person
        sn: Smith
        telephoneNumber : 112
        >
        dn: cn=davesteel,ou =groupa,dc=exam ple,dc=com
        cn: davesteel
        objectClass: top
        objectClass: person
        sn: Steel
        telephoneNumber : 113
        >
        dn: ou=groupb,dc=ex ample,dc=com
        ou: groupb
        objectClass: top
        objectClass: organizationalU nit
        description: Group B
        >
        dn: cn=williamdavis ,ou=groupb,dc=e xample,dc=com
        cn: williamdavis
        objectClass: top
        objectClass: person
        sn: Davis
        telephoneNumber : 122
        >
        dn: cn=jamesjarvis, ou=groupb,dc=ex ample,dc=com
        cn: jamesjarvis
        objectClass: top
        objectClass: person
        sn: Jarvis
        telephoneNumber : 123
        >
        I am creating a python client program that will display the telephone
        list in the same directory structure as is on the LDAP server (i.e. it
        starts with buttons of all the groups, when you click on a group it
        comes up with buttons of all the numbers or groups available, and you
        can continually drill down).
        >
        I was wondering the best way to do this? I have installed and used the
        python-ldap libraries and these allow me to access and search the
        server, but the searches always return a horrible nesting of lists,
        tuples and dictionaries, below is an example of returning just one
        record -
        >
        ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
        'organization'], 'dc': ['example'], 'o': ['Example Organisation']})
        >
        Basically i think i need to parse the search results to create objects
        and build the python buttons around this, but i was hoping someone
        would be able to point me in the correct direction of how to do this?
        Is there a parser available? (there is an ldif library available but
        it is not obvious how this works, i cannot see much documentation, and
        it seems to be deprecated...).
        >
        Many thanks.
        >
        Ian

        Comment

        • Cruelemort

          #5
          Re: LDAP/LDIF Parsing

          On Feb 1, 11:08 pm, "aspineux" <aspin...@gmail .comwrote:
          The tree hierarchy is defined by the DN of each object, the types of
          the object is specified by its objectClass.
          Just collect all items (or do it dynamically by tunning the scope and
          the base of your search request)
          >
          On 1 fév, 18:22, "Cruelemort " <ian.ing...@gma il.comwrote:
          >
          >
          >
          All,
          >
          I am hoping someone would be able to help me with a problem. I have an
          LDAP server running on a linux box, this LDAP server contains a
          telephone list in various groupings, the ldif file of which is -
          >
          dn: dc=example,dc=c om
          objectClass: top
          objectClass: dcObject
          objectClass: organization
          dc: example
          o: Example Organisation
          >
          dn: ou=groupa,dc=ex ample,dc=com
          ou: groupa
          objectClass: top
          objectClass: organizationalU nit
          description: Group A
          >
          dn: cn=johnsmith,ou =groupa,dc=exam ple,dc=com
          cn: johnsmith
          objectClass: top
          objectClass: person
          sn: Smith
          telephoneNumber : 112
          >
          dn: cn=davesteel,ou =groupa,dc=exam ple,dc=com
          cn: davesteel
          objectClass: top
          objectClass: person
          sn: Steel
          telephoneNumber : 113
          >
          dn: ou=groupb,dc=ex ample,dc=com
          ou: groupb
          objectClass: top
          objectClass: organizationalU nit
          description: Group B
          >
          dn: cn=williamdavis ,ou=groupb,dc=e xample,dc=com
          cn: williamdavis
          objectClass: top
          objectClass: person
          sn: Davis
          telephoneNumber : 122
          >
          dn: cn=jamesjarvis, ou=groupb,dc=ex ample,dc=com
          cn: jamesjarvis
          objectClass: top
          objectClass: person
          sn: Jarvis
          telephoneNumber : 123
          >
          I am creating a python client program that will display the telephone
          list in the same directory structure as is on the LDAP server (i.e. it
          starts with buttons of all the groups, when you click on a group it
          comes up with buttons of all the numbers or groups available, and you
          can continually drill down).
          >
          I was wondering the best way to do this? I have installed and used the
          python-ldap libraries and these allow me to access and search the
          server, but the searches always return a horrible nesting of lists,
          tuples and dictionaries, below is an example of returning just one
          record -
          >
          ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
          'organization'], 'dc': ['example'], 'o': ['Example Organisation']})
          >
          Basically i think i need to parse the search results to create objects
          and build the python buttons around this, but i was hoping someone
          would be able to point me in the correct direction of how to do this?
          Is there a parser available? (there is an ldif library available but
          it is not obvious how this works, i cannot see much documentation, and
          it seems to be deprecated...).
          >
          Many thanks.
          >
          Ian- Hide quoted text -
          >
          - Show quoted text -
          Thanks for the replies all - it was a higher level wrapper like Bruno
          mentioned that i was looking for (with objects and attributes based on
          each objectClass), but the code posted above will work fine.

          Many thanks all.

          Ian

          Comment

          • Hallvard B Furuseth

            #6
            Re: LDAP/LDIF Parsing

            Bruno Desthuilliers writes:
            class LdapObject(obje ct):
            (...)
            def __getattr__(sel f, name):
            try:
            data = self._record[name]
            except KeyError:
            raise AttributeError(
            "object %s has no attribute %s" % (self, name)
            )
            Note that LDAP attribute descriptions may be invalid Python
            attribute names. E.g.
            {...
            'title;lang-en': ['The Boss']
            'title;lang-no': ['Sjefen']}
            So you'd have to call getattr() explicitly to get at all the attributes
            this way.
            else:
            # all LDAP attribs are multivalued by default,
            # even when the schema says they are monovalued
            if len(data) == 1:
            return data[0]
            else:
            return data[:]
            IMHO, this just complicates the client code since the client needs to
            inserts checks of isinstance(retu rn value, list) all over the place.
            Better to have a separate method which extracts just the first value of
            an attribute, if you want that.

            --
            Regards,
            Hallvard

            Comment

            • Bruno Desthuilliers

              #7
              Re: LDAP/LDIF Parsing

              Hallvard B Furuseth a écrit :
              Bruno Desthuilliers writes:
              >class LdapObject(obje ct):
              > (...)
              > def __getattr__(sel f, name):
              > try:
              > data = self._record[name]
              > except KeyError:
              > raise AttributeError(
              > "object %s has no attribute %s" % (self, name)
              > )
              >
              Note that LDAP attribute descriptions may be invalid Python
              attribute names. E.g.
              {...
              'title;lang-en': ['The Boss']
              'title;lang-no': ['Sjefen']}
              So you'd have to call getattr() explicitly to get at all the attributes
              this way.
              Yeps, true. Another solution would be to add a __getitem__ method
              pointing to the same implementation, ie:

              __getitem__ = __getattr__
              > else:
              > # all LDAP attribs are multivalued by default,
              > # even when the schema says they are monovalued
              > if len(data) == 1:
              > return data[0]
              > else:
              > return data[:]
              >
              IMHO, this just complicates the client code since the client needs to
              inserts checks of isinstance(retu rn value, list) all over the place.
              Better to have a separate method which extracts just the first value of
              an attribute, if you want that.
              Most of the times, in a situation such as the one described by the OP,
              one knows by advance if a given LDAP attribute will be used as
              monovalued or multivalued. Well, this is at least my own experience...

              Comment

              • =?ISO-8859-1?Q?Michael_Str=F6der?=

                #8
                Re: LDAP/LDIF Parsing

                Cruelemort wrote:
                I was wondering the best way to do this? I have installed and used the
                python-ldap libraries and these allow me to access and search the
                server, but the searches always return a horrible nesting of lists,
                tuples and dictionaries, below is an example of returning just one
                record -
                >
                ('dc=example,dc =com', {'objectClass': ['top', 'dcObject',
                'organization'], 'dc': ['example'], 'o': ['Example Organisation']})
                It's just modeled after the X.500 data model. A DN and the entry. The
                entry consists of attributes which consists of attribute type and a set
                of attribute values.

                You could write your own wrapper class around ldap.ldapobject .LDAPObject
                and overrule method search_s().
                (there is an ldif library available but
                it is not obvious how this works, i cannot see much documentation, and
                it seems to be deprecated...).
                Module ldif is not deprecated. It's actively maintained by me like the
                rest of python-ldap. It parses LDIF and returns the same data structure
                as above. You don't need it for LDAP access anyway. Only for reading
                LDIF files.

                Ciao, Michael.

                Comment

                • Hallvard B Furuseth

                  #9
                  Re: LDAP/LDIF Parsing

                  Bruno Desthuilliers writes:
                  >Hallvard B Furuseth a écrit :
                  >> else:
                  >> # all LDAP attribs are multivalued by default,
                  >> # even when the schema says they are monovalued
                  >> if len(data) == 1:
                  >> return data[0]
                  >> else:
                  >> return data[:]
                  >IMHO, this just complicates the client code since the client needs to
                  >inserts checks of isinstance(retu rn value, list) all over the place.
                  >Better to have a separate method which extracts just the first value of
                  >an attribute, if you want that.
                  >
                  Most of the times, in a situation such as the one described by the OP,
                  one knows by advance if a given LDAP attribute will be used as
                  monovalued or multivalued. Well, this is at least my own experience...
                  But if the attribute is multivalued, you don't know if it will contain
                  just one value or not. If you expect telephoneNumber to be multivalued,
                  but receive just one value '123',
                  for value in foo.telephoneNu mber: print value
                  will print
                  1
                  2
                  3

                  BTW, Cruelemort, remember that attribute names are case-insensitive. If
                  you ask the server to for attribute "cn", it might still return "CN".

                  --
                  Hallvard

                  Comment

                  • Bruno Desthuilliers

                    #10
                    Re: LDAP/LDIF Parsing

                    Hallvard B Furuseth a écrit :
                    Bruno Desthuilliers writes:
                    >
                    >>Hallvard B Furuseth a écrit :
                    >>
                    >>> else:
                    >>> # all LDAP attribs are multivalued by default,
                    >>> # even when the schema says they are monovalued
                    >>> if len(data) == 1:
                    >>> return data[0]
                    >>> else:
                    >>> return data[:]
                    >>>
                    >>>IMHO, this just complicates the client code since the client needs to
                    >>>inserts checks of isinstance(retu rn value, list) all over the place.
                    >>>Better to have a separate method which extracts just the first value of
                    >>>an attribute, if you want that.
                    >>
                    >>Most of the times, in a situation such as the one described by the OP,
                    >>one knows by advance if a given LDAP attribute will be used as
                    >>monovalued or multivalued. Well, this is at least my own experience...
                    >
                    But if the attribute is multivalued, you don't know if it will contain
                    just one value or not.
                    If you know which attributes are supposed to be multivalued in your
                    specific application, then it's time to write a more serious,
                    application-specific wrapper.

                    Comment

                    • =?ISO-8859-1?Q?Michael_Str=F6der?=

                      #11
                      Re: LDAP/LDIF Parsing

                      Bruno Desthuilliers wrote:
                      >
                      If you know which attributes are supposed to be multivalued in your
                      specific application, then it's time to write a more serious,
                      application-specific wrapper.
                      ldap.schema can be used to find that out.

                      Ciao, Michael.

                      Comment

                      Working...