#
# A tcl/tk LDAP search tool.
# Gareth Owen <oweng@aston.ac.uk> 
# v1.0 14-Dec-98
#  1.1  8-Jan-98 
#  1.2 22-Jan-98
#

package require Ldap

lappend auto_path $env(HOME)/.tk/ldapper $syslibdir

if [file exists $syslibdir/Ldapper.ad] {
    option readfile $syslibdir/Ldapper.ad startupFile
}

if [file exists $env(HOME)/.Xdefaults] {
    option readfile $env(HOME)/.Xdefaults userDefault
}

if [file exists $syslibdir/config] {
    source $syslibdir/config
}

if [file exists $env(HOME)/.ldapper] {
    source $env(HOME)/.ldapper
}


# Set the default
set LDAP(Server) $LDAP(0,name)

#
#
#
proc LDAPsearch {scope base maxresults searchterm} {

    global LDAP ldap

    if ![info exists LDAP($LDAP(current),conn)] {
	if [catch {LdapBind [lindex $LDAP($LDAP(current),host) 0] \
		       [lindex $LDAP($LDAP(current),host) 1] {} {}} \
		LDAP($LDAP(current),conn)] {
	    tk_messageBox -type ok -message \
	       "$LDAP($LDAP(current),conn) [join $LDAP($LDAP(current),host) :]"
	    unset LDAP($LDAP(current),conn)
	    return {}
	}
    }

    set ret [LdapSearch $LDAP($LDAP(current),conn) $scope {} $base \
		 maxresults $searchterm $LDAP(attributes)]

    if $LDAP(unbindaftersearch) {
	LdapUnBind $LDAP($LDAP(current),conn)
	unset LDAP($LDAP(current),conn)
    }

    return $ret

}

# Server list
foreach  n [lsort [array names LDAP *,name]] {
    lappend LDAP(servers) $LDAP($n)
}

#
# sets which server to query
#
proc SetServer {} {

    global LDAP

    set LDAP(current) [lsearch $LDAP(servers) $LDAP(Server)]

    if ![info exists LDAP($LDAP(current),c)] {
	regexp {c=(.+)} $LDAP($LDAP(current),base) match LDAP($LDAP(current),c) 
    }
    
    if ![info exists LDAP($LDAP(current),o)] {
	regexp {o=([^,]+)} $LDAP($LDAP(current),base) match LDAP($LDAP(current),o)
    }

    if !$LDAP(searchlock) {
	set LDAP(c) $LDAP($LDAP(current),c)
	set LDAP(o) $LDAP($LDAP(current),o)
    }

}

#
# Set up server 0
#
SetServer

#
# 
#
proc Search {} {

    global LDAP


    switch -exact $LDAP(stype) {
	"contains" { set tp {=*} }
	"ends with" { set tp {=*} }
	"approximates" { set tp {~=} }
	default {set tp =}
    }

    switch -exact $LDAP(attr) {
	"full name" {set filter "cn$tp$LDAP(searchterm)"}
	"family name" { set filter "sn$tp$LDAP(searchterm)"}
	"email address" {set filter "mail$tp$LDAP(searchterm)"}
    }

    switch -exact $LDAP(stype) {
	"contains" { set filter "$filter*"}
        "starts with" {set filter "$filter*"}
        default {set filter $filter}
    }

    set ret [LDAPsearch sub "o=$LDAP(o),c=$LDAP(c)" $LDAP(maxresults) $filter]

    if [llength $ret]<2 {
	tk_messageBox -message "No matches for '$LDAP(searchterm)'"
        return
    }

    .results.e delete 0.0 end

    set flag 0
    set count 0

    foreach r $ret {
	set t [split $r =]
	set att [string tolower [lindex $t 0]]
	foreach b [array names LDAP button,*] {
	    set batt [lindex [split $b ,] 1]
	    if [string first  $batt $att]>-1 {
		.results.e insert end "[lindex $t 0]="
		button .results.e.but$count -text [lindex $t 1] \
		    -command "[lindex $LDAP($b) 0] [lindex $t 1]" \
		    -cursor top_left_arrow \
		    -fg [lindex $LDAP($b) 1] -bg [lindex $LDAP($b) 2]
		.results.e window create end -window .results.e.but$count
		.results.e insert end "\n"
		incr count
		set flag 1
		continue
	    }
	}
	if !$flag {
	.results.e insert end "$r\n"
	}
	set flag 0
    }

}





#
# Browse organisations within a country
#  
proc BrowseO {} {

    global LDAP Country

    if {![info exists LDAP(bo)] || {$LDAP(bo)==""}} {
	set LDAP(bo) "[string index $LDAP(o) 0]*"
    }

    if ![winfo exists .browseo] {
	iso3166
	toplevel .browseo
	frame .browseo.filter
	frame .browseo.data
	frame .browseo.but
	pack .browseo.filter .browseo.data .browseo.but -side top
	label .browseo.filter.label -text [lindex $LDAP(label) 9]
	entry .browseo.filter.e -textvariable LDAP(bo)
	pack .browseo.filter.label .browseo.filter.e -side left
	text .browseo.data.e -relief sunken -borderwidth 4 -height 10 \
	    -width 40 -wrap none -setgrid true \
	    -yscrollcommand ".browseo.data.ysb set"
	scrollbar .browseo.data.ysb -relief flat \
	    -command ".browseo.data.e yview"
	pack .browseo.data.ysb -side right -fill y
	pack .browseo.data.e -expand yes -fill both
	button .browseo.but.search -text Search -command DoBrowse0
	button .browseo.but.clear -text Clear \
	    -command {.browseo.data.e delete 0.0 end;set LDAP(orgcount) 0}
	button .browseo.but.q -text Dismiss -command {wm withdraw .browseo}
	pack .browseo.but.search .browseo.but.clear .browseo.but.q -side left
    }
    wm title .browseo "Browse organisations in $Country($LDAP(c))"
    wm deiconify .browseo

}


proc DoBrowse0 {} {    

    global LDAP 
    set orgs [LDAPsearch one c=$LDAP(c) 0 o=$LDAP(bo)]

    if ![info exists LDAP(orgcount)] {
	set LDAP(orgcount) 0
    }
    
    set bgcol [lindex [.browseo.data.e configure -background] end]
    set fgcol [lindex [.browseo.data.e configure -foreground] end]

    foreach o $orgs {
	if ![string first o= $o] {
	    set name [string range $o 2 end]
	    button .browseo.data.e.but$LDAP(orgcount) -text $name \
		-cursor top_left_arrow -command "set LDAP(o) \"$name\"" \
		-fg $fgcol -bg $bgcol
	    .browseo.data.e window create end \
		-window .browseo.data.e.but$LDAP(orgcount)
	    .browseo.data.e insert end "\n"
	    incr LDAP(orgcount)
	}
    }
}	
    
proc BrowseC {} {

    global LDAP Country

    if ![winfo exists .browsec] {
	iso3166
	toplevel .browsec
	frame .browsec.data
	frame .browsec.but
	pack .browsec.data .browsec.but -side top
	text .browsec.data.e -relief sunken -borderwidth 4 -height 10 \
	    -width 40 -wrap none -setgrid true \
	    -yscrollcommand ".browsec.data.ysb set"
	scrollbar .browsec.data.ysb -relief flat \
	    -command ".browsec.data.e yview"
	pack .browsec.data.ysb -side right -fill y
	pack .browsec.data.e -expand yes -fill both
	button .browsec.but.q -text Dismiss -command {wm withdraw .browsec}
	pack  .browsec.but.q -side left
	wm title .browsec "ISO Top Level Domains"

	set bgcol [lindex [.browsec.data.e configure -background] end]
	set fgcol [lindex [.browsec.data.e configure -foreground] end]
	foreach c [lsort [array names Country]] {
	    button .browsec.data.e.[string tolower $c] -text $c \
		-cursor top_left_arrow -command "set LDAP(c) $c" \
		-fg $fgcol -bg $bgcol	    
	    .browsec.data.e window create end \
		-window .browsec.data.e.[string tolower $c]
	    .browsec.data.e insert end "\t$Country($c)\n"
	}
    }
    wm deiconify .browsec

}


frame .rack
frame .server
frame .base
frame .search
frame .results 
pack .rack .server .base .search .results -side top -expand yes -fill x

button .rack.doit -command {Search} -text [lindex $LDAP(label) 0]
#button .rack.help -command {Help} -text [lindex $LDAP(label) 1]
button .rack.quit -command {destroy .} -text [lindex $LDAP(label) 2]

pack .rack.doit -side left
#.rack.help -side left
pack .rack.quit -anchor e

label .server.serlab -text [lindex $LDAP(label) 3]
eval tk_optionMenu .server.server LDAP(Server) $LDAP(servers)
for {set i 0} {$i<[llength $LDAP(servers)]} {incr i} {
    .server.server.menu entryconfigure $i -indicatoron 0 -command SetServer
}
label .server.mrl -text [lindex $LDAP(label) 4]
eval tk_optionMenu .server.mr LDAP(maxresults) $LDAP(MaxResults)
for {set i 0} {$i<[llength $LDAP(MaxResults)]} {incr i} {
    .server.mr.menu entryconfigure $i -indicatoron 0
}
pack .server.serlab .server.server .server.mrl .server.mr -side left

frame .base.country
frame .base.organ
pack .base.country .base.organ -side left
label .base.country.l -text [lindex $LDAP(label) 5]
entry .base.country.e -textvariable LDAP(c) -width 3
button .base.country.browse -command BrowseC -text [lindex $LDAP(label) 8]
pack .base.country.l .base.country.e .base.country.browse -side left
label .base.organ.l -text [lindex $LDAP(label) 6]
entry .base.organ.e -textvariable LDAP(o)
button .base.organ.browse -command BrowseO -text [lindex $LDAP(label) 8]
pack .base.organ.l .base.organ.e .base.organ.browse -side left
checkbutton .base.lock -text [lindex $LDAP(label) 7] \
    -variable LDAP(searchlock)
pack .base.lock -side left

label .search.l1 -text {Search for}
eval tk_optionMenu .search.attr LDAP(attr) $LDAP(attr,friendly)
for {set i 0} {$i<[llength $LDAP(attr,friendly)]} {incr i} {
    .search.attr.menu entryconfigure $i -indicatoron 0
}
label .search.l2 -text which
eval tk_optionMenu .search.type LDAP(stype) $LDAP(stype,friendly)
for {set i 0} {$i<[llength $LDAP(stype,friendly)]} {incr i} {
    .search.type.menu entryconfigure $i -indicatoron 0
}
entry .search.e -textvariable LDAP(searchterm)
pack .search.l1 .search.attr .search.l2 .search.type \
    -side left
pack .search.e -side right -anchor e 

set w .results
text $w.e -relief sunken -borderwidth 4 -height 20 -width 60 \
	-wrap none -yscrollcommand "$w.ysb set" \
	    -xscrollcommand "$w.xsb set" -setgrid true
scrollbar $w.ysb -relief flat -command "$w.e yview"
scrollbar $w.xsb -relief flat -orient horizontal -command "$w.e xview"
pack $w.ysb -side right -fill y
pack $w.xsb -side bottom -fill x
pack $w.e -expand yes 

bind . <Key-Up> {.results.e yview scroll -1 units}
bind . <Key-Down> {.results.e yview scroll 1 units}
bind . <Prior> {.results.e yview scroll -1 page}
bind . <Next> {.results.e yview scroll 1 page}
bind .search.e <Return> Search
focus .search.e

