+ * 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( '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
+ * 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;
+}
+
+/**
+ * Checks if a string exists in an array, ignoring case.
+ */
+function in_array_ignore_case( $needle, $haystack )
+{
+ if( ! is_array( $haystack ) )
+ return false;
+ if( ! is_string( $needle ) )
+ return false;
+ foreach( $haystack as $element )
+ if( is_string( $element ) && 0 == strcasecmp( $needle, $element ) )
+ 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) )
+ $enc_type = strtolower( $enc_type[1] );
+ else
+ return null;
+
+ /* handle crypt types */
+ if( 0 == strcasecmp( $enc_type, 'crypt') ) {
+ $salt = null;
+ if( preg_match( "/{[^}]+}\\$(.)\\$/", $user_password, $salt) )
+ $salt = $salt[1];
+ else
+ $salt = null;
+ switch( $salt ) {
+ case '': // CRYPT_STD_DES
+ $enc_type = "crypt";
+ break;
+ case '1': // CRYPT_MD5
+ $enc_type = "md5crypt";
+ break;
+ case '2': // CRYPT_BLOWFISH
+ $enc_type = "blowfish";
+ break;
+ default:
+ $enc_type = "crypt";
+ }
+ }
+ return $enc_type;
+}
+
+/**
+ * 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 = $_SESSION['lampath'] . 'tmp';
+
+ $conn = $_SESSION['ldap']->server;
+ $search_result = ldap_read( $conn, $dn, 'objectClass=*', array( $attr_name ) );
+ $entry = ldap_first_entry( $conn, $search_result );
+
+ 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 + |
+ * $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,$attrs))
+
+ //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,$attrs);
+ }// 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* = ". _("required") . "
"); -echo ("** = ". _("required for Samba accounts") . "
"); -echo ("*** = ". _("required for Samba 3 accounts") . "
"); +echo ("** = ". _("required for Samba 3 accounts") . "
"); // password for configuration echo ("\n"); diff --git a/lam/templates/config/confsave.php b/lam/templates/config/confsave.php index f7cca6ff..e60b734f 100644 --- a/lam/templates/config/confsave.php +++ b/lam/templates/config/confsave.php @@ -52,6 +52,7 @@ $suffusers = $_SESSION['conf_suffusers']; $suffgroups = $_SESSION['conf_suffgroups']; $suffhosts = $_SESSION['conf_suffhosts']; $suffdomains = $_SESSION['conf_suffdomains']; +$sufftree = $_SESSION['conf_sufftree']; $usrlstattr = $_SESSION['conf_usrlstattr']; $grplstattr = $_SESSION['conf_grplstattr']; $hstlstattr = $_SESSION['conf_hstlstattr']; @@ -122,6 +123,11 @@ if (!$conf->set_DomainSuffix($suffdomains)) { echo ("\n