#!/usr/bin/perl
#
# Look up default home page based on username using the LDAP tree
# structure.
#
# The basic idea when setting the default home page (or start page, if
# you like) for users is this:
#
# The user object in LDAP is normally located in a ou=people
# subtree. The labeledURI or wWWHomePage (to be compatible with Active
# Directory) attribute of the user and all the user objects parents in
# LDAP, if set, specifies the default home page to use. If not, it
# falls back on about:blank.

use strict;
use warnings;

use Getopt::Std;
use Net::LDAP;
use Debian::Edu;

sub usage {
    my $exitcode = shift;
    print "Usage: $0 [-d] <-u username>\n";
    exit $exitcode if $exitcode;
}

my $debug = 0;

my $homepage = "about:blank";

my %opts;
getopts("du:", \%opts) || usage(1);
$debug = 1 if $opts{d};
my $username = $opts{u};

my $server = $ARGV[0] || find_ldap_server() || "ldap";
my $base   = $ARGV[1] || find_ldap_base($server)
    || "dc=skole,dc=skolelinux,dc=no";


if  ($server) {
    my $ldap = Net::LDAP->new( $server ) or die "$@";
    my $mesg = $ldap->bind();

    $homepage = find_default_homepage($ldap, $username) || $homepage;
    $mesg = $ldap->unbind;
}

if ($homepage) {
    print "$homepage\n";
    exit 0;
}
exit 1;

sub get_homepage_attr {
    my $entry = shift;
    my $wwwhomepage = $entry->get_value ("wWWHomePage", undef );
    return $wwwhomepage if $wwwhomepage;
    my $labeleduri = $entry->get_value ("labeledURI", undef );
    return $labeleduri if $labeleduri;
}

sub find_default_homepage {
    my ($ldap, $username) = @_;
    my @dns;
    if ($username) {
        # First check the users entry
        my $filter = "(uid=$username)";
        my $mesg = $ldap->search( base  => $base, filter => $filter,
                                  attrs => ['cn', 'labeledURI',
                                            'wWWHomePage'] );
        $mesg->code && die $mesg->error;
        my $userdn;
        foreach my $entry ($mesg->entries) {
            $userdn = lc($entry->dn());
            my $homepage = get_homepage_attr($entry);
            return $homepage if $homepage;
            last;
        }
        unless ($userdn) {
            print STDERR "Found no user in LDAP with username '$username''\n" if $debug;
        } else {
            print STDERR "Found user on dn '$userdn'\n" if $debug;
            $base = lc($base);
            $userdn =~ s/,$base$//;

            # Second look for the parent OUs of the user
            my @parts = split(/,/, $userdn);
            shift @parts; # Drop username
            while (@parts) {
                push(@dns, join(",", @parts) . ",$base");
                shift @parts; # Drop username or other part.
            }
        }
    }

    # Also look in the base and root DSE as a last resort
    push(@dns, $base);
    push(@dns, '');

    for my $dn (@dns) {
        print STDERR "Checking $dn\n" if $debug;
        my $filter = "(|(wWWHomePage=*)(labeledURI=*))";
        my $mesg = $ldap->search( base  => $dn, filter => $filter,
                                  scope => 'base',
                                  attrs => ['labeledURI','wWWHomePage'] );
        $mesg->code && die $mesg->error;
        foreach my $entry ($mesg->entries) {
            my $homepage = get_homepage_attr($entry);
            if ($homepage) {
                print STDERR "Found home page '$homepage' on $dn\n" if $debug;
                return (split(/\s+/, $homepage))[0];
            }
        }
    }
    return undef;
}
