
require 'ldap'
require 'uri'

basedn = ''
conn = ''

f = File.new('/etc/openldap/ldap.conf', 'r')
f.readlines.each do |line|
    line = line.strip
    next if line =~ /^#/
    next if line == ''
    line = line.split
    if line[0] == 'BASE'
        basedn = line[1]
    elsif line[0] == 'URI'
        line.shift
        line.each do |uri|
            uri = URI.parse(uri)
            begin
                if uri.scheme == 'ldaps'
                    if ! uri.port
                        uri.port = 636
                    end
                    conn = LDAP::SSLConn.new(uri.host, uri.port)
                else
                    if ! uri.port
                        uri.port = 389
                    end
                    conn = LDAP::Conn.new(uri.host, uri.port)
                end
                conn.bind
                break
            rescue LDAP::ResultError
                next
            end
        end
    end
end
f.close

user_classes = []
group_classes = []

userlist = {}
conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, 'objectClass=posixAccount',
            ['uid', 'gidNumber']) { |entry|
    groups = []
    filter = '(&(objectClass=posixGroup)(|(uniqueMember=' + entry.get_dn + \
	     ')(memberUid=' + entry['uid'][0] + ')))'
    conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, ['cn']) { |group|
        groups << group['cn'][0]
    }
    conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, \
                '(&(objectClass=posixGroup)(gidNumber=' + \
		entry['gidNumber'][0] + '))', \
                ['cn']) { |group|
	groups << group['cn'][0]
    }
    
    # create user class
    if entry['uid'][0] !~ /.*\$.*/
	user_classes << "class user::user::" + entry['uid'][0] + " inherits user::virtual {\n"
	user_classes << "    realize(User::Newuser['" + entry['uid'][0] + "'])\n"
	groups.each do |group|
	    user_classes << "    realize(Group['" + group + "'])\n"
	end
	user_classes << "}\n\n"
    end

    userlist[entry.get_dn()] = entry['uid'][0]
}


conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, 'objectClass=posixGroup',
	    ['cn', 'gidNumber', 'memberUid', 'uniqueMember']) { |entry|

    members = []
    if entry.attrs.index('memberUid')
	entry['memberUid'].each do |member|
	    if userlist.has_value?(member)
		members << member
	    end
	end
    end
    if entry.attrs.index('uniqueMember')
	entry['uniqueMember'].each do |member|
	    if userlist.has_key?(member)
		members << userlist[member]
	    end
	end
    end
    if members.length > 0
	group_classes << "class user::group::" + entry['cn'][0] + " {\n"
	members.uniq.sort.each do |member|
	    group_classes << "    include user::user::" + member + "\n"
	end
	group_classes << "}\n\n"
    end
}

puts user_classes if ARGV.include?("-u")
puts group_classes if ARGV.include?("-g")
