_('Generic Error'), 'body'=>sprintf('%s: %s [%s]', __METHOD__,_('Called to load a class that cant be found'),$className), 'type'=>'error')); } /** * Generic Utility Functions */ /** * Custom error handling function. * When a PHP error occurs, PHP will call this function rather than printing * the typical PHP error string. This provides the application the ability to * format an error message so that it looks better. * Optionally, it can present a link so that a user can search/submit bugs. * This function is not to be called directly. It is exclusively for the use of * PHP internally. If this function is called by PHP from within a context * where error handling has been disabled (ie, from within a function called * with "@" prepended), then this function does nothing. * * @param int $errno The PHP error number that occurred (ie, E_ERROR, E_WARNING, E_PARSE, etc). * @param string $errstr The PHP error string provided (ie, "Warning index "foo" is undefined) * @param string $file The file in which the PHP error ocurred. * @param int $lineno The line number on which the PHP error ocurred * * @see set_error_handler */ function pla_error_handler($errno,$errstr,$file,$lineno) { if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) debug_log('Entered with (%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__, $errno,$errstr,$file,$lineno); /** * error_reporting will be 0 if the error context occurred * within a function call with '@' preprended (ie, @ldap_bind() ); * So, don't report errors if the caller has specifically * disabled them with '@' */ if (ini_get('error_reporting') == 0 || error_reporting() == 0) return; $file = basename($file); $caller = basename($_SERVER['PHP_SELF']); $errtype = ''; switch ($errno) { case E_STRICT: $errtype = 'E_STRICT'; break; case E_ERROR: $errtype = 'E_ERROR'; break; case E_WARNING: $errtype = 'E_WARNING'; break; case E_PARSE: $errtype = 'E_PARSE'; break; case E_NOTICE: $errtype = 'E_NOTICE'; break; case E_CORE_ERROR: $errtype = 'E_CORE_ERROR'; break; case E_CORE_WARNING: $errtype = 'E_CORE_WARNING'; break; case E_COMPILE_ERROR: $errtype = 'E_COMPILE_ERROR'; break; case E_COMPILE_WARNING: $errtype = 'E_COMPILE_WARNING'; break; case E_USER_ERROR: $errtype = 'E_USER_ERROR'; break; case E_USER_WARNING: $errtype = 'E_USER_WARNING'; break; case E_USER_NOTICE: $errtype = 'E_USER_NOTICE'; break; case E_ALL: $errtype = 'E_ALL'; break; default: $errtype = sprintf('%s: %s',_('Unrecognized error number'),$errno); } # Take out extra spaces in error strings. $errstr = preg_replace('/\s+/',' ',$errstr); if ($errno == E_NOTICE) { $body = '
%s: | %s (%s) |
%s: | %s %s %s, %s %s |
Versions: | PLA: %s, PHP: %s, SAPI: %s |
Web server: | %s |
'; 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;
# Just a check to see that we are called right.
if (! isset($www['page']) && ! $fatal)
die("Function error called incorrectly [$msg]");
# if the error is fatal, we'll need to stop here.
if (! isset($www['page']))
$www['page'] = new page(null);
$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);
}
# Do we have a backtrace to display?
if ($backtrace) {
$backtraceblock = new block();
$backtraceblock->SetTitle('PHP Debug Backtrace');
$body = '%s | %s (%s) | |
%s | %s', _('Function'),$line['function']); if (isset($line['args'])) if (file_exists(LIBDIR.'../tools/unserialize.php')) $body .= sprintf(' (%s)', '/tools/unserialize.php', htmlspecialchars(serialize($line['args'])), htmlspecialchars(serialize($line['args']))); else $body .= sprintf(' (%s)',htmlspecialchars(serialize($line['args']))); $body .= ' |
* $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: %s (%s) | |
%s: %s | |
%s: %s | |
%s: (%s) |
* draw_jpeg_photos( 0, "cn=Bob,ou=People,dc=example,dc=com", "jpegPhoto" true, false, "border: 1px; width: 150px" );
* draw_jpeg_photos( 1, "cn=Fred,ou=People,dc=example,dc=com" );
*
*
* @param int $server_id The ID of the server of interest.
* @param string $dn The DN of the entry that contains the jpeg attribute you want to draw.
* @param string $attr_name The name of the attribute containing the jpeg data (usually 'jpegPhoto').
* @param bool $draw_delete_buttons If true, draws a button beneath the image titled 'Delete' allowing the user
* to delete the jpeg attribute by calling JavaScript function deleteAttribute() provided
* in the default modification template.
* @param bool $draw_bytes_and_size If true, draw text below the image indicating the byte size and dimensions.
* @param string $table_html_attrs Specifies optional CSS style attributes for the table tag.
*
* @return void
*/
function draw_jpeg_photos($ldapserver,$dn,$attr_name='jpegPhoto',$draw_delete_buttons=false,
$draw_bytes_and_size=true,$table_html_attrs='align="left"',$img_html_attrs='') {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s,%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$ldapserver->server_id,$dn,$attr_name,$draw_delete_buttons,
$draw_bytes_and_size,$table_html_attrs,$img_html_attrs);
$fixed_width = false;
$fixed_height = false;
if (eregi(' width',$img_html_attrs) || eregi('^width',$img_html_attrs))
$fixed_width = true;
if (eregi(' height=',$img_html_attrs) || eregi('^height=',$img_html_attrs))
$fixed_height = true;
if (isset($table_html_attrs) && trim($table_html_attrs) )
printf(''); printf('%s',$attr_name,_('Delete Photo')); continue; } if (function_exists('getimagesize')) { $jpeg_dimensions = @getimagesize($jpeg_filename); $width = $jpeg_dimensions[0]; $height = $jpeg_dimensions[1]; } else { $width = 0; $height = 0; } if ($width > 300) { $scale_factor = 300 / $width; $img_width = 300; $img_height = intval($height * $scale_factor); } else { $img_width = $width; $img_height = $height; } printf(' ', ($fixed_width ? '' : 'width="'.$img_width.'" '), ($fixed_height ? '' : 'height="'.$img_height.'"'), ($img_html_attrs ? $img_html_attrs : ''),basename($jpeg_filename)); if ($draw_bytes_and_size) printf('%s %s. %s x %s pixels. ',number_format($jpeg_data_size),_('bytes'),$width,$height); if ($draw_delete_buttons) # printf('%s', $attr_name,_('Delete photo')); } if (isset($table_html_attrs) && trim($table_html_attrs)) echo ' |
* Array
* (
* [0] => uid=ppratt
* [1] => ou=People
* [2] => dc=example
* [3] => dc=com
* )
*
*
* NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value';
*/
function pla_explode_dn($dn,$with_attributes=0) {
global $CACHE;
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,$dn,$with_attributes);
if (isset($CACHE['explode'][$dn][$with_attributes])) {
if (DEBUG_ENABLED)
debug_log('Return CACHED result (%s) for (%s)',1,__FILE__,__LINE__,__METHOD__,
$CACHE['explode'][$dn][$with_attributes],$dn);
return $CACHE['explode'][$dn][$with_attributes];
}
$dn = addcslashes($dn,'<>+";');
# split the dn
$result[0] = ldap_explode_dn(dn_escape($dn),0);
$result[1] = ldap_explode_dn(dn_escape($dn),1);
if (! $result[$with_attributes]) {
if (DEBUG_ENABLED)
debug_log('Returning NULL - NO result.',1,__FILE__,__LINE__,__METHOD__);
return array();
}
# Remove our count value that ldap_explode_dn returns us.
unset($result[0]['count']);
unset($result[1]['count']);
# Record the forward and reverse entries in the cache.
foreach ($result as $key => $value) {
# translate hex code into ascii for display
$result[$key] = dn_unescape($value);
$CACHE['explode'][join(',',$result[0])][$key] = $result[$key];
$CACHE['explode'][join(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]);
}
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$dn,$with_attributes,$result[$with_attributes]);
return $result[$with_attributes];
}
/**
* Parse a DN and escape any special characters
*/
function dn_escape($dn) {
$olddn = $dn;
# Check if the RDN has a comma and escape it.
while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn))
$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn);
$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn);
if (DEBUG_ENABLED)
debug_log('Entered with (%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$olddn,$dn);
return $dn;
}
/**
* Parse a DN and unescape any special characters
*/
function dn_unescape($dn) {
if (is_array($dn)) {
$a = array();
foreach ($dn as $key => $rdn) {
$a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
}
return $a;
} else {
return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
}
}
/**
* Fetches the URL for the specified item. This is a convenience function for
* fetching project HREFs (like bugs)
*
* @param string $type One of "open_bugs", "add_bug", "donate", or "add_rfe"
* (rfe = request for enhancement)
* @return string The URL to the requested item.
*/
function get_href($type,$extra_info='') {
$sf = 'https://sourceforge.net';
$pla = 'http://phpldapadmin.wiki.sourceforge.net';
$group_id = '61828';
$bug_atid = '498546';
$rfe_atid = '498549';
$forum_id = '34809';
switch($type) {
case 'add_bug':
return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$bug_atid);
case 'add_rfe':
return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$rfe_atid);
case 'credits':
return sprintf('%s/Credits',$pla);
case 'documentation':
return sprintf('%s/Documentation',$pla);
case 'forum':
return sprintf('%s/mailarchive/forum.php?forum_id=%s',$sf,$forum_id);
case 'open_bugs':
return sprintf('%s/tracker/?group_id=%s&atid=%s',$sf,$group_id,$bug_atid);
case 'search_bug':
return sprintf('%s/tracker/?func=search&group_id=%s&atid=%s&set=custom&_status=100&_group=100&order=summary%s',$sf,$group_id,$bug_atid,$extra_info);
case 'donate':
return sprintf('%s/donate/index.php?group_id=%s',$sf,$group_id);
case 'help':
return sprintf('help.php');
default:
return null;
}
}
/**
* Returns the current time as a double (including micro-seconds).
*
* @return double The current time in seconds since the beginning of the UNIX epoch (Midnight Jan. 1, 1970)
*/
function utime () {
$time = explode(' ',microtime());
$usec = (double)$time[0];
$sec = (double)$time[1];
return $sec + $usec;
}
/**
* Converts an array to a query-string with the option to exclude certain variables
* from the returned query string. This is convenient if callers want to convert the
* current GET query string or POST array into a string and replace certain
* variables with their own.
*
* @param array $array The associate array to convert whose form is such that the keys are the
* names of the variables and the values are said variables' values like this:
*
* Array
* (
* [server_id] = 0,
* [dn] = "dc=example,dc=com",
* [attr] = "sn"
* )
*
* This will produce a string like this: "server_id=0&dn=dc=example,dc=com&attr=sn"
* @param array $exclude_vars (optional) An array of variables to exclude in the resulting string
* @param bool $url_encode_ampersands (optional) By default, this function encodes all ampersand-separators
* as & but callers may dislabe this by specifying false here. For example, URLs on HTML
* pages should encode the ampersands but URLs in header( "Location: http://example.com" ) should
* not be encoded.
* @return string The string created from the array.
*/
function array_to_query_string( $array, $exclude_vars=array(), $url_encode_ampersands=true ) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
count($array),count($exclude_vars),$url_encode_ampersands);
if (! is_array($array))
return '';
if (! $array)
return '';
$str = '';
$i = 0;
foreach($array as $name => $val) {
if(! in_array($name, $exclude_vars)) {
if (is_array($val)) {
foreach($val as $v) {
if ($i > 0)
if($url_encode_ampersands) $str .= '&';
else $str .= '&';
$str .= rawurlencode($name) . '[]=' . rawurlencode($v);
$i++;
}
} else {
if ($i > 0)
if($url_encode_ampersands) $str .= '&';
else $str .= '&';
$str .= rawurlencode($name) . '=' . rawurlencode($val);
$i++;
}
}
}
return $str;
}
/**
* Reverses a DN such that the top-level RDN is first and the bottom-level RDN is last
* For example:
*
* cn=Brigham,ou=People,dc=example,dc=com
*
* Becomes:
*
* dc=com,dc=example,ou=People,cn=Brigham
*
* This makes it possible to sort lists of DNs such that they are grouped by container.
*
* @param string $dn The DN to reverse
* @return string The reversed DN
*
* @see pla_compare_dns
* @see pla_explode_dns
*/
function pla_reverse_dn($dn) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$dn);
return (join(',',array_reverse(pla_explode_dn($dn))));
}
/**
*
*/
function sortAttrs($a,$b) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,$a,$b);
$attrs_display_order = isset($_SESSION[APPCONFIG]->attrs_display_order) ? $_SESSION[APPCONFIG]->attrs_display_order : array();
if ($a == $b)
return 0;
# Check if $a is in $attrs_display_order, get its key
$a_key = array_search($a,$attrs_display_order);
# If not, check if its friendly name is $attrs_display_order, get its key
# If not, assign one greater than number of elements.
if ( $a_key === false ) {
if ($_SESSION[APPCONFIG]->haveFriendlyName($a)) {
$a_key = array_search($_SESSION[APPCONFIG]->getFriendlyName($a),$attrs_display_order);
if ($a_key == '')
$a_key = count($attrs_display_order)+1;
} else {
$a_key = count($attrs_display_order)+1;
}
}
$b_key = array_search($b,$attrs_display_order);
if ($b_key === false) {
if ($_SESSION[APPCONFIG]->haveFriendlyName($b)) {
$b_key = array_search($_SESSION[APPCONFIG]->getFriendlyName($b),$attrs_display_order);
if ($b_key == '')
$b_key = count($attrs_display_order)+1;
} else {
$b_key = count($attrs_display_order)+1;
}
}
# Case where neither $a, nor $b are in $attrs_display_order, $a_key = $b_key = one greater than num elements.
# So we sort them alphabetically
if ($a_key === $b_key) {
$a = strtolower($_SESSION[APPCONFIG]->getFriendlyName($a));
$b = strtolower($_SESSION[APPCONFIG]->getFriendlyName($b));
return strcmp($a,$b);
}
# Case where at least one attribute or its friendly name is in $attrs_display_order
# return -1 if $a before $b in $attrs_display_order
return ($a_key < $b_key) ? -1 : 1;
}
/**
* Compare the names of two Atrribute objects
*/
function attrcmp($a1, $a2) {
return strcmp(strtolower($a1->getFriendlyName()), strtolower($a2->getFriendlyName()));
}
/**
* Reads an array and returns the array values back in lower case
* @param array $array The array to convert the values to lowercase.
* @returns array Array with values converted to lowercase.
*/
function arrayLower($array) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$array);
if (! is_array($array))
return $array;
$newarray = array();
foreach ($array as $key => $value) {
$newarray[$key] = strtolower($value);
}
return $newarray;
}
/**
* Strips all slashes from the specified array in place (pass by ref).
* @param Array $array The array to strip slashes from, typically one of
* $_GET, $_POST, or $_COOKIE.
*/
function array_stripslashes(&$array) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$array);
if (is_array($array))
while (list($key) = each($array))
if (is_array($array[$key]) && $key != $array)
array_stripslashes($array[$key]);
else
$array[$key] = stripslashes($array[$key]);
}
/**
* Gets the USER_AGENT string from the $_SERVER array, all in lower case in
* an E_NOTICE safe manner.
* @return string|false The user agent string as reported by the browser.
*/
function get_user_agent_string() {
if( isset( $_SERVER['HTTP_USER_AGENT'] ) )
$return = strtolower( $_SERVER['HTTP_USER_AGENT'] );
else
$return = false;
if (DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* Determines whether the browser's operating system is UNIX (or something like UNIX).
* @return boolean True if the brower's OS is UNIX, false otherwise.
*/
function is_browser_os_unix() {
$agent_strs = array(
'sunos','sunos 4','sunos 5',
'i86',
'irix','irix 5','irix 6','irix6',
'hp-ux','09.','10.',
'aix','aix 1','aix 2','aix 3','aix 4',
'inux',
'sco',
'unix_sv','unix_system_v','ncr','reliant','dec','osf1',
'dec_alpha','alphaserver','ultrix','alphastation',
'sinix',
'freebsd','bsd',
'x11','vax','openvms'
);
$return = string_in_array_value(get_user_agent_string(),$agent_strs);
if (DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* Determines whether the browser's operating system is Windows.
* @return boolean True if the brower's OS is Windows, false otherwise.
*/
function is_browser_os_windows() {
$agent_strs = array(
'win','win95','windows 95',
'win16','windows 3.1','windows 16-bit','windows','win31','win16','winme',
'win2k','winxp',
'win98','windows 98','win9x',
'winnt','windows nt','win32',
'32bit'
);
$return = string_in_array_value(get_user_agent_string(),$agent_strs);
if (DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* Determines whether the browser's operating system is Macintosh.
* @return boolean True if the brower's OS is mac, false otherwise.
*/
function is_browser_os_mac() {
$agent_strs = array(
'mac','68000','ppc','powerpc'
);
$return = string_in_array_value(get_user_agent_string(),$agent_strs);
if (DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* Checks if a string exists in an array, ignoring case.
*
* @param string $needle What you are looking for
* @param array $haystack The array that you think it is in.
* @return bool True if its there, false if its not.
*/
function in_array_ignore_case($needle,$haystack) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,$needle,$haystack);
if (! is_array($haystack))
return false;
if (! is_string($needle))
return false;
$return = false;
foreach ($haystack as $element) {
if (DEBUG_ENABLED)
debug_log('Comparing (%s) with (%s)',64,__FILE__,__LINE__,__METHOD__,$needle,$element);
if (is_string($element) && 0 == strcasecmp($needle,$element))
$return = true;
}
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$needle,$haystack,$return);
return $return;
}
/**
* Checks if a string exists in part in an array value, ignoring case.
*
* @param string $needle What you are looking for
* @param array $haystack The array that you think it is in.
* @return bool True if its there, false if its not.
*/
function string_in_array_value( $needle, $haystack ) {
# Set default return
$return = false;
if (! is_string($needle)) return $return;
if (! is_array($haystack)) return $return;
foreach ($haystack as $element)
if (is_string($element) && (strpos($needle,$element) !== false)) {
$return = true;
break;
}
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$needle,$haystack,$return);
return $return;
}
/**
* String padding
*
* @param string input string
* @param integer length of the result
* @param string the filling string
* @param integer padding mode
*
* @return string the padded string
*/
function full_str_pad($input, $pad_length, $pad_string = '', $pad_type = 0) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$input,$pad_length,$pad_string,$pad_type);
$str = '';
$length = $pad_length - strlen($input);
if ($length > 0) { // str_repeat doesn't like negatives
if ($pad_type == STR_PAD_RIGHT) { // STR_PAD_RIGHT == 1
$str = $input.str_repeat($pad_string, $length);
} elseif ($pad_type == STR_PAD_BOTH) { // STR_PAD_BOTH == 2
$str = str_repeat($pad_string, floor($length/2));
$str .= $input;
$str .= str_repeat($pad_string, ceil($length/2));
} else { // defaults to STR_PAD_LEFT == 0
$str = str_repeat($pad_string, $length).$input;
}
} else { // if $length is negative or zero we don't need to do anything
$str = $input;
}
return $str;
}
/**
* Gets a DN string using the user-configured tree_display_format string to format it.
*/
function draw_formatted_dn($ldapserver,$entry) {
$dn = $entry->getDn();
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$ldapserver->server_id,$dn);
$format = $_SESSION[APPCONFIG]->GetValue('appearance','tree_display_format');
preg_match_all('/%[a-zA-Z_0-9]+/',$format,$tokens);
$tokens = $tokens[0];
if (DEBUG_ENABLED)
debug_log('The tokens are (%s)',1,__FILE__,__LINE__,__METHOD__,$tokens);
foreach ($tokens as $token) {
if (strcasecmp($token,'%dn') == 0)
$format = str_replace($token,pretty_print_dn($dn),$format);
elseif (strcasecmp($token,'%rdn') == 0)
$format = str_replace($token,pretty_print_dn($entry->getRdn()),$format);
elseif (strcasecmp($token,'%rdnvalue') == 0) {
$rdn = get_rdn($dn,0,true);
$rdn_value = explode('=',$rdn,2);
$rdn_value = $rdn_value[1];
$format = str_replace($token,$rdn_value,$format);
} else {
$attr_name = str_replace('%','',$token);
$attr_values = $ldapserver->getDNAttr($dn,$attr_name);
if (is_null($attr_values) || (count($attr_values) <= 0))
$display = '<'._('none').'>';
elseif (is_array($attr_values))
$display = htmlspecialchars(implode(', ',$attr_values));
else
$display = htmlspecialchars($attr_values);
$format = str_replace($token,$display,$format);
}
}
return $format;
}
/**
* Takes a shadow* attribute and returns the date as an integer.
* @param $attrs array of Attribute objects
* @param $attr a shadow attribute name
*/
function shadow_date( $attrs, $attr) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$attrs,$attr);
$shadowlastchange_attribute = null;
$shadowmax_attribute = null;
$shadowdate_attribute = null;
foreach ($attrs as $attribute) {
if ($attribute->getName() == 'shadowLastChange' || $attribute->getName() == 'shadowlastchange') {
$shadowlastchange_attribute = $attribute;
} elseif ($attribute->getName() == 'shadowMax' || $attribute->getName() == 'shadowmax') {
$shadowmax_attribute = $attribute;
} elseif ($attribute->getName() == $attr || $attribute->getName() == $attr) {
$shadowdate_attribute = $attribute;
}
if ($shadowlastchange_attribute && $shadowmax_attribute && $shadowdate_attribute) {
break;
}
}
$shadowLastChange = $shadowlastchange_attribute ? $shadowlastchange_attribute->getValue(0) : null;
$shadowMax = $shadowmax_attribute ? $shadowmax_attribute->getValue(0) : null;
if( 0 == strcasecmp( $attr, 'shadowLastChange' ) && $shadowLastChange)
$shadow_date = $shadowLastChange;
elseif ( 0 == strcasecmp( $attr, 'shadowMax' ) && ($shadowMax > 0) && $shadowLastChange )
$shadow_date = $shadowLastChange+$shadowMax;
elseif (0 == strcasecmp($attr, 'shadowWarning') && ($shadowdate_attribute->getValue(0) > 0)
&& $shadowLastChange && $shadowMax && $shadowMax > 0)
$shadow_date = $shadowLastChange+$shadowMax-$shadowdate_attribute->getValue(0);
elseif (0 == strcasecmp($attr, 'shadowInactive') && ($shadowdate_attribute->getValue(0) > 0)
&& $shadowLastChange && $shadowMax && $shadowMax > 0)
$shadow_date = $shadowLastChange+$shadowMax+$shadowdate_attribute->getValue(0);
elseif (0 == strcasecmp($attr, 'shadowMin') && ($shadowdate_attribute->getValue(0) > 0)
&& $shadowLastChange)
$shadow_date = $shadowLastChange+$shadowdate_attribute->getValue(0);
elseif (0 == strcasecmp($attr, 'shadowExpire') && ($shadowdate_attribute->getValue(0) > 0))
$shadow_date = $shadowdate_attribute->getValue(0);
else // Couldn't interpret the shadow date (could be 0 or -1 or something)
return false;
return $shadow_date*24*3600;
}
/**
* This function will clean up the values use during a search - namely, values that have brackets
* as that messes up the search filter.
* @param string $val String that will be used in the search filter.
* @return string $result String that is ready for the search filter.
*/
function clean_search_vals( $val ) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$val);
# Remove any escaped brackets already.
$val = preg_replace('/\\\\([\(\)])/','$1',$val);
# The string might be a proper search filter
if (preg_match('/^\([&\|!]\(/',$val) || (preg_match('/\(([^\(|\)])*\)/',$val)))
return $val;
else
return preg_replace('/([\(\)])/','\\\\$1',$val);
}
/**
* Server html select list
*/
function server_select_list ($select_id=null,$only_logged_on=true,$select_name='server_id',$js_script=null) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$select_id,$only_logged_on,$select_name,$js_script);
$count = 0;
$server_menu_html = sprintf('';
if ($count > 1)
return $server_menu_html;
elseif ($count)
return sprintf('%s ',
$server->name,$select_name,$server->server_id);
else
return null;
}
function server_info_list($visible=false) {
$server_info_list = array();
if (isset($_SESSION[APPCONFIG])) {
foreach ($_SESSION[APPCONFIG]->ldapservers->GetServerList() as $id) {
$ldapserver = $_SESSION[APPCONFIG]->ldapservers->Instance($id);
if (! $ldapserver->isVisible($id))
continue;
$server_info_list[$id]['id'] = $id;
$server_info_list[$id]['name'] = $ldapserver->name;
$server_info_list[$id]['base_dns'] = $ldapserver->getBaseDN();
}
}
if (defined('DEBUG_ENABLED') && DEBUG_ENABLED)
debug_log('Entered with (%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$visible,$server_info_list);
return $server_info_list;
}
function enc_type_select_list($enc_type) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$enc_type);
$html = '";
return $html;
}
// Converts a little-endian hex-number to one, that 'hexdec' can convert
function littleEndian($hex) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$hex);
$result = '';
for ($x=strlen($hex)-2; $x >= 0; $x=$x-2)
$result .= substr($hex,$x,2);
return $result;
}
function binSIDtoText($binsid) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$binsid);
$hex_sid=bin2hex($binsid);
$rev = hexdec(substr($hex_sid,0,2)); // Get revision-part of SID
$subcount = hexdec(substr($hex_sid,2,2)); // Get count of sub-auth entries
$auth = hexdec(substr($hex_sid,4,12)); // SECURITY_NT_AUTHORITY
$result = "$rev-$auth";
for ($x=0;$x < $subcount; $x++) {
$subauth[$x] =
hexdec(littleEndian(substr($hex_sid,16+($x*8),8))); // get all SECURITY_NT_AUTHORITY
$result .= "-".$subauth[$x];
}
return $result;
}
/**
* Sort a multi dimensional array.
* @param array $data Multi demension array passed by reference
* @param string $sortby Comma delimited string of sort keys.
* @param bool $rev Whether to reverse sort.
* @returnn array $data Sorted multi demension array.
*/
function masort(&$data,$sortby,$rev=0) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$data,$sortby,$rev);
# if the array to sort is null or empty
if (! $data) return;
static $sort_funcs = array();
if (empty($sort_funcs[$sortby])) {
$code = "\$c=0;\n";
foreach (split(',',$sortby) as $key) {
$code .= "if (is_object(\$a) || is_object(\$b)) {\n";
$code .= " if (\$a->$key != \$b->$key)\n";
if ($rev)
$code .= " return (\$a->$key < \$b->$key ? -1 : 1);\n";
else
$code .= " return (\$a->$key > \$b->$key ? -1 : 1);\n";
$code .= "} else {\n";
$code .= "if ((! isset(\$a['$key'])) && (! isset(\$b['$key']))) return 0;\n";
$code .= "if ((! isset(\$a['$key'])) && isset(\$b['$key'])) return -1;\n";
$code .= "if (isset(\$a['$key']) && (! isset(\$b['$key']))) return 1;\n";
$code .= "if (is_numeric(\$a['$key']) && is_numeric(\$b['$key'])) {\n";
$code .= " if (\$a['$key'] != \$b['$key'])\n";
if ($rev)
$code .= " return (\$a['$key'] < \$b['$key'] ? -1 : 1);\n";
else
$code .= " return (\$a['$key'] > \$b['$key'] ? -1 : 1);\n";
$code .= "} else {\n";
if ($rev)
$code .= " if ( (\$c = strcasecmp(\$b['$key'],\$a['$key'])) != 0 ) return \$c;\n";
else
$code .= " if ( (\$c = strcasecmp(\$a['$key'],\$b['$key'])) != 0 ) return \$c;\n";
$code .= "}}\n";
}
$code .= 'return $c;';
$sort_func = $sort_funcs[$sortby] = create_function('$a, $b',$code);
} else {
$sort_func = $sort_funcs[$sortby];
}
$sort_func = $sort_funcs[$sortby];
uasort($data,$sort_func);
}
/**
* Query LDAP and return a hash.
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @param string $base_dn The base DN to use.
* @param string $filter LDAP Query filter.
* @param string $key LDAP attribute to use as key.
* @param array $attrs LDAP attributes to use as values.
* @param bool $sort Specify false to not sort results by DN
* or true to have the returned array sorted by DN (uses ksort)
* or an array of attribute names to sort by attribute values
* @return array $results Array of values keyed by $key.
*/
function return_ldap_hash($ldapserver,$base_dn,$filter,$key,$attrs,$sort=true) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s,%s,%s,%s,%s)',1,__FILE__,__LINE__,__METHOD__,
$ldapserver->server_id,$base_dn,$filter,$key,$attrs,$sort);
$ldapquery = $ldapserver->search(null,$base_dn,$filter,$attrs,'sub',$sort,LDAP_DEREF_NEVER,0);
$results = array();
foreach ($ldapquery as $dn => $dnattrs) {
if (isset($dnattrs[$key])) {
if (is_array($dnattrs[$key])) {
foreach ($dnattrs[$key] as $i => $k) {
foreach ($attrs as $attr) {
if (isset($dnattrs[$attr])) {
$v = '';
if (is_array($dnattrs[$attr]) && isset($dnattrs[$attr][$i]))
$v = $dnattrs[$attr][$i];
if (is_string($v) && (strlen($v) > 0))
$results[$k][$attr] = $v;
}
}
}
} else {
foreach ($attrs as $attr) {
if (isset($dnattrs[$attr]))
$results[$dnattrs[$key]][$attr] = $dnattrs[$attr];
}
}
}
}
return $results;
}
/**
* This function returns a string automatically generated
* based on the criteria defined in the array $criteria in config.php
*/
function password_generate() {
$no_use_similiar = ! $_SESSION[APPCONFIG]->GetValue('password','use_similar');
$lowercase = $_SESSION[APPCONFIG]->GetValue('password','lowercase');
$uppercase = $_SESSION[APPCONFIG]->GetValue('password','uppercase');
$digits = $_SESSION[APPCONFIG]->GetValue('password','numbers');
$punctuation = $_SESSION[APPCONFIG]->GetValue('password','punctuation');
$length = $_SESSION[APPCONFIG]->GetValue('password','length');
$outarray = array();
if ($no_use_similiar) {
$raw_lower = "a b c d e f g h k m n p q r s t u v w x y z";
$raw_numbers = "2 3 4 5 6 7 8 9";
$raw_punc = "# $ % ^ & * ( ) _ - + = . , [ ] { } :";
} else {
$raw_lower = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
$raw_numbers = "1 2 3 4 5 6 7 8 9 0";
$raw_punc = "# $ % ^ & * ( ) _ - + = . , [ ] { } : |";
}
$llower = explode(" ", $raw_lower);
shuffle($llower);
$lupper = explode(" ", strtoupper($raw_lower));
shuffle($lupper);
$numbers = explode(" ", $raw_numbers);
shuffle($numbers);
$punc = explode(" ", $raw_punc);
shuffle($punc);
if ($lowercase > 0)
$outarray = array_merge($outarray,a_array_rand($llower,$lowercase));
if ($uppercase > 0)
$outarray = array_merge($outarray,a_array_rand($lupper,$uppercase));
if ($digits > 0)
$outarray = array_merge($outarray,a_array_rand($numbers,$digits));
if ($punctuation > 0)
$outarray = array_merge($outarray,a_array_rand($punc,$punctuation));
$num_spec = $lowercase + $uppercase + $digits + $punctuation;
if ($num_spec < $length) {
$leftover = array();
if ($lowercase > 0)
$leftover = array_merge($leftover, $llower);
if ($uppercase > 0)
$leftover = array_merge($leftover, $lupper);
if ($digits > 0)
$leftover = array_merge($leftover, $numbers);
if ($punctuation > 0)
$leftover = array_merge($leftover, $punc);
if (count($leftover) == 0)
$leftover = array_merge($leftover,$llower,$lupper,$numbers,$punc);
shuffle($leftover);
$outarray = array_merge($outarray, a_array_rand($leftover,$length-$num_spec));
}
shuffle($outarray);
$return = implode('', $outarray);
if (DEBUG_ENABLED)
debug_log('Entered with (), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,$return);
return $return;
}
/**
* This function returns an array of $num_req values
* randomly picked from the $input array
*
* @param array of values
* @param integer, number of values in returned array
* @return string the padded string
*/
function a_array_rand($input,$num_req) {
if (count($input) == 0)
return array();
if ($num_req < 1)
return array();
$return = array();
if ($num_req > count($input)) {
for($i = 0; $i < $num_req; $i++) {
$idx = array_rand($input, 1);
$return[] = $input[$idx];
}
} else {
$idxlist = array_rand($input, $num_req);
if ($num_req == 1)
$idxlist = array($idxlist);
for($i = 0; $i < count($idxlist); $i++)
$return[] = $input[$idxlist[$i]];
}
if (DEBUG_ENABLED)
debug_log('Entered with (%s,%s), Returning (%s)',1,__FILE__,__LINE__,__METHOD__,
$input,$num_req,$return);
return $return;
}
/**
* Draws an HTML date selector button which, when clicked, pops up a date selector dialog.
* @param string $attr The name of the date type attribute
*/
function draw_date_selector_link( $attr ) {
if (DEBUG_ENABLED)
debug_log('Entered with (%s)',1,__FILE__,__LINE__,__METHOD__,$attr);
$href = "javascript:dateSelector('$attr');";
$title = _('Click to popup a dialog to select a date graphically');
printf('',$href,$title,$attr);
}
/**
* This is for Opera. By putting "random junk" in the query string, it thinks
* that it does not have a cached version of the page, and will thus
* fetch the page rather than display the cached version
*/
function random_junk() {
$time = gettimeofday();
return md5(strtotime('now').$time['usec']);
}
/**
* Returns a HTML id that can be used in the URL after the #.
*
* @param string $dn The DN to pretty-print.
* @return string
*/
function htmlid($sid,$dn) {
return sprintf('SID%s:%s',$sid,preg_replace('/[\ =,]/','_',$dn));
}
?>