Location: PHPKode > projects > Yet Another LDAP Administrator > yala-0.32/main.php
<?php
if (file_exists("config.inc.php")) require "config.inc.php";
	else die("Config file not found.. read INSTALL file for installation instructions");
require "general.inc.php";
require "ldapfunc.inc.php";
require	"htmloutput.inc.php";

$javascript = "";

# {{{ login() returns binddn and bindpw if true, otherwise
# shows the login form 
function login() {
	# First make the sanity checks
	$_SESSION["yala"] = TRUE;
	sanity_checks();

	# If $ldap_server && $ldap_port are set
	if (array_key_exists("ldap_server", $_SESSION) && array_key_exists("ldap_port", $_SESSION) && $_SESSION["ldap_server"] && $_SESSION["ldap_port"]) {
		# First connect..
		$ldap_func = new LDAPFunc($_SESSION["ldap_server"], $_SESSION["ldap_port"], $_SESSION["ldap_tls"]) or exitOnError(ERROR_LDAP_CANT_CONNECT, $_SESSION["ldap_server"].":".$_SESSION["ldap_port"]);

		# Let's try to login, if successful skip the next stuff
		$bind = $ldap_func->bind($_SESSION["ldap_binddn"], $_SESSION["ldap_bindpw"]);
		if ($bind) {
			return $ldap_func;
		}
			echo "Bind problem: ".ldap_error($ldap_func->ldap_conn)."<BR>";
	}

	# Get settings either from session or from defaults
	if (isset($_SESSION["ldap_server"]))
		$ldap_server	= $_SESSION["ldap_server"];
	else
		if (defined("LDAP_SERVER"))
			$ldap_server	= LDAP_SERVER;
		else
			$ldap_server 	= NULL;

	if (isset($_SESSION["ldap_port"]))
		$ldap_port	= $_SESSION["ldap_port"];
	else
		if (defined("LDAP_PORT"))
			$ldap_port	= LDAP_PORT;
		else
			$ldap_port	= NULL;

	if (isset($_SESSION["ldap_binddn"]))
		$ldap_binddn	= $_SESSION["ldap_binddn"];
	else
		if (defined("LDAP_BINDDN"))
			$ldap_binddn	= LDAP_BINDDN;
		else
			$ldap_binddn	= NULL;

	if (isset($_SESSION["ldap_basedn"]))
		$ldap_basedn	= $_SESSION["ldap_basedn"];
	else
		if (defined("LDAP_BASEDN"))
			$ldap_basedn	= LDAP_BASEDN;
		else
			$ldap_basedn	= NULL;

	if (isset($_SESSION["ldap_tls"]))
		$ldap_tls	= $_SESSION["ldap_tls"];
	else
		if (defined("LDAP_TLS"))
			$ldap_tls	= LDAP_TLS;
		else
			$ldap_tls	= NULL;

	require INCLUDE_PATH."/login_form.inc";
} # }}}

# {{{ logout() - deletes the cookies (Session info..)
function logout() {
	global $javascript;
	if (session_destroy()) 
		echo "Logged out, click <A HREF=\"".MAINFILE."\" TARGET=\"right\">here</A> to login again...<BR>";
	else
		echo "Error logging out!<BR>";
} # }}}

# {{{ flushCache() function just deletes the old cache files 
function flushCache($ldap_func) {

	# Set the filenames of cache files
	$name2oidCacheFile = NAME2OID_CACHEFILE.".".str_replace("/", "", $ldap_func->get_server());
	$objectclassesCacheFile = OBJECTCLASSES_CACHEFILE.".".str_replace("/", "", $ldap_func->get_server());

	if (DEBUG) print ("UNLINKING!\n");
	if (file_exists($name2oidCacheFile)) unlink($name2oidCacheFile);
	if (file_exists($objectclassesCacheFile)) unlink($objectclassesCacheFile);

} # }}}

# {{{ getCachedSchema() - wraps $ldap_func->getSchema() function to add 
# caching. We use the neat serialize() function php has..
#
# Returns the values into $name2oid & $objectclasses
function getCachedSchema($ldap_func, &$name2oid, &$objectclasses) {

	# Set the filenames of cache files
	$name2oidCacheFile = NAME2OID_CACHEFILE.".".str_replace("/", "", $ldap_func->get_server());
	$objectclassesCacheFile = OBJECTCLASSES_CACHEFILE.".".str_replace("/", "", $ldap_func->get_server());
	$cacheIsFine = TRUE;

	/* Can we get it from cache?
	1. If cache files exist *AND*
	2. If CACHE_EXPIRES seconds haven't passed yet since the file's mtime
	*/

	if (!file_exists($name2oidCacheFile) ||
	    !file_exists($objectclassesCacheFile))
		$cacheIsFine = FALSE; # Cache files don't exist, cache is NOT fine
	else {
		if ((filemtime($name2oidCacheFile)+CACHE_EXPIRES<time()) ||
		(filemtime($objectclassesCacheFile)+CACHE_EXPIRES<time())) {
			# Cache expired, then cache is NOT fine
			$cacheIsFine = FALSE; 
		}
	}

	
	if ($cacheIsFine) {
		if ($f = @fopen($name2oidCacheFile, "r")) {
			$str = fread($f, filesize($name2oidCacheFile)) or exitOnError(ERROR_CACHE_CANT_READ, $name2oidCacheFile);
			$name2oid = unserialize($str);
			fclose($f);
		}
		else
			exitOnError(ERROR_CACHE_CANT_READ, $name2oidCacheFile);

		if ($f = @fopen($objectclassesCacheFile, "r")) {
			$str = fread($f, filesize($objectclassesCacheFile)) or exitOnError(ERROR_CACHE_CANT_READ, $objectclassesCacheFile);
			$objectclasses = unserialize($str);
			fclose($f);
		}
		else
			exitOnError(ERROR_CACHE_CANT_READ, $objectclassesCacheFile);
	}
	else { # Cache is no good
		/* Read the schema from LDAP */
		$ldap_func->getSchemaHash($name2oid, $objectclasses);

		/* Save it in cache */
		umask(077); # We don't want the schema world readable..
		if ($f = @fopen($name2oidCacheFile, "w")) {
			fwrite($f, serialize($name2oid)) or exitOnError(ERROR_CACHE_CANT_WRITE, $name2oidCacheFile);
			fclose($f);
		}
		else
			exitOnError(ERROR_CACHE_CANT_WRITE, $name2oidCacheFile);

		if ($f = @fopen($objectclassesCacheFile, "w")) {
			fwrite($f, serialize($objectclasses)) or exitOnError(ERROR_CACHE_CANT_WRITE, $objectclassesCacheFile);
			fclose($f);
		}
		else
			exitOnError(ERROR_CACHE_CANT_WRITE, $objectclassesCacheFile);
	}
}
# }}}

# {{{ viewEntry() displays the given entry's attributes and values,
# according to the schema of its objectclasses
# If no entry is given we display an empty entry of the specified object claases
#
# For each attribute we'll show $empties values in addition
function viewEntry($ldap_func, $entry, $empties = 0, $dn = "", $objectclasses = array()) {
	global $attr_desc; # FIXME Global is ugly

	# Arg check
	if (!$ldap_func || !$entry && !count($objectclasses)) exitOnError(ERROR_FEW_ARGUMENTS);

	$data = array();
	$attributes["must"] = array();
	$attributes["may"] = array();

	# Get the schema contents
	getCachedSchema($ldap_func, $name2oid, $schema_objectclasses);

	if ($entry) { # Existing entry; read it.
		$sr = ldap_read($ldap_func->ldap_conn, formatInputStr($entry), "(objectclass=*)") or exitOnError(ERROR_LDAP_CANT_SEARCH);
		$data = ldap_get_entries($ldap_func->ldap_conn, $sr) or exitOnError(ERROR_LDAP_CANT_SEARCH);

	}
	else { # Empty entry; create a fake entry with objectclasses coming from user input ($objectclasses)
		$data[0]["objectclass"] = array();
		foreach ($objectclasses as $objectclass) {
			array_push($data[0]["objectclass"], $objectclass);
		}
		$data[0]["objectclass"]["count"] = count($objectclasses);
	}


	# Get the attrs of each objectclass and merge them (an entry might have several objectclasses)
	for ($i = 0; $i < $data[0]["objectclass"]["count"]; $i++) {
		$objectclass = $data[0]["objectclass"][$i];

		# Recursively get the may/must attributes of $objectclass and it's
		# superiors.
		$maymust = $ldap_func->getMayMust($objectclass, $schema_objectclasses, $name2oid);

		$attributes["must"] = array_merge($attributes["must"], $maymust["must"]);
		$attributes["may"] = array_merge($attributes["may"], $maymust["may"]);
	}

	# Remove dups + sort
	$attributes["must"] = array_unique($attributes["must"]);
	$attributes["may"]  = array_unique($attributes["may"]);
	asort($attributes["must"]);
	asort($attributes["may"]);


	# ENTRY TITLE COMES HERE
	$htmloutput = new HTMLOutput();
	if ($entry)
		$htmloutput->viewHeader($entry);
	else
		$htmloutput->viewHeader();
	
	# Allow adding/removing empty fields
	# TODO We don't allow this on new-entry-mode because I'm lazy.
	if ($entry) {
		$str = "One <A HREF=\"".MAINFILE."?do=view_entry&amp;entry=".urlencode($entry)."&amp;empties=".($empties+1)."\">more</A> / <A HREF=\"".MAINFILE."?do=view_entry&amp;entry=".urlencode($entry)."&amp;empties=".($empties-1)."\">less</A> empty value field (for each attribute)";
		$htmloutput->viewTitle($str);
	}


	# Show the dn before anything else
	# existsing-entry: get the dn from $data
	# try $dn, else: empty
	if (array_key_exists(0, $data) && array_key_exists("dn", $data[0]))
		$dn = $data[0]["dn"];
	if (!isset($dn)) $dn = "";

	$htmloutput->viewInnerHeader();
	$htmloutput->viewInnerRowDN($dn);

	# Print the must+may attributes and their values
	foreach (array("must", "may") as $attr_type) {
		foreach ($attributes[$attr_type] as $attr) {

			# See if there's a description to this specific attribute
			$acronym_body = "";

			if (isset($attr_desc) && is_array($attr_desc))
				if (array_key_exists($attr, $attr_desc))
					$acronym_body = $attr_desc[$attr];

			if (array_key_exists(strtolower($attr), $data[0]))
				$val  = $data[0][strtolower($attr)];
			else
				$val = NULL;

			# Show all the existing values (if none, at least one empty!) 
			# + $empties empty_values in addition
			for ($j = 0; ($j < ( max($val["count"], 1) + $empties)); $j++) {
				if ($j + 1 > $val["count"]) $value = "";
				else
					$value = formatOutputStr($val[$j]);
				$htmloutput->viewInnerRow($attr, $value, $attr_type == "must", $acronym_body);
			}
		}
	}
	$htmloutput->viewInnerFooter();
	$htmloutput->viewFooter($entry);
}
# }}}

# {{{ modifyEntry() gets the modifications and decides what to do...
function modifyEntry($ldap_func, $post_vars) {
	$htmloutput = new HTMLOutput();
	$modified = 0; # Becomes 1 if anything happens to the entry
	$add_hash = array();
	$del_hash = array();
	$replace_hash = array();

	if (!$ldap_func || !is_array($post_vars)) exitOnError(ERROR_FEW_ARGUMENTS);
	$dn = formatInputStr($post_vars["entry"]);

	$sr = ldap_read($ldap_func->ldap_conn, $dn, "(objectClass=*)") or exitOnError(ERROR_LDAP_CANT_SEARCH);
	$entry = ldap_first_entry($ldap_func->ldap_conn, $sr) or exitOnError(ERROR_LDAP_CANT_SEARCH);
	$attributes = ldap_get_attributes($ldap_func->ldap_conn, $entry);


	#
	# Create add_hash
	# 

	# Pass on each posted attribute
	while ( list($attr, $posted_values) = each($post_vars) ) {
		# We care about this var only if it's an array
		if (!is_array($posted_values)) continue;

		# If $attr wasn't found in ldap (means that it has no 
		# value in ldap yet) - add all values to the 'add_hash'
		if (!isset($attributes[$attr])) {
			foreach ($posted_values as $posted_value) {
				# Skip empty values
				if ($posted_value == "") continue;
				if (!array_key_exists($attr, $add_hash))
					$add_hash[$attr] = array();
				array_push($add_hash[$attr], $posted_value);
			}
			continue;
		}

		$ldap_values = ldap_get_values($ldap_func->ldap_conn, $entry, $attr);

		foreach ($posted_values as $posted_value) {
			# Skip empty values
			if ($posted_value == "") continue;
			if (!in_array($posted_value, $ldap_values)) {
				if (!array_key_exists($attr, $add_hash))
					$add_hash[$attr] = array();
				array_push($add_hash[$attr], $posted_value);
			}
		}
	}


	#
	# Create del_hash
	#

	# Now pass on each attribute from ldap and see if it has a real
	# value in $posted_vars
	for ($i = 0; $i < $attributes["count"]; $i++) {
		$attr = $attributes[$i];
		$ldap_values = ldap_get_values($ldap_func->ldap_conn, $entry, $attr);

		for ($j = 0; $j < $ldap_values["count"]; $j++) {
			if (!in_array($ldap_values[$j], $post_vars[$attr]))  {
				if (!array_key_exists($attr, $del_hash))
					$del_hash[$attr] = array();
				array_push($del_hash[$attr], $ldap_values[$j]);
			}
		}
	}

	#
	# Create replace_hash
	#
	
	# Now we have two hashes, add_hash and del_hash. If we both del a 
	# value of attribute 'x' and add another value - we'd rather REPLACE
	# this value instead of deleting and adding (as long as attribute 
	# 'x' has only a single value!).. (MUST values cannot be deleted, 
	# that is)
	if (is_array($del_hash))
	while ( list($attr, $values) = each($del_hash) ) {

		# If it has more than one value in the directory, we cannot
		# replace it.
		if ($attributes[$attr]["count"] > 1) continue;

		# does the same attribute from del_hash exist in add_hash too?
		if (array_key_exists($attr, $add_hash) && count($add_hash[$attr])) {
			$add = array_shift($add_hash[$attr]);
			$del = array_shift($del_hash[$attr]);

			if (!array_key_exists($attr, $replace_hash))
				$replace_hash[$attr] = array();
			array_push($replace_hash[$attr], $add);
		}
	}

	$operations = array("del", "add", "replace");

	# Now commit the changes, first del, then add, then replace
	$htmloutput->resultsHeader($dn);
	$failed = 0; # Becomes 1 if anything failed
	foreach ($operations as $op) {
		if ($failed) break;

		$varname = $op."_hash"; #either del/add/replace_hash
		if (!count(${$varname})) continue; # If empty, skip
		$modified = 1;
		$htmloutput->resultsTitle($op." attribute..");
		$htmloutput->resultsInnerHeader();

		reset(${$varname});
		while ((list($attr, $values) = each(${$varname})) and !$failed) {
			# FIXME make it commit each operation only once
			foreach($values as $value) {
				$entry = array();

				$entry[$attr] = $value;

				switch($op) {
					case "del": $result = @ldap_mod_del($ldap_func->ldap_conn, $dn, $entry); break;
					case "add": $result = @ldap_mod_add($ldap_func->ldap_conn, $dn, $entry); break;
					case "replace": $result = @ldap_mod_replace($ldap_func->ldap_conn, $dn, $entry); break;
				}
				$htmloutput->resultsInnerRow($attr,
formatOutputStr($value), $result);
				if (!$result) {
					$failed = 1;
					break;
				}
			}
		}
		$htmloutput->resultsInnerFooter();
	}
	if (!$modified) echo
"	<TR><TD ALIGN=\"center\">Nothing was modified!</TD</TR>\n";
	$htmloutput->resultsFooter();
	if ($failed)
		exitOnError(ERROR_LDAP_OP_FAILED, ldap_error($ldap_func->ldap_conn));
} # }}}

# {{{ deleteEntry() deletes the given entry from the directory
function deleteEntry($ldap_func, $dn) {
	$htmloutput = new HTMLOutput();

	
	$dn = formatInputStr($dn);

	$result = @ldap_delete($ldap_func->ldap_conn, $dn);
	$htmloutput->resultsHeader($dn);
	$htmloutput->resultsTitle("Deleting entry..");
	$htmloutput->resultsInnerHeader();
	$htmloutput->resultsInnerRow(NULL, NULL, $result);

	$htmloutput->resultsInnerFooter();
	$htmloutput->resultsFooter();
	if (!$result)
		exitOnError(ERROR_LDAP_OP_FAILED, ldap_error($ldap_func->ldap_conn));
}
# }}}

# {{{ newEntry() creates a new LDAP entry according to the given parameters
function newEntry($ldap_func, $post_vars) {
	$htmloutput = new HTMLOutput();

	$dn = formatInputStr($post_vars["dn"]);
	$htmloutput->resultsHeader($dn);
	$htmloutput->resultsTitle("Adding entry..");
	$htmloutput->resultsInnerHeader();

	# Let's construct $entry, which will contain the future attrs/vals
	$entry = array();
	while (list($attr, $values) = each($post_vars)) {

		# Skip if the value is not an array- it means that it's not
		# a variable ment to be an attribute
		if (!is_array($values)) continue;

		foreach ($values as $value) {
			# Skip if value is empty
			if (!$value) continue;

			if (!array_key_exists($attr, $entry))
				$entry[$attr] = array();

			array_push($entry[$attr], $value);
			$htmloutput->resultsInnerRow($attr,
formatOutputStr($value), -1);
		}
	}
	$result = @ldap_add($ldap_func->ldap_conn, $dn, $entry);
	$htmloutput->resultsInnerRow(NULL, NULL, $result);
	$htmloutput->resultsInnerFooter();
	$htmloutput->resultsFooter();
	if (!$result) 
		exitOnError(ERROR_LDAP_OP_FAILED, ldap_error($ldap_func->ldap_conn));

} # }}}

# {{{ search_form() displays a search form
function search_form($ldap_basedn) {
	include INCLUDE_PATH."/search_form.inc";
} # }}}

# {{{ search() search and return the results as an array
function search($ldap_func, $post_vars) {

	$binddn = $post_vars["basedn"];
	$filter = $post_vars["filter"];
	$scope  = $post_vars["scope"];

	if (!$binddn || !$filter || !$scope)
		exitOnError(ERROR_FEW_ARGUMENTS);

	$info = $ldap_func->search($binddn, $filter, $scope);

	echo "<H2><CENTER>".$info["count"]." result(s)</CENTER></H2><BR>\n";
	if (!$info["count"]) return;

	for ($i = 0; $i < $info["count"]; $i++) {
		$dn = $info[$i]["dn"];
		echo "<A HREF=\"".MAINFILE."?do=view_entry&amp;entry=".urlencode($dn)."\">".$dn."</A><BR>\n";
	}
} # }}}

# {{{ choose_entrytype() displays a form for choosing a new entry type
function choose_entrytype($entry_types, $ldap_func, $parent) {

	$ldap_func->getSchemaHash($name2oid, $schema_objectclasses);
	
	require INCLUDE_PATH."/choose_entrytype_form.inc";
} # }}}

# {{{ new_form() displays a form for adding a new entry
function new_form($ldap_func, $entry_types, $post_vars) {
	$entry_type = $post_vars["entry_type"] or exitOnError(ERROR_FEW_ARGUMENTS);

	$objectclasses_list = array();

	# If we have the parent DN, put ",<parent DN>" as the dn
	if ($post_vars["dn"]) $dn = ",".$post_vars["dn"];
	else
		$dn = "";

	# If custom, list of objectclasses is given as an argument
	if ($entry_type == "custom") {
		if (!count($post_vars["custom_objectclasses"])) exitOnError(ERROR_FEW_ARGUMENTS);
		$objectclasses_list = $post_vars["custom_objectclasses"];
	}
	else # If a specific entry type was chosen, list is in $entry_types
		$objectclasses_list = $entry_types[$entry_type];

	viewEntry($ldap_func, "", 0, $dn, $objectclasses_list);

	
} # }}}

# {{{ modrdn_form() displays a form for modifying the dn
function modrdn_form($ldap_func, $entry) {
	$entry = formatInputStr($entry);
	if (eregi("^([^,]+),(.*)$", $entry, $regs)) {
		$rdn		= $regs[1];
		$superior	= $regs[2];
	}
	include INCLUDE_PATH."/modrdn_form.inc";

} # }}}

# {{{ modrdn() - Modify the RDN and/or the Parent ( = rename )
function modrdn($ldap_func, $post_vars) {
	$htmloutput = new HTMLOutput;
	$entry		= formatInputStr($post_vars["entry"]);
	$newrdn		= formatInputStr($post_vars["newrdn"]);
	$deleteoldrdn	= formatInputStr($post_vars["deleteoldrdn"]);
	$newsuperior	= formatInputStr($post_vars["newsuperior"]);

	$result = ldap_rename($ldap_func->ldap_conn, $entry, $newrdn, $newsuperior, $deleteoldrdn);
	$htmloutput->resultsHeader($entry);
	$htmloutput->resultsTitle("Modify DN..");
	$htmloutput->resultsInnerHeader();
	$htmloutput->resultsInnerRow("dn", formatOutputStr($entry), -1);
	$htmloutput->resultsInnerRow("newrdn", formatOutputStr($newrdn), -1);
	$htmloutput->resultsInnerRow("deleteoldrdn",
formatOutputStr($deleteoldrdn), -1);
	$htmloutput->resultsInnerRow("newsuperior",
formatOutputStr($newsuperior), -1);
	$htmloutput->resultsInnerRow(NULL, NULL, $result);
	$htmloutput->resultsInnerFooter();
	$htmloutput->resultsFooter();
	if (!$result)
		exitOnError(ERROR_LDAP_OP_FAILED, ldap_error($ldap_func->ldap_conn));
} # }}}

###############################################
# Here we BEGIN


session_start();

if (array_key_exists("submit", $_POST))
	$submit		= $_POST["submit"];
else
	$submit = NULL;

if (array_key_exists("do", $_GET))
	$do		= $_GET["do"];
else
	$do = NULL;

if (isset($_POST["ldap_server"])) {

	# Before we use the php session feature, make sure it works :)
	if ($_SESSION["yala"] != TRUE) exitOnError(ERROR_SESSION_SUPPORT_PROBLEM);

	# If we're just after the login form:
	$_SESSION["ldap_server"] = $_POST["ldap_server"];
	$_SESSION["ldap_port"] = $_POST["ldap_port"];
	$_SESSION["ldap_basedn"] = $_POST["ldap_basedn"];
	$_SESSION["ldap_binddn"] = $_POST["ldap_binddn"];
	$_SESSION["ldap_bindpw"] = formatInputStr($_POST["ldap_bindpw"]);
	if (array_key_exists("ldap_tls", $_POST))
		$_SESSION["ldap_tls"]	= TRUE;
	else
		$_SESSION["ldap_tls"]	= FALSE;
}


if ($submit == "Login" || $submit == "Anonymous Login" || $submit == "Delete" || $submit == "New" || $submit == "Modify" || $submit == "Modrdn" || $do == "logout") {
	$javascript .= "top.left.location.reload();\n"; # Refresh after login
}

require INCLUDE_PATH."/header.inc";

# If anonymous login, act as if there is no binddn nor bindpw
if ($submit == "Anonymous Login") {
	$_SESSION["ldap_binddn"] = ""; $_SESSION["ldap_bindpw"] = "";
}
$ldap_func = login();

# Sanity checks on parameters
if (array_key_exists("empties", $_GET)) {
	$empties = $_GET["empties"]; 
	if ($empties < 0) $empties = 0; elseif ($empties > 5) $empties = 5;
}
else
	$empties = NULL;


if (DEBUG) echo $empties;
if ($do) {
	switch ($do) {
		case "reloadschema": flushCache($ldap_func); break;
		case "logout": logout(); break;
		case "search_form": search_form($_SESSION["ldap_basedn"]); break;
		case "modrdn_form": modrdn_form($ldap_func, $_GET["entry"]); break;
		case "view_entry": viewEntry($ldap_func, $_GET["entry"], $empties); break;
		case "choose_entrytype":
			if (array_key_exists("parent", $_GET))
				$parent = $_GET["parent"];
			else
				$parent = "";
			choose_entrytype($entry_types, $ldap_func, $parent);

			break;

		default: exitOnError(ERROR_BAD_OP, $do);
	}
}

if ($submit) { # If it's a form which was submitted (modify/del/add...)
	if (is_array($_POST)) {
		# First format the posted strings
		$post_vars = formatInputArray($_POST);
	  }

	switch ($submit) {
		case "Modrdn": modrdn($ldap_func, $post_vars); break;
		case "Modify": modifyEntry($ldap_func, $post_vars); break;
		case "Delete": deleteEntry($ldap_func, $post_vars["entry"]); break;
		case "New": newEntry($ldap_func, $post_vars); break;
		case "Search": search($ldap_func, $post_vars); break;
		case "Create": new_form($ldap_func, $entry_types, $post_vars); break;
		case "Anonymous Login":
		case "Login": echo "<H2>Welcome! You're logged in.<BR>In case you don't see the tree on the left frame, <A HREF=\"javascript:top.location.reload();\">refresh</A> manually...</H2>"; break;
		default: exitOnError(ERROR_BAD_OP, $submit);
	}
}

require INCLUDE_PATH."/footer.inc";


Return current item: Yet Another LDAP Administrator