diff --git a/INSTALL b/INSTALL index fea99f9..d3a5fcb 100644 --- a/INSTALL +++ b/INSTALL @@ -1,40 +1,49 @@ These instructions assume that you have a working install of: - a. A web server (Apache, IIS, etc). - b. PHP (with LDAP support) + a. A web server (Apache, IIS, etc). + b. PHP (with LDAP support) -Installing phpLDAPAdmin in 4 easy steps: +* Installing phpLDAPadmin in 4 easy steps: -1. Untar the archive (if you're reading this, you've already done that). -2. Put the resulting phpldapadmin directory somewhere in your webroot. -3. Copy 'config.php.example' to 'config.php' and edit to taste. -4. Then, point your browser to the phpldapadmin directory. + 1. Untar the archive (if you're reading this, you already did that). + 2. Put the resulting 'phpldapadmin' directory somewhere in your webroot. + 3. Copy 'config.php.example' to 'config.php' and edit to taste. + 4. Then, point your browser to the phpldapadmin directory. -Browsers +* Browser Notes -phpLDAPAdmin was developed on Mozilla, and will most likely run best thereon. -However, testing has been done on Internet Explorer, and it should work -well also. No testing has been done on either Konqueror (or any khtml-based -browser like Safari) or Opera. If you find a browser incompatibility, -please report it. + phpLDAPadmin was developed on Mozilla, and will most likely run best thereon. + However, testing has been done on Internet Explorer, and it should work + well also. No testing has been done on either Konqueror (or any khtml-based + browser like Safari) or Opera. If you find a browser incompatibility, + please report it. -Contributors (thank you!) +* Contributors (thank you!) + + Project Developers: + + - David Smith Maintainer + - Xavier Renard LDIF master + - Nate Rotschafer Release manager Patch writers: - - Mario Valdez jpegPhoto support, localization (not yet in 0.8.x), html fixes - - Bayu Irawan userPassword encryption support, html fixes, ldap_modify fixes - - Uwe Ebel short_open_tags fix-it script - - Philippe Broussard form auth_type bug report - - Andrew Tipton SUP support in schema-fetching - - Eigil Bjørgum UTF-8 support - - Brandon Lederer DNS entry template + - Bayu Irawan userPassword hash, html fixes, ldap_modify fixes + - Uwe Ebel short_open_tags fix + - Andrew Tipton SUP support in schema parser + - Eigil Bjørgum UTF-8 support + - Brandon Lederer DNS entry template Nathan Rotschafer - - Steve Rigler Password hash patch - - Chric Jackson Blowfish and md5crypt passwords + - Steve Rigler Password hash patch + - Chric Jackson Blowfish and md5crypt passwords + - Marius Rieder Enhanced schema parser + - Nick Burch Many realpath() fixes - Bug reporters: + Translators: - - Colin Tinker (short_open_tags bug report) - - Greg Felix (multi-value update bug report) - - Moritz Mertinkat (creation bug report) + - Uwe Ebel German + - Xavier Renard French + - Dave Smith English ;) + + If you can help translate, please join the phpldapadmin-devel mailing list: + https://lists.sourceforge.net/mailman/listinfo/phpldapadmin-devel diff --git a/VERSION b/VERSION index ac39a10..f374f66 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 +0.9.1 diff --git a/add_oclass.php b/add_oclass.php index 3c5986e..13e4e65 100644 --- a/add_oclass.php +++ b/add_oclass.php @@ -14,17 +14,19 @@ * - new_attrs (array, if any) */ -require 'config.php'; -require 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $encoded_dn = rawurlencode( $dn ); -$new_oclass = stripslashes( $_POST['new_oclass'] ); +$new_oclass = $_POST['new_oclass']; $server_id = $_POST['server_id']; $new_attrs = $_POST['new_attrs']; -check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); -have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); +if( is_server_read_only( $server_id ) ) + pla_error( $lang['no_updates_in_read_only_mode'] ); + +check_server_id( $server_id ) or pla_error( $lang['bad_server_id'] ); +have_auth_info( $server_id ) or pla_error( $lang['not_enough_login_info'] ); $new_entry = array(); $new_entry['objectClass'] = $new_oclass; @@ -40,12 +42,12 @@ if( is_array( $new_attrs ) && count( $new_attrs ) > 0 ) //print_r( $new_entry ); //exit; -$ds = pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP server." ); +$ds = pla_ldap_connect( $server_id ) or pla_error( $lang['could_not_connect'] ); $add_res = @ldap_mod_add( $ds, $dn, $new_entry ); if( ! $add_res ) { - pla_error( "Could not perform ldap_mod_add operation", ldap_error( $ds ), ldap_errno( $ds ) ); + pla_error( $lang['could_not_perform_ldap_mod_add'], ldap_error( $ds ), ldap_errno( $ds ) ); } else { diff --git a/add_oclass_form.php b/add_oclass_form.php index 36c0e9f..80ef6fb 100644 --- a/add_oclass_form.php +++ b/add_oclass_form.php @@ -15,16 +15,18 @@ * - new_oclass */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $encoded_dn = rawurlencode( $dn ); -$new_oclass = stripslashes( $_POST['new_oclass'] ); +$new_oclass = $_POST['new_oclass']; $server_id = $_POST['server_id']; -check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); -have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); +if( is_server_read_only( $server_id ) ) + pla_error( $lang['no_updates_in_read_only_mode'] ); + +check_server_id( $server_id ) or pla_error( $lang['bad_server_id'] ); +have_auth_info( $server_id ) or pla_error( $lang['not_enough_login_info'] ); /* Ensure that the object has defined all MUST attrs for this objectClass. * If it hasn't, present a form to have the user enter values for all the @@ -47,19 +49,19 @@ foreach( $must_attrs as $attr ) if( count( $needed_attrs ) > 0 ) { - ?> - - - + include 'header.php'; ?> -

New Required Attributes

-

This action requires you to add new attribute1?'s':''); ?>

+

+

- Instrucitons: In order to add the objectClass to the object , - you must specify new attribute1?'s':''); ?> that this - objectClass requires. You can do so in this form. + +

@@ -70,7 +72,7 @@ if( count( $needed_attrs ) > 0 ) - + $attr ) { ?> @@ -86,7 +88,7 @@ if( count( $needed_attrs ) > 0 )
New Required Attributes


-
+
diff --git a/add_value.php b/add_value.php index 49d584d..b223ae5 100644 --- a/add_value.php +++ b/add_value.php @@ -8,36 +8,40 @@ * - attr (rawurlencoded) the attribute to which we are adding a value * - server_id * - new_value (form element) + * - binary * * On success, redirect to the edit_dn page. * On failure, echo an error. */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $encoded_dn = rawurlencode( $dn ); -$attr = stripslashes( $_POST['attr'] ); +$attr = $_POST['attr']; $encoded_attr = rawurlencode( $attr ); $server_id = $_POST['server_id']; -$new_value = stripslashes( $_POST['new_value'] ); +$new_value = $_POST['new_value']; $new_value = utf8_encode($new_value); +$is_binary_val = isset( $_POST['binary'] ) ? true : false; -check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); -have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); +if( is_server_read_only( $server_id ) ) + pla_error( $lang['no_updates_in_read_only_mode'] ); -$ds = pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP server" ); +check_server_id( $server_id ) or pla_error( $lang['bad_server_id'] ); +have_auth_info( $server_id ) or pla_error( $lang['not_enough_login_info'] ); -// special case for jpegPhoto attributes: +$ds = pla_ldap_connect( $server_id ) or pla_error( $lang['could_not_connect'] ); + +// special case for binary attributes: // we must go read the data from the file. -if( 0 == strcasecmp( $attr, 'jpegPhoto' ) ) +if( $is_binary_val ) { - $file = $_FILES['jpeg_photo_file']['tmp_name']; + $file = $_FILES['new_value']['tmp_name']; $f = fopen( $file, 'r' ); - $jpeg_data = fread( $f, filesize( $file ) ); + $binary_value = fread( $f, filesize( $file ) ); fclose( $f ); - $new_value = $jpeg_data; + $new_value = $binary_value; } $new_entry = array( $attr => $new_value ); @@ -45,7 +49,7 @@ $new_entry = array( $attr => $new_value ); $add_result = @ldap_mod_add( $ds, $dn, $new_entry ); if( ! $add_result ) - pla_error( "Could not perform ldap_mod_add operation.", ldap_error( $ds ), ldap_errno( $ds ) ); + pla_error( $lang['could_not_perform_ldap_mod_add'], ldap_error( $ds ), ldap_errno( $ds ) ); header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&updated_attr=$encoded_attr" ); diff --git a/add_value_form.php b/add_value_form.php index 013be2c..5646e2b 100644 --- a/add_value_form.php +++ b/add_value_form.php @@ -11,34 +11,36 @@ * */ +require 'common.php'; require 'config.php'; require_once 'functions.php'; -$dn = stripslashes( $_GET['dn'] ); +$dn = $_GET['dn']; $encoded_dn = rawurlencode( $dn ); $server_id = $_GET['server_id']; -$rdn = ldap_explode_dn( $dn, 0 ); +$rdn = pla_explode_dn( $dn ); $rdn = $rdn[0]; $server_name = $servers[$server_id]['name']; -$attr = stripslashes( $_GET['attr'] ); +$attr = $_GET['attr']; $encoded_attr = rawurlencode( $attr ); $current_values = get_object_attr( $server_id, $dn, $attr ); $num_current_values = ( is_array($current_values) ? count($current_values) : 1 ); $is_object_class = ( 0 == strcasecmp( $attr, 'objectClass' ) ) ? true : false; $is_jpeg_photo = ( 0 == strcasecmp( $attr, 'jpegPhoto' ) ) ? true : false; -check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); -have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); +if( is_server_read_only( $server_id ) ) + pla_error( $lang['no_updates_in_read_only_mode'] ); + +check_server_id( $server_id ) or pla_error( $lang['bad_server_id'] ); +have_auth_info( $server_id ) or pla_error( $lang['not_enough_login_info'] ); if( $is_object_class ) { // fetch all available objectClasses and remove those from the list that are already defined in the entry $schema_oclasses = get_schema_objectclasses( $server_id ); - if( ! is_array( $current_values ) ) - $current_values = array( $current_values ); foreach( $current_values as $oclass ) unset( $schema_oclasses[ strtolower( $oclass ) ] ); } else { - $schema_attrs = get_schema_attributes( $server_id ); + $schema_attr = get_schema_attribute( $server_id, $attr ); } ?> @@ -47,11 +49,18 @@ if( $is_object_class ) { -

New value for

-

Server:     Distinguished Name:

+

+ + + +

+

+ : +     + :

-Current list of value1?'s':''; ?> - for attribute : + + : @@ -61,8 +70,23 @@ Current list of value

- Note: You will get an "inappropriate matching" error if you have not
- setup an EQUALITY rule on your LDAP server for jpegPhoto attributes. + +

+ + + + + +

+

@@ -84,7 +108,8 @@ Current list of value -Enter the value you would like to add:
+ +

@@ -102,29 +127,31 @@ Enter the value you would like to add:
-
Note: you may be required to enter new attributes
- that this objectClass requires (MUST attrs)
- - - -
- - - -
-
- +
- + > - + + + + + + + +
- Syntax: + : getType(); ?>
+ getMaxLength() ) { ?> + Max length: getMaxLength() ); ?> + characters + +
diff --git a/collapse.php b/collapse.php index 153ced2..67dbe2e 100644 --- a/collapse.php +++ b/collapse.php @@ -12,18 +12,20 @@ * Note: this script is equal and opposite to expand.php */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( $_GET['dn'] ); +$dn = $_GET['dn']; $encoded_dn = rawurlencode( $dn ); $server_id = $_GET['server_id']; check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); session_start(); -session_is_registered( 'tree' ) or pla_error( "Your session tree is not registered. That's weird. Shouldn't ever happen". - ". Just go back and it should be fixed automagically." ); + +// dave commented this out since it was being triggered for weird reasons +//session_is_registered( 'tree' ) or pla_error( "Your session tree is not registered. That's weird. Shouldn't ever happen". +// ". Just go back and it should be fixed automagically." ); + $tree = $_SESSION['tree']; // and remove this instance of the dn as well @@ -38,6 +40,12 @@ session_write_close(); $time = gettimeofday(); $random_junk = md5( strtotime( 'now' ) . $time['usec'] ); -header( "Location: tree.php?foo=$random_junk#{$server_id}_{$encoded_dn}" ); +// If cookies were disabled, build the url parameter for the session id. +// It will be append to the url to be redirect +$id_session_param=""; +if(SID != ""){ + $id_session_param = "&".session_name()."=".session_id(); +} -; ?> +header( "Location:tree.php?foo=$random_junk%23{$server_id}_{$encoded_dn}$id_session_param" ); +?> diff --git a/common.php b/common.php new file mode 100644 index 0000000..c13714a --- /dev/null +++ b/common.php @@ -0,0 +1,53 @@ + 'Custom', + 'icon' => 'images/object.png', + 'handler' => 'custom.php' ); + +// Strip slashes from GET, POST, and COOKIE variables if this +// PHP install is configured to automatically addslashes() +if ( get_magic_quotes_gpc() && ( ! isset( $slashes_stripped ) || ! $slashes_stripped ) ) { + if( ! function_exists( "array_stripslashes" ) ) { + 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] ); + } + } + + array_stripslashes($_POST); + array_stripslashes($_GET); + array_stripslashes($_COOKIES); + $slashes_stripped = true; +} + +?> diff --git a/config.php.example b/config.php.example index 14f75d1..0830019 100644 --- a/config.php.example +++ b/config.php.example @@ -1,22 +1,24 @@ 'User', + array( 'desc' => 'User Account', 'icon' => 'images/user.png', 'handler' => 'new_user_template.php' ); $templates[] = - array( 'desc' => 'inetOrgPerson', + array( 'desc' => 'Address Book Entry (inetOrgPerson)', 'icon' => 'images/user.png', 'handler' => 'new_address_template.php' ); @@ -125,16 +124,32 @@ $templates[] = 'icon' => 'images/ou.png', 'handler' => 'new_ou_template.php' ); +$templates[] = + array( 'desc' => 'Posix Group', + 'icon' => 'images/ou.png', + 'handler' => 'new_posix_group_template.php' ); + $templates[] = array( 'desc' => 'Samba NT Machine', - 'icon' => 'images/terminal.png', + 'icon' => 'images/nt.png', 'handler' => 'new_nt_machine.php' ); +$templates[] = + array( 'desc' => 'Samba User', + 'icon' => 'images/user.png', + 'handler' => 'new_smbuser_template.php' ); + $templates[] = array( 'desc' => 'DNS Entry', 'icon' => 'images/dc.png', 'handler' => 'new_dns_entry.php' ); +$templates[] = + array( 'desc' => 'Posix Group', + 'icon' => 'images/ou.png', + 'handler' => 'new_posix_group_template.php' ); + + /** **/ /** User-friendly attribute translation **/ /** **/ @@ -147,17 +162,15 @@ $friendly_attrs = array(); $friendly_attrs[ 'facsimileTelephoneNumber' ] = 'Fax'; $friendly_attrs[ 'telephoneNumber' ] = 'Phone'; -/** **/ -/** Some phpLDAPAdmin code to be executed. No touchy. **/ -/** **/ +/** **/ +/** Hidden attributes **/ +/** **/ -// Turn off notices about referencing arrays and such, but leave everything else on. -error_reporting( E_ALL ^ E_NOTICE ); +// You may want to hide certain attributes from being displayed in the editor screen +// Do this by adding the desired attributes to this list (and uncomment it). This +// only affects the editor screen. Attributes will still be visible in the schema +// browser and elsewhere. An example is provided below: -// Always including the 'custom' template (the most generic and flexible) -$templates['custom'] = - array( 'desc' => 'Custom', - 'icon' => 'images/object.png', - 'handler' => 'custom.php' ); +//$hidden_attrs = array( 'jpegPhoto', 'objectClass' ); ?> diff --git a/copy.php b/copy.php index 127ae86..008226d 100644 --- a/copy.php +++ b/copy.php @@ -10,17 +10,19 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; session_start(); -$source_dn = stripslashes( rawurldecode( $_POST['old_dn'] ) ); -$dest_dn = stripslashes( $_POST['new_dn'] ); +$source_dn = rawurldecode( $_POST['old_dn'] ); +$dest_dn = utf8_encode( $_POST['new_dn'] ); $encoded_dn = rawurlencode( $old_dn ); $source_server_id = $_POST['server_id']; $dest_server_id = $_POST['dest_server_id']; -$do_recursive = $_POST['recursive'] == 'on' ? true : false; +$do_recursive = ( isset( $_POST['recursive'] ) && $_POST['recursive'] == 'on' ) ? true : false; + +if( is_server_read_only( $dest_server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); check_server_id( $source_server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $source_server_id ) ); have_auth_info( $source_server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); @@ -72,6 +74,7 @@ if( $copy_result ) if( isset( $tree[$dest_server_id][$container] ) ) { $tree[$dest_server_id][$container][] = $dest_dn; + sort( $tree[ $dest_server_id ][ $container ] ); $tree_icons[$dest_server_id][$dest_dn] = get_icon( $dest_server_id, $dest_dn ); $_SESSION['tree'] = $tree; $_SESSION['tree_icons'] = $tree_icons; @@ -102,7 +105,7 @@ else function r_copy_dn( $source_server_id, $dest_server_id, &$tree, $root_dn, $dest_dn ) { - echo "Copying " . htmlspecialchars( utf8_decode( $root_dn ) ) . "..."; + echo "Copying " . htmlspecialchars( $root_dn ) . "..."; flush(); $copy_result = copy_dn( $source_server_id, $root_dn, $dest_server_id, $dest_dn ); diff --git a/copy_form.php b/copy_form.php index a37a909..101e9fa 100644 --- a/copy_form.php +++ b/copy_form.php @@ -8,13 +8,12 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_GET['dn'] ) ); +$dn = rawurldecode( $_GET['dn'] ); $encoded_dn = rawurlencode( $dn ); $server_id = $_GET['server_id']; -$rdn = ldap_explode_dn( $dn, 0 ); +$rdn = pla_explode_dn( $dn ); $container = $rdn[ 1 ]; for( $i=2; $i -

Copy

+

Copy

Server:     Distinguished Name:

-Copy to a new object:
+Copy to a new object:

@@ -56,7 +55,7 @@ Copy to a new object:
Destination DN: - + diff --git a/create.php b/create.php index 1f643a8..344d7cb 100644 --- a/create.php +++ b/create.php @@ -14,19 +14,21 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$new_dn = stripslashes( $_POST['new_dn'] ); -$new_dn = utf8_encode( $new_dn ); +$new_dn = $_POST['new_dn']; +//$new_dn = utf8_encode( $new_dn ); $encoded_dn = rawurlencode( $new_dn ); $server_id = $_POST['server_id']; $vals = $_POST['vals']; $attrs = $_POST['attrs']; -$required_attrs = $_POST['required_attrs']; +$required_attrs = isset( $_POST['required_attrs'] ) ? $_POST['required_attrs'] : false; $object_classes = unserialize( rawurldecode( $_POST['object_classes'] ) ); $container = get_container( $new_dn ); +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); @@ -40,8 +42,6 @@ if( isset( $required_attrs ) && is_array( $required_attrs ) ) pla_error( "Error, you left the value for required attribute " . htmlspecialchars( $attr ) . " blank." ); - $attr = stripslashes( $attr ); - $val = stripslashes( $val ); $new_entry[ $attr ][] = utf8_encode( $val ); } } @@ -50,11 +50,22 @@ if( isset( $vals ) && is_array( $vals ) ) { foreach( $vals as $i => $val ) { - $val = stripslashes( $val ); $attr = $attrs[$i]; - $attr = stripslashes( $attr ); - if( trim($val) ) - $new_entry[ $attr ][] = utf8_encode( $val ); + if( is_attr_binary( $server_id, $attr ) ) { + if( $_FILES['vals']['name'][$i] != '' ) { + // read in the data from the file + $file = $_FILES['vals']['tmp_name'][$i]; + //echo "Reading in file $file...\n"; + $f = fopen( $file, 'r' ); + $binary_data = fread( $f, filesize( $file ) ); + fclose( $f ); + $val = $binary_data; + $new_entry[ $attr ][] = $val; + } + } else { + if( trim($val) ) + $new_entry[ $attr ][] = utf8_encode( $val ); + } } } @@ -62,6 +73,16 @@ $new_entry['objectClass'] = $object_classes; if( ! in_array( 'top', $new_entry['objectClass'] ) ) $new_entry['objectClass'][] = 'top'; +// UTF-8 magic. Must decode the values that have been passed to us +foreach( $new_entry as $attr => $vals ) + if( is_array( $vals ) ) + foreach( $vals as $i => $v ) + $new_entry[ $attr ][ $i ] = utf8_decode( $v ); + else + $new_entry[ $attr ] = utf8_decode( $vals ); + +//echo "
"; var_dump( $new_dn );print_r( $new_entry ); echo "
"; + $ds = pla_ldap_connect( $server_id ); $add_result = @ldap_add( $ds, $new_dn, $new_entry ); if( $add_result ) @@ -77,6 +98,7 @@ if( $add_result ) if( isset( $tree[$server_id][$container] ) ) { $tree[$server_id][$container][] = $new_dn; + sort( $tree[$server_id][$container] ); $tree_icons[$server_id][$new_dn] = get_icon( $server_id, $new_dn ); } diff --git a/create_form.php b/create_form.php index 53f9c13..0144f2a 100644 --- a/create_form.php +++ b/create_form.php @@ -10,12 +10,14 @@ * - container (rawurlencoded) (optional) */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_REQUEST['server_id']; -$step = $_REQUEST['step'] ? $_REQUEST['step'] : 1; // defaults to 1 -$container = stripslashes( $_REQUEST['container'] ); +$step = isset( $_REQUEST['step'] ) ? $_REQUEST['step'] : 1; // defaults to 1 +$container = $_REQUEST['container']; + +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); diff --git a/creation_template.php b/creation_template.php index 238a2ca..dd20562 100644 --- a/creation_template.php +++ b/creation_template.php @@ -10,17 +10,18 @@ * template */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; - -$template = stripslashes( $_POST['template'] ); +$template = $_POST['template']; $template = $templates[$template]; $server_id = $_POST['server_id']; check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); $server_name = $servers[ $server_id ][ 'name' ]; +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + include 'header.php'; ?> @@ -36,6 +37,7 @@ if( ! isset( $_POST['template'] ) ) pla_error( "No template specified in POST variables.\n" ); $handler = 'templates/creation/' . $template['handler']; +$handler = realpath( $handler ); if( file_exists( $handler ) ) include $handler; else diff --git a/delete.php b/delete.php index 786bf61..5d1bdeb 100644 --- a/delete.php +++ b/delete.php @@ -9,16 +9,18 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $encoded_dn = $_POST['dn']; -$dn = stripslashes( rawurldecode( $encoded_dn ) ); +$dn = rawurldecode( $encoded_dn ); $server_id = $_POST['server_id']; if( $dn === null ) pla_error( "You must specify a DN." ); +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); diff --git a/delete_attr.php b/delete_attr.php new file mode 100644 index 0000000..d48c3bd --- /dev/null +++ b/delete_attr.php @@ -0,0 +1,42 @@ + $junk ) + $redirect_url .= "&modified_attrs[]=$attr"; + header( "Location: $redirect_url" ); +} +else +{ + pla_error( "Could not perform ldap_modify operation.", ldap_error( $ds ), ldap_errno( $ds ) ); +} + +?> diff --git a/delete_form.php b/delete_form.php index d8e0d3c..aeaa141 100644 --- a/delete_form.php +++ b/delete_form.php @@ -9,16 +9,18 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( $_GET['dn'] ); +$dn = $_GET['dn']; $encoded_dn = rawurlencode( $dn ); $server_id = $_GET['server_id']; -$rdn = ldap_explode_dn( $dn, 0 ); +$rdn = pla_explode_dn( $dn ); $rdn = $rdn[0]; $server_name = $servers[$server_id]['name']; +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); @@ -61,7 +63,7 @@ if( $has_children ) {

This object is the root of a sub-tree containing objects -phpLDAPAdmin can recursively delete this object and all of its children. See below for a list of DNs +phpLDAPadmin can recursively delete this object and all of its children. See below for a list of DNs that this will delete. Do you want to do this?

Note: This is potentially very dangerous and you do this at your own risk. This operation cannot be undone. diff --git a/download_binary_attr.php b/download_binary_attr.php new file mode 100644 index 0000000..4e88a4a --- /dev/null +++ b/download_binary_attr.php @@ -0,0 +1,28 @@ + diff --git a/edit.php b/edit.php index 2935dad..5005e73 100644 --- a/edit.php +++ b/edit.php @@ -7,20 +7,22 @@ * Variables that come in as GET vars: * - dn (rawurlencoded) * - server_id + * - modified_attrs (optional) an array of attributes to highlight as + * they were changed by the last operation */ /** If an entry has more children than this, stop searching and display this amount with a '+' */ $max_children = 100; -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_GET['dn'] ) ); -$encoded_dn = rawurlencode( $dn ); -$updated_attr = stripslashes( $_GET['updated_attr'] ); +$dn= $_GET['dn']; +$decoded_dn = rawurldecode( $dn ); +$encoded_dn = rawurlencode( $decoded_dn ); +$modified_attrs = isset( $_GET['modified_attrs'] ) ? $_GET['modified_attrs'] : false; $server_id = $_GET['server_id']; $show_internal_attrs = isset( $_GET['show_internal_attrs'] ) ? true : false; -$rdn = ldap_explode_dn( $dn, 0 ); +$rdn = pla_explode_dn( $dn ); $rdn = $rdn[0]; check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); @@ -42,19 +44,24 @@ if( ! is_array( $oclasses ) ) $oclasses = array( $oclasses ); $avail_attrs = array(); $schema_oclasses = get_schema_objectclasses( $server_id, true ); -foreach( $oclasses as $oclass ) - $avail_attrs = array_merge( $schema_oclasses[ strtolower( $oclass ) ]['must_attrs'], - $schema_oclasses[ strtolower( $oclass ) ]['may_attrs'], - $avail_attrs ); - +$schema_attrs = get_schema_attributes( $server_id ); +foreach( $oclasses as $oclass ) { + $avail_attrs = array_merge( + $schema_oclasses[ strtolower( $oclass ) ]['must_attrs'], + $schema_oclasses[ strtolower( $oclass ) ]['may_attrs'], + $avail_attrs ); +} $avail_attrs = array_unique( $avail_attrs ); $avail_attrs = array_filter( $avail_attrs, "not_an_attr" ); - sort( $avail_attrs ); -/* A boolean flag to indicate whether this entry has a jpegPhoto associated with it. - * TODO If it does, the jpegPhotos will be drawn at the bottom of the form */ -$has_jpeg_photo = false; +$avail_binary_attrs = array(); +foreach( $avail_attrs as $i => $attr ) { + if( is_attr_binary( $server_id, $attr ) ) { + $avail_binary_attrs[] = $attr; + unset( $avail_attrs[ $i ] ); + } +} ?> @@ -71,36 +78,42 @@ $has_jpeg_photo = false; Refresh + title=""> - + Delete this entry + title=""> Copy this entry + title=""> - Export to LDIF - (mac) - (win) - (unix) + + (mac) + (win) + (unix) + + - ">Create a child entry + "> + 0 ) { - View + 0 ) { ?> - - Export subtree to LDIF - (mac) - (win) - (unix) + + (mac) + (win) + (unix) - - - + - - Add a jpegPhoto + + - + + + + + + + +
- - - - - + + + + - + + + + + + + + + - - + - + 0 ) { ?> + + + + + + + + + + + + + + - - - + foreach( get_entry_system_attrs( $server_id, $dn ) as $attr => $vals ) { + $counter++ + ?> + + + + \n"; + echo "\n"; } ?> @@ -250,35 +313,49 @@ if( $show_internal_attrs ) { - - - - - + + + + + - $vals ) { - flush(); - if( $attr == 'dn' ) - continue; - // is there a user-friendly translation available for this attribute? - if( isset( $friendly_attrs[ strtolower( $attr ) ] ) ) { - $attr_display = "" . - $friendly_attrs[ strtolower( $attr ) ] . ""; - } else { - $attr_display = $attr; - } + 0 ) + foreach( $hidden_attrs as $i => $attr_name ) + $hidden_attrs[$i] = strtolower( $attr_name ); + else + $hidden_attrs = array(); +?> + + $vals ) { + + if( isset( $schema_attrs[ strtolower($attr) ] ) ) + $attr_syntax = $schema_attrs[ strtolower( $attr ) ]->getSyntaxOID(); + flush(); + if( 0 == strcasecmp( $attr, 'dn' ) ) + continue; + + // has the config.php specified that this attribute is to be hidden? + if( in_array( strtolower( $attr ), $hidden_attrs ) ) + continue; + + // is there a user-friendly translation available for this attribute? + if( isset( $friendly_attrs[ strtolower( $attr ) ] ) ) { + $attr_display = "" . + $friendly_attrs[ strtolower( $attr ) ] . ""; + } else { + $attr_display = $attr; + } ?> - + @@ -288,152 +365,208 @@ if( $show_internal_attrs ) { - + - + + /* + * Note: at this point, the attribute must be text-based (not binary or jpeg) + */ - - - $val ) { ?> + /* + * If we are in read-only mode, simply draw the attribute values and continue. + */ + if( is_server_read_only( $server_id ) ) { + if( is_array( $vals ) ) { + foreach( $vals as $i => $val ) { + $val = utf8_decode( $val ); + echo $val . "
"; + } + } else { + echo utf8_decode( $vals ) . "
"; + } + continue; + } + + /* + * Is this a userPassword attribute? + */ + if( 0 == strcasecmp( $attr, 'userpassword' ) ) { + $user_password = $vals[0]; + + /* Capture the stuff in the { } to determine if this is crypt, md5, etc. */ + preg_match( "/{([^}]+)}/", $user_password, $enc_type); + $enc_type = strtolower($enc_type[1]); - + // Set the default hashing type if the password is blank (must be newly created) + if( $val == '' ) { + $enc_type = $servers[$server_id]['default_hash']; + } ?> - - - - -
- - - - + - + - - - + + - + - - - - - - - - + + >crypt + >md5 + >md5crypt + >blowfish + >sha - + getType() ) ) { + $val = $vals[0]; + ?> - + + + + + - + ]" - value="" /> + /* + * End of special case attributes. + */ - + /* + * This is a normal attribute, to be displayed and edited in plain text. + */ + foreach( $vals as $i => $val ) { + $val = utf8_decode( $val ); ?> - - - - + + + + + +
+ +

+ + - + $vals ) */ ?> - + + + @@ -441,32 +574,40 @@ if( $show_internal_attrs ) {
Rename Entry + + +
- - + + -
+ + + + - - - - - -
- - Add New Attribute - - - 0 ) { ?> + 0 ) { ?> - + - + - (no new attributes available for this entry) + () - +
+ + + + + + + + + + +
-Internal Attriubtes +> + - -Internal Attriubtes -(hidden) + + +() @@ -230,16 +289,20 @@ if( ($children_count = count( $children ) ) > 0 ) { $val ) { - $counter++ - ?> -
+ +
+ +
(none)
(" . $lang['none'] . ")
- - Modify Attributes - +

- (add value) + + + () +
- - + /* + * Is this attribute binary? + */ + if( is_attr_binary( $server_id, $attr ) ) { + $href = "download_binary_attr.php?server_id=$server_id&dn=$encoded_dn&attr=$attr"; + ?> - + +
+ 1 ) { for( $i=1; $i<=count($vals); $i++ ) { ?> + "> ()
+ +
+ - This attribute contains binary data,
- which cannot be safely displayed
- or edited in a web-browser.
+ + + + +
- - - - -

- - - - - +} +//--> + + + +
+ + + +
$values ) + if( 0 == strcasecmp( $attr, $x ) ) + return false; + return true; } ?> diff --git a/entry_chooser.php b/entry_chooser.php index f71fc87..6b6465d 100644 --- a/entry_chooser.php +++ b/entry_chooser.php @@ -1,7 +1,7 @@ " . htmlspecialchars( $container ) . "
\n"; } +/* Has the use already begun to descend into a specific server tree? */ if( $server_id !== false && $container !== false ) { check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); @@ -43,25 +44,48 @@ if( $server_id !== false && $container !== false ) else foreach( $dn_list as $dn ) { $href = "javascript:returnDN( '$dn' )"; - echo "    " . "" . htmlspecialchars( $dn ) . "
\n"; } } +/* draw the root of the selection tree (ie, list all the servers) */ else { foreach( $servers as $id => $server ) { if( $server['host'] ) { - echo htmlspecialchars( $server['name'] ) . "
\n"; - $dn = ( $server['base'] ? $server['base'] : try_to_get_root_dn( $id ) ); - $href = "javascript:returnDN( '$dn' )"; - echo "    " . - "" . htmlspecialchars( $dn ) . "
\n"; + echo "" . htmlspecialchars( $server['name'] ) . "
\n"; + if( ! have_auth_info( $id ) ) + echo "   (Not logged in)
"; + else { + $dn = ( $server['base'] ? $server['base'] : try_to_get_root_dn( $id ) ); + if( ! $dn ) { + echo "   (Could not determine base DN)
"; + } else { + $href = "javascript:returnDN( '$dn' )"; + echo "    " . + "" . htmlspecialchars( $dn ) . "
\n"; + } + } } } } +// added by PD. 14082003, +// adding the element access allows it to work with javascript arrays + +// the name of the form extracted from the first part of the URL variable. +$formpart=substr($return_form_element,0,strpos($return_form_element,".")); + +// the name of the element extracted from the last part of the URL variable (after the dot) +$elmpart =substr($return_form_element,strpos($return_form_element,".")+1); + +// rebuilt return value +$return_form_element = $formpart . ".elements[\"" . $elmpart . "\"]"; + ?> + diff --git a/images/logo.jpg b/images/logo.jpg new file mode 100644 index 0000000..6eadc24 Binary files /dev/null and b/images/logo.jpg differ diff --git a/images/nt.png b/images/nt.png new file mode 100644 index 0000000..f23a5fa Binary files /dev/null and b/images/nt.png differ diff --git a/images/warning.png b/images/warning.png new file mode 100644 index 0000000..0539ce8 Binary files /dev/null and b/images/warning.png differ diff --git a/index.php b/index.php index 008a941..2b9df6c 100644 --- a/index.php +++ b/index.php @@ -1,26 +1,32 @@ - If you are seeing this in your browser, PHP is not installed on your web server!!! -*/?> + +*******************************************/ - +@require 'common.php'; - +?> + + - phpLDAPAdmin - <?php echo pla_version(); ?> + phpLDAPadmin - <?php echo pla_version(); ?> -

Configure phpLDAPAdmin

+

Configure phpLDAPadmin



-You need to configure phpLDAPAdmin. Edit the file 'config.php' to do so.
+You need to configure phpLDAPadmin. Edit the file 'config.php' to do so.

An example config file is provided in 'config.php.example' @@ -30,7 +36,7 @@ An example config file is provided in 'config.php.example' \n"; +echo "\n"; ?> @@ -38,11 +44,11 @@ echo "\n"; PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd"> -phpLDAPAdmin - <?php echo pla_version(); ?> +phpLDAPadmin - <?php echo pla_version(); ?> - + @@ -66,17 +72,35 @@ function check_config() if( ! extension_loaded( 'ldap' ) ) { pla_error( "Your install of PHP appears to be missing LDAP support. Please install " . - "LDAP support before using phpLDAPAdmin." ); + "LDAP support before using phpLDAPadmin." ); return false; } + /* Make sure they have all the functions we will need */ + $required_functions = array( 'utf8_encode', 'utf8_decode', 'htmlspecialchars' ); + foreach( $required_functions as $function ) { + if( ! function_exists( $function ) ) { + pla_error( "Your install of PHP appears to be missing the function '$function()' " . + "phpLDAPadmin requires this function to work properly." ); + return false; + } + } + /* Make sure the config file is readable */ - if( ! is_readable( 'config.php' ) ) + //if( ! is_readable( 'config.php' ) ) + if( ! is_readable(realpath( 'config.php' )) ) { echo "The config file 'config.php' is not readable. Please check its permissions."; return false; } + /* Make sure their PHP install is up to snuff */ + if( version_compare( phpversion(), "4.1.0" ) < 0 ) + { + echo "You are using php version " . phpversion() . ". phpLDAPadmin requires version 4.1 or greater."; + return false; + } + /* check for syntax errors in config.php */ // capture the result of including the file with output buffering ob_start(); @@ -92,7 +116,7 @@ function check_config() ?> - phpLDAPAdmin Config File Error + phpLDAPadmin Config File Error @@ -151,7 +175,7 @@ function check_config() if( $count == 0 ) { echo "None of the " . count($servers) . " servers in your \$servers array is "; - echo "active in config.php. phpLDAPAdmin cannot proceed util you correct this."; + echo "active in config.php. phpLDAPadmin cannot proceed util you correct this."; return false; } diff --git a/lang/english.php b/lang/english.php new file mode 100644 index 0000000..c4ce9d7 --- /dev/null +++ b/lang/english.php @@ -0,0 +1,142 @@ +To delete an attribute, empty the text field and click save.'; +$lang['viewing_read_only'] = 'Viewing entry in read-only mode.'; +$lang['change_entry_rdn'] = 'Change this entry\'s RDN'; +$lang['no_new_attrs_available'] = 'no new attributes available for this entry'; +$lang['binary_value'] = 'Binary value'; +$lang['add_new_binary_attr'] = 'Add New Binary Attribute'; +$lang['add_new_binary_attr_tooltip'] = 'Add a new binary attribute/value from a file'; +$lang['alias_for'] = 'Alias for'; +$lang['download_value'] = 'download value'; +$lang['delete_attribute'] = 'delete attribute'; +$lang['true'] = 'true'; +$lang['false'] = 'false'; +$lang['none_remove_value'] = 'none, remove value'; +$lang['really_delete_attribute'] = 'Really delete attribute'; + +// Schema browser +$lang['the_following_objectclasses'] = 'The following objectClasses are supported by this LDAP server.'; +$lang['the_following_attributes'] = 'The following attributeTypes are supported by this LDAP server.'; +$lang['the_following_matching'] = 'The following matching rules are supported by this LDAP server.'; +$lang['the_following_syntaxes'] = 'The following syntaxes are supported by this LDAP server.'; +$lang['jump_to_objectclass'] = 'Jump to an objectClass'; +$lang['jump_to_attr'] = 'Jump to an attribute'; +$lang['schema_for_server'] = 'Schema for server'; +$lang['required_attrs'] = 'Required Attributes'; +$lang['optional_attrs'] = 'Optional Attributes'; +$lang['OID'] = 'OID'; +$lang['desc'] = 'Description'; +$lang['is_obsolete'] = 'This objectClass is obsolete'; +$lang['inherits'] = 'Inherits'; +$lang['jump_to_this_oclass'] = 'Jump to this objectClass definition'; +$lang['matching_rule_oid'] = 'Matching Rule OID'; +$lang['syntax_oid'] = 'Syntax OID'; + +// Adding objectClass form +$lang['new_required_attrs'] = 'New Required Attributes'; +$lang['requires_to_add'] = 'This action requires you to add'; +$lang['new_attributes'] = 'new attributes'; +$lang['new_required_attrs_instructions'] = 'Instructions: In order to add this objectClass to this entry, you must specify'; +$lang['that_this_oclass_requires'] = 'that this objectClass requires. You can do so in this form.'; +$lang['add_oclass_and_attrs'] = 'Add ObjectClass and Attributes'; + +// General +$lang['chooser_link_tooltip'] = 'Click to popup a dialog to select an entry (DN) graphically'; +$lang['no_updates_in_read_only_mode'] = 'You cannot perform updates while server is in read-only mode'; +$lang['bad_server_id'] = 'Bad server id'; +$lang['not_enough_login_info'] = 'Not enough information to login to server. Please check your configuration.'; +$lang['could_not_connect'] = 'Could not connect to LDAP server.'; +$lang['could_not_perform_ldap_mod_add'] = 'Could not perform ldap_mod_add operation.'; + +// Add value form +$lang['add_new'] = 'Add new'; +$lang['value_to'] = 'value to'; +$lang['server'] = 'Server'; +$lang['distinguished_name'] = 'Distinguished Name'; +$lang['current_list_of'] = 'Current list of'; +$lang['values_for_attribute'] = 'values for attribute'; +$lang['inappropriate_matching_note'] = 'Note: You will get an "inappropriate matching" error if you have not
' . + 'setup an EQUALITY rule on your LDAP server for this attribute.'; +$lang['enter_value_to_add'] = 'Enter the value you would like to add:'; +$lang['new_required_attrs_note'] = 'Note: you may be required to enter new attributes
that this objectClass requires.'; +$lang['syntax'] = 'Syntax'; + +?> diff --git a/lang/french.php b/lang/french.php new file mode 100644 index 0000000..f7f02b9 --- /dev/null +++ b/lang/french.php @@ -0,0 +1,70 @@ + diff --git a/lang/german.php b/lang/german.php new file mode 100644 index 0000000..54fac8e --- /dev/null +++ b/lang/german.php @@ -0,0 +1,103 @@ +To delete an attribute, empty the text field and click save.'; +$lang['viewing_read_only'] = 'Zeige Eintrag im Nurlesemodus';//'Viewing entry in read-only mode.'; +$lang['change_entry_rdn'] = 'Ändere den RDN des Eintrages';//'Change this entry\'s RDN'; +$lang['no_new_attrs_available'] = 'Keine weiteren Attribute verfügbar für diesen Eintrag';//'no new attributes available for this entry'; +$lang['binary_value'] = 'Binärwert';//'Binary value'; +$lang['add_new_binary_attr'] = 'Neuen Binärwert hinzufügen';//'Add New Binary Attribute'; +$lang['add_new_binary_attr_tooltip'] = 'ABCDEFGH';//'Add a new binary attribute/value from a file'; +$lang['alias_for'] = 'Alias für';//'Alias for'; +$lang['download_value'] = 'Wert herunterladen';//'download value'; +$lang['delete_attribute'] = 'Lösche Attribut';//'delete attribute'; +$lang['true'] = 'Wahr';//'true'; +$lang['false'] = 'Falsch';//'false'; +$lang['none_remove_value'] = 'nichts, entferne den Wert';//?? //'none, remove value'; +$lang['really_delete_attribute'] = 'Lösche das Attribut wirklich';//'Really delete attribute'; + +// Schema browser +$lang['the_following_objectclasses'] = 'Die folgenden objectClass werden vom LDAP-Server unterstützt.';//'The following objectClasses are supported by this LDAP server.'; +$lang['the_following_attributes'] = 'Die folgenden Attribute werden vom LDAP-Server unterstützt.';//'The following attributeTypes are supported by this LDAP server.'; +$lang['the_following_matching'] = 'Die folgenden Suchregeln werden vom LDAP-Server unterstützt.';//'The following matching rules are supported by this LDAP server.'; +$lang['the_following_syntaxes'] = 'Die folgenden Syntaxe werden vom LDAP-Server unterstützt.';//'The following syntaxes are supported by this LDAP server.'; +$lang['jump_to_objectclass'] = 'Gehe zur objectClass';//'Jump to an objectClass'; +$lang['jump_to_attr'] = 'Gehe zum Attribut';//'Jump to an attribute'; +$lang['schema_for_server'] = 'Schema für Server';//'Schema for server'; +$lang['required_attrs'] = 'Notwendige Attribute';//'Required Attributes'; +$lang['optional_attrs'] = 'Optionale Attribute';//'Optional Attributes'; +$lang['OID'] = 'OID';//'OID'; +$lang['desc'] = 'Beschreibung';//'Description'; +$lang['is_obsolete'] = 'Diese objectClass ist veraltet';//'This objectClass is obsolete'; +$lang['inherits'] = 'Abgeleitet von';//'Inherits'; +$lang['jump_to_this_oclass'] = 'Gehe zur objectClass Definition';//'Jump to this objectClass definition'; + +// General +$lang['chooser_link_tooltip'] = "Click to popup a dialog to select an entry (DN) graphically"; + +?> diff --git a/ldap_error_codes.txt b/ldap_error_codes.txt index 4cec107..45e7341 100644 --- a/ldap_error_codes.txt +++ b/ldap_error_codes.txt @@ -18,9 +18,11 @@ 0x10 LDAP_NO_SUCH_ATTRIBUTE "That entry does not contain the attribute specified." 0x11 LDAP_UNDEFINED_TYPE "The attribute type specified is invalid." 0x12 LDAP_INAPPROPRIATE_MATCHING "This usually means that your LDAP server has not defined an equality rule - for the attribute you are trying to alter. This is not phpLDAPAdmin's fault as the + for the attribute you are trying to alter. This is not phpLDAPadmin's fault as the LDAP server has refused to perform the operation (as well it should if there is - no equality rule for it to use for the operation)." + no equality rule for it to use for the operation). This generally applies when + adding a new value to a binary attribute, or removing a single value from a + multi-valued binary attribute." 0x13 LDAP_CONSTRAINT_VIOLATION "Some constraint would be violated by performing the action. This can happen when you try to add a second value to a single-valued attribute, for example." 0x14 LDAP_TYPE_OR_VALUE_EXISTS "An attribute type or attribute value @@ -51,7 +53,8 @@ to exist or that would remove a required attribute, given the current list of ObjectClasses." 0x42 LDAP_NOT_ALLOWED_ON_NONLEAF "The entry you tried to operate on has children. (usually this means you - tried to delete the entry, which you cannot do to an entry with children)." + tried to delete or rename the entry, which you cannot do to an entry + with children)." 0x43 LDAP_NOT_ALLOWED_ON_RDN "You cannot preform that operation on a the relative distinguished name (RDN) of an object." 0x44 LDAP_ALREADY_EXISTS "The object already exists (usually you are trying to create a new object diff --git a/ldif_export.php b/ldif_export.php index 6c30fdc..a51b84c 100644 --- a/ldif_export.php +++ b/ldif_export.php @@ -11,10 +11,9 @@ * - scope (one of 'sub', 'base', or 'one') */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_GET['dn'] ) ); +$dn = rawurldecode( $_GET['dn'] ); $server_id = $_GET['server_id']; $format = $_GET['format']; $scope = $_GET['scope'] ? $_GET['scope'] : 'base'; @@ -23,12 +22,15 @@ check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); $objects = pla_ldap_search( $server_id, 'objectClass=*', $dn, array(), $scope, false ); +$server_name = $servers[ $server_id ][ 'name' ]; +$server_host = $servers[ $server_id ][ 'host' ]; //echo "
";
 //print_r( $objects );
 //exit;
 
 $rdn = get_rdn( $dn );
+$friendly_rdn = get_rdn( $dn, 1 );
 
 switch( $format ) {
 	case 'win': 	$br = "\r\n"; break;
@@ -40,44 +42,62 @@ switch( $format ) {
 if( ! $objects )
 	pla_error( "Search on dn (" . htmlspecialchars($dn) . ") came back empty" );
 
-header( "Content-type: text/plain" );
-header( "Content-disposition: attachment; filename=\"$rdn.ldif\"" );
+// define the max length of a ldif line to 76
+// as it is suggested (implicitely) for (some) binary
+// attributes in rfc 2849 (see note 10)
+
+define("MAX_LDIF_LINE_LENGTH",76);
+
+header( "Content-type: application/download" );
+header( "Content-Disposition: filename=$friendly_rdn.ldif" ); 
 header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); 
 header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" ); 
 header( "Cache-Control: post-check=0, pre-check=0", false );
-header( "Pragma: no-cache" );
 
 echo "version: 1$br$br";
-echo "# LDIF Export for: $rdn$br";
-echo "# Scope: $scope, " . count( $objects ) . " entries$br";
-echo "# Generated by phpLDAPAdmin on " . date("F j, Y g:i a") . "$br";
+echo "# LDIF Export for: " . utf8_decode( $dn ) . "$br";
+echo "# Generated by phpLDAPadmin on " . date("F j, Y g:i a") . "$br";
+echo "# Server: " . utf8_decode( $server_name ) . " ($server_host)$br";
+echo "# Search Scope: $scope$br";
+echo "# Total entries: " . count( $objects ) . "$br"; 
 echo $br;
 
+$counter = 0;
 foreach( $objects as $dn => $attrs )
 {
+	$counter++;
 	unset( $attrs['dn'] );
 	unset( $attrs['count'] );
 
-	if( is_safe_ascii( $dn ) )
-		echo "dn: $dn$br";
-	else
-		echo "dn:: " . base64_encode( $dn ) . $br;
 
+	// display "# Entry 3: cn=test,dc=example,dc=com..."
+	$title_string = "# Entry $counter: " . utf8_decode( $dn ); 
+	if( strlen( $title_string ) > MAX_LDIF_LINE_LENGTH-3 )
+		$title_string = substr( $title_string, 0, MAX_LDIF_LINE_LENGTH-3 ) . "...";
+	echo "$title_string$br";
+
+	// display the DN
+	if( is_safe_ascii( $dn ) )
+	  multi_lines_display("dn: $dn");
+	else
+	  multi_lines_display("dn:: " . base64_encode( $dn ));
+
+	// display all the attrs/values
 	foreach( $attrs as $attr => $val ) {
 		if( is_array( $val ) ) {
 			foreach( $val as $v ) {
 				if( is_safe_ascii( $v ) ) {
-					echo "$attr: $v$br";
+				  multi_lines_display("$attr: $v");
 				} else {
-					echo "$attr:: " . base64_encode( $v ) . $br;
+				  multi_lines_display("$attr:: " . base64_encode( $v ));
 				}
 			}
 		} else {
 			$v = $val;
 			if( is_safe_ascii( $v ) ) {
-				echo "$attr: $v$br";
+			  multi_lines_display("$attr: $v");
 			} else {
-				echo "$attr:: " . base64_encode( $v ) . $br;
+			  multi_lines_display("$attr:: " . base64_encode( $v ));
 			}
 		}
 	}
@@ -91,3 +111,26 @@ function is_safe_ascii( $str )
 			return false;
 	return true;
 }
+
+
+function multi_lines_display($str){
+  global $br;
+  
+  $length_string = strlen($str);
+  $max_length = MAX_LDIF_LINE_LENGTH;
+
+  while ($length_string > $max_length){
+    echo substr($str,0,$max_length).$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 = MAX_LDIF_LINE_LENGTH-1;
+  }
+  echo $str."".$br;
+}
+
+
+?>
diff --git a/ldif_functions.php b/ldif_functions.php
new file mode 100644
index 0000000..e69062f
--- /dev/null
+++ b/ldif_functions.php
@@ -0,0 +1,418 @@
+";
+    }
+    elseif(ereg("^version",trim($current_line))){
+      $ldif_line_found=1;
+      ldif_next_line();
+      // TODO: handle the version number here
+    }
+    //    not valid ldif line was found
+    else{
+      //set the flag warning
+      $warning=1;
+      $warning_message = "No version found - assuming 1";
+    }
+    
+  }//end while
+
+  $warning?0:1;
+}// end get_version() method
+
+
+
+/**
+ * Return a warning message
+ *
+ * @return a warning message
+ */
+
+function ldif_warning_message(){
+  global $warning_message;
+  return $warning_message;
+}
+
+function ldif_error_message(){
+  global $error_message;
+  return $error_message;
+}
+
+/**
+ * Check if the file is valie
+ *
+ *
+ */
+
+function is_valid_file($path_to_file){
+  
+  return file_exists($path_to_file)&&is_file($path_to_file)&&is_readable($path_to_file);
+
+}
+
+/**
+ * Close the file
+ *
+ *
+ */
+
+function ldif_close(){
+  global $fp;
+  @fclose($fp);
+}
+
+/**
+ * Return the action that the ldap server should do with an entry
+ * The default action is add.
+ *
+ * @return the action the server should do.
+ */
+
+function ldif_get_action(){
+  global $current_line;
+  
+  //  default action is add
+  $action ="add";
+  if(ereg("changetype:[ ]*(delete|add|modrdn|moddn|modify)",$current_line,$arr)){
+    $action = $arr[1];
+    ldif_next_line();
+  }
+  return $action;
+}
+
+
+/**
+ * Retrieve the dn of an entry
+ 
+ * @return the dn value of an entry
+ */
+
+function ldif_fetch_dn_entry(){
+
+  global $error;
+  global $current_line;
+  global $error_message;
+  global $line_number;
+  global $number_of_lines;
+  // the value of the dn
+  $current_dn_value;
+
+  //boolean flag to see if any dn was found
+  $dn_found=0;
+  
+
+    while(!ldif_eof()&&!$dn_found&&!$error){
+
+      //skip comment and blank line
+      if(ldif_is_blank_line()||ldif_is_comment_line()){
+	//debug
+	//echo "$line_number - comment\n
"; + ldif_next_line(); + } + // case where the dn is found + elseif(ldif_is_dn_line()){ + $current_dn=$current_line; + //debug + //echo "$line_number - $current_line
"; + $dn_found=1; + } + else{ + $error=1; + $error_message = "Error: Line ".$line_number." - a valid dn is required"; + return false; + } + + }//fin while + + + + // if mainly to hanlde the case + //where a dn was found and is written on several lines + // could be use to test if any white line appears after + if($dn_found&&!ldif_eof()){ + + //boolean flag to see if the dn is written on more than one line + $dn_has_next=0; + + //keeping track of the line number of the dn when first encountered + $dn_line_number = $line_number; + // empty string to store the possible following lines + while(!$dn_has_next){ + ldif_next_line(); + + //if next line begin with a space and is not empty + // append to the previous line + if((substr($current_line,0,1)==" ")){ + ereg_replace("\n|\r|\r\n","",$current_dn =trim($current_dn).trim($current_line)); + } + //else leaving the while loop + else{ + $dn_has_next=1; + + } + + }//end while + + //debug + //echo $dn_line_number." - ".$current_dn."\r\n
"; + // handle base 64 case here + if(ereg("^dn::",$current_dn)){ + + $current_dn = base64_decode(trim(substr($current_dn,4,strlen($current_dn)-1))); + + }else{ + $current_dn = trim(substr($current_dn,3,strlen($current_dn)-1)); + + + } + // echo $dn_line_number."-".$current_dn."
"; + } + + return $current_dn; +} + + +/** + * functions which will return a array of attributes + * for this entry + * + * @return attrs the array of attributes + */ + +function ldif_fetch_attributes_for_entry(){ + global $error; + global $current_line; + global $line_number; + global $error_message; + + global $server_id; + $attribute_value=""; + + //array to store the attribute + $attrs = array(); + + + // while we dont find any empty line or any error occur + while(trim($current_line)!=""&&$error!=1){ + + + //1 - we need to check if it's a valid ldif line. + //----------------------------------------------- + + if(ereg(":",trim($current_line),$arr)&&substr($current_line,0,1)!=" "){ + + //get the position of the character ":" + $pos = strpos($current_line,":"); + + //get the name of the attribute + + $attribute_name = substr($current_line,0, $pos); + // get the value part of the attribute + $attribute_value_part = trim(substr($current_line,$pos+1,strlen($current_line))); + + //2 - we get the description and the "value" part + // now check if it's split over several lines + + $att_has_next = 0; + $attr_line_number=$line_number; + + while(!$att_has_next){ + ldif_next_line(); + + //if there is a another line for the attribute value,it should: + // 1 - begin with a white space + // 2 - have a length > 1 + // 3 - not have the character : + if((substr($current_line,0,1)==" ")&&!ereg(":",trim($current_line))){ + ereg_replace("\n|\r|\r\n","",$attribute_value_part =trim($attribute_value_part).trim($current_line)); + } + else{ + $att_has_next=1; + } + + } + + //3 - need to see if the value is base 64 encoded,an url + //------------------------------------------------------- + $attribute_value=""; + //if the next character in the value part is ":";it's it base 64 encoded + if(substr($attribute_value_part,0,1)==":"){ + + // it is binary data,so we just decode it + $attribute_value = base64_decode(trim(substr($attribute_value_part,1))); + + } + //else if the next charachter is <, we have to handle an url + elseif(substr($attribute_value_part,0,1)=="<"){ + // we need to handle the case for the scheme "file://" as it + //doesn't seem to be supported by fopen + + $file_path_with_scheme= trim(substr($attribute_value_part,1)); + + if(ereg("^file://",$file_path_with_scheme)){ + + $file_path = substr(trim($file_path_with_scheme),7); + if($handle = @fopen($file_path, "rb")){ + $attribute_value = @fread($handle,filesize($file_path)); + @fclose($handle); + } + else{ + $error=1; + $error_message = "Line: ".$attr_line_number. " - Unable to open file ". + $file_path_with_scheme; + return false; + } + } + else{ + $error=1; + $error_message = "Line: ".$attr_line_number. " - the URL seems no to be well formed "; + return false; + } + } + //it's a string + else{ + $attribute_value = trim($attribute_value_part); + } + + $attrs[$attribute_name][] = $attribute_value; + //debug + // echo $attr_line_number."- ".$attribute_name.":".$attribute_value."\r\n
"; + + } + // the attribute line contains the charachter ":" or there is + // at least a white space at the begining + else{ + $error_message = "Line ". $line_number. " - Attribute not well formed"; + $error=1; + return false; + } + } + return $attrs; +} + + diff --git a/ldif_import.php b/ldif_import.php new file mode 100644 index 0000000..7b86cf2 --- /dev/null +++ b/ldif_import.php @@ -0,0 +1,119 @@ + 0 or pla_error( "Uploaded file is empty." ); +check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); +have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); + +include 'header.php'; ?> + + + +

Import LDIF File

+

+ Server: + File: + ( bytes) +

+ +
+
+
This is an experimental and untested feature. Proceed at your own risk.
+The add and delete operations are the only operations currently supported. +
+
+ +Success
"; + } + else{ + echo "failed

"; + pla_error( "Could not add object: " . htmlspecialchars( utf8_decode( $dn ) ), ldap_error( $ds ), ldap_errno( $ds ) ); + } + } + else{ + echo "failed

"; + echo "
".display_error_message(ldif_error_message())."
"; + flush(); + } + } + elseif($action=="delete"){ + echo "Deleting dn: ".$dn_entry." "; + if(@ldap_delete($ds,$dn_entry)){ + echo "Success
"; + flush(); + } + else{ + echo "Failed

"; + flush(); + pla_error( "Could not delete object: " . htmlspecialchars( utf8_decode( $dn ) ), ldap_error( $ds ), ldap_errno( $ds ) ); + + } + } + + } + + +reload_left_frame(); + + +function reload_left_frame(){ + global $server_id; + + echo "\r\n"; +} + +function display_error_message($error_message){ + echo "
".$error_message."
"; +} +function display_warning($warning){ + echo "
".$warning."
"; +} + +?> + + + + + + + + + diff --git a/ldif_import_form.php b/ldif_import_form.php new file mode 100644 index 0000000..7a37dee --- /dev/null +++ b/ldif_import_form.php @@ -0,0 +1,48 @@ + + + + +

Import LDIF File

+

Server:

+ + +
+
+
This is an experimental and untested feature. Proceed at your own risk. +
+The add operation is the only operation currently supported. +
+
+
+ +Select an LDIF file:
+
+ +
+ +
+
+ +
+ + + diff --git a/login.php b/login.php index 2c80ae0..babedbe 100644 --- a/login.php +++ b/login.php @@ -15,12 +15,12 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_POST['server_id']; -$dn = stripslashes( $_POST['login_dn'] ); -$pass = stripslashes( $_POST['login_pass'] ); +$dn = $_POST['login_dn']; +$uid = $_POST['uid']; +$pass = $_POST['login_pass']; $redirect = rawurldecode( $_POST['redirect'] ); $anon_bind = $_POST['anonymous_bind'] == 'on' ? true : false; check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); @@ -37,6 +37,22 @@ if( $anon_bind ) { $host = $servers[$server_id]['host']; $port = $servers[$server_id]['port']; +if ( isset( $servers[$server_id]['login_attr'] ) && + $servers[$server_id]['login_attr'] != "dn" && + $servers[$server_id]['login_attr'] != "") { + + // search for the "uid" first + $ds = ldap_connect ( $host, $port ); + $ds or pla_error( "Could not contact '" . htmlspecialchars( $host ) . "' on port '" . htmlentities( $port ) . "'" ); + @ldap_bind ($ds) or pla_error( "Could not bind anonymously to server. " . + "Unless your server accepts anonymous binds, " . + "the login_attr feature will not work properly."); + $sr=@ldap_search($ds,$servers[$server_id]['base'],$servers[$server_id]['login_attr'] ."=". $uid, array("dn"), 0, 1); + $result = @ldap_get_entries($ds,$sr); + $dn = $result[0]["dn"]; + @ldap_unbind ($ds); +} + // verify that the login is good $ds = @ldap_connect( $host, $port ); $ds or pla_error( "Could not connect to '" . htmlspecialchars( $host ) . "' on port '" . htmlentities( $port ) . "'" ); @@ -49,7 +65,9 @@ $bind_result = @ldap_bind( $ds, $dn, $pass ); if( ! $bind_result ) pla_error( "Bad username/password. Try again" ); -$expire = $cookie_time==0 ? null : time()+$cookie_time; +if( ! isset( $cookie_time ) ) + $cookie_time = 0; +$expire = $cookie_time == 0 ? null : time()+$cookie_time; if( $anon_bind ) { // we set the cookie val to 0 for anonymous binds. $res1 = setcookie( "pla_login_dn_$server_id", '0', $expire, dirname( $_SERVER['PHP_SELF'] ) ); diff --git a/login_form.php b/login_form.php index e09eec6..fefd20d 100644 --- a/login_form.php +++ b/login_form.php @@ -9,8 +9,7 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_GET['server_id']; $server = $servers[$server_id]; @@ -43,9 +42,9 @@ check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars -Warning: this is an insecure (non-SSL) connection!
- SSL is recommended when transmitting sensitive passwords.
-
+
+Warning: This web connection is unencrypted (not https).
+
@@ -64,8 +63,12 @@ check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars Anonymous Bind + +Login DN';} ?> +" size="40" value="" /> Password diff --git a/logout.php b/logout.php index 86f0fc7..98951a8 100644 --- a/logout.php +++ b/logout.php @@ -9,8 +9,7 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_GET['server_id']; check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); diff --git a/new_attr.php b/new_attr.php index f9d36fb..ee3bccb 100644 --- a/new_attr.php +++ b/new_attr.php @@ -9,33 +9,52 @@ * - server_id * - attr * - val + * - binary */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = stripslashes( rawurldecode( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $server_id = $_POST['server_id']; -$attr = stripslashes( $_POST['attr'] ); -$val = stripslashes( $_POST['val'] ); +$attr = $_POST['attr']; +$val = $_POST['val']; $val = utf8_encode( $val ); $encoded_dn = rawurlencode( $dn ); $encoded_attr = rawurlencode( $attr ); +$is_binary_val = isset( $_POST['binary'] ) ? true : false; + +if( ! $is_binary_val && $val == "" ) { + pla_error( "You left the attribute value blank. Please go back and try again." ); +} + +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); -// special case for jpegPhoto attributes: -// we must go read the data from the file. -if( 0 == strcasecmp( $attr, 'jpegPhoto' ) ) -{ - $file = $_FILES['jpeg_photo_file']['tmp_name']; +// special case for binary attributes (like jpegPhoto and userCertificate): +// we must go read the data from the file and override $val with the binary data +if( $is_binary_val ) { + $file = $_FILES['val']['tmp_name']; $f = fopen( $file, 'r' ); - $jpeg_data = fread( $f, filesize( $file ) ); + $binary_data = fread( $f, filesize( $file ) ); fclose( $f ); - $val = $jpeg_data; + $val = $binary_data; } +// Automagically hash new userPassword attributes according to the +// chosen in config.php. +if( 0 == strcasecmp( $attr, 'userpassword' ) ) +{ + if( $servers[$server_id]['default_hash'] != '' ) { + $enc_type = $servers[$server_id]['default_hash']; + $new_val = password_hash( $new_val, $enc_type ); + $val = $new_val; + } +} + + $ds = pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP server" ); $new_entry = array( $attr => $val ); $result = @ldap_mod_add( $ds, $dn, $new_entry ); diff --git a/new_jpeg_photo_form.php b/new_jpeg_photo_form.php deleted file mode 100644 index a97598f..0000000 --- a/new_jpeg_photo_form.php +++ /dev/null @@ -1,46 +0,0 @@ - - - - -

Add a jpegPhoto to

-

Server2:     Distinguished Name: -

- - -Select a jpeg file:
-
- -
- - - -
-
- -
- - - - diff --git a/rdelete.php b/rdelete.php index 6e78aa0..a9f7421 100644 --- a/rdelete.php +++ b/rdelete.php @@ -9,16 +9,18 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $encoded_dn = $_POST['dn']; -$dn = stripslashes( rawurldecode( $encoded_dn ) ); +$dn = rawurldecode( $encoded_dn ); $server_id = $_POST['server_id']; if( ! $dn ) pla_error( "You must specify a DN." ); +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP server" ); @@ -66,7 +68,7 @@ if( $del_result ) parent.left_frame.location.reload(); - Object and sub-tree deleted successfully. + Object and sub-tree deleted successfully. Deleting " . htmlspecialchars( utf8_decode( $dn ) ) . "..."; + echo "
Deleting " . htmlspecialchars( $dn ) . "..."; flush(); if( ldap_delete( $ds, $dn ) ) { echo " Success
\n"; @@ -99,7 +101,7 @@ function pla_rdelete( $server_id, $dn ) foreach( $children as $child_dn ) { pla_rdelete( $server_id, $child_dn ); } - echo "Deleting " . htmlspecialchars( utf8_decode( $dn ) ) . "..."; + echo "Deleting " . htmlspecialchars( $dn ) . "..."; flush(); if( ldap_delete( $ds, $dn ) ) { echo " Success
\n"; diff --git a/refresh.php b/refresh.php index b446218..fd670aa 100644 --- a/refresh.php +++ b/refresh.php @@ -9,8 +9,7 @@ * - server_id */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_GET['server_id']; diff --git a/rename.php b/rename.php index 095cd64..e513a09 100644 --- a/rename.php +++ b/rename.php @@ -10,21 +10,26 @@ * - new_rdn */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; -$dn = rawurldecode( stripslashes( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $server_id = $_POST['server_id']; -$new_rdn = stripslashes( $_POST['new_rdn'] ); +$new_rdn = $_POST['new_rdn']; $new_rdn = utf8_encode($new_rdn); +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); + check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); $ds = pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP sever" ); // build the container string -$old_rdn = ldap_explode_dn( $dn, 0 ); +$old_rdn = pla_explode_dn( $dn ); $container = $old_rdn[ 1 ]; for( $i=2; $i.
+
+
+ This could happen for several reasons, the most probable of which are: +
    +
  • The server does not fully support the LDAP protocol.
  • +
  • Your version of PHP does not correctly perform the query.
  • +
  • Or lastly, phpLDAPadmin doesn't know how to fetch the schema for your server.
  • +
+ Please + report this as a bug"; + ?> - + - pla_error( "Could not retrieve schema from " . htmlspecialchars($servers[$server_id]['name']) . ".
-
- This could happen for several reasons, the most probable of which are: -
    -
  • The server does not fully support the LDAP protocol.
  • -
  • Your version of PHP does not correctly perform the query.
  • -
  • Or lastly, phpLDAPAdmin doesn't know how to fetch the schema for your server.
  • -
- Please report this - as a bug. - " ); +
+
+ objectClasses' ); ?> + | + Attributes' ); ?> + | + Syntaxes' ); ?> + | + Matching Rules' ); ?> +
+
-} else { ?> + -

Schema for server

+ -
- objectClasses' ); ?> - | - Syntaxes' ); ?> - | - Attributes' ); ?> - | - Matching Rules' ); ?> -
-
+if( $view == 'syntaxes' ) { + $highlight_oid = isset( $_GET['highlight_oid'] ) ? $_GET['highlight_oid'] : false; + echo "
" . $lang['the_following_syntaxes'] . "

\n\n"; + echo "\n\n\n"; + echo "\n"; + flush(); + $counter=1; + $schema_syntaxes = get_schema_syntaxes( $server_id ); + if( ! $schema_syntaxes ) pla_error( $schema_error_str ); + foreach( $schema_syntaxes as $oid => $desc ) { + $counter++; + $oid = htmlspecialchars( $oid ); + $desc = htmlspecialchars( $desc['description'] ); + if( $highlight_oid && $highlight_oid == $oid ) + echo ""; + else + echo ""; + echo "\n\n"; + } + echo "
" . $lang['syntax_oid'] . "" . $lang['desc'] . "
$oid$desc
\n"; - +} elseif( $view == 'attributes' ) { + echo "
" . $lang['the_following_attributes'] . "

\n"; + flush(); + $schema_attrs = get_schema_attributes( $server_id ); + $schema_object_classes = get_schema_objectclasses( $server_id ); + if( ! $schema_attrs || ! $schema_object_classes ) + pla_error( $schema_error_str ); + // do a reverse-mapping to add in which objectClasses each attributeType is used + foreach( $schema_object_classes as $object_class ) { + if( isset( $object_class['must_attrs'] ) && is_array( $object_class['must_attrs'] ) ) + $must_attrs = $object_class['must_attrs']; + else + $must_attrs = array(); + if( isset( $object_class['may_attrs'] ) && is_array( $object_class['may_attrs'] ) ) + $may_attrs = $object_class['may_attrs']; + else + $may_attrs = array(); + $attrs = array_unique( array_merge( $must_attrs, $may_attrs ) ); + foreach( $attrs as $attr_name ) + if( isset( $schema_attrs[ strtolower( $attr_name ) ] ) ) + $schema_attrs[ strtolower( $attr_name ) ]->addUsedInObjectClass( $object_class['name'] ); + } - "; + //print_r( $schema_attrs ); + //echo "
"; - //echo '
'; print_r( $schema['attrs'] ); 	
-		?>
+	?>
+	:
+	
 
-		 $val )
-			{
-				if( $key != 'val' && $val != null )  {
-					$counter++;
-					echo "$key$val\n";
-				}
-			}
+	
+ + \n\n"; + $counter = 0; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; - ?> + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; -
getName() ) . "\">"; + echo $attr->getName() . "
Description" . ( $attr->getDescription() == null ? '(no description)' : $attr->getDescription() ). "
OID" . $attr->getOID() . "
Obsolete?" . ( $attr->getIsObsolete() ? 'Yes' : 'No' ) . "
Inherits" . ( $attr->getSupAttribute()==null? '(none)' : $attr->getSupAttribute() ) . "
Equality" . ( $attr->getEquality() == null ? '(not specified)' : $attr->getEquality() ) . "
Ordering" . ( $attr->getOrdering()==null? '(not specified)' : $attr->getOrdering() ) . "
Substring Rule" . ( $attr->getSubstr()==null? '(not specified)' : $attr->getSubstr() ) . "
Syntax"; + if( null != $attr->getType() ) { + echo "getSyntaxOID() . "#" . $attr->getSyntaxOID(); + echo "\">" . $attr->getType() . " (" . $attr->getSyntaxOID() . ")"; + } else { + echo $attr->getSyntaxOID(); } - else - pla_error( "Bad schema entry for attribute: " . htmlspecialchars( $attr ) ); + echo "
Single Valued" . ( $attr->getIsSingleValue() ? 'Yes' : 'No' ) . "
-
- - \n"; + echo "Collective?\n"; + echo "" . ( $attr->getIsCollective() ? 'Yes' : 'No' ) . "\n"; + echo "\n\n"; - } elseif( $view == 'syntaxes' ) { - echo "
The following syntaxes are supported by this LDAP server

\n\n"; - echo "\n\n\n"; - echo "\n"; - $counter=1; - foreach( get_schema_syntaxes( $server_id ) as $oid => $desc ) { - $counter++; - $oid = htmlspecialchars( $oid ); - $desc = htmlspecialchars( $desc['description'] ); - echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo ""; + echo "\n\n"; + + echo "\n"; + echo "\n"; + echo ""; + echo "\n\n"; + + flush(); + } + echo "
Syntax OIDDescription
$oid$desc
User Modification" . ( $attr->getIsNoUserModification() ? 'No' : 'Yes' ) . "
Usage" . ( $attr->getUsage() ? $attr->getUsage() : '(not specified)' ) . "
Maximum Length" . ( $attr->getMaxLength() === null ? + '(not applicable)' : + number_format( $attr->getMaxLength() ) . ' characters' ) . "
Aliases"; + if( count( $attr->getAliases() ) == 0 ) + echo "(none)"; + else + foreach( $attr->getAliases() as $alias_attr_name ) + echo "$alias_attr_name "; + echo "
Used by objectClasses"; + if( count( $attr->getUsedInObjectClasses() ) == 0 ) + echo "(none)"; + else + foreach( $attr->getUsedInObjectClasses() as $used_in_oclass) + echo "$used_in_oclass "; + echo "
\n"; + +} elseif( $view == 'matching_rules' ) { + echo "
" . $lang['the_following_matching'] . "

\n\n"; + echo "\n\n\n"; + echo "\n"; + flush(); + $counter=1; + $schema_matching_rules = get_schema_matching_rules( $server_id ); + if( ! $schema_matching_rules ) pla_error( $schema_error_str ); + foreach( $schema_matching_rules as $oid => $attr ) { + $counter++; + $oid = htmlspecialchars( $oid ); + $desc = htmlspecialchars( $attr ); + echo "\n"; + } + echo "
" . $lang['matching_rule_oid'] . "" . $lang['desc'] . "
$oid$attr
\n"; + +} else { + echo "
" . $lang['the_following_objectclasses'] . "

\n"; + flush(); + $schema_oclasses = get_schema_objectclasses( $server_id ); + if( ! $schema_oclasses ) pla_error( $schema_error_str ); + ?> + : + +
+ $attrs ) { ?> + +

+

:

+ +

:

+ +

Type:

+ +

+ + +

: $object_class ) { + echo '' . htmlspecialchars( $object_class ) . ''; + if( $i < count( $attrs['sup'] ) - 1 ) + echo ', '; } - echo "\n"; + ?>

- } elseif( $view == 'attributes' ) { - echo "
The following attributes are supported by this LDAP server

\n\n"; - echo "\n"; - foreach( get_schema_attributes( $server_id ) as $attr ) { - echo "\n"; - $counter = 0; - foreach( $attr as $key => $val ) - { - if( $key != 'val' && $val != null ) { - $counter++; - echo ""; - echo "\n"; - } - } - } - echo "
" . $attr['name'] . "
$key$val
\n"; - } elseif( $view == 'matching_rules' ) { - echo "
The following matching rules are supported by this LDAP server

\n\n"; - echo "\n\n\n"; - echo "\n"; - $counter=1; - foreach( get_schema_matching_rules( $server_id ) as $oid => $attr ) { - $counter++; - $oid = htmlspecialchars( $oid ); - $desc = htmlspecialchars( $attr ); - echo "\n"; - } - echo "
Matching Rule OIDDescription
$oid$attr
\n"; - - - - } else { ?> - - Jump to an objectClass: - -
- - $attrs ) { ?> - - [top] -

objectClass

-

OID

- -

Description

- -

Inherits

-
- - - - - - +
Required AttributesOptional Attributes
+ + + + + + - + +
- 0 ) { + 0 ) { echo ' + + 0 ) { + echo ' - - 0 ) { - echo ' +
- ?> - - - - - - - - - + + diff --git a/schema_functions.php b/schema_functions.php new file mode 100644 index 0000000..76fdada --- /dev/null +++ b/schema_functions.php @@ -0,0 +1,910 @@ +oid = null; + $this->name = null; + $this->description = null; + $this->sup_classes = array(); + $this->type = null; + $this->must_attrs = array(); + $this->may_attrs = array(); + $this->is_obsolete = false; + } + + /* + * Parses a raw LDAP objectClass string into this object's $this vars + */ + function ObjectClass( $raw_ldap_schema_string ) + { + $this->initVars(); + $class = $raw_ldap_schema_string; + $strings = preg_split ("/[\s,]+/", $class, -1,PREG_SPLIT_DELIM_CAPTURE); + for($i=0; $iname)==0) + $this->name = $strings[$i]; + else + $this->name .= " " . $strings[$i]; + }while(!preg_match("/\'$/s", $strings[$i])); + } else { + $i++; + do { + $i++; + if(strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= " " . $strings[$i]; + } while(!preg_match("/\'$/s", $strings[$i])); + do { + $i++; + }while($strings[$i]!=")"); + } + break; + case 'DESC': + do { + $i++; + if(strlen($this->description)==0) + $this->description=$this->description . $strings[$i]; + else + $this->description=$this->description . " " . $strings[$i]; + }while(!preg_match("/\'$/s", $strings[$i])); + break; + case 'OBSOLETE': + $this->is_obsolete = TRUE; + break; + case 'SUP': + if($strings[$i+1]!="(") { + $i++; + array_push ($this->sup_classes, $strings[$i]); + }else{ + $i++; + do { + $i++; + if($strings[$i]!="$") + array_push( $this->sup_classes, $strings[$i] ); + }while($strings[$i+1]!=")"); + } + break; + case 'ABSTRACT': + $this->type='abstract'; + break; + case 'STRUCTURAL': + $this->type='structural'; + break; + case 'AUXILIARY': + $this->type='auxiliary'; + break; + case 'MUST': + if($strings[$i+1]!="(") { + $i++; + array_push ($this->must_attrs, $strings[$i]); + }else{ + $i++; + do { + $i++; + if($strings[$i]!="$") + array_push ($this->must_attrs, $strings[$i]); + }while($strings[$i+1]!=")"); + } + sort($this->must_attrs); + break; + case 'MAY': + if($strings[$i+1]!="(") { + $i++; + array_push ($this->may_attrs, $strings[$i]); + }else{ + $i++; + do + { + $i++; + if($strings[$i]!="$") + array_push ($this->may_attrs, $strings[$i]); + }while($strings[$i+1]!=")"); + } + sort($this->may_attrs); + break; + default: + if(preg_match ("/[\d\.]+/i",$strings[$i])) + $this->oid = $strings[$i]; + } + } + + $this->name = preg_replace("/^\'/", "", $this->name); + $this->name = preg_replace("/\'$/", "", $this->name); + $this->description = preg_replace("/^\'/", "", $this->description); + $this->description = preg_replace("/\'$/", "", $this->description); + } + + /* Getters */ + function getMustAttrs() + { + return $this->must_attrs; + } + + function getMayAttrs() + { + return $this->may_attrs; + } + + function getName() + { + return $this->name; + } + + function getDescription() + { + return $this->description; + } + + function getSupClasses() + { + return $this->sup_classes; + } + + function getType() + { + return $this->type; + } + + function getIsObsolete() + { + return $this->is_obsolete; + } + + /* + * Adds the specified array of attributes to this objectClass' list of + * MUST attributes. The resulting array of must attributes will contain + * unique members. + */ + function addMustAttrs( $new_must_attrs ) + { + if( ! is_array( $new_must_attrs ) ) + return; + if( 0 == count( $new_must_attrs ) ) + return; + $this->must_attrs = array_values( array_unique( array_merge( $this->must_attrs, $new_must_attrs ) ) ); + } + + /* + * Behaves identically to addMustAttrs, but it operates on the MAY + * attributes of this objectClass. + */ + function addMayAttrs( $new_may_attrs ) + { + if( ! is_array( $new_may_attrs ) ) + return; + if( 0 == count( $new_may_attrs ) ) + return; + $this->may_attrs = array_values( array_unique( array_merge( $this->may_attrs, $new_may_attrs ) ) ); + } + + /* + * Returns an associative array of this objectClass. + * This exists for backwards compatibility for portions of PLA + * that have not yet been made aware of the new object oriented + * ObjectClass code. + */ + function toAssoc() + { + return array ( + 'oid' => $this->oid, + 'name' => $this->name, + 'description' => $this->description, + 'sup' => $this->sup_classes, + 'type' => $this->type, + 'must_attrs' => $this->must_attrs, + 'may_attrs' => $this->may_attrs, + 'is_obsolete' => $this->is_obsolete ); + } +} + +/* + * Represents an LDAP AttributeType + */ +class AttributeType +{ + /* The OID of this attributeType: ie, 1.2.3.4*/ + var $oid; + /* The name of this attributeType */ + var $name; + /* string: the description */ + var $description; + /* boolean: is it obsoloete */ + var $is_obsolete; + /* The attribute from which this attribute inherits (if any) */ + var $sup_attribute; + /* The equality rule used */ + var $equality; + /* The ordering of the attributeType */ + var $ordering; + /* Boolean: supports substring matching? */ + var $sub_str; + /* The full syntax string, ie 1.2.3.4{16} */ + var $syntax; + /* boolean: is single valued only? */ + var $is_single_value; + /* boolean: is collective? */ + var $is_collective; + /* boolean: can use modify? */ + var $is_no_user_modification; + /* The usage string set by the LDAP schema */ + var $usage; + /* An array of alias attribute names, strings */ + var $aliases; + /* The max number of characters this attribute can be */ + var $max_length; + /* A string description of the syntax type (taken from the LDAPSyntaxes) */ + var $type; + /* An array of objectClasses which use this attributeType (must be set by caller) */ + var $used_in_object_classes; + + /* + * Initialize the class' member variables + */ + function initVars() + { + $this->oid = null; + $this->name = null; + $this->description = null; + $this->is_obsolete = false; + $this->sup_attribute = null; + $this->equality = null; + $this->ordering = null; + $this->sub_str = null; + $this->syntax_oid = null; + $this->syntax = null; + $this->max_length = null; + $this->is_single_value= false; + $this->is_collective = false; + $this->is_no_user_modification = false; + $this->usage = null; + $this->aliases = array(); + $this->type = null; + $this->used_in_object_classes = array(); + } + + /* + * Parses a raw LDAP objectClass string into this object's $this vars + */ + function AttributeType( $raw_ldap_attr_string ) + { + //echo "$raw_ldap_attr_string
"; + $this->initVars(); + $attr = $raw_ldap_attr_string; + $strings = preg_split ("/[\s,]+/", $attr, -1,PREG_SPLIT_DELIM_CAPTURE); + for($i=0; $iname)==0) + $this->name = $strings[$i]; + else + $this->name .= " " . $strings[$i]; + }while(!preg_match("/\'$/s", $strings[$i])); + // this attribute has no aliases + $this->aliases = array(); + } else { + $i++; + do { + $i++; + if(strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= " " . $strings[$i]; + } while(!preg_match("/\'$/s", $strings[$i])); + // add alias names for this attribute + while($strings[++$i]!=")") { + $alias = $strings[$i]; + $alias = preg_replace("/^\'/", "", $alias ); + $alias = preg_replace("/\'$/", "", $alias ); + $this->aliases[] = $alias; + } + } + break; + case 'DESC': + do { + $i++; + if(strlen($this->description)==0) + $this->description=$this->description . $strings[$i]; + else + $this->description=$this->description . " " . $strings[$i]; + }while(!preg_match("/\'$/s", $strings[$i])); + break; + case 'OBSOLETE': + $this->is_obsolete = TRUE; + break; + case 'SUP': + $i++; + $this->sup_attribute = $strings[$i]; + break; + case 'EQUALITY': + $i++; + $this->equality = $strings[$i]; + break; + case 'ORDERING': + $i++; + $this->ordering = $strings[$i]; + break; + case 'SUBSTR': + $i++; + $this->sub_str = $strings[$i]; + break; + case 'SYNTAX': + $i++; + $this->syntax = $strings[$i]; + $this->syntax_oid = preg_replace( "/{\d+}$/", "", $this->syntax ); + // does this SYNTAX string specify a max length (ie, 1.2.3.4{16}) + if( preg_match( "/{(\d+)}$/", $this->syntax, $this->max_length ) ) + $this->max_length = $this->max_length[1]; + else + $this->max_length = null; + if($strings[$i+1]=="{") { + do { + $i++; + $this->name .= " " . $strings[$i]; + } while($strings[$i]!="}"); + } + break; + case 'SINGLE-VALUE': + $this->is_single_value = TRUE; + break; + case 'COLLECTIVE': + $this->is_collective = TRUE; + break; + case 'NO-USER-MODIFICATION': + $this->is_no_user_modification = TRUE; + break; + case 'USAGE': + $i++; + $this->usage = $strings[$i]; + break; + default: + if(preg_match ("/[\d\.]+/i",$strings[$i])) + $this->oid = $strings[$i]; + } + } + + $this->name = preg_replace("/^\'/", "", $this->name); + $this->name = preg_replace("/\'$/", "", $this->name); + $this->description = preg_replace("/^\'/", "", $this->description); + $this->description = preg_replace("/\'$/", "", $this->description); + } + + /* Getters */ + function getOID() + { + return $this->oid; + } + + function getName() + { + return $this->name; + } + + function getDescription() + { + return $this->description; + } + + function getIsObsolete() + { + return $this->is_obsolete; + } + + function getUsage() + { + return $this->usage; + } + + function getSupAttribute() + { + return $this->sup_attribute; + } + + function getEquality() + { + return $this->equality; + } + + function getOrdering() + { + return $this->ordering; + } + + function getSubstr() + { + return $this->sub_str; + } + + function getAliases() + { + return $this->aliases; + } + + /* + * Returns the entire raw syntax string for this attr, for example: 1.2.3.4{16} + */ + function getSyntaxString() + { + return $this->syntax; + } + + /* + * Differs from getSyntaxString() in that it only returns the actual OID with any length + * specification removed. Ie, if the syntax string is 1.2.3.4{16}, this retruns + * 1.2.3.4. + */ + function getSyntaxOID() + { + return $this->syntax_oid; + } + + /* + * Returns the maximum length specified by this attribute (ie, "16" in 1.2.3.4{16}) + */ + function getMaxLength() + { + return $this->max_length; + } + + function getIsSingleValue() + { + return $this->is_single_value; + } + + function getIsCollective() + { + return $this->is_collective; + } + + function getIsNoUserModification() + { + return $this->is_no_user_modification; + } + + function getType() + { + return $this->type; + } + + /* + * Removes an attribute name from the alias array. + */ + function removeAlias( $remove_alias_name ) + { + foreach( $this->aliases as $i => $alias_name ) { + if( 0 == strcasecmp( $alias_name, $remove_alias_name ) ) { + unset( $this->aliases[ $i ] ); + $this->aliases = array_values( $this->aliases ); + return true; + } + } + return false; + } + + /* + * Adds an attribute name to the alias array. + */ + function addAlias( $new_alias_name ) + { + $this->aliases[] = $new_alias_name; + } + + function setName( $new_name ) + { + $this->name = $new_name; + } + + function setDescription( $new_desc ) + { + $this->description = $new_desc; + } + + function setSupAttribute( $new_sup_attr ) + { + $this->sup_attribute = $new_sup_attr; + } + + function setAliases( $new_aliases ) + { + $this->aliases = $new_aliases; + } + + function setType( $new_type ) + { + $this->type = $new_type; + } + + function addUsedInObjectClass( $object_class_name ) + { + if( ! in_array( $object_class_name, $this->used_in_object_classes ) ) { + $this->used_in_object_classes[] = $object_class_name; + } + } + + function getUsedInObjectClasses() + { + return $this->used_in_object_classes; + } +} + +/* + * Returns an associative array of objectClasses for the specified + * $server_id. Each array entry's key is the name of the objectClass + * in lower-case. + * The sub-entries consist of sub-arrays called 'must_attrs' and + * 'may_attrs', and sub-entries called 'oid', 'name' and 'description'. + * + * The bulk of this function came from the good code in the + * GPL'ed LDAP Explorer project. Thank you. + */ +function get_schema_objectclasses( $server_id ) +{ + // cache the schema to prevent multiple schema fetches from LDAP server + static $cache = array(); + if( isset( $cache[$server_id] ) ) { + //echo "Using oclass cache.
"; + return $cache[$server_id]; + } + + $ds = pla_ldap_connect( $server_id ); + if( ! $ds ) + return false; + + // try with the standard DN + $result = @ldap_read($ds, 'cn=subschema', '(objectClass=*)', + array( 'objectclasses' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + // try again, with a different schema DN + $result = @ldap_read($ds, 'cn=schema', '(objectClass=*)', + array( 'objectclasses' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + // give up + return false; + + $raw_oclasses = @ldap_get_entries($ds,$result ); + + // build the array of objectClasses + $object_classes = array(); + for( $i=0; $i < $raw_oclasses[0]['objectclasses']['count']; $i++ ) { + $class_string = $raw_oclasses[0]["objectclasses"][$i]; + if( $class_string == null || 0 == strlen( $class_string ) ) + continue; + $object_class = new ObjectClass( $class_string ); + $name = $object_class->getName(); + $key = strtolower( $name ); + $object_classes[ $key ] = $object_class->toAssoc(); + } + + // go back and add any inherited MUST/MAY attrs to each objectClass + foreach( $object_classes as $name => $object_class ) { + $sup_classes = $object_class['sup']; + $must = $object_class['must_attrs']; + $may = $object_class['may_attrs']; + + foreach( $sup_classes as $sup_class ) + add_sup_class_attrs( $name, $sup_class, $object_classes, $must, $may ); + $object_classes[ $name ][ 'must_attrs' ] = $must; + $object_classes[ $name ][ 'may_attrs' ] = $may; + } + + ksort( $object_classes ); + + // cache the schema to prevent multiple schema fetches from LDAP server + $cache[ $server_id ] = $object_classes; + return( $object_classes ); +} + +/* + * Helper function for get_schema_objectclasses. This is a recursive function that + * will add MUST and MAY attributes based on an objectclas' inherited objectclasses. + */ +function add_sup_class_attrs( $oclass, $sup_class, &$oclasses, &$must_attrs, &$may_attrs ) +{ + //echo "add_sup_class_attrs( $oclass, $sup_class )
"; + // base cases + if( 0 == strcasecmp( $sup_class, 'top' ) ) return; + if( ! isset( $oclasses[ strtolower( $sup_class ) ] ) ) return; + + // recursive case + $new_must = $oclasses[ strtolower( $sup_class ) ]['must_attrs']; + $new_may = $oclasses[ strtolower( $sup_class ) ]['may_attrs']; + $must_attrs = array_unique( array_merge( $new_must, $must_attrs ) ); + $may_attrs = array_unique( array_merge( $new_may, $may_attrs ) ); + + $sup_classes = $oclasses[ strtolower( $sup_class ) ]['sup']; + if( is_array( $sup_classes ) && count( $sup_classes ) > 0 ) + foreach( $sup_classes as $sup_sup_class ) + add_sup_class_attrs( $sup_class, $sup_sup_class, $oclasses, $must_attrs, $may_attrs ); +} + +/* + * Retrieves the schema for a single attribute. + */ +function get_schema_attribute( $server_id, $attr_name ) +{ + $attr_name = preg_replace( "/;.*$/U", "", $attr_name ); + $schema_attrs = get_schema_attributes( $server_id ); + $attr_name = strtolower( $attr_name ); + $schema_attr = isset( $schema_attrs[ $attr_name ] ) ? + $schema_attrs[ $attr_name ] : + null; + return $schema_attr; +} + +/* + * Returns an associative array of attributes for the specified + * $server_id. Each array entry's key is the name of the attribute, + * in lower-case. + * The sub-entries are 'oid', 'syntax', 'equality', 'substr', 'name', + * and 'single_value'. + * + * The bulk of this function came from the good code in the + * GPL'ed LDAP Explorer project. Thank you. It was extended + * considerably for application here. + */ +function get_schema_attributes( $server_id, $lower_case_keys = false ) +{ + // Cache gets filled in later (bottom). each subsequent call uses + // the cache which has the attributes already fetched and parsed + static $cache = null; + if( isset( $cache[ $server_id ] ) ) { + //echo "Using attr cache
"; + return $cache[ $server_id ]; + } + + $ds = pla_ldap_connect( $server_id ); + if( ! $ds ) + return false; + + // get all the attributeTypes + $result = @ldap_read($ds, 'cn=subschema', '(objectClass=*)', + array( 'attributeTypes' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + $result = @ldap_read($ds, 'cn=schema', '(objectClass=*)', + array( 'attributeTypes' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + + if( $result ) + $raw_attrs = ldap_get_entries( $ds, $result ); + else + $raw_attrs = array(); + + $syntaxes = get_schema_syntaxes( $server_id ); + + // build the array of attribueTypes + $attrs = array(); + for( $i=0; $i < $raw_attrs[0]['attributetypes']['count']; $i++ ) { + $attr_string = $raw_attrs[0]['attributetypes'][$i]; + if( $attr_string == null || 0 == strlen( $attr_string ) ) + continue; + $attr = new AttributeType( $attr_string ); + if( isset( $syntaxes[ $attr->getSyntaxOID() ] ) ) + $attr->setType( $syntaxes[ $attr->getSyntaxOID() ]['description'] ); + $name = $attr->getName(); + $key = strtolower( $name ); + $attrs[ $key ] = $attr; + } + + add_aliases_to_attrs( $attrs ); + add_sup_to_attrs( $attrs ); + + ksort( $attrs ); + + // cache the schema to prevent multiple schema fetches from LDAP server + $cache[ $server_id ] = $attrs; + return( $attrs ); +} + +/* + * For each attribute that has multiple names, this function adds unique entries to + * the attrs array for those names. Ie, attributeType has name 'gn' and 'givenName'. + * This function will create a unique entry for 'gn' and 'givenName'. + */ +function add_aliases_to_attrs( &$attrs ) +{ + // go back and add data from aliased attributeTypes + foreach( $attrs as $name => $attr ) { + $aliases = $attr->getAliases(); + if( is_array( $aliases ) && count( $aliases ) > 0 ) { + // foreach of the attribute's aliases, create a new entry in the attrs array + // with its name set to the alias name, and all other data copied + foreach( $aliases as $i => $alias_attr_name ) { + $new_attr = $attr; + $new_attr->setName( $alias_attr_name ); + $new_attr->addAlias( $attr->getName() ); + $new_attr->removeAlias( $alias_attr_name ); + $new_attr_key = strtolower( $alias_attr_name ); + $attrs[ $new_attr_key ] = $new_attr; + } + } + } +} + +/* + * Adds inherited values to each attributeType specified by the SUP directive. + * Supports infinite levels of inheritance. + */ +function add_sup_to_attrs( &$attrs ) +{ + // go back and add any inherited descriptions from parent attributes (ie, cn inherits name) + foreach( $attrs as $key => $attr ) { + $sup_attr = $attr->getSupAttribute(); + while( $sup_attr != null ) { + if( ! isset( $attrs[ strtolower( $sup_attr ) ] ) ){ + pla_error( "Warning: attributeType '" . $attr->getName() . "' inherits from + '" . $sup_attr . "', but attributeType '" . $sup_attr . "' does not + exist." ); + return; + } + + $sup_attr = $attrs[ strtolower( $sup_attr ) ]; + // if the inhertied attriute does not inherit any furth attributes, + // copy its values and move on to the next attributeType + if( null == $sup_attr->getSupAttribute() ) { + // only three values are allowed to be set when an attributeType SUPs another + // attributeType: NAME, DESC, and SUP + $tmp_name = $attr->getName(); + $tmp_desc = $attr->getDescription(); + $tmp_sup = $attr->getSupAttribute(); + $tmp_aliases = $attr->getAliases(); + + $attr = $sup_attr; + + $attr->setName( $tmp_name ); + $attr->setDescription( $tmp_desc ); + $attr->setSupAttribute( $tmp_sup); + $attr->setAliases( $tmp_aliases ); + // replace this attribute in the attrs array now that we have populated + // new values therein + $attrs[$key] = $attr; + $sup_attr = null; + } else { + // set the sup_attr to the name of the attributeType from which + // this attributeType inherits and move up the inheritance chain. + $sup_attr = $sup_attr->getSupAttribute(); + } + } + } +} + +/* + * Returns an associate array of the server's schema matching rules + */ +function get_schema_matching_rules( $server_id ) +{ + static $cache; + + // cache the schema to prevent multiple schema fetches from LDAP server + if( isset( $cache[$server_id] ) ) { + //echo "Using matching rules cache.
"; + return $cache[$server_id]; + } + + $ds = pla_ldap_connect( $server_id ); + + if( ! $ds ) + return false; + + // get all the attributeTypes + $result = @ldap_read($ds, 'cn=subschema', '(objectClass=*)', + array( 'matchingRules', 'matchingRuleUse' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + $result = @ldap_read($ds, 'cn=schema', '(objectClass=*)', + array( 'matchingRules', 'matchingRuleUse' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + + if( $result ) + $raw = ldap_get_entries( $ds, $result ); + else + return( array() ); + + // build the array of attributes + $rules = array(); + for( $i=0; $i < $raw[0]['matchingrules']['count']; $i++ ) + { + $rule = $raw[0]['matchingrules'][$i]; + preg_match( "/[\s]+([\d\.]+)[\s]+/", $rule, $oid); + preg_match( "/[\s]+NAME[\s]+'([\)\(:?\.a-zA-Z0-9\-_ ]+)'/", $rule, $name ); + + $key = strtolower( trim( $oid[1] ) ); + if( ! $key ) continue; + + $rules[$key] = $name[1]; + //$rules[$key]['name'] = $name[1]; + } + + ksort( $rules ); + + // cache the schema to prevent multiple schema fetches from LDAP server + $cache[$server_id] = $rules; + return $rules; +} + +/* + * Returns an associate array of the syntax OIDs that this LDAP server uses mapped to + * their descriptions. + */ +function get_schema_syntaxes( $server_id ) +{ + static $cache; + + // cache the schema to prevent multiple schema fetches from LDAP server + if( isset( $cache[$server_id] ) ) { + //echo "Using syntax cache.
"; + return $cache[$server_id]; + } + + $ds = pla_ldap_connect( $server_id ); + + if( ! $ds ) + return false; + + // get all the attributeTypes + $result = @ldap_read($ds, 'cn=subschema', '(objectClass=*)', + array( 'ldapSyntaxes' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + $result = @ldap_read($ds, 'cn=schema', '(objectClass=*)', + array( 'ldapSyntaxes' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + + if( $result ) + $raw = ldap_get_entries( $ds, $result ); + else + return( array() ); + + // build the array of attributes + $syntaxes = array(); + for( $i=0; $i < $raw[0]['ldapsyntaxes']['count']; $i++ ) + { + $syntax = $raw[0]['ldapsyntaxes'][$i]; + preg_match( "/[\s]+([\d\.]+)[\s]+/", $syntax, $oid); + preg_match( "/[\s]+DESC[\s]+'([\)\(:?\.a-zA-Z0-9\-_ ]+)'/", $syntax, $description ); + + $key = strtolower( trim( $oid[1] ) ); + if( ! $key ) continue; + + $syntaxes[$key] = array(); + $syntaxes[$key]['description'] = $description[1]; + } + + ksort( $syntaxes ); + + // cache the schema to prevent multiple schema fetches from LDAP server + $cache[$server_id] = $syntaxes; + + return $syntaxes; +} + +?> diff --git a/search.php b/search.php index e264bbc..bb48108 100644 --- a/search.php +++ b/search.php @@ -13,8 +13,7 @@ * - base_dn, scope, filter */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; $server_id = $_GET['server_id']; @@ -27,25 +26,33 @@ else { check_server_id( $server_id ) or pla_error( "Bad server_id: " . var_dump( htmlspecialchars( $server_id ) ) ); } +$js_on_change_string =''; + if( $_GET['form'] == 'advanced' ) { + $js_on_change_string = 'onChange="document.forms[0].base_dn.value=servers[document.forms[0].server_id.value].getBaseDn()"'; + } // build the server drop-down html and JavaScript array (for base_dns) -$server_menu_html = ''; + +$server_info_list =array(); + foreach( $servers as $id => $server ) { $base_dn = $server['base'] ? $server['base'] : try_to_get_root_dn( $id ); - $js_dn_list .= '"' . $server['base'] . '",'; + $server_info_list[$id]['id'] = $id; + $server_info_list[$id]['name'] = $server['name']; + $server_info_list[$id]['base_dn'] = $base_dn; + if( $server['host'] ) { $server_menu_html .= ''; } } -// trim off the trailing comma -$js_dn_list = substr( $js_dn_list, 0, strlen($js_dn_list)-1 ); + $server_menu_html .= ''; -$filter = stripslashes( $_GET['filter'] ); +$filter = $_GET['filter']; $filter = utf8_encode($filter); -$attr = stripslashes( $_GET['attribute'] ); +$attr = $_GET['attribute']; // grab the base dn for the search if( isset( $_GET['base_dn'] ) ) @@ -55,8 +62,8 @@ elseif( '' != $servers[$server_id]['base'] ) else $base_dn = try_to_get_root_dn( $server_id ); -$criterion = stripslashes( $_GET['criterion'] ); -$form = stripslashes( $_GET['form'] ); +$criterion = $_GET['criterion']; +$form = $_GET['form']; $scope = $_GET['scope'] ? $_GET['scope'] : 'sub'; //echo "
";print_r( $_GET );echo "
"; ?> @@ -88,7 +95,7 @@ if( $_GET['search'] ) if( $form == 'advanced' ) { $search_result_attributes = isset( $_GET['display_attrs'] ) ? - stripslashes( $_GET['display_attrs'] ) : + $_GET['display_attrs'] : $search_result_attributes; process_config(); } @@ -117,12 +124,22 @@ if( $_GET['search'] ) { switch( $criterion ) { case 'starts with': + // to fix bug 789113 + if( $filter == "*" ) + $filter = ""; $filter = "($attr=$filter*)"; break; case 'contains': - $filter = "($attr=*$filter*)"; + // to fix bug 789113 + if( $filter == "*" ) + $filter = "($attr=*)"; + else + $filter = "($attr=*$filter*)"; break; case 'ends with': + // to fix bug 789113 + if( $filter == "*" ) + $filter = ""; $filter = "($attr=*$filter)"; break; case 'equals': @@ -139,12 +156,11 @@ if( $_GET['search'] ) } $time_start = utime(); - $results = pla_ldap_search( $server_id, $filter, $base_dn, - array_merge( $search_result_attributes, array( $search_result_title_attribute ) ), - $scope ); + $results = pla_ldap_search( $server_id, $filter, $base_dn, $search_result_attributes, $scope ); $time_end = utime(); $time_elapsed = round( $time_end - $time_start, 2 ); $count = count( $results ); + ?>
@@ -159,25 +175,27 @@ if( $_GET['search'] ) $attrs ) { ?> - - + + - + $values ) { ?> - + @@ -188,7 +206,7 @@ if( $_GET['search'] )

-
Search happily performed by phpLDAPAdmin in +
Search happily performed by phpLDAPadmin in seconds.
+ + addToServersList(new server(,"","")); + + + -
Advanced Search Form
-(Simple Search Form)
+
+()

- - -
+ + +
- +
diff --git a/search_form_simple.php b/search_form_simple.php index 3a23006..6fab9e7 100644 --- a/search_form_simple.php +++ b/search_form_simple.php @@ -5,8 +5,8 @@
- @@ -74,32 +74,55 @@ if( $step == 2 ) // build a list of required attributes: $dn = $rdn . ',' . $container; - $schema = get_schema( $server_id ); - $attrs = $schema['attrs']; + //$attrs = get_schema_attributes( $server_id ); + $schema_oclasses = get_schema_objectclasses( $server_id ); $required_attrs = array(); $all_attrs = array(); foreach( $oclasses as $oclass ) { - $required_attrs = array_merge( $required_attrs, $schema['oclasses'][strtolower($oclass)]['must_attrs'] ); - $all_attrs = array_merge( $all_attrs, $schema['oclasses'][strtolower($oclass)]['must_attrs'], - $schema['oclasses'][strtolower($oclass)]['may_attrs'] ); + $required_attrs = array_merge( $required_attrs, $schema_oclasses[strtolower($oclass)]['must_attrs'] ); + $all_attrs = array_merge( $all_attrs, $schema_oclasses[strtolower($oclass)]['must_attrs'], + $schema_oclasses[strtolower($oclass)]['may_attrs'] ); } $required_attrs = array_unique( $required_attrs ); $all_attrs = array_unique( $all_attrs ); sort( $required_attrs ); sort( $all_attrs ); + + // remove binary attributes and add them to the binary_attrs array + $binary_attrs = array(); + foreach( $all_attrs as $i => $attr_name ) { + if( is_attr_binary( $server_id, $attr_name ) ) { + unset( $all_attrs[ $i ] ); + $binary_attrs[] = $attr_name; + } + } + $attr_select_html = ""; foreach( $all_attrs as $a ) { // is there a user-friendly translation available for this attribute? if( isset( $friendly_attrs[ strtolower( $a ) ] ) ) { $attr_display = htmlspecialchars( $friendly_attrs[ strtolower( $a ) ] ) . " (" . - htmlspecialchars($a) . ")"; + htmlspecialchars($a) . ")"; } else { $attr_display = htmlspecialchars( $a ); } - echo $attr_display; - $attr_select_html .= "\n"; + $attr_select_html .= "\n"; + } + + $binary_select_html = ""; + if( count( $binary_attrs ) > 0 ) { + foreach( $binary_attrs as $a ) { + if( isset( $friendly_attrs[ strtolower( $a ) ] ) ) { + $attr_display = htmlspecialchars( $friendly_attrs[ strtolower( $a ) ] ) . " (" . + htmlspecialchars( $a ) . ")"; + } else { + $attr_display = htmlspecialchars( $a ); + } + + $binary_attr_select_html .= "\n"; + } } // add the required attribute based on the RDN provided by the user @@ -107,29 +130,19 @@ if( $step == 2 ) // in the list of required attributes. $rdn_attr = trim( substr( $rdn, 0, strpos( $rdn, '=' ) ) ); $rdn_value = trim( substr( $rdn, strpos( $rdn, '=' ) + 1 ) ); - if( ! in_array( $rdn_attr, $required_attrs ) ) + if( in_array( $rdn_attr, $all_attrs ) && ! in_array( $rdn_attr, $required_attrs ) ) $required_attrs[] = $rdn_attr; - ?> -

Step 2 of 2: Specify attributes and values

-
-
Simple Search Form
-(Advanced Search Form)
+

+()

@@ -24,7 +24,11 @@
Container: +
- - + Instructions: + Enter values for the required attributes.
+ Then specify any optional attributes. 0 ) { ?> + Finally, you may
specify optional binary attributes from a file if needed. +
- - -
- Creating entry with DN: - - Instrucions: Enter values for the - required attributes. Then create any optional attributes. You - can specify multi-valued attributes as well.
-
- - + @@ -139,7 +152,11 @@ if( $step == 2 ) - $attr ) { ?> + \n"; + } else + + foreach( $required_attrs as $count => $attr ) { ?> @@ -150,7 +167,7 @@ if( $step == 2 ) // is there a user-friendly translation available for this attribute? if( isset( $friendly_attrs[ strtolower( $attr ) ] ) ) { $attr_display = "" . - htmlspecialchars( $friendly_attrs[ strtolower( $attr ) ] ) . ""; + htmlspecialchars( $friendly_attrs[ strtolower( $attr ) ] ) . ""; } else { $attr_display = htmlspecialchars( $attr ); } @@ -158,7 +175,7 @@ if( $step == 2 ) echo $attr_display; ?> - @@ -166,16 +183,33 @@ if( $step == 2 ) - + + + + + + + + + + + + + + + 0 ) { ?> + + - - - + +
Required Attributes
(none)
" name="required_attrs[]" value="" size="40" />
Optional Attributes
(none)
+
Optional Binary Attributes
-
+ +
diff --git a/templates/creation/new_address_template.php b/templates/creation/new_address_template.php index 681e420..aef0f0f 100755 --- a/templates/creation/new_address_template.php +++ b/templates/creation/new_address_template.php @@ -1,12 +1,12 @@ Name: - - + + @@ -136,18 +138,18 @@ function autoFillCommonName( form ) - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Common name:
First name:
Last name:
Organization:
City:
Postal code:
Street:
Work phone:
Fax:
Mobile:
Email:
Container:
Common name:
First name:
Last name:
Organization:
City:
Postal code:
Street:
Work phone:
Fax:
Mobile:
Email:
Container:

+ + + + diff --git a/templates/creation/new_dns_entry.php b/templates/creation/new_dns_entry.php index ec9689f..dd665fc 100755 --- a/templates/creation/new_dns_entry.php +++ b/templates/creation/new_dns_entry.php @@ -1,9 +1,9 @@ Container DN: - + @@ -52,9 +52,9 @@ if( ! $step ) Container: - + @@ -67,7 +67,7 @@ have_auth_info( $server_id ) or pla_error( "Not enough information to login to s
  • gidNumber
  • acctFlags
  • cn
  • -
  • in container
  • +
  • in container
  • To change these values, edit the template file: templates/creation/new_nt_machine.php
    @@ -81,8 +81,8 @@ have_auth_info( $server_id ) or pla_error( "Not enough information to login to s " /> - + diff --git a/templates/creation/new_ou_template.php b/templates/creation/new_ou_template.php index c7f572c..be501fc 100644 --- a/templates/creation/new_ou_template.php +++ b/templates/creation/new_ou_template.php @@ -1,9 +1,9 @@ Container DN: - + @@ -47,8 +47,8 @@ have_auth_info( $server_id ) or pla_error( "Not enough information to login to s + +

    New Posix Group

    + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Posix Group Name: (example: MyGroup, do not include "cn=")
    GID Number: (example: 2000)
    Container DN: +
    Users: (example: dsmith)
    + +
    + +

    +
    + + + + + + + + + + + + + + + + + + + + + +
    + Really create this new Posix Group entry?
    +
    + + + + + + +
    Name
    Container
    gidNumber
    Member UIDs + $uid ) + echo htmlspecialchars($uid) . "
    "; ?> +
    +
    +
    +
    + + + diff --git a/templates/creation/new_smbuser_template.php b/templates/creation/new_smbuser_template.php new file mode 100644 index 0000000..bc46243 --- /dev/null +++ b/templates/creation/new_smbuser_template.php @@ -0,0 +1,276 @@ + + + + +

    New Samba3-User Account

    + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    UID Number:
    Samba SID:
    First name:
    Last name:
    User name:
    Password:
    Password:
    Encryption: + + crypt +
    Login Shell: + + /bin/csh +
    Container: +
    Unix Group:
    Windows Group:
    Home Directory:

    +
    + + +

    Confirm account creation:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    User name:
    First name:
    Last name:
    Password:[secret]
    Login Shell:
    UID Number:
    GID Number:
    Container:
    Home dir:
    +
    +
    + + diff --git a/templates/creation/new_user_template.php b/templates/creation/new_user_template.php index d2845f1..aa6526f 100644 --- a/templates/creation/new_user_template.php +++ b/templates/creation/new_user_template.php @@ -1,12 +1,12 @@ -

    phpLDAPAdmin -

    +

    phpLDAPadmin -

    - + - +
    Request a new feature - (see open requests) + ()
    Report a bug - (see open bugs) + ()
    -
    + $server_tree ) { $server_name = $servers[$server_id]['name']; echo ''; echo ''; - echo ''; + echo ''; // do we have what it takes to authenticate here, or do we need to // present the user with a login link (for 'form' auth_types)? @@ -90,28 +87,40 @@ foreach( $servers as $server_id => $server_tree ) { rawurlencode( $servers[$server_id]['base'] ); $logout_href = 'logout.php?server_id=' . $server_id; $info_href = 'server_info.php?server_id=' . $server_id; + $import_href = 'ldif_import_form.php?server_id=' . $server_id; - if( $servers[$server_id]['auth_type'] == 'form' && have_auth_info( $server_id ) ) - echo "Logged in as: " . htmlspecialchars(get_logged_in_dn($server_id)) . "
    "; - // Draw the quick-links below the server name: // ( schema | search | refresh | create ) - echo '('; - echo 'schema | '; - echo 'search | '; - echo 'refresh | '; - echo ''; + echo ' | ' . $lang['logout'] . ''; + echo ' )'; + + if( $servers[$server_id]['auth_type'] == 'form' && have_auth_info( $server_id ) ) + echo ""; + if( is_server_read_only( $server_id ) ) + echo ""; - $rdn = utf8_decode( $dn ); + // Fetch and display the base DN for this server + //$rdn = utf8_decode( $dn ); if( null == $servers[ $server_id ]['base'] ) { $base_dn = try_to_get_root_dn( $server_id ); } else { @@ -134,26 +143,32 @@ foreach( $servers as $server_id => $server_tree ) { $edit_href = "edit.php?server_id=$server_id&dn=" . rawurlencode( $base_dn ); $icon = get_icon( $server_id, $base_dn ); - echo "\n"; - echo ""; - echo "\n"; - echo "\n"; + echo ""; + echo "\n"; + echo "\n"; echo "\n"; } else { if( "" === $base_dn || null === $base_dn ) { // The server refuses to give out the base dn - echo ""; + echo ""; // Proceed to the next server. We cannot draw anything else for this server. continue; } else { // For some unknown reason, we couldn't determine the base dn - echo ""; + echo ""; // Proceed to the next server. We cannot draw anything else for this server. continue; } @@ -164,31 +179,38 @@ foreach( $servers as $server_id => $server_tree ) { // Is the root of the tree expanded already? if( isset( $tree[$server_id][$base_dn] ) ) { foreach( $tree[ $server_id ][ $base_dn ] as $child_dn ) - draw_tree_html( $child_dn, $server_id, 1 ); - echo ''; - echo ''; - echo ''; - echo ''; + draw_tree_html( $child_dn, $server_id, 0 ); + if( ! is_server_read_only( $server_id ) ) { + echo ''; + echo ''; + echo ''; + } } } else // have_auth_info() returned false. { // We don't have enough information to login to this server + // Draw the "login..." link $login_href = "login_form.php?server_id=$server_id"; + echo ''; } - } } ?>
    server' . htmlspecialchars( $server_name ) . '
    '; - + echo '
    '; + echo '' . htmlspecialchars( $server_name ) . '
    " . + $lang['logged_in_as'] . htmlspecialchars(get_logged_in_dn($server_id)) . + "
    " . + "(" . $lang['read_only'] . ")
    $base_dn"; + echo ""; + echo "$base_dn
    Could not determine "; - echo "the root of your LDAP tree.
    It appears that the LDAP server has "; - echo "been configured to not give it out. Please specify it in config.php"; - echo "
    "; + echo $lang['could_not_determine_root']; + echo '
    '; + echo $lang['ldap_refuses_to_give_root']; + echo '
    '; + echo $lang['please_specify_in_config']; + echo "
    Could not determine "; - echo "the root of your LDAP tree.
    Please specify it in config.php"; - echo "
    "; + echo $lang['could_not_determine_root']; + echo '
    '; + echo $lang['please_specify_in_config']; + echo "
    Create New
    ' . $lang['create_new'] . '
    +"; print_r( $tree ); +?> + @@ -201,7 +223,7 @@ exit; */ function draw_tree_html( $dn, $server_id, $level=0 ) { - global $servers, $tree, $tree_icons; + global $servers, $tree, $tree_icons, $lang; $id = $server_id; $encoded_dn = rawurlencode( $dn ); @@ -214,41 +236,41 @@ function draw_tree_html( $dn, $server_id, $level=0 ) $tree_icons[ $server_id ][ $dn ] = get_icon( $server_id, $dn ); $img_src = 'images/' . $tree_icons[ $server_id ][ $dn ]; - $rdn = ldap_explode_dn( $dn, 0 ); - $rdn = utf8_decode( $rdn[0] ); + $rdn = pla_explode_dn( $dn ); + $rdn = $rdn[0]; echo ''; for( $i=0; $i<=$level; $i++ ) { - echo ''; + echo '' . "\n"; } - // is this node expanded? + // is this node expanded? (deciding whether to draw "+" or "-") if( isset( $tree[$server_id][$dn] ) ) { ?> plus - (' . count( $tree[$server_id][$dn] ) . ')'; ?> - + (' . count( $tree[$server_id][$dn] ) . ')'; + } else { ?> minus - - + - + + target="right_frame"> @@ -270,8 +292,9 @@ function draw_tree_html( $dn, $server_id, $level=0 ) echo ''; echo ''; - echo 'Create New'; + echo '' . + $lang['create_new'] . ''; } echo ''; diff --git a/update.php b/update.php index 8c58bf7..7f751c9 100644 --- a/update.php +++ b/update.php @@ -7,30 +7,45 @@ * Variables that come in on the query string: * - dn (rawurlencoded) * - server_id - * - update_array (an array in the form expected by PHP's ldap_modify) + * - update_array (an array in the form expected by PHP's ldap_modify, except for deletions) * (will never be empty: update_confirm.php ensures that) + * + * Attribute deletions: + * To specify that an attribute is to be deleted (whether multi- or single-valued), + * enter that attribute in the update array like this: attr => ''. For example, to + * delete the 'sn' attribute from an entry, the update array would look like this: + * Array ( + * sn => '' + * ) + * * On success, redirect to edit.php * On failure, echo an error. */ -require 'config.php'; -require_once 'functions.php'; +require 'common.php'; + +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); $server_id = $_POST['server_id']; -$dn = stripslashes( rawurldecode( $_POST['dn'] ) ); +$dn = rawurldecode( $_POST['dn'] ); $encoded_dn = rawurlencode( $dn ); $update_array = $_POST['update_array']; -//echo "
    "; print_r( $update_array ); echo "
    "; - check_server_id( $server_id ) or pla_error( "Bad server_id: " . htmlspecialchars( $server_id ) ); have_auth_info( $server_id ) or pla_error( "Not enough information to login to server. Please check your configuration." ); -is_array( $update_array ) or pla_error( "update_array is malformed. This might be a phpLDAPAdmin bug. Please report it." ); +is_array( $update_array ) or pla_error( "update_array is malformed. This might be a phpLDAPadmin bug. Please report it." ); +// check for delete attributes (indicated by the attribute entry appearing like this: attr => '' foreach( $update_array as $attr => $val ) if( ! is_array( $val ) ) if( $val == '' ) $update_array[ $attr ] = array(); + else + $update_array[ $attr ] = $val; + else + foreach( $val as $i => $v ) + $update_array[ $attr ][ $i ] = $v; $ds = pla_ldap_connect( $server_id ); $res = @ldap_modify( $ds, $dn, $update_array ); diff --git a/update_confirm.php b/update_confirm.php index 4c32cff..ad5d345 100644 --- a/update_confirm.php +++ b/update_confirm.php @@ -9,8 +9,8 @@ * makes the change. * */ -include 'config.php'; -include 'functions.php'; + +require 'common.php'; include 'header.php'; @@ -21,7 +21,8 @@ $rdn = get_rdn( $dn ); $old_values = $_POST['old_values']; $new_values = $_POST['new_values']; $update_array = array(); - +if( is_server_read_only( $server_id ) ) + pla_error( "You cannot perform updates while server is in read-only mode" ); ?> @@ -36,17 +37,37 @@ foreach( $new_values as $attr => $new_val ) if( $new_val != $old_values[ $attr ] ) { // special case for userPassword attributes - if( 0 == strcasecmp( $attr, 'userPassword' ) ) - { - $enc_type = $_POST['enc_type']; - $new_val = password_hash( $new_val, $enc_type ); - } + if( 0 == strcasecmp( $attr, 'userPassword' ) && $new_val != '' ) + $new_val = password_hash( $new_val, $_POST['enc_type'] ); $update_array[ $attr ] = $new_val; } } -//echo "
    "; print_r( $update_array ); echo "
    "; +// special case check for a new enc_type for userPassword (not otherwise detected) +if( $_POST['enc_type'] != $_POST['old_enc_type'] && $_POST['new_values']['userpassword'] != '' ) { + $new_password = password_hash( $_POST['new_values']['userpassword'], $_POST['enc_type'] ); + $update_array[ 'userpassword' ] = $new_password; +} + +// strip empty vals from update_array and ensure consecutive indices for each attribute +foreach( $update_array as $attr => $val ) { + if( is_array( $val ) ) { + foreach( $val as $i => $v ) + if( null == $v || 0 == strlen( $v ) ) + unset( $update_array[$attr][$i] ); + $update_array[$attr] = array_values( $update_array[$attr] ); + } +} + +// at this point, the update_array should look like this (example): +// Array ( +// cn => Array( +// [0] => 'Dave', +// [1] => 'Bob' ) +// sn => 'Smith', +// telephoneNumber => '555-1234' ) +// This array should be ready to be passed to ldap_modify() ?> 0 ) { ?> @@ -67,21 +88,36 @@ foreach( $new_values as $attr => $new_val ) "; + echo htmlspecialchars( utf8_encode( $v ) ) . "
    "; else - echo htmlspecialchars( $old_values[ $attr ] ) . "
    "; + echo htmlspecialchars( utf8_encode( $old_values[ $attr ] ) ) . "
    "; echo ""; - if( is_array( $new_val ) ) - foreach( $new_val as $i => $v ) + + // is this a multi-valued attribute? + if( is_array( $new_val ) ) { + foreach( $new_val as $i => $v ) { if( $v == '' ) { // remove it from the update array if it's empty unset( $update_array[ $attr ][ $i ] ); $update_array[ $attr ] = array_values( $update_array[ $attr ] ); - } else - echo htmlspecialchars( $v ) . "
    "; + } else { + echo htmlspecialchars( utf8_encode( $v ) ) . "
    "; + } + } + + // was this a multi-valued attribute deletion? If so, + // fix the $update_array to reflect that per update_confirm.php's + // expectations + if( $update_array[ $attr ] == array( 0 => '' ) || $update_array[ $attr ] == array() ) { + $update_array[ $attr ] = ''; + echo '[attribute deleted]'; + } + } else if( $new_val != '' ) echo htmlspecialchars( $new_val ) . "
    "; + else + echo '[attribute deleted]'; echo "
    \n\n"; } diff --git a/view_jpeg_photo.php b/view_jpeg_photo.php index f524716..12c6c41 100644 --- a/view_jpeg_photo.php +++ b/view_jpeg_photo.php @@ -1,7 +1,6 @@ + +
    +
    +
    +
    +
    +
    +Use the menu to the left to navigate. +