diff --git a/lam/docs/devel/other_libs.htm b/lam/docs/devel/other_libs.htm index 60a7e331..5c1ba4b6 100644 --- a/lam/docs/devel/other_libs.htm +++ b/lam/docs/devel/other_libs.htm @@ -28,17 +28,10 @@ tags. The message variables are included with printf().
The parameters of StatusMessage() are described in the developer FAQ.

-

Tree view and schema browser

-The files tree.inc and schema.inc contain functions which are needed by -the tree view and the schema browser.
+

Schema browser

+The file schema.inc contains functions which are needed by +the schema browser.
These functions were copied from phpLDAPadmin (PLA).

- \ No newline at end of file diff --git a/lam/lib/export.inc b/lam/lib/export.inc deleted file mode 100755 index 58df28b0..00000000 --- a/lam/lib/export.inc +++ /dev/null @@ -1,967 +0,0 @@ -'ldif', - 'desc' => 'LDIF', - 'extension' => 'ldif' -); - -$exporters[] = array( - 'output_type'=>'dsml', - 'desc' => 'DSML V.1', - 'extension' => 'xml' -); - -$exporters[] = array( - 'output_type'=>'vcard', - 'desc' => 'VCARD 2.1', - 'extension' => 'vcf' -); - -$exporters[] = array( - 'output_type'=>'csv', - 'desc' => 'CSV', - 'extension' => 'csv' -); - -/** - * This class encapsulate informations about the ldap server - * from which the export is done. - * The following info are provided within this class: - * - * $base_dn: if the source of the export is the ldap server, - * it indicates the base dn of the search. - * $query_filter: if the source of the export is the ldap server, - * it indicates the query filter for the search. - * $scope: if the source of the export is the ldap server, - * it indicates the scope of the search. - * - * @package tools - */ - -class LdapExportInfo { - - var $base_dn; - var $query_filter; - var $scope; - - /** - * Create a new LdapExportInfo object - * - * @param String $base_dn the base_dn for the search in a ldap server - * @param String $query_filter the query filter for the search - * @param String $scope the scope of the search in a ldap server - */ - - function LdapExportInfo($base_dn = NULL, $query_filter = NULL, $scope = NULL){ - $this->base_dn = $base_dn; - $this->query_filter = $query_filter; - $this->scope = $scope; - } -} - - -/** - * This class represents the base class of all exporters - * It can be subclassed directly if your intend is to write - * a source exporter(ie. it will act only as a decoree - * which will be wrapped by an another exporter.) - * If you consider writting an exporter for filtering data - * or directly display entries, please consider subclass - * the PlaExporter - * - * @see PlaExporter - * @package tools - */ - -class PlaAbstractExporter{ - - /** - * Return the number of entries - * @return int the number of entries to be exported - */ - function pla_num_entries(){} - - /** - * Return true if there is some more entries to be processed - * @return bool if there is some more entries to be processed - */ - function pla_has_entry(){} - - /** - * Return the entry as an array - * @return array an entry as an array - */ - function pla_fetch_entry_array(){} - - /** - * Return the entry as an Entry object - * @return Entry an entry as an Entry Object - */ - function pla_fetch_entry_object(){} - - /** - * Return a PlaLdapInfo Object - * @return LdapInfo Object with info from the ldap serveur - */ - function pla_get_ldap_info(){} - -}// end PlaAbstractExporter - - - -/** - * PlaExporter acts a wrapper around another exporter. - * In other words, it will act as a decorator for another decorator - * - * @package tools - */ -class PlaExporter extends PlaAbstractExporter{ - // the default CRLN - var $br="\n"; - // the wrapped $exporter - var $exporter; - - /** - * Constructor - * @param source $source the decoree for this exporter - */ - function PlaExporter( $source ){ - $this->exporter = $source; - } - - /** - * Return the number of entries - * @return int the number of entries to be exported - */ - function pla_num_entries(){ - return $this->exporter->pla_num_entries(); - } - - /** - * Return true if there is some more entries to be processed - * @return bool if there is some more entries to be processed - */ - function pla_has_entry(){ - return $this->exporter->pla_has_entry(); - } - - /** - * Return the entry as an array - * @return array an entry as an array - */ - function pla_fetch_entry_array(){ - return $this->exporter->pla_fetch_entry_array(); - } - - /** - * Return the entry as an Entry object - * @return Entry an entry as an Entry Object - */ - function pla_fetch_entry_object(){ - return $this->exporter->pla_fetch_entry_object(); - } - - /** - * Return a PlaLdapInfo Object - * @return LdapInfo Object with info from the ldap serveur - */ - function pla_get_ldap_info(){ - return $this->exporter->pla_get_ldap_info(); - } - - /** - * Helper method to check if the attribute value should be base 64 encoded. - * @param String $str the string to check. - * @return bool true if the string is safe ascii, false otherwise. - */ - function is_safe_ascii( $str ){ - for( $i=0; $i 127 ) - return false; - return true; - } - - /** - * Abstract method use to export data. - * Must be implemented in a sub-class if you write an exporter - * which export data. - * Leave it empty if you write a sub-class which do only some filtering. - */ - function export(){} - - /** - * Set the carriage return /linefeed for the export - * @param String $br the CRLF to be set - */ - function setOutputFormat( $br ){ - $this->br = $br; - } - -}// end PlaExporter - - -/** - * Export data from a ldap server - * @extends PlaAbstractExporter - * @package tools - */ - -class PlaLdapExporter extends PlaAbstractExporter{ - var $entry_id; - var $results; - var $scope; - var $entry_array; - var $num_entries; - var $ldap_info; - var $queryFilter; - var $hasNext; - var $attributes; - var $ds; - /** - * Create a PlaLdapExporter object. - * @param String $queryFilter the queryFilter for the export - * @param String $base_dn the base_dn for the data to export - * @param String $scope the scope for export - */ - function PlaLdapExporter($queryFilter , $base_dn , $scope, $attributes){ - $this->scope = $scope; - $this->base_dn = $base_dn; - $this->queryFilter = $queryFilter; - // infos for the server - $this->ldap_info = new LdapExportInfo($base_dn,$queryFilter,$scope); - // boolean to check if there is more entries - $this->hasNext = 0; - // boolean to check the state of the connection - - $this->attributes = $attributes; - - $this->ds = $_SESSION['ldap']->server(); - - // get the data to be exported - if( $this->scope == 'base' ) - $this->results = @ldap_read($this->ds, $this->base_dn, $this->queryFilter,$this->attributes); - elseif( $this->scope == 'one' ) - $this->results = @ldap_list($this->ds, $this->base_dn, $this->queryFilter, $this->attributes); - else // scope == 'sub' - $this->results = @ldap_search($this->ds, $this->base_dn, $this->queryFilter, $this->attributes, 0, 0, 0, LDAP_DEREF_NEVER); - - // if no result, there is a something wrong - if( ! $this->results ) - StatusMessage("ERROR", 'Encountered an error while performing search.', ldap_error( $this->ds )); - - // get the number of entries to be exported - $this->num_entries = @ldap_count_entries( $this->ds,$this->results ); - - if( $this->entry_id = @ldap_first_entry( $this->ds,$this->results ) ){ - $this->hasNext = 1; - } - }//end constructor - - /** - * Return the entry as an array - * @return array an entry as an array - */ - function pla_fetch_entry_array(){ - return $this->entry_array; - } - - /** - * Return the entry as an Entry object - * @return Entry an entry as an Entry Object - */ - function pla_fetch_entry_object(){ - // to do - } - - /** - * Return a PlaLdapInfo Object - * @return LdapInfo Object with info from the ldap serveur - */ - function pla_get_ldap_info(){ - return $this->ldap_info; - } - - /** - * Return the number of entries - * @return int the number of entries to be exported - */ - function pla_num_entries(){ - return $this->num_entries; - } - - /** - * Return true if there is some more entries to be processed - * @return bool if there is some more entries to be processed - */ - function pla_has_entry(){ - if( $this->hasNext ){ - unset( $this->entry_array ); - $dn = @ldap_get_dn( $this->ds,$this->entry_id ); - $this->entry_array['dn'] = $dn; - - //get the attributes of the entry - $attrs = @ldap_get_attributes($this->ds,$this->entry_id); - $attr = @ldap_first_attribute( $this->ds,$this->entry_id ); - if(($attr !== false) && ($attr !== null)) { - - //iterate over the attributes - while( $attr ){ - if( is_attr_binary($attr ) ){ - $this->entry_array[$attr] = @ldap_get_values_len( $this->ds,$this->entry_id,$attr ); - } - else{ - $this->entry_array[$attr] = @ldap_get_values( $this->ds,$this->entry_id,$attr ); - } - unset( $this->entry_array[$attr]['count'] ); - $attr = @ldap_next_attribute( $this->ds,$this->entry_id ); - }// end while attr - - if(!$this->entry_id = @ldap_next_entry( $this->ds,$this->entry_id ) ){ - $this->hasNext = 0; - } - }// end if attr - return true; - } - else{ - return false; - } - } - -} // end PlaLdapExporter - -/** - * Export entries to ldif format - * @extends PlaExporter - * @package tools - */ -class PlaLdifExporter extends PlaExporter{ - - // variable to keep the count of the entries - var $counter = 0; - - // the maximum length of the ldif line - var $MAX_LDIF_LINE_LENGTH = 76; - - /** - * Create a PlaLdifExporter object - * @param PlaAbstractExporter $exporter the source exporter - */ - function PlaLdifExporter( $exporter ){ - $this->exporter = $exporter; - } - - /** - * Export entries to ldif format - */ - function export(){ - $pla_ldap_info = $this->pla_get_ldap_info(); - $this->displayExportInfo($pla_ldap_info); - - //While there is an entry, fecth the entry as an array - while($this->pla_has_entry()){ - $entry = $this->pla_fetch_entry_array(); - $this->counter++; - - // display comment before each entry - $title_string = "# " . _("Entry") . " " . $this->counter . ": " . $entry['dn'] ; - if( strlen( $title_string ) > $this->MAX_LDIF_LINE_LENGTH-3 ) - $title_string = substr( $title_string, 0, $this->MAX_LDIF_LINE_LENGTH-3 ) . "..."; - echo "$title_string$this->br"; - - // display dn - if( $this->is_safe_ascii( $entry['dn'] )) - $this->multi_lines_display("dn: ". $entry['dn']); - else - $this->multi_lines_display("dn:: " . base64_encode( $entry['dn'] )); - array_shift($entry); - - // display the attributes - foreach( $entry as $key => $attr ){ - foreach( $attr as $value ){ - if( !$this->is_safe_ascii($value) || is_attr_binary($key ) ){ - $this->multi_lines_display( $key.":: " . base64_encode( $value ) ); - } - else{ - $this->multi_lines_display( $key.": ".$value ); - } - } - }// end foreach $entry - - echo $this->br; - // flush every 5th entry (sppeds things up a bit) - if( 0 == $this->counter % 5 ) - flush(); - } - } - - // display info related to this export - function displayExportInfo($pla_ldap_info){ - echo "version: 1$this->br$this->br"; - echo "# " . sprintf( _("LDIF Export for: %s"), $pla_ldap_info->base_dn ) . $this->br; - echo "# " . _('Search scope') . ": " . $pla_ldap_info->scope . $this->br; - echo "# " . _('Search filter') . ": " . $pla_ldap_info->query_filter . $this->br; - echo "# " . _('Total entries') . ": " . $this->pla_num_entries() . $this->br; - echo $this->br; - } - - /** - * Helper method to wrap ldif lines - * @param String $str the line to be wrapped if needed. - */ - function multi_lines_display( $str ){ - - $length_string = strlen($str); - $max_length = $this->MAX_LDIF_LINE_LENGTH; - - while ($length_string > $max_length){ - echo substr($str,0,$max_length).$this->br." "; - $str= substr($str,$max_length,$length_string); - $length_string = strlen($str); - - // need to do minus one to align on the right - // the first line with the possible following lines - // as these will have an extra space - $max_length = $this->MAX_LDIF_LINE_LENGTH-1; - } - echo $str."".$this->br; - } - -} - -/** - * Export entries to DSML v.1 - * @extends PlaExporter - * @package tools - */ - -class PlaDsmlExporter extends PlaExporter{ - - //not in use - var $indent_step = 2; - var $counter = 0; - - /** - * Create a PlaDsmlExporter object - * @param PlaAbstractExporter $exporter the decoree exporter - */ - function PlaDsmlExporter( $exporter ){ - $this->exporter = $exporter; - } - - /** - * Export the entries to DSML - */ - function export(){ - $pla_ldap_info = $this->pla_get_ldap_info(); - // not very elegant, but do the job for the moment as we have just 4 level - $directory_entries_indent = " "; - $entry_indent= " "; - $attr_indent = " "; - $attr_value_indent = " "; - - // print declaration - echo "$this->br"; - - // print root element - echo "$this->br"; - - // print info related to this export - echo "" . $this->br; - - - echo $directory_entries_indent."$this->br"; - //While there is an entry, fetch the entry as an array - while($this->pla_has_entry()){ - $entry = $this->pla_fetch_entry_array(); - $this->counter++; - // display dn - echo $entry_indent."".$this->br; - array_shift($entry); - - // echo the objectclass attributes first - if(isset($entry['objectClass'])){ - echo $attr_indent."".$this->br; - foreach($entry['objectClass'] as $ocValue){ - echo $attr_value_indent."$ocValue".$this->br; - } - echo $attr_indent."".$this->br; - unset($entry['objectClass']); - } - - $binary_mode = 0; - // display the attributes - foreach($entry as $key=>$attr){ - echo $attr_indent."".$this->br; - - // if the attribute is binary, set the flag $binary_mode to true - $binary_mode = is_attr_binary($key)?1:0; - - foreach($attr as $value){ - echo $attr_value_indent."".($binary_mode?base64_encode( $value): htmlspecialchars( $value ) )."".$this->br; - } - echo $attr_indent."".$this->br; - }// end foreach $entry - echo $entry_indent."".$this->br; - - // flush every 5th entry (speeds things up a bit) - if( 0 == $this->counter % 5 ) - flush(); - } - echo $directory_entries_indent."$this->br"; - echo "".$this->br; - } -} - - -/** - * @package tools - */ -class PlaVcardExporter extends PlaExporter{ - - // mappping one to one attribute - var $vcardMapping = array('cn' => 'FN', - 'title' => 'TITLE', - 'homePhone' => 'TEL;HOME', - 'mobile' => 'TEL;CELL', - 'mail' => 'EMAIL;Internet', - 'labeledURI' =>'URL', - 'o' => 'ORG', - 'audio' => 'SOUND', - 'facsmileTelephoneNumber' =>'TEL;WORK;HOME;VOICE;FAX', - 'jpegPhoto' => 'PHOTO;ENCODING=BASE64', - 'businessCategory' => 'ROLE', - 'description' => 'NOTE' - ); - - var $deliveryAddress = array("postOfficeBox", - "street", - "l", - "st", - "postalCode", - "c"); - - function PlaVcardExporter($exporter){ - $this->exporter = $exporter; - } - - /** - * When doing an exporter, the method export need to be overriden. - * A basic implementation is provided here. Customize to your need - **/ - - function export(){ - - // With the method pla->get_ldap_info, - // you have access to some values related - // to you ldap server - $ldap_info = $this->pla_get_ldap_info(); - $base_dn = $ldap_info->base_dn; - $scope = $ldap_info->scope; - $server_name = $ldap_info->name; - $server_host = $ldap_info->host; - - while( $this->pla_has_entry() ){ - $entry = $this->pla_fetch_entry_array(); - - //fetch the dn - $dn = $entry['dn']; - unset( $entry['dn'] ); - - // check the attributes needed for the delivery address - // field - $addr = "ADR:"; - foreach( $this->deliveryAddress as $attr_name ){ - if( isset( $entry[$attr_name] ) ){ - $addr .= $entry[$attr_name][0]; - unset($entry[$attr_name]); - } - $addr .= ';'; - } - echo "BEGIN:VCARD$this->br"; - - // loop for the attributes - foreach( $entry as $attr_name=>$attr_values ){ - - // if an attribute of the ldap entry exist - // in the mapping array for vcard - if( isset( $this->vcardMapping[$attr_name] ) ){ - - // case of organisation. Need to append the - // possible ou attribute - if( 0 == strcasecmp( $attr_name , 'o' )){ - echo $this->vcardMapping[$attr_name].":$attr_values[0]"; - if( isset($entry['ou'] ) ) - foreach( $entry['ou'] as $ou_value ){ - echo ";$ou_value"; - } - } - // the attribute is binary. (to do : need to fold the line) - else if( 0 == strcasecmp( $attr_name,'audio') || 0 == strcasecmp( $attr_name,'jpegPhoto') ){ - echo $this->vcardMapping[$attr_name].":$this->br"; - echo " ".base64_encode( $attr_values[0]); - } - /* else if( $attr_name == "sn"){ - echo $this->vcardMapping[$attr_name].":$attr_values[0]"; - } - elseif( $attr_name == "homePostalAddress"){ - }*/ - // else just print the value with the relevant attribute name - else{ - echo $this->vcardMapping[$attr_name].":$attr_values[0]"; - } - echo $this->br; - } - } - // need to check - echo "UID:$dn"; - echo $this->br; - echo "VERSION:2.1"; - echo $this->br; - echo $addr; - echo $this->br; - echo "END:VCARD"; - echo $this->br; - }// end while - } -} - - - - -/** - * Export to cvs format - * - * @author Glen Ogilvie - * @package tools - */ - -class PlaCSVExporter extends PlaExporter{ - - function PlaCSVExporter($exporter){ - $this->exporter = $exporter; - } - - /** - * When doing an exporter, the method export need to be overriden. - * A basic implementation is provided here. Customize to your need - **/ - - var $separator = ","; - var $qualifier = '"'; - var $multivalue_separator = " | "; - var $escapeCode = '"'; - - function export(){ - - // With the method pla->get_ldap_info, - // you have access to some values related - // to you ldap server - $ldap_info = $this->pla_get_ldap_info(); - $base_dn = $ldap_info->base_dn; - $scope = $ldap_info->scope; - $server_name = $ldap_info->name; - $server_host = $ldap_info->host; - - $entries = array(); - $headers = array(); - - // go thru and find all the attribute names first. This is needed, because, otherwise we have - // no idea as to which search attributes were actually populated with data - while( $this->pla_has_entry() ) { - $entry = $this->pla_fetch_entry_array(); - foreach (array_keys($entry) as $key) { - if (!in_array($key, $headers)) - array_push($headers,$key); - } - array_push($entries, $entry); - } - - $num_headers = count($headers); - - // print out the headers - for ($i = 0; $i < $num_headers; $i++) { - echo $this->qualifier. $headers[$i].$this->qualifier; - if ($i < $num_headers-1) - echo $this->separator; - } - - array_shift($headers); - $num_headers--; - - echo $this->br; - - // loop on every entry - foreach ($entries as $entry) { - - //print the dn - $dn = $entry['dn']; - unset( $entry['dn'] ); - echo $this->qualifier. $this->LdapEscape($dn).$this->qualifier.$this->separator; - - // print the attributes - for($j=0;$j<$num_headers;$j++){ - - $attr_name = $headers[$j]; - - echo $this->qualifier; - if (key_exists($attr_name, $entry)) { - $binary_attribute = is_attr_binary($attr_name )?1:0; - - $attr_values = $entry[$attr_name]; - - $num_attr_values = count( $attr_values ); - for( $i=0 ; $i<$num_attr_values; $i++){ - if($binary_attribute) - echo base64_encode($attr_values[$i]); - else - echo $this->LdapEscape($attr_values[$i]); - - if($i < $num_attr_values - 1) - echo $this->multivalue_separator; - - } - }// end if key - echo $this->qualifier; - if( $j < $num_headers - 1 ) - echo $this->separator; - } - echo $this->br; - } - }//end export - - // function to escape data, where the qualifier happens to also - // be in the data. - function LdapEscape ($var) { - return str_replace($this->qualifier, $this->escapeCode.$this->qualifier, $var); - } -} - - - - -/** - * @package tools - */ - -class MyCustomExporter extends PlaExporter{ - - function MyCutsomExporter($exporter){ - $this->exporter = $exporter; - } - - /** - * When doing an exporter, the method export need to be overriden. - * A basic implementation is provided here. Customize to your need - **/ - - - function export(){ - - // With the method pla->get_ldap_info, - // you have access to some values related - // to you ldap server - $ldap_info = $this->pla_get_ldap_info(); - $base_dn = $ldap_info->base_dn; - $scope = $ldap_info->scope; - $server_name = $ldap_info->name; - $server_host = $ldap_info->host; - - - // Just a simple loop. For each entry - // do your custom export - // see PlaLdifExporter or PlaDsmlExporter as an example - while( $this->pla_has_entry() ){ - $entry = $this->pla_fetch_entry_array(); - - //fetch the dn - $dn = $entry['dn']; - unset( $entry['dn'] ); - - // loop for the attributes - foreach( $entry as $attr_name=>$attr_values ){ - foreach( $attr_values as $value ){ - - // simple example - // echo "Attribute Name:".$attr_name; - // echo " - value:".$value; - // echo $this->br; - } - } - - }// end while - } - -} - -/** - * Gets the USER_AGENT string from the $_SERVER array, all in lower case in - * an E_NOTICE safe manner. - * @return String 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; -} - -/** - * 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 = get_user_agent_string(); - if( ! $agent ) - return false; - $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' - ); - foreach( $unix_agent_strs as $agent_str ) - if( strpos( $agent, $agent_str ) !== false ) - return true; - return false; -} - -/** - * 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 = get_user_agent_string(); - if( ! $agent ) - return false; - $win_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', - 'win32', - '32bit' - ); - foreach( $win_agent_strs as $agent_str ) - if( strpos( $agent, $agent_str ) !== false ) - return true; - return false; -} - -/** - * 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 = get_user_agent_string(); - if( ! $agent ) - return false; - $mac_agent_strs = array( - 'mac', - '68000', - 'ppc', - 'powerpc' - ); - foreach( $mac_agent_strs as $agent_str ) - if( strpos( $agent, $agent_str ) !== false ) - return true; - return false; -} - - -?> diff --git a/lam/lib/tree.inc b/lam/lib/tree.inc deleted file mode 100644 index 4d7add90..00000000 --- a/lam/lib/tree.inc +++ /dev/null @@ -1,1338 +0,0 @@ -, so if I wanted to scroll to - * dc=example,dc=com for server 3, the URL would be: - * tree.php#3_dc%3Dexample%2Cdc%3Dcom - * - * @package lists - * @subpackage tree - * @author David Smith - * @author Roland Gruber - */ - -/* - * Strip slashes from GET and POST variables if this - * PHP install is configured to automatically addslashes() - */ -if (get_magic_quotes_gpc() && (! isset($slashes_stripped) || ! $slashes_stripped)) { - array_stripslashes($_GET); - array_stripslashes($_POST); - $slashes_stripped = true; -} - -/** - * 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 (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]); -} - -/** - * Prints the HTML of the tree view. - */ -function draw_server_tree() -{ - global $tree; - global $tree_icons; - - - $refresh_href = 'refresh.php'; - $create_href = 'create_form.php?container=' . - rawurlencode( $_SESSION['config']->get_Suffix('tree') ); - - // Draw the quick-links below the server name: - // ( schema | search | refresh | create ) - echo ''; - echo ''; - echo '( '; - echo '' . _('Refresh') . ''; - if (checkIfWriteAccessIsAllowed()) { - echo ' | '; - echo '' . _('Create new entry') . ''; - } - echo ' )'; - - // Fetch and display the base DN for this server - $base_dn = $_SESSION['config']->get_Suffix('tree'); - - // Did we get a base_dn for this server somehow? - if( $base_dn ) { - echo "\n\n\n\n"; - - // is the root of the tree expanded already? - if( isset( $tree[$base_dn] ) ) { - $expand_href = "collapse.php?" . - "dn=" . rawurlencode( $base_dn ); - $expand_img = "../../graphics/minus.png"; - $expand_alt = "-"; - $child_count = number_format( count( $tree[$base_dn] ) ); - } - else { - $expand_href = "expand.php?" . - "dn=" . rawurlencode( $base_dn ); - $expand_img = "../../graphics/plus.png"; - $expand_alt = "+"; - $child_count = count( get_container_contents( - $base_dn, 0, - '(objectClass=*)') ); - if( $child_count > $limit ) - $child_count = $limit . '+'; - } - - $edit_href = "edit.php?dn=" . rawurlencode( $base_dn ); - - $icon = isset( $tree_icons[ $base_dn ] ) - ? $tree_icons[ $base_dn ] - : get_icon( $base_dn ); - - echo ""; - echo "\"$expand_alt\""; - echo ""; - echo "\"img\"\n"; - echo "" . pretty_print_dn( $base_dn ) . ''; - if( $child_count ) - echo " ($child_count)"; - echo "\n"; - echo "\n"; - - if(isset($tree[ $base_dn ]) - && count( $tree[ $base_dn ] ) > 10 ) - draw_create_link( $base_dn, -1, urlencode( $base_dn )); - - } - - flush(); - - // Is the root of the tree expanded already? - if( isset( $tree[$base_dn] ) && is_array( $tree[$base_dn] ) ) { - foreach( $tree[ $base_dn ] as $child_dn ) - draw_tree_html( $child_dn, 0 ); - if (checkIfWriteAccessIsAllowed()) { - echo ''; - echo '' . 
-							_('Create new entry') . ''; - echo '' . _('Create new entry') . ''; - } - } - -} - -/** - * Checks and fixes an initial session's tree cache if needed. - * - * This function is not meant as a user-callable function, but rather a convenient, - * automated method for checking the initial data structure of the session. - */ -function initialize_session_tree() -{ - if( ! array_key_exists( 'tree', $_SESSION ) ) - $_SESSION['tree'] = array(); - if( ! array_key_exists( 'tree_icons', $_SESSION ) ) - $_SESSION['tree_icons'] = build_initial_tree_icons(); - - // Make sure that the tree index is indeed well formed. - if( ! is_array( $_SESSION['tree'] ) ) - $_SESSION['tree'] = array(); - if( ! is_array( $_SESSION['tree_icons'] ) ) - $_SESSION['tree_icons'] = build_initial_tree_icons(); - -} - -/** - * Builds the initial array that stores the icon-lookup for each server's DN in the tree browser. The returned - * array is then stored in the current session. The structure of the returned array is simple, and looks like - * this: - * - * Array - * ( - * [0] => Array - * ( - * [dc=example,dc=com] => "dcobject.png" - * ) - * [1] => Array - ( - * [o=Corporation] => "o.png" - * ) - * ) - * - * This function is not meant as a user-callable function, but rather a convenient, automated method for - * setting up the initial data structure for the tree viewer's icon cache. - */ -function build_initial_tree_icons() -{ - $tree_icons = array(); - - // initialize an empty array for each server - $tree_icons = array(); - $tree_icons[ $_SESSION['config']->get_Suffix('tree') ] = get_icon( $_SESSION['config']->get_Suffix('tree') ); - - return $tree_icons; -} - -/** - * Gets whether an entry exists based on its DN. If the entry exists, - * returns true. Otherwise returns false. - * - * @param string $dn The DN of the entry of interest. - * - * @return bool - */ -function dn_exists( $dn ) -{ - $search_result = @ldap_read( $_SESSION['ldap']->server(), $dn, 'objectClass=*', array('dn') ); - - if( ! $search_result ) - return false; - - $num_entries = ldap_count_entries( $_SESSION['ldap']->server(), $search_result ); - - if( $num_entries > 0 ) - return true; - else - return false; -} - -/** - * Gets a list of child entries for an entry. Given a DN, this function fetches the list of DNs of - * child entries one level beneath the parent. For example, for the following tree: - * - * - * dc=example,dc=com - * ou=People - * cn=Dave - * cn=Fred - * cn=Joe - * ou=More People - * cn=Mark - * cn=Bob - * - * - * Calling get_container_contents( "ou=people,dc=example,dc=com" ) - * would return the following list: - * - * - * cn=Dave - * cn=Fred - * cn=Joe - * ou=More People - * - * - * @param string $dn The DN of the entry whose children to return. - * @param int $size_limit (optional) The maximum number of entries to return. - * If unspecified, no limit is applied to the number of entries in the returned. - * @param string $filter (optional) An LDAP filter to apply when fetching children, example: "(objectClass=inetOrgPerson)" - * @return array An array of DN strings listing the immediate children of the specified entry. - */ -function get_container_contents( $dn, $size_limit=0, $filter='(objectClass=*)' ) -{ - $search = @ldap_list( $_SESSION['ldap']->server(), $dn, $filter, array( 'dn' ), 1, $size_limit, 0); - if( ! $search ) - return array(); - $search = ldap_get_entries( $_SESSION['ldap']->server(), $search ); - - $return = array(); - for( $i=0; $i<$search['count']; $i++ ) { - $entry = $search[$i]; - $dn = $entry['dn']; - $return[] = $dn; - } - - return $return; -} - -/** - * 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 /../../graphics/ 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 string $dn The DN of the entry whose icon you wish to fetch. - * - * @return string - */ -function get_icon( $dn ) -{ - // fetch and lowercase all the objectClasses in an array - $object_classes = get_object_attr( $dn, 'objectClass', true ); - - 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; - 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( 'sambadomain', $object_classes ) ) - return 'smbDomain.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( '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'; -} - -/** - * Much like get_object_attrs(), but only returns the values for - * one attribute of an object. Example calls: - * - * - * print_r( get_object_attr( 0, "cn=Bob,ou=people,dc=example,dc=com", "sn" ) ); - * // prints: - * // Array - * // ( - * // [0] => "Smith" - * // ) - * - * print_r( get_object_attr( 0, "cn=Bob,ou=people,dc=example,dc=com", "objectClass" ) ); - * // prints: - * // Array - * // ( - * // [0] => "top" - * // [1] => "person" - * // ) - * - * - * @param string $dn The distinguished name (DN) of the entry whose attributes/values to fetch. - * @param string $attr The attribute whose value(s) to return (ie, "objectClass", "cn", "userPassword") - * @param bool $lower_case_attr_names (optional) If true, all keys of the returned associative - * array will be lower case. Otherwise, they will be cased as the LDAP server returns - * them. - * @see get_object_attrs - */ -function get_object_attr( $dn, $attr ) -{ - $search = @ldap_read( $_SESSION['ldap']->server(), $dn, '(objectClass=*)', array( $attr ), 0, 0, 0 ); - - if( ! $search ) - return false; - - $entry = ldap_first_entry( $_SESSION['ldap']->server(), $search ); - - if( ! $entry ) - return false; - - $attrs = ldap_get_attributes( $_SESSION['ldap']->server(), $entry ); - - if( ! $attrs || $attrs['count'] == 0 ) - return false; - - $vals = ldap_get_values( $_SESSION['ldap']->server(), $entry, $attr ); - unset( $vals['count'] ); - return $vals; -} - -/** - * Given a DN string, this returns the 'RDN' portion of the string. - * For example. given 'cn=Manager,dc=example,dc=com', this function returns - * 'cn=Manager' (it is really the exact opposite of get_container()). - * - * @param string $dn The DN whose RDN to return. - * @param bool $include_attrs If true, include attributes in the RDN string. - * See http://php.net/ldap_explode_dn for details - * - * @return string The RDN - * @see get_container - */ -function get_rdn( $dn, $include_attrs=0 ) -{ - if( $dn == null ) - return null; - $rdn = pla_explode_dn( $dn, $include_attrs ); - if( 0 == count($rdn) ) - return $dn; - if( ! isset( $rdn[0] ) ) - return $dn; - $rdn = $rdn[0]; - return $rdn; -} - -/** - * Explode a DN into an array of its RDN parts. This function is UTF-8 safe - * and replaces the buggy PHP ldap_explode_dn() which does not properly - * handle UTF-8 DNs and also causes segmentation faults with some inputs. - * - * @param string $dn The DN to explode. - * @param int $with_attriutes (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details) - * - * @return array An array of RDN parts of this format: - * - * Array - * ( - * [0] => uid=ppratt - * [1] => ou=People - * [2] => dc=example - * [3] => dc=com - * ) - * - */ -function pla_explode_dn( $dn, $with_attributes=0 ) -{ - // replace "\," with the hexadecimal value for safe split - $var = preg_replace("/\\\,/","\\\\\\\\2C",$dn); - - // split the dn - $result = explode(",",$var); - - //translate hex code into ascii for display - foreach( $result as $key => $value ) - $result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value); - - return $result; -} - -/** - * 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 ) -{ - $dn = pla_explode_dn( $dn ); - foreach( $dn as $i => $element ) { - $element = htmlspecialchars( $element ); - $element = explode( '=', $element, 2 ); - $element = implode( '=', $element ); - $dn[$i] = $element; - } - $dn = implode( ',', $dn ); - - return $dn; -} - -/** - * 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 they are obviously the same, return immediately - if( 0 === 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($dn2_parts) ) { - return 1; - } elseif( count( $dn2_parts ) > count( $dn1_parts ) ) { - return -1; - } else { - return 0; - } -} - -/** - * 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 - */ -function pla_reverse_dn($dn) -{ - foreach (pla_explode_dn($dn) as $key => $branch) { - - // pla_expode_dn returns the array with an extra count attribute, we can ignore that. - if ( $key === "count" ) continue; - - if (isset($rev)) { - $rev = $branch.",".$rev; - } else { - $rev = $branch; - } - } - return $rev; -} - -/** - * Gets a DN string using the user-configured tree_display_format string to format it. - */ -function draw_formatted_dn( $dn ) -{ - $format = '%rdn'; - preg_match_all( "/%[a-zA-Z_0-9]+/", $format, $tokens ); - $tokens = $tokens[0]; - foreach( $tokens as $token ) { - if( 0 == strcasecmp( $token, '%dn' ) ) - $format = str_replace( $token, pretty_print_dn( $dn ), $format ); - elseif( 0 == strcasecmp( $token, '%rdn' ) ) - $format = str_replace( $token, pretty_print_dn( get_rdn( $dn ) ), $format ); - elseif( 0 == strcasecmp( $token, '%rdnvalue' ) ) { - $rdn = get_rdn( $dn ); - $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 = get_object_attr( $dn, $attr_name ); - if( null == $attr_values ) - $display = 'none'; - elseif( is_array( $attr_values ) ) - $display = htmlspecialchars( implode( ', ', $attr_values ) ); - else - $display = htmlspecialchars( $attr_values ); - $format = str_replace( $token, $display, $format ); - } - } - echo $format; -} - -/** - * Gets the attributes/values of an entry. Returns an associative array whose - * keys are attribute value names and whose values are arrays of values for - * said attribute. Optionally, callers may specify true for the parameter - * $lower_case_attr_names to force all keys in the associate array (attribute - * names) to be lower case. - * - * Sample return value of get_object_attrs( 0, "cn=Bob,ou=pepole,dc=example,dc=com" ) - * - * - * Array - * ( - * [objectClass] => Array - * ( - * [0] => person - * [1] => top - * ) - * [cn] => Array - * ( - * [0] => Bob - * ) - * [sn] => Array - * ( - * [0] => Jones - * ) - * [dn] => Array - * ( - * [0] => cn=Bob,ou=pepole,dc=example,dc=com - * ) - * ) - * - * - * @param string $dn The distinguished name (DN) of the entry whose attributes/values to fetch. - * @param bool $lower_case_attr_names (optional) If true, all keys of the returned associative - * array will be lower case. Otherwise, they will be cased as the LDAP server returns - * them. - * @param int $deref For aliases and referrals, this parameter specifies whether to - * follow references to the referenced DN or to fetch the attributes for - * the referencing DN. See http://php.net/ldap_search for the 4 valid - * options. - * @return array - * @see get_entry_system_attrs - * @see get_object_attr - */ -function get_object_attrs( $dn, $lower_case_attr_names=false, $deref=LDAP_DEREF_NEVER ) -{ - - $conn = $_SESSION['ldap']->server(); - $search = @ldap_read( $conn, $dn, '(objectClass=*)', array( ), 0, 0, 0, $deref ); - - if( ! $search ) - return false; - - $entry = ldap_first_entry( $conn, $search ); - - if( ! $entry ) - return false; - - $attrs = ldap_get_attributes( $conn, $entry ); - - if( ! $attrs || $attrs['count'] == 0 ) - return false; - - $num_attrs = $attrs['count']; - unset( $attrs['count'] ); - - // strip numerical inices - for( $i=0; $i<$num_attrs; $i++ ) - unset( $attrs[$i] ); - - $return_array = array(); - foreach( $attrs as $attr => $vals ) { - if( $lower_case_attr_names ) - $attr = strtolower( $attr ); - if( is_attr_binary( $attr ) ) - $vals = ldap_get_values_len( $conn, $entry, $attr ); - unset( $vals['count'] ); - $return_array[ $attr ] = $vals; - } - - ksort( $return_array ); - - return $return_array; -} - -/** - * Given an attribute name and server ID number, this function returns - * whether the attrbiute may contain binary data. This is useful for - * developers who wish to display the contents of an arbitrary attribute - * but don't want to dump binary data on the page. - * - * @param string $attr_name The name of the attribute to test. - * @return bool - * - * @see is_jpeg_photo - */ -function is_attr_binary( $attr_name ) -{ - $attr_name = strtolower( $attr_name ); - /** Determining if an attribute is binary can be an expensive - operation. We cache the results for each attr name on each - server in the $attr_cache to speed up subsequent calls. - The $attr_cache looks like this: - Array - 0 => Array - 'objectclass' => false - 'cn' => false - 'usercertificate' => true - 1 => Array - 'jpegphoto' => true - 'cn' => false - */ - - static $attr_cache; - if( isset( $attr_cache[ $attr_name ] ) ) - return $attr_cache[ $attr_name ]; - - if( $attr_name == 'userpassword' ) { - $attr_cache[ $attr_name ] = false; - return false; - } - - // Quick check: If the attr name ends in ";binary", then it's binary. - if( 0 == strcasecmp( substr( $attr_name, strlen( $attr_name ) - 7 ), ";binary" ) ) { - $attr_cache[ $attr_name ] = true; - return true; - } - - // See what the server schema says about this attribute - $schema_attr = get_schema_attribute( $attr_name ); - if( ! $schema_attr ) { - // Strangely, some attributeTypes may not show up in the server - // schema. This behavior has been observed in MS Active Directory. - $type = null; - $syntax = null; - } else { - $type = $schema_attr->getType(); - $syntax = $schema_attr->getSyntaxOID(); - } - - if( 0 == strcasecmp( $type, 'Certificate' ) || - 0 == strcasecmp( $type, 'Binary' ) || - 0 == strcasecmp( $attr_name, 'usercertificate' ) || - 0 == strcasecmp( $attr_name, 'usersmimecertificate' ) || - 0 == strcasecmp( $attr_name, 'networkaddress' ) || - 0 == strcasecmp( $attr_name, 'objectGUID' ) || - 0 == strcasecmp( $attr_name, 'objectSID' ) || - $syntax == '1.3.6.1.4.1.1466.115.121.1.10' || - $syntax == '1.3.6.1.4.1.1466.115.121.1.28' || - $syntax == '1.3.6.1.4.1.1466.115.121.1.5' || - $syntax == '1.3.6.1.4.1.1466.115.121.1.8' || - $syntax == '1.3.6.1.4.1.1466.115.121.1.9' ) { - $attr_cache[ $attr_name ] = true; - return true; - } else { - $attr_cache[ $attr_name ] = false; - return false; - } -} - -/** - * 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 ) -{ - $attr_name = preg_replace( "/;.*$/U", "", $attr_name ); - return $attr_name; -} - -/** - * Gets the operational attributes for an entry. Given a DN, this function fetches that entry's - * operational (ie, system or internal) attributes. These attributes include "createTimeStamp", - * "creatorsName", and any other attribute that the LDAP server sets automatically. The returned - * associative array is of this form: - * - * Array - * ( - * [creatorsName] => Array - * ( - * [0] => "cn=Admin,dc=example,dc=com" - * ) - * [createTimeStamp]=> Array - * ( - * [0] => "10401040130" - * ) - * [hasSubordinates] => Array - * ( - * [0] => "FALSE" - * ) - * ) - * - * - * @param string $dn The DN of the entry whose interal attributes are desired. - * @param int $deref For aliases and referrals, this parameter specifies whether to - * follow references to the referenced DN or to fetch the attributes for - * the referencing DN. See http://php.net/ldap_search for the 4 valid - * options. - * @return array An associative array whose keys are attribute names and whose values - * are arrays of values for the aforementioned attribute. - */ -function get_entry_system_attrs( $dn, $deref=LDAP_DEREF_NEVER ) -{ - $conn = $_SESSION['ldap']->server(); - $attrs = array( 'creatorsname', 'createtimestamp', 'modifiersname', - 'structuralObjectClass', 'entryUUID', 'modifytimestamp', - 'subschemaSubentry', 'hasSubordinates', '+' ); - $search = @ldap_read( $conn, $dn, '(objectClass=*)', $attrs, 0, 0, 0, $deref ); - if( ! $search ) - return false; - $entry = ldap_first_entry( $conn, $search ); - if( ! $entry) - return false; - $attrs = ldap_get_attributes( $conn, $entry ); - if( ! $attrs ) - return false; - if( ! isset( $attrs['count'] ) ) - return false; - $count = $attrs['count']; - unset( $attrs['count'] ); - $return_attrs = array(); - for( $i=0; $i<$count; $i++ ) { - $attr_name = $attrs[$i]; - unset( $attrs[$attr_name]['count'] ); - $return_attrs[$attr_name] = $attrs[$attr_name]; - } - return $return_attrs; -} - -function arrayLower($array) { - foreach ($array as $key => $value) { - $newarray[$key] = strtolower($value); - } - return $newarray; -} - -/** - * Used to determine if the specified attribute is indeed a jpegPhoto. If the - * specified attribute is one that houses jpeg data, true is returned. Otherwise - * this function returns false. - * - * @param string $attr_name The name of the attribute to test. - * @return bool - * @see draw_jpeg_photos - */ -function is_jpeg_photo( $attr_name ) -{ - // easy quick check - if( 0 == strcasecmp( $attr_name, 'jpegPhoto' ) || - 0 == strcasecmp( $attr_name, 'photo' ) ) - return true; - - // go to the schema and get the Syntax OID - $schema_attr = get_schema_attribute( $attr_name ); - if( ! $schema_attr ) - return false; - - $oid = $schema_attr->getSyntaxOID(); - $type = $schema_attr->getType(); - - if( 0 == strcasecmp( $type, 'JPEG' ) ) - return true; - if( $oid == '1.3.6.1.4.1.1466.115.121.1.28' ) - return true; - - return false; -} - -/** - * Given an attribute name and server ID number, this function returns - * whether the attrbiute contains boolean data. This is useful for - * developers who wish to display the contents of a boolean attribute - * with a drop-down. - * - * @param string $attr_name The name of the attribute to test. - * @return bool - */ -function is_attr_boolean( $attr_name ) -{ - $type = ( $schema_attr = get_schema_attribute( $attr_name ) ) ? - $schema_attr->getType() : - null; - if( 0 == strcasecmp( 'boolean', $type ) || - 0 == strcasecmp( 'isCriticalSystemObject', $attr_name ) || - 0 == strcasecmp( 'showInAdvancedViewOnly', $attr_name ) ) - return true; - else - return false; -} - -/** - * 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 ) -{ - $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 ) -{ - $url_regex = '/(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/'; - if( preg_match( $url_regex, $str ) ) - return true; - else - return false; - -} - -function sortAttrs($a,$b) { - return strcmp ($a, $b); -} - -/** - * Determines if an attribute's value can contain multiple lines. Attributes that fall - * in this multi-line category may be configured in config.php. Hence, this function - * accesses the global variable $multi_line_attributes; - * - * Usage example: - * - * if( is_muli_line_attr( "postalAddress" ) ) - * echo ""; - * else - * echo ""; - * - * - * @param string $attr_name The name of the attribute of interestd (case insensivite) - * @param string $val (optional) The current value of the attribute (speeds up the - * process by searching for carriage returns already in the attribute value) - * @return bool - */ -function is_multi_line_attr( $attr_name, $val=null ) -{ - // First, check the optional val param for a \n or a \r - if( null != $val && - ( false !== strpos( $val, "\n" ) || - false !== strpos( $val, "\r" ) ) ) - return true; - - // Next, compare strictly by name first - global $multi_line_attributes; - if( isset( $multi_line_attributes ) && is_array( $multi_line_attributes ) ) - foreach( $multi_line_attributes as $multi_line_attr_name ) - if( 0 == strcasecmp( $multi_line_attr_name, $attr_name ) ) { - return true; - } - - global $multi_line_syntax_oids; - if( isset( $multi_line_syntax_oids ) && is_array( $multi_line_syntax_oids ) ) { - $schema_attr = get_schema_attribute( $attr_name ); - if( ! $schema_attr ) - return false; - $syntax_oid = $schema_attr->getSyntaxOID(); - if( ! $syntax_oid ) - return false; - foreach( $multi_line_syntax_oids as $multi_line_syntax_oid ) - if( $multi_line_syntax_oid == $syntax_oid ) - return true; - } - - return false; - -} - -/** - * Returns true if the attribute specified is required to take as input a DN. - * Some examples include 'distinguishedName', 'member' and 'uniqueMember'. - * @param string $attr_name The name of the attribute of interest (case insensitive) - * @return bool - */ -function is_dn_attr( $attr_name ) -{ - // Simple test first - $dn_attrs = array( "aliasedObjectName" ); - foreach( $dn_attrs as $dn_attr ) - if( 0 == strcasecmp( $attr_name, $dn_attr ) ) - return true; - - // Now look at the schema OID - $attr_schema = get_schema_attribute( $attr_name ); - if( ! $attr_schema ) - return false; - $syntax_oid = $attr_schema->getSyntaxOID(); - if( '1.3.6.1.4.1.1466.115.121.1.12' == $syntax_oid ) - return true; - if( '1.3.6.1.4.1.1466.115.121.1.34' == $syntax_oid ) - return true; - $syntaxes = get_schema_syntaxes(); - if( ! isset( $syntaxes[ $syntax_oid ] ) ) - return false; - $syntax_desc = $syntaxes[ $syntax_oid ]->getDescription(); - if( false !== strpos( strtolower($syntax_desc), 'distinguished name' ) ) - return true; - return false; -} - -function get_enc_type( $user_password ) -{ - /* Capture the stuff in the { } to determine if this is crypt, md5, etc. */ - $enc_type = null; - if( preg_match( "/{([^}]+)}/", $user_password, $enc_type) ) - return strtoupper($enc_type[1]); - else - return null; -} - -/** - * Draw the jpegPhoto image(s) for an entry wrapped in HTML. Many options are available to - * specify how the images are to be displayed. - * - * Usage Examples: - * - * 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 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( $dn, $attr_name='jpegPhoto', $draw_delete_buttons=false, - $draw_bytes_and_size=true, $table_html_attrs='align="left"', $img_html_attrs='' ) -{ - $jpeg_temp_dir = dirname(__FILE__) . '/../tmp'; - - $conn = $_SESSION['ldap']->server(); - $search_result = ldap_read( $conn, $dn, 'objectClass=*', array( $attr_name ) ); - $entry = ldap_first_entry( $conn, $search_result ); - - echo "
\n\n"; - // for each jpegPhoto in the entry, draw it (there may be only one, and that's okay) - $jpeg_data = @ldap_get_values_len( $conn, $entry, $attr_name ); - if( ! is_array( $jpeg_data ) ) { - echo "Could not fetch jpeg data from LDAP server for attribute " . htmlspecialchars( $attr_name ); - return; - } - for( $i=0; $i<$jpeg_data['count']; $i++ ) - { - // ensures that the photo is written to the specified jpeg_temp_dir - $jpeg_temp_dir = realpath($jpeg_temp_dir.'/'); - $jpeg_filename = $jpeg_temp_dir . '/' . 'jpg' . $_SESSION['ldap']->new_rand() . '.jpg'; - $outjpeg = @fopen($jpeg_filename, "wb"); - fwrite($outjpeg, $jpeg_data[$i]); - fclose ($outjpeg); - $jpeg_data_size = filesize( $jpeg_filename ); - if( $jpeg_data_size < 6 && $draw_delete_buttons ) { - echo _('jpegPhoto contains errors'); - echo '
'. _('Delete') .''; - 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 = $height * $scale_factor; - } else { - $img_width = $width; - $img_height = $height; - } - echo "
\n"; - if( $draw_bytes_and_size ) { - echo "" . number_format($jpeg_data_size) . " bytes. "; - echo "$width x $height pixels.
\n\n"; - } - - if( $draw_delete_buttons ) - { ?> - - Delete Photo -
\n\n"; -} - -/** - * A handy ldap searching function very similar to PHP's ldap_search() with the - * following exceptions: Callers may specify a search scope and the return value - * is an array containing the search results rather than an LDAP result resource. - * - * Example usage: - * - * $samba_users = ldap_search( 0, "(&(objectClass=sambaAccount)(objectClass=posixAccount))", - * "ou=People,dc=example,dc=com", array( "uid", "homeDirectory" ) ); - * print_r( $samba_users ); - * // prints (for example): - * // Array - * // ( - * // [uid=jsmith,ou=People,dc=example,dc=com] => Array - * // ( - * // [dn] => "uid=jsmith,ou=People,dc=example,dc=com" - * // [uid] => "jsmith" - * // [homeDirectory] => "\\server\jsmith" - * // ) - * // [uid=byoung,ou=People,dc=example,dc=com] => Array - * // ( - * // [dn] => "uid=byoung,ou=Samba,ou=People,dc=example,dc=com" - * // [uid] => "byoung" - * // [homeDirectory] => "\\server\byoung" - * // ) - * // ) - * - * - * WARNING: This function will use a lot of memory on large searches since the entire result set is - * stored in a single array. For large searches, you should consider sing the less memory intensive - * PHP LDAP API directly (ldap_search(), ldap_next_entry(), ldap_next_attribute(), etc). - * - * @param string $filter The LDAP filter to use when searching (example: "(objectClass=*)") (see RFC 2254) - * @param string $base_dn The DN of the base of search. - * @param array $attrs An array of attributes to include in the search result (example: array( "objectClass", "uid", "sn" )). - * @param string $scope The LDAP search scope. Must be one of "base", "one", or "sub". Standard LDAP search scope. - * @param bool $sort_results Specify false to not sort results by DN or true to have the - * returned array sorted by DN (uses ksort) - * @param int $deref When handling aliases or referrals, this specifies whether to follow referrals. Must be one of - * LDAP_DEREF_ALWAYS, LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING, or LDAP_DEREF_FINDING. See the PHP LDAP API for details. - */ -function pla_ldap_search( $filter, $base_dn=null, $attrs=array(), $scope='sub', $sort_results=true, $deref=LDAP_DEREF_ALWAYS ) -{ - $ds = $_SESSION['ldap']->server(); - switch( $scope ) { - case 'base': - $search = @ldap_read( $ds, $base_dn, $filter, $attrs, 0, 0, 0, $deref ); - break; - case 'one': - $search = @ldap_list( $ds, $base_dn, $filter, $attrs, 0, 0, 0, $deref ); - break; - case 'sub': - default: - $search = @ldap_search( $ds, $base_dn, $filter, $attrs, 0, 0, 0, $deref ); - break; - } - - if( ! $search ) - return array(); - - $return = array(); - //get the first entry identifier - if( $entry_id = ldap_first_entry($ds,$search) ) - - //iterate over the entries - while($entry_id) { - - //get the distinguished name of the entry - $dn = ldap_get_dn($ds,$entry_id); - - //get the attributes of the entry - $attrs = ldap_get_attributes($ds,$entry_id); - $return[$dn]['dn'] = $dn; - - //get the first attribute of the entry - if($attr = ldap_first_attribute($ds,$entry_id)) - - //iterate over the attributes - while($attr){ - if( is_attr_binary($attr)) - $values = ldap_get_values_len($ds,$entry_id,$attr); - else - $values = ldap_get_values($ds,$entry_id,$attr); - - //get the number of values for this attribute - $count = $values['count']; - unset($values['count']); - if($count==1) - $return[$dn][$attr] = $values[0]; - else - $return[$dn][$attr] = $values; - - $attr = ldap_next_attribute($ds,$entry_id); - }// end while attr - - $entry_id = ldap_next_entry($ds,$entry_id); - - } // end while entry_id - - if( $sort_results && is_array( $return ) ) - ksort( $return ); - - return $return; -} - -/** - * Given a DN string, this returns the parent container portion of the string. - * For example. given 'cn=Manager,dc=example,dc=com', this function returns - * 'dc=example,dc=com'. - * - * @param string $dn The DN whose container string to return. - * - * @return string The container - * @see get_rdn - */ -function get_container( $dn ) -{ - $parts = pla_explode_dn( $dn ); - if( count( $parts ) <= 1 ) - return null; - $container = $parts[1]; - for( $i=2; $i