#!/usr/bin/perl
#
# Copyright (C) 2003 VA Linux Systems Japan, K.K.
#
# LICENSE NOTICE
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#

use Getopt::Std;
use Net::LDAP;

$mhost = "localhost";

getopt('fl');
$conf = $opt_f || "/usr/local/openldap/etc/openldap/slapd.master.conf";

if ($#ARGV+1 != 1) {
    print "Bad arguments\n";
    exit(1);
}

($reject) = @ARGV;

($rejname = $reject) =~ s/^.*\///g;

if ($opt_l) {
    $lock = "$opt_l/$rejname.lock";
} else {
    $lock = "$reject.lock";
}

if (!open(LOCK, ">$lock")) {
    print "Can't open $lock\n";
    exit(1);
}
eval{ flock(LOCK, 2); };
if ($@){
    exit(1);
}

if (!open(REJ, "<$reject")) {
    print "Can't open $reject\n";
    exit(1);
}

if (!(($shost = $rejname) =~ s/:.*//)){
    print "Bad reject file name\n";
    exit(1);
}

($adm, $pass) = &getadmpasswd($conf, $shost);

if (!($mldap = Net::LDAP->new($mhost))) {
    print "Can't connect $mhost\n";
    exit(1);
}
if (!($sldap = Net::LDAP->new($shost))) {
    print "Can't connect $shost\n";
    exit(1);
}

$mldap->bind($adm, password => $pass);
$sldap->bind($adm, password => $pass);

while(<REJ>) {
    $line = "$line$_";
    chop($_);

    /^dn: / && {($dn = $_) =~ s/^dn: *//};

   if (!$_) {
       my $retry = 0;

     CHECK:
       $mdata = &getdata($mldap, $dn);
       $sdata = &getdata($sldap, $dn);

       if ($mdata ne $sdata) {
	   if (!$retry) {
	       $retry = 1;
	       sleep(2);
	       goto CHECK;
	   }
	   print $line;
       }
       $line = "";
   }
}

$mldap->unbind;
$sldap->unbind;


sub getadmpasswd {
    local($file, $host) = @_;
    local($adm, $passwd);
    my $match = 0;

    if (!open(FILE, "<$file")) {
	print "Can't open $file\n";
	return;
    }

    while (<FILE>) {
	/^replica host=$host/ && {$match = 1};
	$match || next;
	chop($_);
	s/binddn=['"]*([^\s'"]*)// && {$adm = $1};
	s/credentials=['"]*([^\s'"]*)// && {$passwd = $1};
	/^\s*$/ && last;
    }
    close(FILE);

    return $adm, $passwd;
}

sub getdata {
    local($ldap, $dn) = @_;
    local($attrs, $data);

    my $result = $ldap->search(base => $dn, scope => "base", filter => "(objectclass=*)");
    my $rc = $result->code;
    $rc && return $rc;

    my $entry = $result->shift_entry;
    foreach my $attr ($entry->attributes) {
	$attrs =  join("|", $entry->get_value($attr));
	$data = "$data$attr:$attrs,";
    }

    return $data;
}
