LdapService.py 4.69 KB
#!/usr/bin/python

import time
import random
import mmap
import sys, getopt
from struct import pack
from collections import deque

from os.path import dirname, realpath
from sys import argv, path
path.append(dirname(realpath(__file__)) + '/lib')

from Server import Server

from Event.EventHandler import EventHandler
from Event.EventDispatcher import EventDispatcher
from Communication.EndPoint import CommunicationEndPoint

from Protocol.Http.Http import Http
from Protocol.Websocket.Websocket import Websocket

from LdapTree import LdapTree

class Application(EventHandler):
    def __init__(self, hosturi, binddn, basedn, password):
        super(Application, self).__init__()

        self._event_methods = {
            EventDispatcher.eventId('heartbeat')     : self._heartbeat,
            CommunicationEndPoint.eventId('new_msg') : self._handle_data,
            CommunicationEndPoint.eventId('close')   : self._handle_close,
            CommunicationEndPoint.eventId('upgrade') : self._upgrade
        }

        self._websockets = []

        self._wstest   = open('websocket.html', 'r+b')
        self._wstestmm = mmap.mmap(self._wstest.fileno(), 0)

        random.seed()

        self.ldaptree = LdapTree(hosturi, binddn, basedn, password, False)

    def __del__(self):
        self._wstestmm.close()
        self._wstest.close()

    def _upgrade(self, event):
        self._websockets.append(event.subject)
        # let other also handle the upgrade .. no return True

    def _heartbeat(self, event):
        now = pack('!d', time.time())
        for event.subject in self._websockets:
            self.issueEvent(event.subject, 'send_msg', now)

        return True

    def _handle_data(self, event):
        protocol = event.subject.getProtocol()

        if event.subject.hasProtocol(Http):
            if event.data.isRequest():
                if event.data.getUri() == '/':
                    resp = protocol.createResponse(event.data, 200, 'OK')
                    resp.setBody(self._wstestmm[0:])
                elif event.data.getUri() == '/ldap':
                    resp = protocol.createResponse(event.data, 200, 'OK')
                    resp.setHeader('Content-Type', 'image/svg+xml')
                    resp.setBody(self.ldaptree.graph())
                else:
                    resp = protocol.createResponse(event.data, 404, 'Not Found')
                    resp.setBody('<h1>404 - Not Found</h1>')

                self.issueEvent(event.subject, 'send_msg', resp)

        return True

    def _handle_close(self, event):
        if event.subject in self._websockets:
            print 'websocket closed...'
            self._websockets = [w for w in self._websockets if w!=event.subject]

        return True

def usage():
    print "Usage: " + sys.argv[0] + " ARGUMENT... [OPTIONS]... bindip bindport\n"
    print "Start a webserver on the given bindip and bindport. On the page a"
    print "tree representation of all DNs starting with a given base DN is"
    print "visualized."
    print "Only simple binds to the directory with DN and password are supported.\n"
    print "ARGUMENTS:\n"
    print "  {:30s} : {:s}".format('-H, --hosturi=URI', 'The URI to the ldap server to query in the form:')
    print "  {:30s}   {:s}".format('', 'ldap[s]://host.uri[:port]')
    print "  {:30s} : {:s}".format('-D, --binddn=DN', 'The DN to use for the LDAP bind.')
    print "  {:30s} : {:s}".format('-p, --password=PASSWORD', 'The password to use for the LDAP bind.')
    print "  {:30s} : {:s}\n".format('-b, --basedn=DN', 'The DN to start the tree with.')
    print "OPTIONS:\n"
    print "  {:30s} : {:s}".format('-h, --help', 'Show this help page')

def main():
    try:
        opts, args = getopt.getopt(
                sys.argv[1:],
                'hH:D:b:p:',
                ['help', 'hosturi=', 'binddn=', 'basedn=', 'password='])
    except getopt.GetoptError as err:
        print str(err)
        usage()
        sys.exit(2)

    hosturi = binddn = basedn = password = None

    for o, a in opts:
        if o in ["-h", "--help"]:
            usage()
            sys.exit(0)
        elif o in ["-H", "--hosturi"]:
            hosturi = a
        elif o in ["-D", "--binddn"]:
            binddn = a
        elif o in ["-b", "--basedn"]:
            basedn = a
        elif o in ["-p", "--password"]:
            password = a
        else:
            print "unknown parameter: " + a
            usage()
            sys.exit(2)

    if not hosturi or not binddn or not basedn or not password:
        usage()
        sys.exit(2)

    server = Server(Application(hosturi, binddn, basedn, password))
    server.bindTcp(args[0], int(args[1]), Http())
    server.start(1.0)

if __name__ == '__main__':
    main()

# vim: set ft=python et ts=8 sw=4 sts=4: