From ed7caca53b4943672eb61799c82efee2b761078e Mon Sep 17 00:00:00 2001 From: Deon George Date: Tue, 30 Jun 2009 18:07:14 +1000 Subject: [PATCH] RELEASE 0.9.1 --- INSTALL | 63 +- VERSION | 2 +- add_oclass.php | 18 +- add_oclass_form.php | 36 +- add_value.php | 32 +- add_value_form.php | 87 +- collapse.php | 22 +- common.php | 53 + config.php.example | 139 +-- copy.php | 15 +- copy_form.php | 13 +- create.php | 44 +- create_form.php | 10 +- creation_template.php | 10 +- delete.php | 8 +- delete_attr.php | 42 + delete_form.php | 12 +- download_binary_attr.php | 28 + edit.php | 577 ++++++----- entry_chooser.php | 42 +- expand.php | 23 +- functions.php | 732 ++++++-------- header.php | 5 +- images/logo.jpg | Bin 0 -> 16958 bytes images/nt.png | Bin 0 -> 957 bytes images/warning.png | Bin 0 -> 1891 bytes index.php | 52 +- lang/english.php | 142 +++ lang/french.php | 70 ++ lang/german.php | 103 ++ ldap_error_codes.txt | 9 +- ldif_export.php | 77 +- ldif_functions.php | 418 ++++++++ ldif_import.php | 119 +++ ldif_import_form.php | 48 + login.php | 28 +- login_form.php | 13 +- logout.php | 3 +- new_attr.php | 43 +- new_jpeg_photo_form.php | 46 - rdelete.php | 14 +- refresh.php | 3 +- rename.php | 15 +- schema.php | 450 +++++---- schema_functions.php | 910 ++++++++++++++++++ search.php | 68 +- search_form_advanced.php | 15 +- search_form_simple.php | 10 +- search_util.js | 76 ++ server_info.php | 3 +- style.css | 93 +- templates/creation/custom.php | 110 ++- templates/creation/new_address_template.php | 98 +- templates/creation/new_dns_entry.php | 12 +- templates/creation/new_nt_machine.php | 14 +- templates/creation/new_ou_template.php | 10 +- .../creation/new_posix_group_template.php | 117 +++ templates/creation/new_smbuser_template.php | 276 ++++++ templates/creation/new_user_template.php | 4 +- tree.php | 155 +-- update.php | 29 +- update_confirm.php | 66 +- view_jpeg_photo.php | 3 +- welcome.php | 10 + 64 files changed, 4356 insertions(+), 1389 deletions(-) create mode 100644 common.php create mode 100644 delete_attr.php create mode 100644 download_binary_attr.php create mode 100644 images/logo.jpg create mode 100644 images/nt.png create mode 100644 images/warning.png create mode 100644 lang/english.php create mode 100644 lang/french.php create mode 100644 lang/german.php create mode 100644 ldif_functions.php create mode 100644 ldif_import.php create mode 100644 ldif_import_form.php delete mode 100644 new_jpeg_photo_form.php create mode 100644 schema_functions.php create mode 100644 search_util.js create mode 100644 templates/creation/new_posix_group_template.php create mode 100644 templates/creation/new_smbuser_template.php create mode 100644 welcome.php 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 0000000000000000000000000000000000000000..6eadc24a9317bb7c58705e73d61d33665e270d89 GIT binary patch literal 16958 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 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



- - \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. +
    -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' ) . "
    -