_('Generic Error'),
'body'=>sprintf('%s: %s [%s]',
__METHOD__,_('Called to load a class that cant be found'),$className),
'type'=>'error'));
}
/**
* Generic Utility Functions
*/
/**
* Returns the phpLDAPadmin version currently running. The version
* is read from the file named VERSION.
*
* @return string The current version as read from the VERSION file.
*/
function pla_version() {
$version_file = realpath(LIBDIR.'../VERSION');
if (! file_exists($version_file))
$return = 'UNKNOWN';
else {
$f = fopen($version_file,'r');
$version = trim(fread($f, filesize($version_file)));
fclose($f);
# We use cvs_prefix, because CVS will translate this on checkout otherwise.
$cvs_prefix = '\$Name:';
$return = preg_replace('/^'.$cvs_prefix.' RELEASE-([0-9_]+)\s*\$$/','$1',$version);
$return = preg_replace('/_/','.',$return);
# Check if we are a CVS copy.
if (preg_match('/^'.$cvs_prefix.'?\s*\$$/',$return))
$return = 'CVS';
# Check if we are special CVS branch
elseif (preg_match('/^'.$cvs_prefix.'?\s*([a-zA-Z]+)?\s*\$$/',$return,$match))
$return = $match[1];
# If return is still the same as version, then the tag is not one we expect.
elseif ($return == $version)
$return = 'UNKNOWN';
}
if (defined('DEBUG_ENABLED') && DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* This function will convert the browser two character language into the
* default 5 character language, where the country portion should NOT be
* assumed to be upper case characters of the first two characters.
*/
function auto_lang($lang) {
switch ($lang) {
case 'ja': return 'ja_JP';
case 'cs': return 'cs_CZ';
default: return sprintf('%s_%s',$lang,strtoupper($lang));
}
}
/**
* Makes sure that the config file is properly setup and
* that your install of PHP can handle LDAP stuff.
*/
function check_config($config_file) {
global $config,$ldapservers;
global $queries, $attrs_display_order;
global $hidden_attrs, $hidden_except_dn, $hidden_attrs_ro;
global $read_only_attrs, $read_only_except_dn, $unique_attrs;
# Read in config_default.php
require_once LIBDIR.'config_default.php';
# Make sure their PHP version is current enough
if (strcmp(phpversion(),REQUIRED_PHP_VERSION) < 0)
pla_error(sprintf('phpLDAPadmin requires PHP version %s or greater.
(You are using %s)',
REQUIRED_PHP_VERSION,phpversion()));
# Make sure this PHP install has all our required extensions
if (! extension_loaded('ldap'))
system_message(array(
'title'=>_('Missing required extension'),
'body'=> 'Your install of PHP appears to be missing LDAP support.
Please install LDAP support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)',
'type'=>'error'));
# Make sure that we have php-xml loaded.
if (! function_exists('xml_parser_create'))
system_message(array(
'title'=>_('Missing required extension'),
'body'=> 'Your install of PHP appears to be missing XML support.
Please install XML support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)',
'type'=>'error'));
# Make sure their session save path is writable, if they are using a file system session module, that is.
if ( ! strcasecmp('Files',session_module_name() && ! is_writable(realpath(session_save_path()))))
system_message(array(
'title'=>_('Missing required extension'),
'body'=> 'Your PHP session configuration is incorrect. Please check the value of session.save_path in your php.ini to ensure that the directory specified there exists and is writable. The current setting of "'.session_save_path().'" is un-writable by the web server.',
'type'=>'error'));
$config = new Config;
/* Check for syntax errors in config.php
As of php 4.3.5, this NO longer catches fatal errors :( */
ob_start();
require $config_file;
$str = '';
if (ob_get_level()) {
$str = ob_get_contents();
ob_end_clean();
}
if ($str) {
$str = strip_tags($str);
$matches = array();
preg_match('/(.*):\s+(.*):.*\s+on line (\d+)/',$str,$matches);
if (isset($matches[1]) && isset($matches[2]) && isset($matches[3])) {
$error_type = $matches[1];
$error = $matches[2];
$line_num = $matches[3];
$file = file($config_file);
echo ''."\n";
echo ''."\n";
echo "\n";
echo '';
echo '
'; print_r($variable); print ''; if ($die) die(); } /** * Debug Logging to Syslog * * The global debug level is turned on in your configuration file by setting: *
* $config->custom->debug['level'] = 255;
*
* together with atleast one output direction (currently file and syslog are supported).
*
* $config->custom->debug['file'] = '/tmp/pla_debug.log';
* $config->custom->debug['syslog'] = true;
*
*
* The debug level is turned into binary, then if the message levels bit is on
* the message will be sent to the debug log. (Thus setting your debug level to 255,
* all bits on, will results in all messages being printed.)
*
* The message level bits are defined here.
* 0( 1) = Entry/Return results from function calls.
* 1( 2) = Configuration Processing
* 2( 4) = Template Processing
* 3( 8) = Schema Processing
* 4( 16) = LDAP Server Communication
* 5( 32) = Tree Processing
* 7( 64) = Other non generic messages
* 8(128) = Page Processing
* @param string $msg Message to send to syslog
* @param int $level Log bit number for this message.
* @see syslog.php
*/
function debug_log($msg,$level=0) {
global $debug_file,$timer;
# Temporary, to catch when these are not set in the function arguments.
$file = __FILE__;
$line = __LINE__;
$method = __METHOD__;
# In case we are called before we are fully initialised or if debugging is not set.
if (! isset($_SESSION[APPCONFIG]) || ! ($_SESSION[APPCONFIG]->GetValue('debug','file')
|| $_SESSION[APPCONFIG]->GetValue('debug','syslog')))
return false;
$debug_level = $_SESSION[APPCONFIG]->GetValue('debug','level');
if (! $debug_level || (! ($level & $debug_level)))
return;
$debugaddr = false;
if ($_SESSION[APPCONFIG]->GetValue('debug','addr')) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] == $_SESSION[APPCONFIG]->GetValue('debug','addr'))
$debugaddr = true;
elseif ($_SERVER['REMOTE_ADDR'] == $_SESSION[APPCONFIG]->GetValue('debug','addr'))
$debugaddr = true;
} else $debugaddr = true;
if (! $debugaddr)
return;
# If we are limiting debug to a browser, then check that
$caller = basename( $_SERVER['PHP_SELF'] );
if (func_num_args() > 2) {
$args = func_get_args();
array_shift($args);
array_shift($args);
# This is temporary, until we change all the debug_log statements.
if (is_string($args[0]) && preg_match('/.php$/',$args[0])) {
$file = array_shift($args);
$line = array_shift($args);
$method = array_shift($args);
}
$fargs = array();
foreach ($args as $key) {
if (is_array($key) || is_object($key))
array_push($fargs,serialize($key));
else
array_push($fargs,$key);
}
$msg = vsprintf($msg, array_values($fargs));
}
if (function_exists('stopwatch'))
$timer = stopwatch();
else
$timer = null;
$debug_message = sprintf('[%2.3f] %3s-%s(%04s): %s: %s',$timer,$level,basename($file),$line,$method,substr($msg,0,200));
if ($debug_file || $_SESSION[APPCONFIG]->GetValue('debug','file')) {
if (! $debug_file)
$debug_file = fopen($_SESSION[APPCONFIG]->GetValue('debug','file'),
$_SESSION[APPCONFIG]->GetValue('debug','append') ? 'a' : 'w');
fwrite($debug_file,$debug_message."\n");
}
if ($_SESSION[APPCONFIG]->GetValue('debug','syslog'))
syslog_notice($debug_message);
return syslog_notice( sprintf('%s(%s): %s',$caller,$level,$msg) );
}
/**
* Display an error message in the system message panel of the page.
*/
function error($msg,$type='note',$fatal=false,$backtrace=false) {
global $www;
global $counter;
# if the error is fatal, we'll need to stop here.
if (! isset($www['page']) && $fatal)
$www['page'] = new page(null);
# Just a check to see that we are called right.
if (! isset($www['page']) && ! $fatal)
die("Function error called incorrectly [$msg]");
$www['page']->setsysmsg(array('title'=>_('Error'),'body'=>$msg,'type'=>$type));
# Spin loop detection
if ($counter++ > 20) {
debug_dump("Spin loop detection.");
debug_dump(array('msg'=>$msg,'session'=>$_SESSION['sysmsg'],'www'=>$www),1);
}
if ($fatal)
$www['page']->display(array('tree'=>false));
}
/**
* Return the result of a form variable, with optional default
*/
function get_request($attr,$type=null,$die=false,$default=null) {
switch($type) {
case 'GET':
$value = isset($_GET[$attr]) ? $_GET[$attr] : $default;
break;
case 'REQUEST':
$value = isset($_REQUEST[$attr]) ? $_REQUEST[$attr] : $default;
break;
case 'SESSION':
$value = isset($_SESSION[$attr]) ? $_SESSION[$attr] : $default;
break;
case 'POST':
default:
$value = isset($_POST[$attr]) ? $_POST[$attr] : $default;
break;
}
if (! is_array($value) && trim($value) == "")
$value = $default;
if ($die && is_null($value))
system_message(array(
'title'=>_('Generic Error'),
'body'=>sprintf('%s: Called "%s" without "%s" using "%s"',
basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),$attr,$type),
'type'=>'error'),
sprintf('index.php?server_id=%s',$ldapserver->server_id));
return $value;
}
/**
* Record a system message.
* This function can be used as an alternative to generate a system message, if page hasnt yet been defined.
*/
function system_message($msg,$redirect=null) {
if (! is_array($msg))
return null;
if (! isset($msg['title']) && ! isset($msg['body']))
return null;
$_SESSION['sysmsg'][] = $msg;
if ($redirect) {
header("Location: $redirect");
die();
}
}
/**
* Other Functions
*/
/**
* Encryption using blowfish algorithm
*
* @param string original data
* @param string the secret
*
* @return string the encrypted result
*
* @access public
*
* @author lem9 (taken from the phpMyAdmin source)
*/
function pla_blowfish_encrypt($data,$secret=null) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$data,$secret);
# If our secret is null or blank, get the default.
if ($secret === null || ! trim($secret))
$secret = $_SESSION[APPCONFIG]->GetValue('session','blowfish');
# If the secret isnt set, then just return the data.
if (! trim($secret))
return $data;
if (file_exists(LIBDIR.'blowfish.php'))
require_once LIBDIR.'blowfish.php';
else
return $data;
$pma_cipher = new Horde_Cipher_blowfish;
$encrypt = '';
for ($i=0; $i
* $obfuscate_password_display = true;
*
*
* @param string $enc Password encoding type
* @return bool
*/
function obfuscate_password_display($enc=null) {
if ($_SESSION[APPCONFIG]->GetValue('appearance','obfuscate_password_display'))
$return = true;
elseif (! $_SESSION[APPCONFIG]->GetValue('appearance','show_clear_password') && (is_null($enc) || $enc == 'clear'))
$return = true;
else
$return = false;
if (DEBUG_ENABLED)
debug_log('Entered with (%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$enc,$return);
return $return;
}
/**
* Returns an HTML-beautified version of a DN.
* Internally, this function makes use of pla_explode_dn() to break the
* the DN into its components. It then glues them back together with
* "pretty" HTML. The returned HTML is NOT to be used as a real DN, but
* simply displayed.
*
* @param string $dn The DN to pretty-print.
* @return string
*/
function pretty_print_dn($dn) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$dn);
$dn_save = $dn;
$dn = pla_explode_dn($dn);
if (! $dn)
return $dn_save;
foreach ($dn as $i => $element) {
$element = htmlspecialchars($element);
$element = explode('=',$element,2);
$element = implode('=',$element);
$dn[$i] = $element;
}
$dn = implode(',',$dn);
return $dn;
}
/**
* Given a string, this function returns true if the string has the format
* of a DN (ie, looks like "cn=Foo,dc=example,dc=com"). Returns false otherwise.
* The purpose of this function is so that developers can examine a string and
* know if it looks like a DN, and draw a hyperlink as needed.
*
* (See unit_test.php for test cases)
*
* @param string $attr The attribute to examine for "DNness"
* @see unit_test.php
* @return bool
*/
function is_dn_string($str) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$str);
/* Try to break the string into its component parts if it can be done
ie, "uid=Manager" "dc=example" and "dc=com" */
$parts = pla_explode_dn($str);
if (! is_array($parts) || ! count($parts))
return false;
/* Foreach of the "parts", look for an "=" character,
and make sure neither the left nor the right is empty */
foreach ($parts as $part) {
if (! strpos($part,"="))
return false;
$sub_parts = explode('=',$part,2);
$left = $sub_parts[0];
$right = $sub_parts[1];
if ( ! strlen(trim($left)) || ! strlen(trim($right)))
return false;
if (strpos($left,'#') !== false)
return false;
}
# We survived the above rigor. This is a bonified DN string.
return true;
}
/**
* Get whether a string looks like an email address (user@example.com).
*
* @param string $str The string to analyze.
* @return bool Returns true if the specified string looks like
* an email address or false otherwise.
*/
function is_mail_string($str) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$str);
$mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/";
if (preg_match($mail_regex,$str))
return true;
else
return false;
}
/**
* Get whether a string looks like a web URL (http://www.example.com/)
*
* @param string $str The string to analyze.
* @return bool Returns true if the specified string looks like
* a web URL or false otherwise.
*/
function is_url_string($str) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$str);
$url_regex = '/(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/';
if (preg_match($url_regex,$str))
return true;
else
return false;
}
/**
* Get a customized file for a server
* We don't need any caching, because it's done by PHP
*
* @param int $server_id The ID of the server
* @param string $filename The requested filename
*
* @return string The customized filename, if exists, or the standard one
*/
function get_custom_file($server_id,$filename,$path) {
# Set default return
$return = $path.$filename;
$custom = $_SESSION[APPCONFIG]->ldapservers->GetValue($server_id,'custom','pages_prefix');
if (! is_null($custom) && is_file(realpath($path.$custom.$filename)))
$return = $path.$custom.$filename;
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$server_id,$filename,$path,$return);
return $return;
}
/**
* Compares 2 DNs. If they are equivelant, returns 0, otherwise,
* returns their sorting order (similar to strcmp()):
* Returns < 0 if dn1 is less than dn2.
* Returns > 0 if dn1 is greater than dn2.
*
* The comparison is performed starting with the top-most element
* of the DN. Thus, the following list:
*
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* dc=example,dc=com
* cn=Fred,ou=people,dc=example,dc=org
* cn=Dave,ou=people,dc=example,dc=org
*
* Will be sorted thus using usort( $list, "pla_compare_dns" ):
*
* dc=com
* dc=example,dc=com
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* cn=Dave,ou=people,dc=example,dc=org
* cn=Fred,ou=people,dc=example,dc=org
*
*
* @param string $dn1 The first of two DNs to compare
* @param string $dn2 The second of two DNs to compare
* @return int
*/
function pla_compare_dns($dn1,$dn2) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,$dn1,$dn2);
# If pla_compare_dns is passed via a tree, then we'll just get the DN part.
if (is_array($dn1))
$dn1 = $dn1['dn'];
if (is_array($dn2))
$dn2 = $dn2['dn'];
# If they are obviously the same, return immediately
if (! strcasecmp($dn1,$dn2))
return 0;
$dn1_parts = pla_explode_dn(pla_reverse_dn($dn1));
$dn2_parts = pla_explode_dn(pla_reverse_dn($dn2));
assert(is_array($dn1_parts));
assert(is_array($dn2_parts));
# Foreach of the "parts" of the smaller DN
for ($i=0; $i < count($dn1_parts) && $i < count($dn2_parts); $i++) {
/* dnX_part is of the form: "cn=joe" or "cn = joe" or "dc=example"
ie, one part of a multi-part DN. */
$dn1_part = $dn1_parts[$i];
$dn2_part = $dn2_parts[$i];
/* Each "part" consists of two sub-parts:
1. the attribute (ie, "cn" or "o")
2. the value (ie, "joe" or "example") */
$dn1_sub_parts = explode('=',$dn1_part,2);
$dn2_sub_parts = explode('=',$dn2_part,2);
$dn1_sub_part_attr = trim($dn1_sub_parts[0]);
$dn2_sub_part_attr = trim($dn2_sub_parts[0]);
if (0 != ($cmp = strcasecmp($dn1_sub_part_attr,$dn2_sub_part_attr)))
return $cmp;
$dn1_sub_part_val = trim($dn1_sub_parts[1]);
$dn2_sub_part_val = trim($dn2_sub_parts[1]);
if (0 != ($cmp = strcasecmp($dn1_sub_part_val,$dn2_sub_part_val)))
return $cmp;
}
/* If we iterated through all entries in the smaller of the two DNs
(ie, the one with fewer parts), and the entries are different sized,
then, the smaller of the two must be "less than" than the larger. */
if (count($dn1_parts) > count($dn2_parts)) {
return 1;
} elseif (count($dn2_parts) > count($dn1_parts)) {
return -1;
} else {
return 0;
}
}
/**
* Prunes off anything after the ";" in an attr name. This is useful for
* attributes that may have ";binary" appended to their names. With
* real_attr_name(), you can more easily fetch these attributes' schema
* with their "real" attribute name.
*
* @param string $attr_name The name of the attribute to examine.
* @return string
*/
function real_attr_name($attr_name) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$attr_name);
$attr_name = preg_replace('/;.*$/U','',$attr_name);
return $attr_name;
}
/**
* For hosts who have 'enable_auto_uid_numbers' set to true, this function will
* get the next available uidNumber using the host's preferred mechanism
* (uidpool or search). The uidpool mechanism uses a user-configured entry in
* the LDAP server to store the last used uidNumber. This mechanism simply fetches
* and increments and returns that value. The search mechanism is more complicated
* and slow. It searches all entries that have uidNumber set, finds the smalles and
* "fills in the gaps" by incrementing the smallest uidNumber until an unused value
* is found. Both mechanisms do NOT prevent race conditions or toe-stomping, so
* care must be taken when actually creating the entry to check that the uidNumber
* returned here has not been used in the mean time. Note that the two different
* mechanisms may (will!) return different values as they use different algorithms
* to arrive at their result. Do not be alarmed if (when!) this is the case.
*
* Also note that both algorithms are susceptible to a race condition. If two admins
* are adding users simultaneously, the users may get identical uidNumbers with this
* function.
*
* See config.php.example for more notes on the two auto uidNumber mechanisms.
*
* @param object $ldapserver The LDAP Server Object of interest.
* @return int
*
* @todo Must turn off auto_uid|gid in template if config is disabled.
*/
function get_next_number(&$ldapserver,$startbase='',$type='uid',$increment=false,$filter=false) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$ldapserver->server_id,$startbase,$type,$increment,$filter);
if (! $_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','enable'))
return false;
# Based on the configured mechanism, go get the next available uidNumber!
$mechanism = $_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','mechanism');
switch ($mechanism) {
case 'search' :
if (! $startbase) {
$base_dn = $_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','search_base');
if (is_null($base_dn))
pla_error(sprintf(_('You specified the "auto_uid_number_mechanism" as "search" in your
configuration for server %s, but you did not specify the
"auto_uid_number_search_base". Please specify it before proceeding.'),$ldapserver->name));
} else {
$base_dn = $startbase;
}
if (! $ldapserver->dnExists($base_dn))
pla_error(sprintf(_('Your phpLDAPadmin configuration specifies an invalid auto_uid_search_base for server %s'),
$ldapserver->name));
$filter = '(|(uidNumber=*)(gidNumber=*))';
$results = array();
# Check see and use our alternate uid_dn and password if we have it.
$con = $ldapserver->connect(false,'auto_search',false,true,
$_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','dn'),
$_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','pass'));
if (! $con)
pla_error(sprintf(_('Unable to bind to %s with your with auto_uid credentials. Please check your configuration file.'),$ldapserver->name));
$search = $ldapserver->search($con,$base_dn,$filter,array('uidNumber','gidNumber'),'sub',false,$_SESSION[APPCONFIG]->GetValue('deref','search'));
if (! is_array($search))
pla_error('Untrapped error.');
foreach ($search as $dn => $attrs) {
$attrs = array_change_key_case($attrs);
$entry = array();
switch ($type) {
case 'uid' :
if (isset($attrs['uidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['uidnumber'];
$results[] = $entry;
}
break;
case 'gid' :
if (isset($attrs['gidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['gidnumber'];
$results[] = $entry;
}
break;
default :
pla_error(sprintf('Unknown type [%s] in search',$type));
}
}
# construct a list of used numbers
$autonum = array();
foreach ($results as $result)
if (isset($result['uniqnumber']))
$autonum[] = $result['uniqnumber'];
$autonum = array_unique($autonum);
sort($autonum);
foreach ($autonum as $uid)
$uid_hash[$uid] = 1;
# start with the least existing autoNumber and add 1
if ($_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','min'))
$minNumber = $_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','min');
else
$minNumber = intval($autonum[0]) + 1;
# this loop terminates as soon as we encounter the next available minNumber
while (isset($uid_hash[$minNumber]))
$minNumber++;
return $minNumber;
break;
case 'uidpool':
$con = $ldapserver->connect(false,'auto_search',false,true,
$_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','dn'),
$_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','pass'));
if (! $con)
pla_error(sprintf(_('Unable to bind to %s with your with auto_uid credentials. Please check your configuration file.'),$ldapserver->name));
# assume that uidpool dn is set in config file if no filter given
if (empty($filter))
$uidpool_dn = $_SESSION[APPCONFIG]->ldapservers->GetValue($ldapserver->server_id,'auto_number','uidpool_dn');
else {
$filter = str_replace(array('&',':::'),array('&',','),$filter);
$dns = $ldapserver->search($con,$startbase,$filter,array('dn'),'sub');
switch (count($dns)) {
case '1':
break;
case '0':
pla_error(_('Uidpool dn not found, please change filter parameter'));
default:
pla_error(_('There is more than one dn for uidpool,please change filter parameter'));
}
list ($key,$attrs) = each($dns);
$attrs = array_change_key_case($attrs);
$uidpool_dn = $attrs['dn'];
}
if (empty($uidpool_dn))
pla_error(_('uidpool_dn not found. Please check filter (arg 3) or set up uidpool_dn in config file'));
$attrs = array($type);
$key = strtolower($type);
$realkey = $type;
$number = $ldapserver->search($con,$uidpool_dn,$filter,$attrs,'base');
list($rkey,$number) = each($number);
$number = array_change_key_case($number);
$number = $number[$key];
if (isset($increment) && ($increment == 'true')) {
$updatedattr = array ($key => $number + 1);
$ldapserver->modify($uidpool_dn,$updatedattr);
}
return $number;
break;
# No other cases allowed. The user has an error in the configuration
default :
pla_error( sprintf( _('You specified an invalid value for auto_uid_number_mechanism ("%s")
in your configration. Only "uidpool" and "search" are valid.
Please correct this problem.') , $mechanism) );
}
}
/**
* Given a DN and server ID, this function reads the DN's objectClasses and
* determines which icon best represents the entry. The results of this query
* are cached in a session variable so it is not run every time the tree
* browser changes, just when exposing new DNs that were not displayed
* previously. That means we can afford a little bit of inefficiency here
* in favor of coolness. :)
*
* This function returns a string like "country.png". All icon files are assumed
* to be contained in the /images/ directory of phpLDAPadmin.
*
* Developers are encouraged to add new icons to the images directory and modify
* this function as needed to suit their types of LDAP entries. If the modifications
* are general to an LDAP audience, the phpLDAPadmin team will gladly accept them
* as a patch.
*
* @param int $server_id The ID of the LDAP server housing the DN of interest.
* @param string $dn The DN of the entry whose icon you wish to fetch.
*
* @return string
*/
function get_icon( $ldapserver, $dn ) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$ldapserver->server_id,$dn);
// fetch and lowercase all the objectClasses in an array
$object_classes = $ldapserver->getDNAttr($dn,'objectClass',true);
if (! is_array($object_classes))
$object_classes = array($object_classes);
if( $object_classes === null || $object_classes === false || ! is_array( $object_classes ) )
$object_classes = array();
foreach( $object_classes as $i => $class )
$object_classes[$i] = strtolower( $class );
$rdn = get_rdn( $dn );
$rdn_parts = explode( '=', $rdn, 2 );
$rdn_value = isset( $rdn_parts[0] ) ? $rdn_parts[0] : null;
$rdn_attr = isset( $rdn_parts[1] ) ? $rdn_parts[1] : null;
unset( $rdn_parts );
// return icon filename based upon objectClass value
if( in_array( 'sambaaccount', $object_classes ) &&
'$' == $rdn{ strlen($rdn) - 1 } )
return 'nt_machine.png';
if( in_array( 'sambaaccount', $object_classes ) )
return 'nt_user.png';
elseif( in_array( 'person', $object_classes ) ||
in_array( 'organizationalperson', $object_classes ) ||
in_array( 'inetorgperson', $object_classes ) ||
in_array( 'account', $object_classes ) ||
in_array( 'posixaccount', $object_classes ) )
return 'user.png';
elseif( in_array( 'organization', $object_classes ) )
return 'o.png';
elseif( in_array( 'organizationalunit', $object_classes ) )
return 'ou.png';
elseif( in_array( 'organizationalrole', $object_classes ) )
return 'uid.png';
elseif( in_array( 'dcobject', $object_classes ) ||
in_array( 'domainrelatedobject', $object_classes ) ||
in_array( 'domain', $object_classes ) ||
in_array( 'builtindomain', $object_classes ))
return 'dc.png';
elseif( in_array( 'alias', $object_classes ) )
return 'go.png';
elseif( in_array( 'room', $object_classes ) )
return 'door.png';
elseif( in_array( 'device', $object_classes ) )
return 'device.png';
elseif( in_array( 'document', $object_classes ) )
return 'document.png';
elseif( in_array( 'country', $object_classes ) ) {
$tmp = pla_explode_dn( $dn );
$cval = explode( '=', $tmp[0], 2 );
$cval = isset( $cval[1] ) ? $cval[1] : false;
if( $cval && false === strpos( $cval, ".." ) &&
file_exists( realpath( sprintf("./images/countries/%s.png",strtolower($cval)) ) ) )
return sprintf("countries/%s.png",strtolower($cval));
else
return 'country.png';
}
elseif( in_array( 'jammvirtualdomain', $object_classes ) )
return 'mail.png';
elseif( in_array( 'locality', $object_classes ) )
return 'locality.png';
elseif( in_array( 'posixgroup', $object_classes ) ||
in_array( 'groupofnames', $object_classes ) ||
in_array( 'group', $object_classes ) )
return 'ou.png';
elseif( in_array( 'applicationprocess', $object_classes ) )
return 'process.png';
elseif( in_array( 'groupofuniquenames', $object_classes ) )
return 'uniquegroup.png';
elseif( in_array( 'iphost', $object_classes ) )
return 'host.png';
elseif( in_array( 'nlsproductcontainer', $object_classes ) )
return 'n.png';
elseif( in_array( 'ndspkikeymaterial', $object_classes ) )
return 'lock.png';
elseif( in_array( 'server', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'volume', $object_classes ) )
return 'hard-drive.png';
elseif( in_array( 'ndscatcatalog', $object_classes ) )
return 'catalog.png';
elseif( in_array( 'resource', $object_classes ) )
return 'n.png';
elseif( in_array( 'ldapgroup', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'ldapserver', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'nisserver', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'rbscollection', $object_classes ) )
return 'ou.png';
elseif( in_array( 'dfsconfiguration', $object_classes ) )
return 'nt_machine.png';
elseif( in_array( 'applicationsettings', $object_classes ) )
return 'server-settings.png';
elseif( in_array( 'aspenalias', $object_classes ) )
return 'mail.png';
elseif( in_array( 'container', $object_classes ) )
return 'folder.png';
elseif( in_array( 'ipnetwork', $object_classes ) )
return 'network.png';
elseif( in_array( 'samserver', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'lostandfound', $object_classes ) )
return 'find.png';
elseif( in_array( 'infrastructureupdate', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'filelinktracking', $object_classes ) )
return 'files.png';
elseif( in_array( 'automountmap', $object_classes ) ||
in_array( 'automount', $object_classes ) )
return 'hard-drive.png';
elseif( 0 === strpos( $rdn_value, "ipsec" ) ||
0 == strcasecmp( $rdn_value, "IP Security" ) ||
0 == strcasecmp( $rdn_value, "MSRADIUSPRIVKEY Secret" ) ||
0 === strpos( $rdn_value, "BCKUPKEY_" ) )
return 'lock.png';
elseif( 0 == strcasecmp( $rdn_value, "MicrosoftDNS" ) )
return 'dc.png';
// Oh well, I don't know what it is. Use a generic icon.
else
return 'object.png';
}
/**
* Appends a servers base to a "sub" dn or returns the base.
*
* @param string $base The baseDN to be added if the DN is relative
* @param string $sub_dn The DN to be made absolute
* @return string|null Returns null if both base is null and sub_dn is null or empty
*/
function expand_dn_with_base( $base,$sub_dn ) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$base,$sub_dn);
$empty_str = ( is_null($sub_dn) || ( ( $len = strlen( trim( $sub_dn ) ) ) == 0 ) );
if ( $empty_str ) {
return $base;
} elseif ( $sub_dn[$len - 1] != ',' ) {
// If we have a string which doesn't need a base
return $sub_dn;
} else {
return $sub_dn . $base;
}
}
/**
* Reads the query, checks all values and sets defaults.
*
* @param int $query_id The ID of the predefined query.
* @return array The fixed query or null on error
*/
function get_cleaned_up_predefined_search($query_id) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$query_id);
if (! isset($_SESSION[APPCONFIG]->queries[$query_id]))
return null;
$query = $_SESSION[APPCONFIG]->queries[$query_id];
$base = (isset($query['base'])) ? $query['base'] : null;
if (isset($query['filter']) && trim($query['filter']))
$filter = $query['filter'];
else
$filter = 'objectclass=*';
$scope = isset($query['scope']) && (in_array($query['scope'],array('base','sub','one'))) ?
$query['scope'] : 'sub';
if (isset($query['attributes']) && trim($query['filter']))
$attrib = $query['attributes'];
else
$attrib = 'dn, cn, sn, objectClass';
return array('base'=>$base,'filter'=>$filter,'scope'=>$scope,'attributes'=>$attrib);
}
/**
* Used to generate a random salt for crypt-style passwords. Salt strings are used
* to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses
* not only the user's password but also a randomly generated string. The string is
* stored as the first N characters of the hash for reference of hashing algorithms later.
*
* --- added 20021125 by bayu irawan %s | |||
---|---|---|---|
'; printf(' | %s | ',$msg); echo '||
%s: %s | |||
%s: %s (%s) | |||
%s: %s | |||
%s: %s | |||
%s: (%s) | |||
%s | |||
%s | %s | ||
%s | %s | ||
%s | %s | ||
%s | %s | ||
%s | %s (%s) | ||
%s | %s',_('Function'),$line['function']); if (isset($line['args'])) print_r($line['args']); echo ' |