#!/usr/bin/python

import sys
from ldaptor.protocols.ldap import ldapclient, ldif, ldapsyntax, distinguishedname, ldapconnector
from ldaptor.protocols import pureber, pureldap
from ldaptor import usage, ldapfilter
from twisted.internet import protocol, reactor, defer

class Search(ldapclient.LDAPClient):
    def connectionMade(self):
	d=self.bind()
	d.addCallback(self._handle_bind_success)
	d.addErrback(self.factory.deferred.errback)

    def _printResults(self, o):
	sys.stdout.write(str(o))

    def _handle_bind_success(self, x):
	matchedDN, serverSaslCreds = x
	o=ldapsyntax.LDAPEntry(client=self,
                               dn=self.factory.base)
	d=o.search(filterText=self.factory.filt,
		   attributes=self.factory.attributes,
		   callback=self._printResults)
	d.chainDeferred(self.factory.deferred)

class SearchFactory(protocol.ClientFactory):
    protocol = Search

    def __init__(self, deferred, base, filt, attributes):
	self.deferred=deferred
	self.base=base
	self.filt=filt
	self.attributes=attributes

    def clientConnectionFailed(self, connector, reason):
	self.deferred.errback(reason)

exitStatus=0

def error(fail):
    print >>sys.stderr, 'fail:', fail.getErrorMessage()
    global exitStatus
    exitStatus=1

def main(base, serviceLocationOverride, filter_text, attributes):
    d=defer.Deferred()
    s=SearchFactory(d, base, filter_text, attributes)
    d.addErrback(error)
    d.addBoth(lambda x: reactor.stop())

    dn = distinguishedname.DistinguishedName(stringValue=base)
    c = ldapconnector.LDAPConnector(reactor, dn, s, overrides=serviceLocationOverride)
    c.connect()

    reactor.run()
    sys.exit(exitStatus)

class MyOptions(usage.Options, usage.Options_service_location, usage.Options_base):
    """LDAPtor command line search utility"""

    def parseArgs(self, filter, *attributes):
	self.opts['filter'] = filter
	self.opts['attributes'] = attributes

if __name__ == "__main__":
    try:
	config = MyOptions()
	config.parseOptions()
    except usage.UsageError, ue:
	sys.stderr.write('%s: %s\n' % (sys.argv[0], ue))
	sys.exit(1)

    main(config.opts['base'],
	 config.opts['service-location'],
	 config.opts['filter'],
	 config.opts['attributes'])
