From 763843c16a86885947dae98e7c0a68b6b3515d01 Mon Sep 17 00:00:00 2001 From: Deon George Date: Tue, 30 Jun 2009 18:05:37 +1000 Subject: [PATCH] RELEASE 0.9.0 --- INSTALL | 40 + LICENSE | 341 ++++++ VERSION | 1 + add_oclass.php | 55 + add_oclass_form.php | 108 ++ add_value.php | 52 + add_value_form.php | 133 +++ collapse.php | 43 + config.php.example | 163 +++ copy.php | 167 +++ copy_form.php | 86 ++ create.php | 114 ++ create_form.php | 81 ++ creation_template.php | 45 + delete.php | 65 + delete_form.php | 157 +++ edit.php | 472 ++++++++ entry_chooser.js | 6 + entry_chooser.php | 73 ++ expand.php | 60 + functions.php | 1174 +++++++++++++++++++ header.php | 11 + images/bug.png | Bin 0 -> 278 bytes images/children.png | Bin 0 -> 438 bytes images/country.png | Bin 0 -> 707 bytes images/cut.png | Bin 0 -> 340 bytes images/dc.png | Bin 0 -> 1140 bytes images/find.png | Bin 0 -> 1428 bytes images/folder.png | Bin 0 -> 1217 bytes images/light.png | Bin 0 -> 733 bytes images/locality.png | Bin 0 -> 751 bytes images/lock.png | Bin 0 -> 858 bytes images/mail.png | Bin 0 -> 899 bytes images/minus.png | Bin 0 -> 98 bytes images/move.png | Bin 0 -> 483 bytes images/o.png | Bin 0 -> 1305 bytes images/object.png | Bin 0 -> 1297 bytes images/ou.png | Bin 0 -> 1330 bytes images/phone.png | Bin 0 -> 878 bytes images/photo.png | Bin 0 -> 572 bytes images/plus.png | Bin 0 -> 102 bytes images/refresh.png | Bin 0 -> 785 bytes images/save.png | Bin 0 -> 658 bytes images/server.png | Bin 0 -> 1424 bytes images/star.png | Bin 0 -> 700 bytes images/terminal.png | Bin 0 -> 851 bytes images/trash.png | Bin 0 -> 678 bytes images/uid.png | Bin 0 -> 654 bytes images/up.png | Bin 0 -> 382 bytes images/user.png | Bin 0 -> 773 bytes index.php | 161 +++ ldap_error_codes.txt | 85 ++ ldif_export.php | 93 ++ login.php | 107 ++ login_form.php | 79 ++ logout.php | 54 + new_attr.php | 46 + new_jpeg_photo_form.php | 46 + rdelete.php | 113 ++ refresh.php | 54 + rename.php | 91 ++ schema.php | 226 ++++ search.php | 212 ++++ search_form_advanced.php | 50 + search_form_simple.php | 42 + server_info.php | 49 + style.css | 360 ++++++ templates/creation/custom.php | 186 +++ templates/creation/new_address_template.php | 210 ++++ templates/creation/new_dns_entry.php | 91 ++ templates/creation/new_nt_machine.php | 128 ++ templates/creation/new_ou_template.php | 84 ++ templates/creation/new_user_template.php | 242 ++++ tree.php | 281 +++++ update.php | 49 + update_confirm.php | 143 +++ view_jpeg_photo.php | 28 + 77 files changed, 6757 insertions(+) create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 VERSION create mode 100644 add_oclass.php create mode 100644 add_oclass_form.php create mode 100644 add_value.php create mode 100644 add_value_form.php create mode 100644 collapse.php create mode 100644 config.php.example create mode 100644 copy.php create mode 100644 copy_form.php create mode 100644 create.php create mode 100644 create_form.php create mode 100644 creation_template.php create mode 100644 delete.php create mode 100644 delete_form.php create mode 100644 edit.php create mode 100644 entry_chooser.js create mode 100644 entry_chooser.php create mode 100644 expand.php create mode 100644 functions.php create mode 100644 header.php create mode 100644 images/bug.png create mode 100644 images/children.png create mode 100644 images/country.png create mode 100644 images/cut.png create mode 100644 images/dc.png create mode 100644 images/find.png create mode 100644 images/folder.png create mode 100644 images/light.png create mode 100644 images/locality.png create mode 100644 images/lock.png create mode 100644 images/mail.png create mode 100644 images/minus.png create mode 100644 images/move.png create mode 100644 images/o.png create mode 100644 images/object.png create mode 100644 images/ou.png create mode 100644 images/phone.png create mode 100644 images/photo.png create mode 100644 images/plus.png create mode 100644 images/refresh.png create mode 100644 images/save.png create mode 100644 images/server.png create mode 100644 images/star.png create mode 100644 images/terminal.png create mode 100644 images/trash.png create mode 100644 images/uid.png create mode 100644 images/up.png create mode 100644 images/user.png create mode 100644 index.php create mode 100644 ldap_error_codes.txt create mode 100644 ldif_export.php create mode 100644 login.php create mode 100644 login_form.php create mode 100644 logout.php create mode 100644 new_attr.php create mode 100644 new_jpeg_photo_form.php create mode 100644 rdelete.php create mode 100644 refresh.php create mode 100644 rename.php create mode 100644 schema.php create mode 100644 search.php create mode 100644 search_form_advanced.php create mode 100644 search_form_simple.php create mode 100644 server_info.php create mode 100644 style.css create mode 100644 templates/creation/custom.php create mode 100755 templates/creation/new_address_template.php create mode 100755 templates/creation/new_dns_entry.php create mode 100644 templates/creation/new_nt_machine.php create mode 100644 templates/creation/new_ou_template.php create mode 100644 templates/creation/new_user_template.php create mode 100644 tree.php create mode 100644 update.php create mode 100644 update_confirm.php create mode 100644 view_jpeg_photo.php diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..fea99f9 --- /dev/null +++ b/INSTALL @@ -0,0 +1,40 @@ +These instructions assume that you have a working install of: + a. A web server (Apache, IIS, etc). + b. PHP (with LDAP support) + +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. + +Browsers + +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!) + + 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 + Nathan Rotschafer + - Steve Rigler Password hash patch + - Chric Jackson Blowfish and md5crypt passwords + + Bug reporters: + + - Colin Tinker (short_open_tags bug report) + - Greg Felix (multi-value update bug report) + - Moritz Mertinkat (creation bug report) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..022e560 --- /dev/null +++ b/LICENSE @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..ac39a10 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.9.0 diff --git a/add_oclass.php b/add_oclass.php new file mode 100644 index 0000000..3c5986e --- /dev/null +++ b/add_oclass.php @@ -0,0 +1,55 @@ + $new_oclass ); + +if( is_array( $new_attrs ) && count( $new_attrs ) > 0 ) + foreach( $new_attrs as $attr => $val ) + $new_entry[ $attr ] = $val; + +//echo "
"; 
+//print_r( $new_entry );
+//exit;
+
+$ds = pla_ldap_connect( $server_id ) or pla_error( "Could not connect to LDAP server." );
+$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 ) );
+}
+else
+{
+	header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn" );
+}
+
+?>
diff --git a/add_oclass_form.php b/add_oclass_form.php
new file mode 100644
index 0000000..36c0e9f
--- /dev/null
+++ b/add_oclass_form.php
@@ -0,0 +1,108 @@
+ $junk )
+	$current_attrs[] = strtolower($attr);
+// grab the required attributes for the new objectClass
+$must_attrs = get_schema_objectclasses( $server_id );
+$must_attrs = $must_attrs[ strtolower($new_oclass) ]['must_attrs'];
+sort( $must_attrs );
+// build a list of the attributes that this new objectClass requires,
+// but that the object does not currently contain
+$needed_attrs = array();
+foreach( $must_attrs as $attr )
+	if( ! in_array( strtolower($attr), $current_attrs ) )
+		$needed_attrs[] = $attr;
+
+if( count( $needed_attrs ) > 0 )
+{
+	?>
+
+
+	
+	
+	
+	

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. + +
+
+ +
+ + + + + + + + $attr ) { ?> + + + + + + + + + +
New Required Attributes
+
+
+
+
+
+ + + + + $new_oclass ) ); + if( ! $add_res ) + pla_error( "Could not perform ldap_mod_add operation.", ldap_error( $ds ), ldap_errno( $ds ) ); + else + header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn" ); + +} + +?> diff --git a/add_value.php b/add_value.php new file mode 100644 index 0000000..49d584d --- /dev/null +++ b/add_value.php @@ -0,0 +1,52 @@ + $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 ) ); + +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 new file mode 100644 index 0000000..013be2c --- /dev/null +++ b/add_value_form.php @@ -0,0 +1,133 @@ + + + + + + +

New value for

+

Server:     Distinguished Name:

+ +Current list of value1?'s':''; ?> + for attribute : + + + +
+ +
+ + +

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

+ + + + +
    + 1 )*/ { + foreach( $current_values as $val ) { ?> + +
  • + + + + +
  • + + +
+ + + +Enter the value you would like to add:
+
+ + + +
+ + + + +
Note: you may be required to enter new attributes
+ that this objectClass requires (MUST attrs)
+ + + + + + + +
+
+ + + + + + + + + + +
+ Syntax: +
+ + + + + diff --git a/collapse.php b/collapse.php new file mode 100644 index 0000000..153ced2 --- /dev/null +++ b/collapse.php @@ -0,0 +1,43 @@ + diff --git a/config.php.example b/config.php.example new file mode 100644 index 0000000..14f75d1 --- /dev/null +++ b/config.php.example @@ -0,0 +1,163 @@ + 'User', + 'icon' => 'images/user.png', + 'handler' => 'new_user_template.php' ); + +$templates[] = + array( 'desc' => 'inetOrgPerson', + 'icon' => 'images/user.png', + 'handler' => 'new_address_template.php' ); + +$templates[] = + array( 'desc' => 'Organizational Unit', + 'icon' => 'images/ou.png', + 'handler' => 'new_ou_template.php' ); + +$templates[] = + array( 'desc' => 'Samba NT Machine', + 'icon' => 'images/terminal.png', + 'handler' => 'new_nt_machine.php' ); + +$templates[] = + array( 'desc' => 'DNS Entry', + 'icon' => 'images/dc.png', + 'handler' => 'new_dns_entry.php' ); + +/** **/ +/** User-friendly attribute translation **/ +/** **/ + +$friendly_attrs = array(); + +// Use this array to map attribute names to user friendly names. For example, if you +// don't want to see "facsimileTelephoneNumber" but rather "Fax". + +$friendly_attrs[ 'facsimileTelephoneNumber' ] = 'Fax'; +$friendly_attrs[ 'telephoneNumber' ] = 'Phone'; + +/** **/ +/** Some phpLDAPAdmin code to be executed. No touchy. **/ +/** **/ + +// Turn off notices about referencing arrays and such, but leave everything else on. +error_reporting( E_ALL ^ E_NOTICE ); + +// Always including the 'custom' template (the most generic and flexible) +$templates['custom'] = + array( 'desc' => 'Custom', + 'icon' => 'images/object.png', + 'handler' => 'custom.php' ); + +?> diff --git a/copy.php b/copy.php new file mode 100644 index 0000000..127ae86 --- /dev/null +++ b/copy.php @@ -0,0 +1,167 @@ +\n"; + echo "

Copying " . htmlspecialchars( $source_dn ) . "

\n"; + echo "

Recursive copy progress

\n"; + echo "

"; + echo "\n"; + echo "Building snapshot of tree to copy... "; + flush(); + build_tree( $source_server_id, $source_dn, $snapshot_tree ); + echo " Success
\n"; + flush(); + + // prevent script from bailing early on a long delete + @set_time_limit( 0 ); + + $copy_result = r_copy_dn( $source_server_id, $dest_server_id, $snapshot_tree, $source_dn, $dest_dn ); + echo "
\n"; +} else { + $copy_result = copy_dn( $source_server_id, $source_dn, $dest_server_id, $dest_dn ); +} + +if( $copy_result ) +{ + $edit_url="edit.php?server_id=$dest_server_id&dn=" . rawurlencode( $dest_dn ); + $new_rdn = get_rdn( $dest_dn ); + $container = get_container( $dest_dn ); + if( session_is_registered( 'tree' ) ) + { + $tree = $_SESSION['tree']; + $tree_icons = $_SESSION['tree_icons']; + if( isset( $tree[$dest_server_id][$container] ) ) + { + $tree[$dest_server_id][$container][] = $dest_dn; + $tree_icons[$dest_server_id][$dest_dn] = get_icon( $dest_server_id, $dest_dn ); + $_SESSION['tree'] = $tree; + $_SESSION['tree_icons'] = $tree_icons; + session_write_close(); + } + } + + ?> + + +
+ Copy successful! Would you like to view the new entry? +
+
+
+
+ + + Copying " . htmlspecialchars( utf8_decode( $root_dn ) ) . "..."; + flush(); + $copy_result = copy_dn( $source_server_id, $root_dn, $dest_server_id, $dest_dn ); + + if( ! $copy_result ) { + global $R_COPY_ERROR; + return false; + } + + echo "Success
\n"; + flush(); + + $children = $tree[ $root_dn ]; + if( is_array( $children ) && count( $children ) > 0 ) + { + foreach( $children as $child_dn ) { + $child_rdn = get_rdn( $child_dn ); + $new_dest_dn = $child_rdn . ',' . $dest_dn; + r_copy_dn( $source_server_id, $dest_server_id, $tree, $child_dn, $new_dest_dn ); + } + } + else + { + return true; + } + + return true; +} + +function copy_dn( $source_server_id, $source_dn, $dest_server_id, $dest_dn ) +{ + global $ds; + $ds = pla_ldap_connect( $dest_server_id ) or pla_error( "Could not connect to LDAP server" ); + $attrs = get_object_attrs( $source_server_id, $source_dn ); + $new_entry = $attrs; + // modify the prefix-value (ie "bob" in cn=bob) to match the destination DN's value. + $rdn_attr = substr( $dest_dn, 0, strpos( $dest_dn, '=' ) ); + $rdn_value = get_rdn( $dest_dn ); + $rdn_value = substr( $rdn_value, strpos( $rdn_value, '=' ) + 1 ); + $new_entry[ $rdn_attr ] = $rdn_value; + // don't need a dn attribute in the new entry + unset( $new_entry['dn'] ); + $add_result = @ldap_add( $ds, $dest_dn, $new_entry ); + if( ! $add_result ) { + echo "

"; + pla_error( "Failed to copy $source_dn (server: $source_server_id) to " . + "$dest_dn (server: $dest_server_id)", ldap_error( $ds ), ldap_errno( $ds ) ); + } + + return $add_result; +} + +function build_tree( $source_server_id, $root_dn, &$tree ) +{ + $children = get_container_contents( $source_server_id, $root_dn ); + if( is_array( $children ) && count( $children ) > 0 ) + { + $tree[ $root_dn ] = $children; + foreach( $children as $child_dn ) + build_tree( $source_server_id, $child_dn, $tree ); + } + +} diff --git a/copy_form.php b/copy_form.php new file mode 100644 index 0000000..a37a909 --- /dev/null +++ b/copy_form.php @@ -0,0 +1,86 @@ + $server ) +{ + if( $server['host'] ) + { + $select_server_html .= "\n"; + } +} + +$children = get_container_contents( $server_id, $dn ); + +?> + + + + +

Copy

+

Server:     Distinguished Name:

+ +
+Copy to a new object:
+
+
+ + + + + + + + + + + + + + + + + + 0 ) { ?> + + + + + + + + +
Destination DN: + +
Destination Server:
Note: Copying between different servers only works if there are no schema violations
+ Recursively copy all children of this object as well.
+
+ +
+ + diff --git a/create.php b/create.php new file mode 100644 index 0000000..1f643a8 --- /dev/null +++ b/create.php @@ -0,0 +1,114 @@ + $val ) + { + if( $val == '' ) + 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 ); + } +} + +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 ); + } +} + +$new_entry['objectClass'] = $object_classes; +if( ! in_array( 'top', $new_entry['objectClass'] ) ) + $new_entry['objectClass'][] = 'top'; + +$ds = pla_ldap_connect( $server_id ); +$add_result = @ldap_add( $ds, $new_dn, $new_entry ); +if( $add_result ) +{ + $edit_url="edit.php?server_id=$server_id&dn=" . rawurlencode( $new_dn ); + + // update the session tree to reflect the change + session_start(); + if( session_is_registered( 'tree' ) ) + { + $tree = $_SESSION['tree']; + $tree_icons = $_SESSION['tree_icons']; + + if( isset( $tree[$server_id][$container] ) ) { + $tree[$server_id][$container][] = $new_dn; + $tree_icons[$server_id][$new_dn] = get_icon( $server_id, $new_dn ); + } + + $_SESSION['tree'] = $tree; + $_SESSION['tree_icons'] = $tree_icons; + session_write_close(); + } + + ?> + + + + + + + + + + + + + Redirecting... here. + + + diff --git a/create_form.php b/create_form.php new file mode 100644 index 0000000..53f9c13 --- /dev/null +++ b/create_form.php @@ -0,0 +1,81 @@ +'; +$js_dn_list = ''; +foreach( $servers as $id => $server ) { + if( $server['host'] ) { + $server_menu_html .= ''; + } +} +$server_menu_html .= ''; + +?> + + + + + +

Create Object

+

Choose a template

+

Select a template for the creation process

+
+ + + + + + + + + + + + + + + +
Server:
Template: + + + $template ) { ?> + + + + + + +
+
+ +
+ + + diff --git a/creation_template.php b/creation_template.php new file mode 100644 index 0000000..238a2ca --- /dev/null +++ b/creation_template.php @@ -0,0 +1,45 @@ + + + +

Create Object

+

On server '', + using template ''

+ +" . htmlspecialchars( $template['handler'] ) . + " for this template. But, this handler does not exist in the 'templates/creation' directory." ); + + diff --git a/delete.php b/delete.php new file mode 100644 index 0000000..786bf61 --- /dev/null +++ b/delete.php @@ -0,0 +1,65 @@ + $subtree ) + foreach( $subtree as $key => $sub_tree_dn ) + if( 0 == strcasecmp( $sub_tree_dn, $dn ) ) + unset( $tree[$server_id][$tree_dn][$key] ); + } + + $_SESSION['tree'] = $tree; + session_write_close(); + + ?> + + + + Object deleted successfully. + + 0 ? true : false; + +?> + + + + +

Delete

+

Server:     Distinguished Name:

+ + + +
You cannot delete the base DN entry of the LDAP server.
+ + + + + + + + + +
Permanently delete all children also?

+ + + + + +
+ +

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 +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. +Take into consideration aliases and other such things that may cause problems. +
+
+ + + + + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
+

+ +
+
+A list of all the DNs that this action will delete:
+ + +
+ + + +
+ + + +
+ +Are you sure you want to permanently delete this object?
+
+DN:
+
Server:
+
+ + + + + + +
+
+
+ + + +
+ +
+
+
+ + + +
+
+
+ +
+ +
+ + + + + + + + diff --git a/edit.php b/edit.php new file mode 100644 index 0000000..2935dad --- /dev/null +++ b/edit.php @@ -0,0 +1,472 @@ + + + + + +

+

Server:     Distinguished Name:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 ) { + if( $children_count == $max_children ) + $children_count = $children_count . '+'; + +?> + + + + + + + + + 0 ) { ?> + + + + + + + + + + + + + + + + + +
Refresh
Delete this entry
Copy this entry
Export to LDIF + (mac) + (win) + (unix) +
">Create a child entry
View
Export subtree to LDIF + (mac) + (win) + (unix) +
Add a jpegPhoto
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + $val ) { + $counter++ + ?> + + + + + \n"; +} + +?> + + + + + + + + + + + + + + + + + $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; + } + + ?> + + + + + + + + + + + + + + + + + + + + + + + + $val ) { ?> + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Rename Entry + +
+ + + + +
+
+
+ + Add New Attribute + + + 0 ) { ?> + + + + + + + + (no new attributes available for this entry) + + +
+ + + + +Internal Attriubtes + + + + + +Internal Attriubtes +(hidden) + + + + +
(none)
+ + Modify Attributes + +
+
+ (add value) +
+ + + + + + + + This attribute contains binary data,
+ which cannot be safely displayed
+ or edited in a web-browser.
+
+ + + + + +
+ + + +
+ + + diff --git a/entry_chooser.js b/entry_chooser.js new file mode 100644 index 0000000..4f0aeca --- /dev/null +++ b/entry_chooser.js @@ -0,0 +1,6 @@ +function dnChooserPopup( form_element ) +{ + mywindow=open('entry_chooser.php','myname','resizable=no,width=600,height=370,scrollbars=1'); + mywindow.location.href = 'entry_chooser.php?form_element=' + form_element; + if (mywindow.opener == null) mywindow.opener = self; +} diff --git a/entry_chooser.php b/entry_chooser.php new file mode 100644 index 0000000..f71fc87 --- /dev/null +++ b/entry_chooser.php @@ -0,0 +1,73 @@ +Automagic Entry Chooser\n"; + +if( $container ) { + echo "Server: " . htmlspecialchars( $servers[ $server_id ][ 'name' ] ) . "
\n"; + echo "Looking in: " . htmlspecialchars( $container ) . "
\n"; +} + +if( $server_id !== false && $container !== 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." ); + pla_ldap_connect( $server_id ) or pla_error( "Coult not connect to LDAP server." ); + $dn_list = get_container_contents( $server_id, $container ); + + $base_dn = $servers[ $server_id ][ 'base' ]; + if( ! $base_dn ) + $base_dn = try_to_get_root_dn( $server_id ); + + if( $container == $base_dn ) { + $parent_container = false; + $up_href = "entry_chooser.php?form_element=$return_form_element"; + } else { + $parent_container = get_container( $container ); + $up_href = "entry_chooser.php?form_element=$return_form_element&server_id=$server_id&container=" . + rawurlencode( $parent_container ); + } + echo " " . + " Back Up...
\n"; + + if( count( $dn_list ) == 0 ) + echo "   (no entries)
\n"; + else + foreach( $dn_list as $dn ) { + $href = "javascript:returnDN( '$dn' )"; + echo "    " . + "" . htmlspecialchars( $dn ) . "
\n"; + } +} +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"; + } + } +} + +?> + + diff --git a/expand.php b/expand.php new file mode 100644 index 0000000..d8bbbcb --- /dev/null +++ b/expand.php @@ -0,0 +1,60 @@ + diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..9b134cb --- /dev/null +++ b/functions.php @@ -0,0 +1,1174 @@ + $class ) + $object_classes[$i] = strtolower( $class ); + + // get the prefix (ie: dc, ou, cn, uid) + $exploded_dn = ldap_explode_dn( $dn, 0 ); + $rdn = $dn[0]; + $prefix = explode( '=', $rdn ); + $prefix = $prefix[0]; + + // Is it a person or some type of account/user? + if( in_array( 'person', $object_classes ) || + in_array( 'organizationalperson', $object_classes ) || + in_array( 'inetorgperson', $object_classes ) || + in_array( 'account', $object_classes ) || + in_array( 'posixaccount', $object_classes ) ) + return 'user.png'; + // Is it an organization? + elseif ( in_array( 'organization', $object_classes ) ) + return 'o.png'; + // Is it an organizational Unit? + elseif( in_array( 'organizationalunit', $object_classes ) ) + return 'ou.png'; + // Is it a domain controler (dc) + elseif( in_array( 'dcobject', $object_classes ) || + in_array( 'domainrelatedobject', $object_classes ) ) + return 'dc.png'; + elseif( in_array( 'country', $object_classes ) ) + return 'country.png'; + elseif( in_array( 'jammvirtualdomain', $object_classes ) ) + return 'mail.png'; + elseif( in_array( 'locality', $object_classes ) ) + return 'locality.png'; + // Oh well, I don't know what it is. Use a generic icon. + else + return 'object.png'; +} + +/* + * Given a server_id, returns whether or not we have enough information + * to authenticate against the server. For example, if the user specifies + * 'cookie' in the config for that server, it checks the $_COOKIE array to + * see if the cookie username and password is set for the server. + */ +function have_auth_info( $server_id ) +{ + global $servers; + + if( ! is_numeric( $server_id ) || ! isset( $servers[$server_id] ) ) + return false; + + $server = $servers[$server_id]; + + if( $server['auth_type'] == 'form' ) + { + global $_COOKIE; + if( isset( $_COOKIE[ 'pla_login_dn_' . $server_id ] ) && + isset( $_COOKIE[ 'pla_pass_' . $server_id ] ) ) + return true; + else + return false; + } + // whether or not the login_dn or pass is specified, we return + // true here. (if they are blank, we do an anonymous bind anyway) + elseif( $server['auth_type'] == 'config' ) + { + return true; + } + else + { + pla_error( "Error: You have an error in your config file. The only two allowed + values for 'auth_type' in the $servers section are 'config' and + 'form'. You entered '" . htmlspecialchars($server['auth_type']) . "', which + is not allowed. " ); + } +} + +function get_logged_in_pass( $server_id ) +{ + global $_COOKIE; + $pass = $_COOKIE[ 'pla_login_pass_' . $server_id ]; + + if( $pass == '0' ) + return false; + else + return $pass; +} +function get_logged_in_dn( $server_id ) +{ + global $_COOKIE; + $dn = $_COOKIE[ 'pla_login_dn_' . $server_id ]; + + if( $dn == '0' ) + return 'Anonymous'; + else + return $dn; +} + +/* + * Specify a $server_id (0,1,2...) based on the order it appears in config.php. + * The first is 0, the second is 1, etc. You rarely will need to consult + * config.php since those values are usually generated dynamically in hrefs. + */ +function pla_ldap_connect( $server_id ) +{ + if( ! check_server_id( $server_id ) ) + return false; + + if( ! have_auth_info( $server_id ) ) + return false; + + global $servers; + + // cache the connection, so if we are called multiple + // times, we don't have to reauthenticate with the LDAP server + + static $conns; + if( $conns[$server_id] ) + return $conns[$server_id]; + + $host = $servers[$server_id]['host']; + $port = $servers[$server_id]['port']; + if( ! $port ) $port = 389; + + $conn = @ldap_connect( $host, $port ); + + if( ! $conn ) return false; + + // go with LDAP version 3 if possible (needed for renaming and Novell schema fetching) + @ldap_set_option( $conn, LDAP_OPT_PROTOCOL_VERSION, 3 ); + + // try to fire up TLS is specified in the config + if( $servers[ $server_id ][ 'tls' ] == true ) { + function_exists( 'ldap_start_tls' ) or pla_error( "Your PHP install does not support TLS" ); + @ldap_start_tls( $conn ) or pla_error( "Could not start TLS.
Please check your ". + "LDAP server configuration." ); + } + + // grab the auth info based on the auth_type for this server + if( $servers[ $server_id ][ 'auth_type' ] == 'config' ) { + $login_dn = $servers[$server_id]['login_dn']; + $login_pass = $servers[$server_id]['login_pass']; + } elseif( $servers[ $server_id ][ 'auth_type' ] == 'form' ) { + global $_COOKIE; + $login_dn = $_COOKIE['pla_login_dn_' . $server_id ]; + $login_pass = $_COOKIE['pla_pass_' . $server_id ]; + + // Was this an anonyous bind (the cookie stores 0 if so)? + if( '0' == $login_dn ) { + $login_dn = null; + $login_pass = null; + } + } else { + pla_error( "You have an error in your config file. auth_type of " . + htmlspecialchars( $servers[ $server_id ][ 'auth_type' ] ) . + " is not valid." ); + } + + $res = @ldap_bind( $conn, $login_dn, $login_pass ); + + if( ! $res ) return false; + + // store the cached connection resource + $conns[$server_id] = $conn; + + return $conn; +} + +/* + * Returns an array listing the DNs contained by the specified $dn + */ +function get_container_contents( $server_id, $dn, $size_limit=0 ) +{ + $con = pla_ldap_connect( $server_id ); + if( ! $con ) return false; + + $search = @ldap_list( $con, $dn, 'objectClass=*', array( 'dn' ), 1, $size_limit ); + if( ! $search ) + return array(); + $search = ldap_get_entries( $con, $search ); + + $return = array(); + + for( $i=0; $i<$search['count']; $i++ ) + { + $entry = $search[$i]; + $dn = $entry['dn']; + $return[] = $dn; + } + + return $return; +} + +/* + * Builds the initial tree that is stored in the session variable 'tree'. + * Simply returns an array with an entry for each active server in + * config.php + */ +function build_initial_tree() +{ + global $servers; + $tree = array(); + foreach( $servers as $id => $server ) { + if( $server['host'] == '' ) { + continue; + /* + $root_dn = try_to_get_root_dn( $id ); + echo "Root is $root_dn
"; + if( $root_dn ) + $tree[$id][$root_dn] = array(); + */ + } + + $dn = $server['base']; + $tree[$id] = array(); + } + + return $tree; +} + +/* + * Builds the initial array that stores the icon-lookup for each DN in the tree browser + */ +function build_initial_tree_icons() +{ + global $servers; + $tree_icons = array(); + + // initialize an empty array for each server + foreach( $servers as $id => $server ) { + if( $server['host'] == '' ) + continue; + $tree_icons[ $id ] = array(); + $tree_icons[ $id ][ $server['base'] ] = get_icon( $id, $server['base'] ); + } + + return $tree_icons; +} + +function get_entry_system_attrs( $server_id, $dn ) +{ + $conn = pla_ldap_connect( $server_id ); + if( ! $conn ) return false; + + $search = @ldap_read( $conn, $dn, '(objectClass=*)', array("+"), 0, 200, 0, LDAP_DEREF_ALWAYS ); + + if( ! $search ) + return false; + + $entry = ldap_first_entry( $conn, $search ); + $attrs = ldap_get_attributes( $conn, $entry ); + foreach( $attrs as $name => $vals ) + if( is_numeric( $name ) || $name == 'count' ) + unset( $attrs[$name] ); + else + $attrs[$name] = $vals[0]; + return $attrs; +} + +/* + * Returns the attribute/value pairs for the given $dn on the given + * $server_id. If the attribute is single valued, it will return + * a single value for that attribute. Otherwise, it will return an + * array of values for that attribute. Here's a sample return value: + * + * Array + * ( + * [objectclass] => Array + * ( + * [0] => organizationalRole + * [1] => krb5principal + * [2] => kerberosSecurityObject + * ) + * [cn] => Manager + * [krbname] => phpldap@EXAMPLE.COM + * [dn] => cn=Manager,dc=example,dc=com + * ) + */ +function get_object_attrs( $server_id, $dn, $lower_case_attr_names = false ) +{ + $conn = pla_ldap_connect( $server_id ); + if( ! $conn ) return false; + + $search = @ldap_read( $conn, $dn, '(objectClass=*)' ); + + if( ! $search ) + return false; + + $entry = ldap_first_entry( $conn, $search ); + $attrs = ldap_get_attributes( $conn, $entry ); + //$attrs = ldap_get_entries( $conn, $search ); + + if( ! $attrs || $attrs['count'] == 0 ) + return false; + + //$attrs = $attrs[0]; + $num_attrs = $attrs['count']; + unset( $attrs['count'] ); + + for( $i=0; $i<$num_attrs; $i++ ) + unset( $attrs[$i] ); + + $return_array = array(); + foreach( $attrs as $attr => $vals ) { + if( $lower_case_attr_names ) + $attr = strtolower( $attr ); + $count = $vals['count']; + unset( $vals['count'] ); + if( $count == 1 ) + $return_array[ $attr ] = $vals[0]; + else + $return_array[ $attr ] = $vals; + } + + ksort( $return_array ); + + return $return_array; +} + +/* + * Returns true if the passed string $temp contains all printable + * ASCII characters. Otherwise (like if it contains binary data), + * returns false. + */ +function is_printable_str($temp) { + $len = strlen($temp); + for ($i=0; $i<$len; $i++) { + $ascii_val = ord( substr( $temp,$i,1 ) ); + if( $ascii_val < 32 || $ascii_val > 126 ) + return false; + } + + return true; +} + +/* + * Much like get_object_attrs(), but only returns the entry for + * one attribute of an object. Again, if the attribute contains + * multiple values, returns an array of values. Otherwise, it + * returns the single attribute value. + * TODO: Don't call get_object_attrs() and filter. Do the actual ldap_read() ourselves (for efficiencey) + */ +function get_object_attr( $server_id, $dn, $attr ) +{ + $attr = strtolower( $attr ); + $attrs = get_object_attrs( $server_id, $dn, true ); + if( isset( $attrs[$attr] ) ) + return $attrs[$attr]; + else + return false; +} + +/* + * Returns true if $var is not white space only, and false otherwise. + */ +function not_white( $var ) +{ + return trim($var) != "" ? true : false; +} + +/* + * 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 ) +{ + $ds = pla_ldap_connect( $server_id ); + + if( ! $ds ) + return false; + + // get all the objectClasses + $result = @ldap_read($ds, 'cn=subschema', '(objectClass=*)', + array( 'objectclasses' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + if( ! $result ) + $result = @ldap_read($ds, 'cn=schema', '(objectClass=*)', + array( 'objectclasses' ), 0, 200, 0, LDAP_DEREF_ALWAYS ); + + if( ! $result ) return false; + if( $result ) $raw_oclasses = ldap_get_entries($ds,$result ); + + // build the array of objectClasses + $oclasses = array(); + for( $att=0; $att < count( $raw_oclasses[0]["objectclasses"] ); $att++ ) + { + $class = $raw_oclasses[0]["objectclasses"][$att]; + + preg_match( "/[\s]+NAME[\s'\(]+([a-zA-Z0-9\-_]+)[\s'\)]/" , $class, $name); + preg_match( "/[\s]+([\d\.]+)[\s]+NAME/", $class, $oid ); + preg_match( "/[\s]+DESC[\s]+'([a-zA-Z0-9\-_ ]+)'/", $class, $description ); + preg_match( "/[\s]+SUP[\s]+([a-zA-Z0-9\-_]+)[\s]/", $class, $sup ); + + $key = strtolower( trim( $name[1] ) ); + $oclass_name = trim( $name[1] ); + if( ! $key ) continue; + + $oclasses[$key] = array(); + $oclasses[$key]['oid'] = trim( $oid[1] ); + $oclasses[$key]['description'] = trim( $description[1] ); + $oclasses[$key]['sup'] = trim( $sup[1] ); + + unset( $name ); + unset( $syntax ); + unset( $desription ); + + // get all the required attributes + preg_match( "/MUST[\s\(]+([a-zA-Z0-9\s$]+)(MAY|\))/" , $class, $must_attrs ); + $must_attrs = str_replace( ' ', '', $must_attrs[1] ); + $oclasses[$key]['must_attrs'] = array_filter( explode( '$', $must_attrs ), "not_white" ); + + // get all the optional attributes + preg_match( "/MAY[\s\(]+([a-zA-Z0-9\s$]+)(MUST|\))/" , $class, $may_attrs ); + $may_attrs = str_replace( ' ', '', $may_attrs[1] ); + $oclasses[$key]['may_attrs'] = array_filter( array_merge( $oclasses[$key]['must_attrs'], explode( '$', $may_attrs) ), "not_white" ); + unset( $must_attrs ); + unset( $may_attrs ); + + $oclasses[$key]['name'] = $oclass_name; + } + + // go back and add any inherited MUST/MAY attrs to each objectClass + foreach( $oclasses as $oclass => $attrs ) + { + $new_must = $attrs['must_attrs']; + $new_may = $attrs['may_attrs']; + $sup_attr = $attrs['sup']; + + while( $sup_attr && $sup_attr != "top" ) { + $new_must = array_merge( $new_must, $oclasses[strtolower($sup_attr)]['must_attrs'] ); + $new_may = array_merge( $new_may, $oclasses[strtolower($sup_attr)]['may_attrs'] ); + $sup_attr = $oclasses[strtolower($sup_attr)]['sup']; + } + + $oclasses[$oclass]['must_attrs'] = array_unique( $new_must ); + $oclasses[$oclass]['may_attrs'] = array_unique( $new_may ); + } + + ksort( $oclasses ); + + return $oclasses; + +} + +/* + * Returns an associate array of the server's schema matching rules + */ +function get_schema_matching_rules( $server_id ) +{ + static $cache; + + if( isset( $cache[$server_id] ) ) + 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[$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; + + if( isset( $cache[$server_id] ) ) + 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[$server_id] = $syntaxes; + + return $syntaxes; +} + +/* + * 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 ) +{ + $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 attributes + $attrs = array(); + for( $i=0; $i < $raw_attrs[0]['attributetypes']['count']; $i++ ) + { + $attr = $raw_attrs[0]['attributetypes'][$i]; + + preg_match( "/[\s]+NAME[\s'\(]+([a-zA-Z0-9\-_]+)[\s'\)]/" , $attr, $name); + preg_match( "/\s+NAME\s+'([a-zA-Z0-9\-_]+)'\s/" , $attr, $name); + preg_match( "/[\s]+([\d\.]+)[\s]+NAME/", $attr, $oid ); + preg_match( "/[\s]+DESC[\s]+'([\)\(:?\.a-zA-Z0-9\-_ ]+)'/", $attr, $description ); + preg_match( "/[\s]+SYNTAX[\s]+([\d\.]+)/", $attr, $syntax); + preg_match( "/[\s]+EQUALITY[\s]+([a-zA-Z]+)/", $attr, $equality); + preg_match( "/[\s]+SUBSTR[\s]+([a-zA-Z]+)/", $attr, $substr); + preg_match( "/[\s]+SUP[\s]+([a-zA-Z0-9\-_]+)/", $attr, $sup ); + + if( preg_match( "/[\s]+SINGLE-VALUE[\s]+/", $attr, $single_value ) ) + $single_value = 'Yes'; + else + $single_value = 'No'; + + // If this schema attribute has multiple names (like: "NAME ( 'uid' 'userid' )"), then we need + // to create a matching attribute entry for each name it bares. + if( preg_match( "/\s+NAME\s+\(\s*['\sa-zA-Z0-9\-_]+\s*\)/", $attr, $multi_name ) ) { + $multi_name = $multi_name[0]; + preg_match_all( "/'([a-zA-Z0-9\-_]+)'/", $multi_name, $multiple_names ); + $multiple_names = $multiple_names[1]; + //print_r( $multiple_names ); + + foreach( $multiple_names as $name ) { + $key = strtolower( trim( $name ) ); + $attr_name = trim( $name ); + if( ! $key ) continue; + + $attrs[$key] = array(); + $attrs[$key]['oid'] = trim( $oid[1] ); + $attrs[$key]['description'] = trim( $description[1] ); + $attrs[$key]['syntax'] = trim( $syntax[1] ); + $attrs[$key]['type'] = $syntaxes[ trim($syntax[1]) ]['description']; + $attrs[$key]['equality'] = trim( $equality[1] ); + $attrs[$key]['substr'] = trim( $substr[1] ); + $attrs[$key]['single_value'] = $single_value; + $attrs[$key]['sup'] = trim( $sup[1] ); + $attrs[$key]['name'] = $attr_name; + + $count = 1; + for( $j=0; $j $desc ) + { + $sup_attr = $desc['sup']; + while( $sup_attr ) { + if( ! $attrs[ $sup_attr ]['sup'] ) { + $attrs[ $attr ][ 'syntax' ] = $attrs[ $sup_attr ]['syntax']; + $attrs[ $attr ][ 'equality' ] = $attrs[ $sup_attr ]['equality']; + $attrs[ $attr ][ 'substr' ] = $attrs[ $sup_attr ]['substr']; + $attrs[ $attr ][ 'single_value' ] = $attrs[ $sup_attr ]['single_value']; + break; + } else { + $sup_attr = $attrs[ $sup_attr ]['sup']; + } + } + } + + ksort( $attrs ); + + return $attrs; +} + +/* + * A wrapper function to save you from having to call get_schema_objectclasses() + * and get_schema_attributes(). Returns an array with two indexes: 'oclasses' + * and 'attributes', as defined by their respective functions above. + */ +function get_schema( $server_id ) +{ + $ds = pla_ldap_connect( $server_id ); + + if( ! $ds ) + return false; + + $attrs = get_schema_attributes($server_id, $lower_case_all ); + $oclasses = get_schema_objectclasses($server_id, $lower_case_all ); + + if( ! $oclasses ) + return false; + + $schema = array( 'attrs' => $attrs, + 'oclasses' => $oclasses ); + return $schema; +} + +/* + * A do-it-all ldap_search function. You can even specify the search scope. Other than + * that, it's pretty much the same as the PHP ldap_search() call, except it returns + * an array of results, rather than an LDAP result resource. + */ +function pla_ldap_search( $server_id, $filter, $base_dn=null, $attrs=array(), $scope='sub', $sort_results=true ) +{ + global $servers; + + if( ! isset($servers[$server_id]) || $servers[$server_id]['host'] == '' ) + return false; + + if( $base_dn == null ) + $base_dn = $servers[$server_id]['base']; + + $ds = pla_ldap_connect( $server_id ); + if( ! $ds ) + return false; + + switch( $scope ) { + case 'base': + $search = @ldap_read( $ds, $base_dn, $filter, $attrs ); + break; + case 'one': + $search = @ldap_list( $ds, $base_dn, $filter, $attrs ); + break; + case 'sub': + default: + $search = @ldap_search( $ds, $base_dn, $filter, $attrs ); + break; + } + + if( ! $search ) + return array(); + + $search = ldap_get_entries( $ds, $search ); + + $return = array(); + foreach( $search as $id => $attrs ) { + if( ! is_array( $attrs ) ) + continue; + for( $i=0; $i<$attrs['count']; $i++ ) + unset( $attrs[$i] ); + $dn = $attrs['dn']; + foreach( $attrs as $attr => $vals ) { + $count = $vals['count']; + unset( $vals['count'] ); + if( $count == 1 ) + $return[$dn][$attr] = $vals[0]; + else + $return[$dn][$attr] = $vals; + } + } + + if( $sort_results ) ksort( $return ); + return $return; + +} + +/* + * Transforms the user-configured lists into arrays and such. This is a little weird, but + * it takes the comma-separated lists (like the search result attribute list) in config.php + * and turns them into arrays. Only call this ONCE per script. Any subsequent call will + * mess up the arrays. This function operates only on global variables defined in config.php. + */ +function process_config() +{ + global $search_result_attributes; + $search_result_attributes = explode( ",", $search_result_attributes ); + array_walk( $search_result_attributes, "trim_it" ); + + global $search_attributes_display; + $search_attributes_display = explode( ",", $search_attributes_display ); + array_walk( $search_attributes_display, "trim_it" ); + + global $search_attributes; + $search_attributes= explode( ",", $search_attributes); + array_walk( $search_attributes, "trim_it" ); + + global $search_criteria_options; + $search_criteria_options= explode( ",", $search_criteria_options); + array_walk( $search_criteria_options, "trim_it" ); +} + +/* + * Call-by-reference to trim a string. Used to filter empty entries out of the arrays + * that we generate in process_config(). + */ +function trim_it( &$str ) +{ + $str = trim($str); +} + +/* + * Checks the server id for sanity. Ensures that the server is indeed in the configured list and active + */ +function check_server_id( $server_id ) +{ + global $servers; + if( ! is_numeric( $server_id ) || ! isset( $servers[$server_id] ) || $servers[$server_id]['host'] == '' ) + return false; + else + return true; +} + +/* + * Used to generate a random salt for crypt-style passwords + * --- added 20021125 by bayu irawan --- + * --- ammended 20030625 by S C Rigler --- + */ +function random_salt( $length ) +{ + $possible = '0123456789'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + './'; + $str = ""; + mt_srand((double)microtime() * 1000000); + while( strlen( $str ) < $length ) + { + $str .= substr( $possible, ( rand() % strlen( $possible ) ), 1 ); + } + /* + * Commented out following line because of problem + * with crypt function in update.php + * --- 20030625 by S C Rigler --- + */ + //$str = "\$1\$".$str."\$"; + return $str; +} + +/* + * Goes through the user-configured server list and looks for an available server_id, + * ie one that has specified enough information to login. This is for choosing the + * server to display in the drop-down box in search.php mostly. + */ +function get_avail_server_id() +{ + global $servers; + + for( $i=0; $i 0 ) { + return $err_codes[ $err_no ]; + } else { + } + + $err_codes_file = 'ldap_error_codes.txt'; + + if( ! file_exists( $err_codes_file ) ) + return false; + if( ! is_readable( $err_codes_file ) ) + return false; + if( ! ($f = fopen( $err_codes_file, 'r' )) ) + return false; + + $contents = fread( $f, filesize( $err_codes_file ) ); + preg_match_all( "/0x[A-Fa-f0-9][A-Za-z0-9]\s+[0-9A-Za-z_]+\s+\"[^\"]*\"\n/", $contents, $entries ); + $err_codes = array(); + foreach( $entries[0] as $e ) + { + preg_match( "/(0x[A-Za-z0-9][A-Za-z0-9])\s+([0-9A-Za-z_]+)\s+\"([^\"]*)\"/", $e, $entry ); + $hex_code = $entry[1]; + $title = $entry[2]; + $desc = $entry[3]; + $desc = preg_replace( "/\s+/", " ", $desc ); + $err_codes[ $hex_code ] = array( 'title' => $title, 'desc' => $desc ); + } + + return $err_codes[ $err_no ]; +} + +/* + * Spits out an HTML-formatted error string. If you specify the optional + * parameters, pla_error will lookup the error number and display a + * verbose message in addition to the message you pass it. + */ +function pla_error( $msg, $ldap_err_msg=null, $ldap_err_no=-1 ) +{ + include_once 'header.php'; + + echo "
"; + echo "
\n\n"; + echo "

Error

\n\n"; + echo "
$msg
"; + echo "

\n"; + + if( $ldap_err_msg ) + echo "LDAP Server Said: " . htmlspecialchars( $ldap_err_msg ) . "

\n"; + + if( $ldap_err_no != -1 ) { + $ldap_err_no = ( '0x' . str_pad( dechex( $ldap_err_no ), 2, 0, STR_PAD_LEFT ) ); + $verbose_error = pla_verbose_error( $ldap_err_no ); + + if( $verbose_error ) { + echo "Error number: $ldap_err_no (" . + $verbose_error['title'] . ")

\n"; + echo "Description: " . $verbose_error['desc'] . "

\n\n"; + } else { + echo "Error number: $ldap_err_no

\n"; + echo "Description: (no description available)
\n\n"; + } + } + + echo "
\n"; + echo "
"; + die(); +} + +/* + * Reads the friendly_attrs array as defined in config.php and lower-cases all + * the keys. Will return an empty array if the friendly_attrs array is not defined + * in config.php. + */ +function process_friendly_attr_table() +{ + require 'config.php'; + global $friendly_attrs; + $attrs_table = array(); + if( isset( $friendly_attrs ) && is_array( $friendly_attrs ) ) + foreach( $friendly_attrs as $old_name => $new_name ) + $attrs_table[ strtolower( $old_name ) ] = $new_name; + else + return array(); + + return $attrs_table; +} + +/* + * Returns true if the specified DN exists on the specified server, or false otherwise + */ +function dn_exists( $server_id, $dn ) +{ + if( ! check_server_id( $server_id ) ) + return false; + + $ds = pla_ldap_connect( $server_id ); + + if( ! $ds ) + return false; + + $search_result = @ldap_read( $ds, $dn, 'objectClass=*', array('dn') ); + + if( ! $search_result ) + return false; + + $num_entries = ldap_count_entries( $ds, $search_result ); + + if( $num_entries > 0 ) + return true; + else + return false; +} + +/* + * Given a DN and server_id, this draws fetches the jpegPhoto binary data and echo's the + * HTML necesary to draw it. You can optionally have it draw the 'delete' button below + * each image. This function supports multiple jpegPhotos. + */ +function draw_jpeg_photos( $server_id, $dn, $draw_delete_buttons=false ) +{ + global $jpeg_temp_dir; + global $jpeg_tmp_keep_time; + + $conn = pla_ldap_connect( $server_id ); + $search_result = ldap_search( $conn, $dn, 'objectClass=*', array( 'jpegPhoto' ) ); + $entry = ldap_first_entry( $conn, $search_result ); + + echo "
\n\n"; + // for each jpegPhoto in the entry, draw it (there may be only one, and that's okay) + $jpeg_data = ldap_get_values_len( $conn, $entry, "jpegphoto"); + for( $i=0; $i<$jpeg_data['count']; $i++ ) + { + $jpeg_filename = $jpeg_temp_dir . '/' . basename( tempnam ('.', 'djp') ); + $outjpeg = fopen($jpeg_filename, "wb"); + fwrite($outjpeg, $jpeg_data[$i]); + fclose ($outjpeg); + $jpeg_data_size = filesize( $jpeg_filename ); + if( $jpeg_data_size < 6 ) { + echo "jpegPhoto contains errors
"; + echo 'Delete Photo'; + continue; + } + + $jpeg_dimensions = getimagesize ($jpeg_filename); + $width = $jpeg_dimensions[0]; + $height = $jpeg_dimensions[1]; + if( $width > 300 ) { + $scale_factor = 300 / $width; + $img_width = 300; + $img_height = $height * $scale_factor; + } else { + $img_width = $width; + $img_height = $height; + } + echo "
\n"; + echo "" . number_format($jpeg_data_size) . " bytes. "; + echo "$width x $height pixels.
\n\n"; + + if( $draw_delete_buttons ) + { ?> + + Delete Photo +
\n\n"; + + // If they have misconfigured their config.php, use default values + if( ! isset( $jpeg_tmp_keep_time ) ) + $jpeg_tmp_keep_time = 120; + + if( $jpeg_tmp_keep_time == 0 ) + $jpeg_tmp_keep_time = 10; + + // delete old jpeg files. + $jpegtmp_wildcard = "djp.*"; + $handle = opendir($jpeg_temp_dir); + while (($file = readdir($handle)) != false) + if (eregi($jpegtmp_wildcard, $file)) + { + $file = "$jpeg_temp_dir/$file"; + if ((time() - filemtime($file)) > $jpeg_tmp_keep_time) + unlink ( $file ); + } + closedir($handle); + +} + +/* + * Returns the root DN of the specified server_id, or false if it + * can't find it (ie, the server won't give it to us). + * Tested with OpenLDAP 2.0, Netscape iPlanet, and Novell eDirectory 8.7 (nldap.com) + * Please report any and all bugs!! + */ +function try_to_get_root_dn( $server_id ) +{ + if( ! have_auth_info( $server_id ) ) + return false; + + $ds = pla_ldap_connect( $server_id ); + if( ! $ds ) + return false; + + $r = @ldap_read( $ds, '', 'objectClass=*', array( 'namingContexts' ) ); + if( ! $r ) + return false; + + $r = @ldap_get_entries( $ds, $r ); + if( isset( $r[0]['namingcontexts'][0] ) ) { + $root_dn = $r[0]['namingcontexts'][0]; + return $root_dn; + } else { + return false; + } +} + +/* + * Hashes a password and returns the hash based on the enc_type, which can be one of + * crypt, md5, sha, or clear. + */ +function password_hash( $password_clear, $enc_type ) +{ + switch( $enc_type ) + { + case 'crypt': + $new_value = '{crypt}' . crypt( $password_clear, random_salt(2) ); + break; + case 'md5': + $new_value = '{md5}' . base64_encode( pack( 'H*' , md5( $password_clear) ) ); + break; + case 'md5crypt': + $new_value = '{crypt}' . crypt( $password_clear , '$1$' . random_salt(9) ); + break; + case 'blowfish': + $new_value = '{crypt}' . crypt( $password_clear , '$2$' . random_salt(13) ); + break; + case 'sha': + if( function_exists( 'mhash' ) ) { + $new_value = '{sha}' . base64_encode( mhash( MHASH_SHA1, $password_clear) ); + } else { + pla_error( "Your PHP install does not have the mhash() function." . + " Cannot do SHA hashes." ); + } + break; + case 'clear': + default: + $new_value = $password_clear; + } + + return $new_value; +} + +/* + * Returns the version as a string as stored in the VERSION file. + */ +function pla_version() +{ + if( ! file_exists( 'VERSION' ) ) + return 'unknown version'; + + $f = fopen( 'VERSION', 'r' ); + $version = fread( $f, filesize( 'VERSION' ) ); + fclose( $f ); + return $version; +} + +function draw_chooser_link( $form_element ) +{ + $href = "javascript:dnChooserPopup('$form_element');"; + echo ""; + echo "browse\n"; +} + +?> diff --git a/header.php b/header.php new file mode 100644 index 0000000..4f79c7e --- /dev/null +++ b/header.php @@ -0,0 +1,11 @@ +\n"; ?> + + + + + phpLDAPAdmin + + + diff --git a/images/bug.png b/images/bug.png new file mode 100644 index 0000000000000000000000000000000000000000..132f93f98dba1fd2f821d40948d9d88eb21c9fb5 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!aez;V>;M1%g<09=OqmiK5U_xi z%~(e#hK2QymewaGmNyR`yzukcvT0LGcFv!+mOuagyx6hhPg=^-iV6FG+8IlN{DK)A zp4~_Tagw~{XE)7O>#GCL0&ySDp}Eqj1M zF`h1tAr*6K{XO{(IB-ZQ1zmdj|9FI$D^$*mcfRH4m;Ud_tQ{ zWfmlE_E!x~nG*kHC2ymRj@w6p4ZdsztlSmz)||R9?dy&c?r+Zg`S(%Gs_aB9;}V;{ S8oPk@FnGH9xvXeb9CPl4OP;RS3Qq*fTku|cbLIUzj z0s!*+6wGESMMtG$?TEcr695o$fnX4jrSaCK$84r%f+OSt?p22Xiy;0g|ItsuM#$VV zL8-ZPHb+vA_?W{vJ4d7Zvnw+H5ixR>rG@<)57B)Wv6#WBdnDr=9)LfGn7&OBJ=_87 zQvXN*02bW=vza2Jc!Wl|sBVW``;u34@&57zKN6_67t5_&dZeNO%w|d^31Trrwf&FC gqhScA?xm4`11O4oV#)QVVgLXD07*qoM6N<$f+^Co%K!iX literal 0 HcmV?d00001 diff --git a/images/country.png b/images/country.png new file mode 100644 index 0000000000000000000000000000000000000000..7640da3a463dff20a3023b866374eb01475ef018 GIT binary patch literal 707 zcmV;!0zCbRP)UHRJX6Pk=*48fo?kC#-L=iL^ez(?v>jOiywj_z4xe5Y;S`BKo+=rS8 z#xE`caPHw#04f!an`JN>X<$H>8RFQxSF(hxR$*lY!Y~(1b3p-I2l(^k0pN3bJ?Qr# zjy1*@k_4;;6_rrsDl9Mi#L1*EuKb7D1kks=pw_Un0|y6Sj3rIITNMey@C-zCD3`t1 zXjDKBkE*Y(t^zO~dogP*)@GzBgtCNEO9Vj!)LEZ29Qt((dG>L0^fdK&kYTMR2n9-& z34-$=s^FaOI2`)qBT;aeqqkbS(}po|GN8Y|gp}1ORSLU37z|)Cq3ce5{Z9KxTwUZa pN53|;sPfqyJ1>g(M63Tr`~`0e5lx=!z@`8I002ovPDHLkV1n}tIR5|u literal 0 HcmV?d00001 diff --git a/images/cut.png b/images/cut.png new file mode 100644 index 0000000000000000000000000000000000000000..3c21b9bd89a93c00a01294b31f22ea4141c792d0 GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+g!3HExhN-duDYhhUcNd2LAh=-f^2tCE&H|6f zVg?3oArNM~bhqvgP>{XE)7O>#GAj#{7}L9VcR=bMdb&7mhhEH%g7>!R&t^By@nXt2 zQ?txWVxH3~rLM(JON5vhJePi`_2@|Yrn+TOfvtGtEXV65GJWhnF1fG2eYj|ANcX=- zJvB3@WnO$Co!UE1KzqUmRu{GDE#FQoOO3j-Zu=VHHO4FUZWdrtkyd;rb3mg{YgO)? zg})Nt3w+;g`_yHcPFM2kxCf6vmxi4EGV9PrSsr$0me~vp4|-&G%=<0yqr14KZ)&%% ht?H5IF=x{EFor~0O%K}qbSu!a44$rjF6*2Ung9^Ui@X2; literal 0 HcmV?d00001 diff --git a/images/dc.png b/images/dc.png new file mode 100644 index 0000000000000000000000000000000000000000..2769a479b6d79c1054ea45e9cb423e7604806e8c GIT binary patch literal 1140 zcmV-)1dIELP)r2?(cQb|eZ4?@zWNh`LsRH`%@8;$yduis4c z2cwD6`VW|xG?*BFs?k`}A8MnR*iz+DYFmY6rLd*@fbIkKHM=`I_xe2>z{F_cNj`J# z+_~pFcg{U$1pPk~>&xu$TR;VH0iMr-5Qu{uP@wRD{eKw;vdA8A0Bi#iuuvGVC_irm zy!JA<0cA->#3R_kA}MtX_t!xh6c)hq?lv^s7!Ly{_+(>}iYktF z7B?L`t5U@!xw{{El{LSsW_PRA{oLst&Zg$Z#l*C}GUUrwacQwh~ zTMwt~vEG~~I7=oygzz%JI-Fnrk~#3Ij*Ac_jXg!K*0xNMt_i!M@`lT$ju%P>mWzK8 z)xu4EwF5-Di=<{F*?LCL4ye9_@8$>eqa22m1r0vP2Eb|Z0Xx4*sN7PsmDGl#bdZeS zu8QL?X2fjS72z&(Qo!<1D1DdO%6cfPbV^DovbI_Zr^a`f^N~r4t7&L(TKGWO4gsBo z@hS2(nT+1b-CJuYj*r@&dFNSeD*iRCm_Z5~D|D!8i0VrB(5huoET4y#E{dw#$e3Bk z;Uir z6OG`Dg+iw)j~sK?xDE)X<1t#3#WX(qDFyu3Ncy7m;qp%E8XTg0HY-Fj>G1gdey?f1 zh4?&Z2lFg^AG`@h0hf!J^80T`gTdpnqr)E8b+Kk?By25YK8TZX^G_9?PN;6A#f-(o zJ+D`N6$*_lOZh!w+W_ZyjfGbLpXwW+3P_SNnDBU}9*m9cOT}Uj$8OwE;R}~k`n#EY zekwj=WX$m`kx0{`&!>&}e39$9+!yN_OYr;;+3fRDjQ4^{unTa(^MUASpA38iDH5b< zUc7Vy_X(81LC}L%;}qTo3t+R&@odu^81V`7AB&4U1-PsD1slel$}L;cm#rUxP)&2s2(5Z)4dn3#M0000rArEY0$OWD%xZD%jt-I>{$@u5SwgoqD5`g@vl=J)-6 z=X=ha?}7j81ttB9o>E{vuoQRz6#fh0xxlt)G`jDTk9Xcbbl^v&?aHNGH2Tt6pbQWJ z8CdP}`99ma^_|v=ii*zx2OvC2^k^Uhjlk;7o8R2DVtG@|;zd#a>`0|sEo8Aw6IpiC z(?1;B@cJ8PeLi3Mtu323u35cm#^OcMKsucfc73(GfB%7l&9+PRS%G)=?)hfd;)VqQ zw@Y;7vI>GIAqpa*C?E(T76LidU|dm6pSMIP5Bmg362P)hRh_HXJJk2y|L{{_50C^* zY)b$sL!Xc(R7Xb1PLczr2$%xn$s~#K6rw|?r@L2t`0zfKC9<+v9Q+pBkcu&vQF@`7bq2$Sx)*xE*BVuYcG z8r!yQXF+{Ev**mgDf;N`@1(oCmleyFAv>LT{Q>8JpMMzzt^ql~5`jA4qq_Okuim(I z#}EV&%QP?z165TSPbwTccADnqX8e9HveSX=aIm1hp32Jkq|yTVSV#! zfDdp2I2s$Gd$(-f*f^0*yM~7ba4oDwQ}cjHAzz^HejmBKipNue!yzGwPAt>FFF6SX zr=lnx(y0_7zYlL|32WD^jGR2xvIH0gRPp8?9bJR*0jZGBbNhA&q9kKk7KTxzpsEN6 zl$Vt-7?0b_X5#nzaeLhO{a!LD695YVS$45>Nn>eU?YxbE7my^&qBk)zzG?QXnZb#P z9OdOx2?xFCnnt0Zp=kzVN`juA9z1S86%~~vl@zB=og|%&k;}SS+SEiS97YgD(uzV? zPp`YHtNRF$k$_Apm2r98B};<=uWSN!weu(xvJ{I&^kR|ZxXMI+gxhzn(RS@TfAw}U zo{ZCaxq}&1KKgnSl)4=pKlYpU)BeLs%b81UrfIeTiew*%?$NR2ibz#uRWg|r)~;Je zEz`+^$mm!BP-YeDUSCqeo9%KHS?M|G_lPOF#-3 zmjDaUbiMdMEfhACmxa8MNQ8jTgK4NZBqvU}1li?dO8GQGp%7+KqrLr>arw&i{Dq6x z9@N%Wc^A}Id1A5tPE9k<0uO-%kbZOyEMQnkWdfmqzo9G~a@N$$MU)))!_x=^!kDJU zy{j-5CczuDe(E|t!<=(^bxi}fe#>Sjk88meEpcklj?sv1Y_xX_;zFo3&> zk+G)ovcSw0E0>E!El*-7&hKYh^zXhukoxub`PQDk!6W&Cb_i$(27siln~BcOzTujh zNbS(jU^Jc9zXq~^^<=aPfD32}hl9I!?s$9d-Mg`T>-Em~Kz#TD&<2bGd3${oo5TfF z0keP_``tcZ1Tdb;ZYFcy3#TvjW(F zATR?6*d!^NIBSa*?Z5AlbJ@m}+4Bh-V?Iv+CS%-V0}b1OZa-Vk=@;w|lkKtg54}%; iM4q_$!g7TnZ3{T_&dvjw6Tdj$#2e_`Tgee zyUy70`1+}*r{^PCmOB_@>zy6#E3dxt@_9*$A2UsJn@m%Wn?L=;o=|?&`~iVeILK^(*H*ca+5%8XD$3 z9*-{)iF`|nPyBxWhrPYM%x1Ge*L6grQA8u#(A6}W>p0g+dzhKKhd|(A>b-NPo7F;& z-~Ve}`*SJ0v9J&dyMOfB*ASQ&alr?c2s@pMP3=_Uzlt>8v8Xts)GD zVIm$+AhfXtJtv{nqoKWl!)4dNjS?)Qh}-coNNu6nv4`WWCaP>2fA{h=%skkv zryjA6OBdhYy86u(8?+qbrV4JAP{?Jm5spAs((p7p(Aiakre-%Bj%sp1jvz7;yA$() z5W0-N(d5?n$#Y+(Vu@^vgNhy<8Sy_2VW@C9Oq}d)0?Zm@vROofX{_ZV zfZM{cZYSDWDf)62PH>(_GM%9e6fVixyW|aaamnU#O|SL7^v;Q6ZH!UGmPv3DQ9EuH zMT%&u;pl1v+Nw+>H*=W1ub}%x5EhSPW4(yvmW-jvCHNP&`v~b5-2s*3$AN*LEoL*h zXaWTAh*)$l9Esgd8NJY=qmkasQwD~yhGHQNIho;i?uDpK7!b@dn98yB+t|#!lHBE- zz}zfUgq%>sLc}wabwzTZ(^PQ8VoqqPM*Xl*C}{|8$x)i`-9xar*;6tDzR_usI>G-f zgK#7wJ$MGw5a#fDEJSx)C}fH#<~gKIbv~O41L#c3~P3#6NDlZ>67f& zTbwC!i=dTnwVs-oS7;QO1yg5O3Q9ub6D+X~!JNaG4J=JZCCL(X7ELSfm1t=O51|wU z9MpEE*U^mA!DM_joZ!@}>3wWvDh>{sZaf&DUN|MEmDa{uyTe;gBW0&TuoZKL zSjvf7Zv@MW^|(1QFByjQJ1J{O(&ceG0Mnj`Co|to2Uf4%99vW;=Y#E~l2+f{7+hxqnXqXEu`$<1eLiK^?NiaPtuR@`uPlR^TU-@Q(zg!<ZdP zC2r$$UJqQ=4w_#uJNXD_RNNZeKzJ*5gWlXGc}TMUG;o<-xx|aAF}xIvUm2QS^WU0$ zRJ|Taw>NoQ)tz29ySrM4!QnY8lg)ii_9GLnxVyTa%M7lDe+V0@wuLmL4WM%%0)lyH|UAZ=8=r8YSE2FinnBDn-Y~AEu_J zUOoqq0pJu3ti()5M#g$ZN5{It;Si(rH(Lk+pT9<&K65FUh=1$MWD+v~3frdQP+#8= z?d!XKvAWtrs;VUF@i19Ym@LaomKbGJqPTVYev_goX8|Z>fd2l0{Y_0#iBjT`Boa{+ zw#(;}S_1*4+3%O@s0^ujPn&)C$cY00yxV~lvxr8UYaPd>j^p|nqaCtL0*o;#%S?B; zlan2)am#T+p>Pm@yb~be@gJIDID%4e%d)7~>&p{DyoO@(&kD4aPGi$0h?2prU~1&{(9X?0P#IOr<#@tP2Ga3=}4qk z)&OYu6WqTQux0Z;?rGJtke2(PGL1YHC3RagPg P00000NkvXXu0mjf$~;YF literal 0 HcmV?d00001 diff --git a/images/locality.png b/images/locality.png new file mode 100644 index 0000000000000000000000000000000000000000..c80540b027830140c9638ac71fea175e604e4eb7 GIT binary patch literal 751 zcmVrK2$G&+uqi6(eYcU5)I!kZZ9DsC+J8oK-A$43>F0g0bi+4Pa7 z{=I=K=HT*zfq|#&*s+^|8C>38yc;kr$$OpmVuZ+RncIW8Yvn^B1L0-G7uUCBefb`-TS`kK>_gUS(QDTyJ`C{ zLdqP!pBTcC5lKW#jMko@s)!mU%G=RlybrWha`tXr$-=2Ct6n;h#)4Un207s4c~xTAaf3gq-2zzO2{2pB#0oTM=hd3zeodD?>?q?K_|cVOtnHE zJgnl13Wck1>e?g?o18Jkn0WoXimHJoG%D}LYM2;rB`_$;)!VTZx@p5o&fhVruVG?p zl8)}K8N>Tmb$(f~8jA^2;r-YP7IbtXBA5z(;%~NYT*Lj#|AQVo`;m`+KDo<~AozwS z%Q8|*NDx99u$YKRQSpQjFcHj*_PGVy`>}1f^Wrc0iM6#gve_)Es-Er7 zRi#iU5Cj3`a+$fgIo8+LMKl_v-EK2BHYTU1r^)4V)M_;h!$9e&0aojnzKBN6dWxon zNW^nAEFVn?x6dNvsYD!V^1d~TG* zg(ZIYrbjBRqt&dxxVF5)Yp$d57AwIjZ!rO1o zGyl;ozW!n#&$~-LZ_=MT!=Hx%2m2lFKWHOT2GX*tIITmB7}RRNp@n<`zfB^1hw77i z)c&ng+W3c+ui)rFLwn}I2bbUFt&11=d|`=e%QtXcNG0LYJMj7&{g|0S;zo=_q)8%{ zL8KB$tG>(ijd}FQ3Hd>R*ZG@H(4Y_-<;nUk}T!+JlAc`Z%3m0BxU{I&! zRH-+P87{^+K4}qGz;>Z0VCd}2G^`?@e7p+H)@>qDq|t}WXOO0WGQXV1u@iA*ZU k(E((C92r8FrSI?XAF!ZPCmODjAOHXW07*qoM6N<$f<38|-2eap literal 0 HcmV?d00001 diff --git a/images/mail.png b/images/mail.png new file mode 100644 index 0000000000000000000000000000000000000000..bd77affeb51061919eb5586fb6a0e58382678a0c GIT binary patch literal 899 zcmV-}1AP36P)T0}x3> zK~#90g_PS$BUu!NzpC1asjApY3MVE+8H^GGf*=ax6srE`v7b0fB)-XY;JD;QLR=#d!C1BnrN*_@a_J4 zXsu^#Fc@%mcXxh!d;6P|@#6CX)$q9Ag*;p69W#vBB!ubU=WN&W| zAq11jgj6cU!omWUWf4UY0Jd%8I1cG_no_BR)|ytUMY&v_sd*u#q}goZ`#xJ+Thr`^ zVK@zz$z)JUp|!>|&8gl(2y(d`qtS@d(^H+AG-J(N;Yy+@-F zQp)LF9LG}~lO$P|g=v~Jn@wu9+9Zmi5ugmmaeiN1T>RCx?X=d~{BSgqq$W(iA3jO* zd_16oAfVsxKPaXC1a1uAXW%Db9!ULgQ2aj>Fao{+UyP4{E-(iq6>j{y?+>9rOaen- Z^f!rg&agD@m!kjx002ovPDHLkV1liGn!x}7 literal 0 HcmV?d00001 diff --git a/images/minus.png b/images/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..6ff906688af9463498977a826b9baa9f7557d86d GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4^3?%3Nf7cA+1o(uwUbyq1uDc(|YY$R;1f)bf rT^vIyZY6W@mL@o~#c2opbf{#=Il{)C>3VS!P@cil)z4*}Q$iB}d>0za literal 0 HcmV?d00001 diff --git a/images/move.png b/images/move.png new file mode 100644 index 0000000000000000000000000000000000000000..9542d5161f4fef66dcd46b49452c382f8c5cbd13 GIT binary patch literal 483 zcmV<90UZ8`P)=4TLHZ&p-oKrThFZNQjs=G~@rjbXVZ$&C z_yZrU=a%Lgo7wZc0BFCok+Cysoruk>JTZj?uS%;p+*uOa^lv!1m<07L?4?q`!g3HZ z^0tTlp}b{!vuIS^qTGQg*NWC);jGMc-5>DPq+vBn`@3rzC~FVXzroQH2d}L#C;~|R z`RB=W0%1z;ooyW7`?z^%BX^Wj+rcOkixR`ePbs@;s4}T=UI<>9BInga8+luVs&yaE znFG@_kzP+j^f@f~Nch9oN)>F48RQf^1%l!ZV002ovPDHLkV1kMU$^`%b literal 0 HcmV?d00001 diff --git a/images/o.png b/images/o.png new file mode 100644 index 0000000000000000000000000000000000000000..dfb89eb506b1b236e7f91e1351368a88278dae5b GIT binary patch literal 1305 zcmV+!1?KvRP)RxWJLW5g}9|p#tJk zpsGZrwu#!bv`u2yj$iwjotd2n2U^r3zW3kf_#^mF8@)~J?d*_Ve~T)W2XV^F=i~Fx z8sjm>lmX!}7wK%i(67!;tPu&|?7w^VHnz6W!%`*mwl_EH8@*n?TCE;9LJv*`<88@B zDe%4NjLV~=XQ%h3seMHJ@C+(T;fRGb?}8s39H7-&4ce=#TbD0g{;a>V^TqP=^7U%1 zQ5!CDFNry!dFt*SK9@&hoT4ay@yp5gjN-RkBqJlahO_^Gg|G}un7`Uxzi{>H`(JNg zyz*tM+uP0I7lu5?Oaqb@u$U+0ctT4tY3|T4ZPl8(uTy^|K0m!>WHtm~7ywjO+O)FT zYd6+*zi995e-(DN`Y|o|QJTYA56wma^9ArIF-SGgs8>mqb!#H>ZoGOasiX54p7;TV zFTB=9AKMrAOS_k^ezJSz;G53o&VFOL9@NSO)XP3rssTF7Aw;ghbAti{0;f>)9hiq; zI!_ydb6718Ve&D%cKsUJ*xGIM_b%OB?X2x5ngz2&p;IqlDP$-x55`&)0w1mAGG4qK z;P}}9DNg~LAt;5_LaBUHr|h-{p0MU>n>L%R&U&}|VY~ZYZIWojsYK{GFcjbw2@cO< z{QBn$m@Gw{X2^4e@n`~@XDAgcDTQHMF#jV>aGPo42p6)&rP`(*qgG2~nZm+p_)6ks zX7JPDIqn|~kd9Ab`8gDiL9_s0Od*_vGcqt*@4>kSgS8|Rvhr${*8Ou1og2VfB;26k z2hheKP6g69!RTy=JRX8Li6R5EuMth>(77QdS9RxXh0W)4_@%Oj)yg@CFkoN-!STx( z0-s`Qt&Y!`kA8#Uju+wKgBc_jU``j zU#!%Nf#+dwy#`7N)*A&BsKX+PFpnZo;?QnZ;HnNm;K6tkETUNor;h+PV}Ct8b}lH5 z8lAN}-CqC3R&{CHXFfgHZKKEl3X4S);qHScc<}f+gh-GrViY|KpLwuW<*?Zk*!(`6 zoq4&GP)ce-J*_P1u%NWrs8xzS1tBotoMSedA&nyFJcAS|M&~n}497S<8=2|g^h_qx zTh53d0Xy&jKnd>RC`r>yD(BJGQmxXe6oW$OQ)0D*$}&)=5ikcr91!@3d8#MF!ALB| zKifR{4laKPAoTzM&OvLLJ8LFN@|jZ7H#)CbtwJs&5lWF%WQcj@=1Jm);}Ji3di-=g zd~w^z=v!EI55N?FA#eX7WdSYMYPD8p?dp1O>(kzP_v2!@e1SOE%7pNvIOXS)$#8IX zb~HLU{ev&2zdNIj05=7Y190zvuOr0si?x+zW4Y1T3`$`S&bIPgl|-gQ#?vuRq8BRT zr_SgJfDC{E-~izNz}G6JEC`s#eBU`6IBPv?t+U4D)*1!pasc)X^rpW7(S*2YTA$q9 P00000NkvXXu0mjfsIg_f literal 0 HcmV?d00001 diff --git a/images/object.png b/images/object.png new file mode 100644 index 0000000000000000000000000000000000000000..a77ff35caa86aad7478b687bce3b450ef8ca9352 GIT binary patch literal 1297 zcmV+s1@8KZP)ZHQ(#!7&q(=@Mp^Y|DO`C7S)%lEvYS znalp|$ChPTNVb{q0~3?Qh%z@B5V zYM7?nBeb2!IjL*9m7-m)hVFcMgraip*1YT;OQBHTjL)ZWzA*#6#;mxw*qoSXInmg7 z@zIF?nlUMn=0VNuLxI7MfQ5t-r+b^5=`p=A^St zO<%oNU;nPfWU{l7i3t9@c^%c28YDe!T~t2Z3B#NMoVaL2hIJP^SYBZ&u-j|hUT=*p zGxNqnzu&*cEXsz|<}+t5H|(s=lQl<44+-f z!Typ1sL0ADp)lsOScDg1v7D=JcPyxBy8M=FA{k^mZuB`>AfTY4LV?k!VeX-f($Xr7 zzxX*09c#jejeo=MVHge7;P}zEVVw)W8jXT4E@JS~WdsNAFvC+dURH&k;_#4+nP~}C z)d~b*1}!aD;J$qqM$1b$)e=Lk(~LLE(vYI4$f~Z!)Wvq(YHfu|*(Xq#PalX4atj1R zbp2*RXZMd7_fEiINQBw!Bu6sx>~`eYY?yVsalf}0_b#--5RSk|q$*`kZAhken5Yhm zdYxAt=^bB@ODx7PKOcoC$`Az!2?=(Hk`X&xt`+%`Ce=Uya)io81Z$D0KmmOoCcHv0 z3&G(1;M7#VMi&BcuaGk$6h#9GQGlkYoJS*?RhHMQs7LbzDfiI#9I!;YZ8WVVREptn zu=}q&?UEpf6`JbW7Hi~zkvNMghlLce~yEvag_%j4;~IXyF6=5!Wh%=jjl$I}tIH~PypMG1D0 z&5S=3YVVntm=gsdKZmZTq49D49r)Dmz&Se9!(uFpYTw?e`g)XfeDL$?n_k4U{CwiUm_U-$T(p!& zNGJ3VW(g||pglB_s2_UY^ff)}1wxpxsi8YvRn4aCHyHg3Jt4T5K1yO300000NkvXX Hu0mjfxy5A^ literal 0 HcmV?d00001 diff --git a/images/ou.png b/images/ou.png new file mode 100644 index 0000000000000000000000000000000000000000..3e767c7cebd18c77a3e8b98b3c5cded70444d3f5 GIT binary patch literal 1330 zcmV-21DN3OWEw!cV%(OGp>D-yQ+vktoLd8gYlaqWmH{W;8 zdCz-Z_;1KSSPd4u6Pgt2y{jy!t3fpZJOtzeE zR%CB~=fEo9FDJx=_}`F#1(U;NV%x?CMcv8;B2-ZCw4KBvkMj8O&1x8^aJ4Yx>>Pg1|RROM^*g@1QHTPCV@WE z&%wjLCf{#}?9g%?12Rq$dz>rj`OWpxdv9*%n?tWtou8u6duvAPRxV=u)63}U=tR%i z7&!^kFhSS=Jht5LD-TK!00F?~&@GLtMXsqVDH=&>i>k^)p~vf&Q&nC}cVCpjSb}Yv z))FWP(9)6M!k>fGhG*e&xk03`jZxwQU83RSNKaDZEMPie-K^Z}aTk__iqw3+m)!@y zVBwsp?0I<$TQ{tsQ1!ET?ksLZEUGGMIosI9*TG0YfkLP9JV3rF zq4H3$YR)}1m1UtKwys}8k(!U+>mifVIq=C*)^6EFP|c@q(Jbc8oJ`$)bCKmBXa0zD zu3gecG};_lx*6Lad0dK8MQMO zZ*9NO)f*ugD7ZQ7uAT^n-4d;p#lRH>9Q$`-2@E}w@06DFIqCh^q12IlF9Y-x2o!u8FOO_@e3TS|?*uz7`u6T5_ zXRw>a2qyKmBZhksKwUb`{HX>Xc4)+Epek(RE9@Xz{ABt}40 zr=z+Y(FxoR_u27*Mq95o@3I9aB&3Wf1eOqtST;kx0CH*Nm{Bm6G-rSzz>+{W!Rsx> z5)zV(jzk0)0CE6w)vE_=MN3^OcDr7YB=MOA2~&U&fZ|5DePd@F^(td>$eEy9UMdJv#unm9pkA^qOw+jOp}IX*wJjW1azWP2oRcN# zQwli74LX^CfB5;_Q$4+n_fPsJ$}mwW&K0{cls zK~#90MUc&I97Pm`zpDP3nV!kac))*=42s4fN*34)oIn(TH@pTbHtg~W?0F6rY!R!x z01^rth-1kSLfFatxINvTo}TLJs_J6l7_M|T_vq@J^9gQ7Jo)^K;r@91;PmwL>qVB` z^}Z2t9AAHO|Ne`U)6q34<9~ye)Rb0n=ijQ9y#ZP5CUthU#*tk z#qIXbl~O;vd;9iJzyt>e2i=3i!*8EHd-i-|^x;rzEw;8c+1MB&Wgv`eTKnVi*jX1( zr;|UFQrE%p@$u%z_wIc^9`D~N`KonYQr4S;HqmZ4=5xs80?#?Dk zRWvr_v%^PJbV#~M7)4PB2tx0@5CQ@zi9|>%j;QMzr4$HHyWIlcqShLYSW#sL8)(AFv0Q4(Qjzpq;JH~K zEZ1w{nugw;K9$x)0n}b%oj}`$xH~{;gE5AxQa4Y|I$tactTF8F-o@4>8>0`1<2Gp= z5yV|4lL^z=3}Y<-(l;JmY2HmHESJ}WQJeL;=ISaVj60NN$#gnpSuAOq=Elk6g|0PO zo+A(x#fpBvPaq{#rKz++DTTH6|4st$z4usasg0&s6;xG45Ckl;j8+^|mL=Xb|B(or z#tUaHc+X%kU|p{1CLMwxK#u($hkJ2=yX*{Z`2*ZHYszg_c zvMjOII%7-&ATQIjDpsr4LO_xvbd!Wu9FcT7wBndvuZ#Dd*=#nsoX=Chg?YBf(#y-A zUcUVOqn(}YLA%`+08&cox~4XUlUJ|QY&QK>YkdaP;raRb3ivV4GZ#hCQ}2D>gM1$! z=bT<#U7gM6^Iw27z>4>p1p2@hkN~%L00$I63Y0+eFX~95*JqCT+yDRo07*qoM6N<$ Ef(E3R;s5{u literal 0 HcmV?d00001 diff --git a/images/photo.png b/images/photo.png new file mode 100644 index 0000000000000000000000000000000000000000..f9574048bee0d664b73ee2cc800474bed183e759 GIT binary patch literal 572 zcmV-C0>k}@P)!DUf6tbscxxEkU^_yD|v%N?&K#CRt$@nO7ZLW16m zxP+KxTv%pydV0F5+JoQy%RYa6KiRJ~pH9lW0*nATL-L(S9Ga%Nzh5pE3#h7U@8!Ny z%6l&<4HTKh7^9TRvTSGP`DipkP??CFpMSWz`k}IDUFkz`b}fd^dq15{$Kx^lA4K$U z{}_q4wqG0_9g%S8`);*DojHq`sZl+)K#Cwm3B9fG#(P%9)(?B6F++AJQf9K(LrBn*OFAK+!lrS)pwN`6QL|SW3 zsjh2dH2^TPwKgdR4LRz{U{)4Sx;D)J+`KzGJ2`o?>XyEX8ImN8k_k!7v>JvXGF@JN zpU;;7W#1){fti&e)CTh0Hcc~|&7N&-`Yv2te45?-^q!MS8VqQKM8ruZdy`kkwpw!{ z^7Y#nYvJ(lKq)B8atMMc>D-m4r*DaJV-;Eqt3J{yh15RA#^24Z=a4DweK3ec;SfP_ zaHX}VHIj8YrNo@DZQFW&ho-S+ouwC{q34w15d89?@8e_Jw*LUW78*~2H{1CD0000< KMNUMnLSTZjEB@vH literal 0 HcmV?d00001 diff --git a/images/plus.png b/images/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..f66b1a80934c34bf818efa50824d96bc138f8e04 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4^3?%3Nf7cA+1o(uwUbyq1uDc(|YY$R;1f(Q9 vT^vIyZY6W@mL@P9X5;u4)tJz%5Fp1e;Rpx2`?oLpKs5}Wu6{1-oD!M<GzA9e2YRW7ghxrDu zu(!FQSRJvP2VNPHQ_H<$YEpM+M>KG9N6sP8NCX$Fk*y;N@%~BN)_xPv48*7-mR!KL z$&gZBcK>nGqx)qw*yyNnFm5YE)3)mFfC!0Fz$(~TZ`M&$qXFyZ$`|e2R^rEDp zZvj4-o%EWWn1=@GtSWVR?1Lph1EBmGB?MRotN_9RZ7@8SjD;m4YK=hvbwDkU39JO> z^V_Y+!A6?kTLQwO))-2|!XpHb7!*d%iuard<7b?g^Pd+g1%J_AcY%qJWzCi P00000NkvXXu0mjfRzhEt literal 0 HcmV?d00001 diff --git a/images/save.png b/images/save.png new file mode 100644 index 0000000000000000000000000000000000000000..a7811a44fec7051d9c4e797fdc6a7cfb806e606f GIT binary patch literal 658 zcmV;D0&V??P)O(Ei9UoiK zTc;9b3QfR;IZ{gXCioVhzE;PBI~DLl22vETNf~0K)+$hvavo#$`YjVd#x8u=!cQEywyMlD{FPEEuE}Pxbm1GTR^$=*wRW<4lxa zRV^%2i%gLtQ1Q%IG2FApi)tD=NfAaNJkLXYtB-nZ5&a>_@Hlh4lN*({J7K`H4;xr~ zvZ2A8bI@}X(ICRRJqFj7otKVdf&?c;Q=ZF&fL?HA!=%P4R-FP+G@Yy|G(n@;knT^y zu9Pdfki}A(??|eTWLf{nUolwnMHQwlO^vJfR}q6CunhR=@{Ck-bap#B4X5N_QWEfk s0O4188=p)+6w>DmMWSQ+he(yph*Sa;x_0SXT zUqJ1>y;LoiN+5wyMb(N>mVhB7b<^0f<7M`(&o|VTgP{_i^y*t?=6SyNd6(hn^#_kn zA}~=91X2ox0!+f%?e2B9Yme4Dqmbh0=6}{nJbM?$iJ~YKOQo5`6DO2RCd2cBu#m}S zQ@W;Gf3Ds68U$BHab8JqVr6BuP%K`~DTRtpKBXtJUN&DKpCit(U9R8P$aWmEU6-V2 zoF>a<`u(@t9|Qbbm^UDKB|))RoR3fB4_Vjhk^_6bcS#flG7Xa_ zj^iV;d>UA(0p3d`$|=fQx#DDI&vHpHEz%8>4Bf;n9kLu7H-|wY&-Fm)ksOw&+w1w3 zX>x)jDAyO1Kt7^Ecw7)axTKoodlmuAEcdyccwF-9;mJ3FJ~3sa_;A`Lh0 zsYW0TaEP~vECk$#fs;JUsYH~ba)f%lULd2cst-Z1J0KY&NFI%1vD2Wftu1Qo>`=4W90pUAB$8#>mm?8x>&X*a@Aduw<`Gy67I-m60Kk*F zY0lXQmQpNIKA$HvHCkR;Btev@)9q5Hvloyd_o=zl;I`{^A(2Q3s-~{0eKq3S_NO4& zf{lB?s#eM6ptV5`3Mvu_Q+8tFxfIZu?L{$5$z(FfnvIPOq^uL9Y+u)@-&Yy#aEyAu zADf@gCsQe@TrT^$T#jSe;`^*x{UH4u7u^%2EFGJTCaphwK#w1;!!r@Z77l`pBJqdl zSPTgc9zMMI_Nh~!LH|ijRsC%MNs`2|mJpR?f^|$pIp3nd46F*VYg#f==J-7>4qKzSjCK97I+Yi#b|zMiF%z5;?W7@ zyMO;)A5#5C>l~L^7e2N+pWGWmZVcm{d%LcB>soRYLHg zAI^lJ_ps;d4<7sg!Y`1jfBlCYOlVd62i%=|b9VN^d#kJGs@3YzLaC(Sjqp~z9%x^! zRH%VeZMAl3x7DKB;~K54t-0%W?|$yu_BZ>{Mq)5{fZN=?fA8KS%-`WRc=SN|z}Z+V z{=wnu^wH`YM}ps^fZ}2;yn#SJ+uZc)o14F)FMU727@fyF7=8G{dhXc5!iCdk&YUez zP0gVdDK~E3q+hOHy<+M5mmt`9;r(FyIt1*4aAkU0DNRn!MPjitwOVcBS*`XJIxGX< e-$ny?qJIJ6eZ8O%c*~gp0000_YP)`C>4?IXf6hSeiXrVT#6+*NTNhgYh zf{ivRYL!OBqYymM7?%X&6%E8S8#eCd-|N5s@3Y9Ek&SOL%{$M`Ff+h^ z=~Li_2d3z#jrSp_cB&-d6$abu!k+IP*TTvkH7Hq<;R8V}6XVVBrVl}SV2sejiYYhu zv{g^+{rNXcV|Ut8OBJiHQ4>cQ2PY^JBmfx_Bmg1^C01eat^J5?xr$_0g&8d)06+kc zx!1lviQMIw;qN9U07;ONKupf1KoS8g0vL%&n0L_s@4mZw2d-r2v2!IsF%%RYFKtMUyGeDJG=m>QPP(u-`qd7pn@`9 zN!5H`Ua5*Od!*-CFlTH&@w)oz)~;)?5k^$!LIAB*c+(6(IR7MdzHWgAZl)W!DEC@{ i?$|PZao_1j^YCwW_X9iEQV`7m000032-t&mbu=9tKQfP!V#iL=o&XO^5_qYdH)9K6ru; z1o4EZG_GZRv}Uzf5^pyFNGZ|u2PQvJbHu7DF(z_~Y`1?ijw7WMOxv)!v%)${R3&Oe zM4&N<22A6q7?KJ;cx(uPAVN%$>+5S)s};^UR?7u#+tPI%(K)0Qj4`B?aGj%R8XD7} zs;KA;q$&g-7{?J~4BcWeTcByEwPLL$+f36m7-OJ9tze8nL{Js1A1A!`q@4Nst8aL9 z^NP)8gQ`$Vq1M?~r4(X}#2CprQ%a`Pj7BAh&`iUC_nunemnTnHE>}Ey_=xq8m?1UnoCLJ&li^Ye3dyB$A2e$36yOU};DI6gjRzu$9t zc}d^*jN`~OO{gj*XHtr&Ds~tLBm_i+i;D|VN?2<#rsBQFImbATY`0rtj5CM`UJ@}S zQq05{v11V4d3VkIdmn+B#Vw^^N+FLEnhQB+j$B7+9qVpM$_mv`KX{L>b6^a17zRXy z_uqc&R@50N)|p9F$vKnroVAjnR7cl2j4|x{E!2uV91a|Y0V;r@mO?J&zu}xSDQC*- zz7%Rns79u7!Z}Nf8S~~Fcli9XPdPdLusY{hE>|qNj?OLSY{mJ7L{&s}HlY50wX3V= d=Gn6={so}?UiTi4LoWaT002ovPDHLkV1nwJbo~GT literal 0 HcmV?d00001 diff --git a/images/trash.png b/images/trash.png new file mode 100644 index 0000000000000000000000000000000000000000..d88ddbb1777a0eb32967518df5ddb02c3e28ce93 GIT binary patch literal 678 zcmV;X0$KfuP)8WMLequ_ndpVhjTL=fyfF|o-bny zo1~YZwI=)=0%VSIM=*eS@_5ngb-$UtUtQDf{xF}K@6E!kiW&7s zKwcIQr);V>uCns7v1El`LS)`UWF?SNns*6`B@!K@b%)NbMmi1%L8>*a;k}FlOZiEg z%cb+!6E3zT$W7!ZoR;J#rsL+ijFnW_YUFL2w?%1 zAa2JQ3&70^79ZZ@`HN**N|E*wuxz582nHYo1jQ0*s!4PL9GEo~}~gT23M>{xy* zfh`2S?}HFHjtiDJMjHwTpp^Po6c3Q}(!YiM0W?20S$@5O+E6e!B$LH z^f0UYcN&1ol`_?v*U-BO%{4_3__SJzH03{EG8|w;R+v%EA73%TZvimbGjNT37XSbN M07*qoM6N<$f;&MVQ2+n{ literal 0 HcmV?d00001 diff --git a/images/uid.png b/images/uid.png new file mode 100644 index 0000000000000000000000000000000000000000..7be48fb8cd09d6adfc48954e1907f38d3bb0c3b1 GIT binary patch literal 654 zcmV;90&)F`P)jL%;Pn)6~ zp+z7;99L)q8&6i(@;pDhvS!nc7x4PcUW2hXn?r(7S4e~~4wNS)&tLR1=iDr~xz%s_ zpCYEMNeNI9QX-`U1SCOHp6#ty*-X@(cLimD^%ZdQkQYW-ZbURRu<80K^-R;In0T@uAMdL%H@{m-*2~J%XyJ%VN zE@#($GnW&I^uH7h;s`cp6e}0&OCWbNaqnkKr2DFgq@H3 zGts7?ud1dvE>`|~(zIvbA{ONS6{SQaYpg6)B3o60TPim(N oN=PK6hSf)_xH~Spv5tS$Z>|sW3LxX?DF6Tf07*qoM6N<$f^GL0UH||9 literal 0 HcmV?d00001 diff --git a/images/up.png b/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..865ec1551b0b7e030fe25b5ddd76dbb4584f33e3 GIT binary patch literal 382 zcmeAS@N?(olHy`uVBq!ia0vp@K+MI#1|;*}T{!}z*pj^6T^Rm@;DWu&Cj&(|3p^r= z85p>QK$!8;-MT+OLG}_)Usv|a?4k@xdf)zj0m?ISd%8G=RLrTJXz11KDA2n9E{llr zqPYv2S`!4dxi@awBFMj>^#SLR%@qvVABDC}%UbHOfhTF9!bO$e|2OYGpR`y}tn$OD z{Cj6?+$YYMlH4VuP@V6*n01}!^3R^t&oi}x7xe39=sftt;}tJZeS&R;oRTp|o0H4o zGk4++F;7r_63`G+{M~@z>87nm{w8a&KM{J$IECqm+!49(>-lfql`Fb>a0Wg5sk%6Z z?T=S!dF0pEtMv4znN*#ce?5H8IX^Me9l5LOAG5BAT*0-cu;zv0HVfPL!KKdv=LYx) z>^rI0Jaq}v%&GG&j$dp{FU}Ra$+4o2-8;Lr;ae?SlX0o?d^xWXUM zbK66O5SJ=ZLM5VBDoxs$lGyR$c)c?_!@+iB5Pi~DPkQq{@6EiKfq$CVDJubp}{;aS!@;H zD)60A;^vJjMrN@hjs#N&S2D%rrly@KMrF`G5P*lksh-0tQqZ}zVf?qBWgsM_3;Z?q zTw0ODT0rpp@bk#;zOFhxumZ4v34R|Fyjy^ax^EtLUgxwA@*XtbLWe8AcogqY1V03m>f zc2klX(OArC0T+qprNm!%*5Rd~_Dc^yg7*Q5C(*nFie>nCI0;V&u3@q7>w&MoP?*q@$#8Zc8~1iy}m8Vs^(zec(h+qInSg0l7oSxtZMf9w%9$g zkAai(&e}w`L)uz<(l_Jog|kdkQ#sGuV&+dLHOCXdlm3NqNbQ<-!`seQzlz@7FCPM2 zZ08?H-Ds~4clBEF8~aCR7zMV58yhL7s~=LdK6c(s`zQUw-vRXJ_rCc8AYHx4WNP{I zAg4I$;@uv{Zx3l+&MB^aM7nX4>znWEq+#;2;v@&q&Gr2JZzRgIe)T=L)aI*uU!$rK zb(FF9#}J~FBwa-+Npn2`Ku^l)3>6X~1UiZ-t)-oJx!c>~m!0QqzZw%qF}AJ=&Jn`w z9%WTos>)*ROd)urHf%q8K^-L9&t4$4Aq0P(vta%KGq5k;G0U|e00000NkvXXu0mjf D-(YCl literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..008a941 --- /dev/null +++ b/index.php @@ -0,0 +1,161 @@ + + + + + + + + + phpLDAPAdmin - <?php echo pla_version(); ?> + + + + +

Configure phpLDAPAdmin

+
+
+
+You need to configure phpLDAPAdmin. Edit the file 'config.php' to do so.
+
+An example config file is provided in 'config.php.example' + +
+ + + +\n"; + +?> + + + +phpLDAPAdmin - <?php echo pla_version(); ?> + + + + + + + + + + + + + + + + + phpLDAPAdmin Config File Error + + + + +

Config file error

+

Syntax error on line

+ +
+ Looks like your config file has a syntax error on line . + Here is a snippet around that line +
+
+
+ + "; + if( $i < 0 ) + continue; + echo "" . ($i+1) . ": " . htmlspecialchars($file[ $i ]) . "
"; + if( $i+1 == $line_num ) + echo "
"; + } + ?> + + +
+ Hint: Sometimes these errors are caused by lines preceding the line reported. + + + + $server ) + if( $server['host'] ) + $count++; + 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."; + return false; + } + + return true; +} + +?> diff --git a/ldap_error_codes.txt b/ldap_error_codes.txt new file mode 100644 index 0000000..4cec107 --- /dev/null +++ b/ldap_error_codes.txt @@ -0,0 +1,85 @@ +0x00 LDAP_SUCCESS "The operation completed successfully." +0x01 LDAP_OPERATIONS_ERROR "An operations error occurred." +0x02 LDAP_PROTOCOL_ERROR "A protocol violation was detected." +0x03 LDAP_TIMELIMIT_EXCEEDED "The operation timed out waiting to complete." +0x04 LDAP_SIZELIMIT_EXCEEDED "The LDAP sever refused to serve such a large result set." +0x05 LDAP_COMPARE_FALSE "A compare operation returned false." +0x06 LDAP_COMPARE_TRUE "A compare operation returned true." +0x07 LDAP_AUTH_METHOD_NOT_SUPPORTED "The authentication method you specified is not supported by + the LDAP server." +0x08 LDAP_STRONG_AUTH_REQUIRED "This LDAP server requires strong (encrypted) authentication, + not clear text." +0x09 LDAP_PARTIAL_RESULTS "The result set received is a partial result set." +0x0a LDAP_REFERRAL "" +0x0b LDAP_ADMINLIMIT_EXCEEDED "" +0x0c LDAP_UNAVAILABLE_CRITICAL_EXTENSION "" +0x0d LDAP_CONFIDENTIALITY_REQUIRED "" +0x0e LDAP_SASL_BIND_INPROGRESS "" +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 + 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)." +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 + specified already exists in the entry" +0x15 LDAP_INVALID_SYNTAX "An invalid attribute value was specified." +0x20 LDAP_NO_SUCH_OBJECT "That object does not exist." +0x21 LDAP_ALIAS_PROBLEM "An alias in the directory points to a + non-existent entry." +0x22 LDAP_INVALID_DN_SYNTAX "You used an invalid syntax in the specified DN." +0x23 LDAP_IS_LEAF "The object specified is a leaf" +0x24 LDAP_ALIAS_DEREF_PROBLEM "A problem was encountereed when + dereferencing an alias" +0x30 LDAP_INAPPROPRIATE_AUTH "Inappropriate authentication was + specifiedi (e.g., LDAP_AUTH_SIMPLE was + specified and the entry does not have + a userPassword attribute)." +0x31 LDAP_INVALID_CREDENTIALS "Incorrect login DN and/or password." +0x32 LDAP_INSUFFICIENT_ACCESS "You do not have sufficient permissions + to perform that operation." +0x33 LDAP_BUSY "The LDAP server is busy." +0x34 LDAP_UNAVAILABLE "The LDAP server is unavailable." +0x35 LDAP_UNWILLING_TO_PERFORM "The LDAP server refused to perform the operation." +0x36 LDAP_LOOP_DETECT "A loop was detected." +0x3C LDAP_SORT_CONTROL_MISSING "" +0x3D LDAP_INDEX_RANGE_ERROR "" +0x40 LDAP_NAMING_VIOLATION "A naming violation occurred." +0x41 LDAP_OBJECT_CLASS_VIOLATION "You tried to perform an operation that would cause an undefined attribute + 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)." +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 + on top of an existing one)" +0x45 LDAP_NO_OBJECT_CLASS_MODS "ObjectClass modifications are not + allolwed." +0x46 LDAP_RESULTS_TOO_LARGE "" +0x47 LDAP_AFFECTS_MULTIPLE_DSAS "" +0x50 LDAP_OTHER "" +0x51 LDAP_SERVER_DOWN "The LDAP server is down." +0x52 LDAP_LOCAL_ERROR "" +0x53 LDAP_ENCODING_ERROR "" +0x54 LDAP_DECODING_ERROR "" +0x55 LDAP_TIMEOUT "" +0x56 LDAP_AUTH_UNKNOWN "" +0x57 LDAP_FILTER_ERROR "The LDAP search filter specified is inavlid." +0x58 LDAP_USER_CANCELLED "The user cancelled the LDAP operation." +0x59 LDAP_PARAM_ERROR "An ldap routine was called with a bad + parameter." +0x5a LDAP_NO_MEMORY "An memory allocation (e.g., malloc(3) + or other dynamic memory allocator) + call failed in an ldap library rou- + tine." +0x5b LDAP_CONNECT_ERROR "" +0x5c LDAP_NOT_SUPPORTED "The requested operation is not supported by the LDAP server." +0x5d LDAP_CONTROL_NOT_FOUND "" +0x5e LDAP_NO_RESULTS_RETURNED "The search came back empty." +0x5f LDAP_MORE_RESULTS_TO_RETURN "The LDAP server has more results that it would like to return." +0x60 LDAP_CLIENT_LOOP "" +0x61 LDAP_REFERRAL_LIMIT_EXCEEDED "This means that a search was performed that required the LDAP + server to follow a chain of referrals that was too lengthy." diff --git a/ldif_export.php b/ldif_export.php new file mode 100644 index 0000000..6c30fdc --- /dev/null +++ b/ldif_export.php @@ -0,0 +1,93 @@ +"; +//print_r( $objects ); +//exit; + +$rdn = get_rdn( $dn ); + +switch( $format ) { + case 'win': $br = "\r\n"; break; + case 'mac': $br = "\r"; break; + case 'unix': + default: $br = "\n"; break; +} + +if( ! $objects ) + pla_error( "Search on dn (" . htmlspecialchars($dn) . ") came back empty" ); + +header( "Content-type: text/plain" ); +header( "Content-disposition: attachment; filename=\"$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 $br; + +foreach( $objects as $dn => $attrs ) +{ + unset( $attrs['dn'] ); + unset( $attrs['count'] ); + + if( is_safe_ascii( $dn ) ) + echo "dn: $dn$br"; + else + echo "dn:: " . base64_encode( $dn ) . $br; + + foreach( $attrs as $attr => $val ) { + if( is_array( $val ) ) { + foreach( $val as $v ) { + if( is_safe_ascii( $v ) ) { + echo "$attr: $v$br"; + } else { + echo "$attr:: " . base64_encode( $v ) . $br; + } + } + } else { + $v = $val; + if( is_safe_ascii( $v ) ) { + echo "$attr: $v$br"; + } else { + echo "$attr:: " . base64_encode( $v ) . $br; + } + } + } + echo $br; +} + +function is_safe_ascii( $str ) +{ + for( $i=0; $i 127 ) + return false; + return true; +} diff --git a/login.php b/login.php new file mode 100644 index 0000000..2c80ae0 --- /dev/null +++ b/login.php @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + Redirecting... Click here if nothing happens.
+ + + +
+
+
+ Logged in to
+ + (anonymous bind) + +
+
+
+ Click here to go to the search form. +
+ + + + + + diff --git a/login_form.php b/login_form.php new file mode 100644 index 0000000..e09eec6 --- /dev/null +++ b/login_form.php @@ -0,0 +1,79 @@ + + + + + + + +
+

Authenticate to server

+
+ + + +Warning: this is an insecure (non-SSL) connection!
+ SSL is recommended when transmitting sensitive passwords.
+
+ + + +
+ +
+ + + + +
+ + + + + + + + + + + + + + + + + + + +
diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..86f0fc7 --- /dev/null +++ b/logout.php @@ -0,0 +1,54 @@ + + + + + + + + + + +
+
+
+ Logged out successfully from
+
+ + + + diff --git a/new_attr.php b/new_attr.php new file mode 100644 index 0000000..f9d36fb --- /dev/null +++ b/new_attr.php @@ -0,0 +1,46 @@ + $val ); +$result = @ldap_mod_add( $ds, $dn, $new_entry ); + +if( $result ) + header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&updated_attr=$encoded_attr" ); +else + pla_error( "Failed to add the attribute.", ldap_error( $ds ) , ldap_errno( $ds ) ); diff --git a/new_jpeg_photo_form.php b/new_jpeg_photo_form.php new file mode 100644 index 0000000..a97598f --- /dev/null +++ b/new_jpeg_photo_form.php @@ -0,0 +1,46 @@ + + + + +

Add a jpegPhoto to

+

Server2:     Distinguished Name: +

+ + +Select a jpeg file:
+
+ +
+ + + +
+
+ +
+ + + + diff --git a/rdelete.php b/rdelete.php new file mode 100644 index 0000000..6e78aa0 --- /dev/null +++ b/rdelete.php @@ -0,0 +1,113 @@ +\n"; +echo "

Deleting" . htmlspecialchars( $dn) . "

\n"; +echo "

Recursive delete progress

\n"; +echo "

"; +echo "\n"; +flush(); + +// prevent script from bailing early on a long delete +@set_time_limit( 0 ); + +$del_result = pla_rdelete( $server_id, $dn ); +echo "
\n"; +if( $del_result ) +{ + // kill the DN from the tree browser session variable and + // refresh the tree viewer frame (left_frame) + + if( session_is_registered( 'tree' ) ) + { + $tree = $_SESSION['tree']; + + // does it have children? (it shouldn't, but hey, you never know) + if( isset( $tree[$server_id][$dn] ) ) + unset( $tree[$server_id][$dn] ); + + // search and destroy + foreach( $tree[$server_id] as $tree_dn => $subtree ) + foreach( $subtree as $key => $sub_tree_dn ) + if( 0 == strcasecmp( $sub_tree_dn, $dn ) ) + unset( $tree[$server_id][$tree_dn][$key] ); + } + + $_SESSION['tree'] = $tree; + session_write_close(); + + ?> + + + + Object and sub-tree deleted successfully. + + Deleting " . htmlspecialchars( utf8_decode( $dn ) ) . "..."; + flush(); + if( ldap_delete( $ds, $dn ) ) { + echo " Success
\n"; + return true; + } else { + pla_error( "Failed to delete dn: " . htmlspecialchars( utf8_decode( $dn ) ), + ldap_error( $ds ), ldap_errno( $ds ) ); + } + } else { + foreach( $children as $child_dn ) { + pla_rdelete( $server_id, $child_dn ); + } + echo "Deleting " . htmlspecialchars( utf8_decode( $dn ) ) . "..."; + flush(); + if( ldap_delete( $ds, $dn ) ) { + echo " Success
\n"; + return true; + } else { + pla_errror( "Failed to delete dn: " . htmlspecialchars( utf8_decode( $dn ) ), + ldap_error( $ds ), ldap_errno( $ds ) ); + } + } + +} diff --git a/refresh.php b/refresh.php new file mode 100644 index 0000000..b446218 --- /dev/null +++ b/refresh.php @@ -0,0 +1,54 @@ + $children ) + { + $tree[$server_id][$dn] = get_container_contents( $server_id, $dn ); + foreach( $tree[$server_id][$dn] as $child_dn ) + $tree_icons[$server_id][$child_dn] = get_icon( $server_id, $child_dn ); + sort( $tree[ $server_id ][ $dn ] ); + } +} +else +{ + header( "Location: tree.php#$server_id" ); +} + +$_SESSION['tree'] = $tree; +$_SESSION['tree_icons'] = $tree_icons; +session_write_close(); + +header( "Location: tree.php#$server_id" ); + + +?> diff --git a/rename.php b/rename.php new file mode 100644 index 0000000..095cd64 --- /dev/null +++ b/rename.php @@ -0,0 +1,91 @@ + $children ) { + foreach( $children as $i => $child_dn ) { + if( 0 == strcasecmp( $child_dn, $old_dn ) ) { + $tree[$server_id][$parent_dn][$i] = $new_dn; + } + } + } + // Update the icon tree to reflect the change (remove the old DN and add the new one) + $tree_icons[ $server_id ][ $new_dn ] = $tree_icons[ $server_id ][ $old_dn ]; + unset( $tree_icons[ $server_id ][ $old_dn ] ); + + $_SESSION['tree'] = $tree; + $_SESSION['tree_icons'] = $tree_icons; + session_write_close(); + + $edit_url="edit.php?server_id=$server_id&dn=" . rawurlencode( "$new_rdn,$container" ); + + ?> + + + + + + + + + + + Redirecting... click here if you're impatient. + + + + + + + +" . 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. + " ); + +} else { ?> + +

Schema for server

+ +
+
+ objectClasses' ); ?> + | + Syntaxes' ); ?> + | + Attributes' ); ?> + | + Matching Rules' ); ?> +
+
+ + + + + '; print_r( $schema['attrs'] ); + ?> + +
+ Attribute definition for

+ + + $val ) + { + if( $key != 'val' && $val != null ) { + $counter++; + echo "\n"; + } + } + } + else + pla_error( "Bad schema entry for attribute: " . htmlspecialchars( $attr ) ); + + ?> + +
$key$val
+
+ + 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 "
Syntax OIDDescription
$oid$desc
\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 ) { + echo ' + + 0 ) { + echo ' +
+ + + + + + + + diff --git a/search.php b/search.php new file mode 100644 index 0000000..e264bbc --- /dev/null +++ b/search.php @@ -0,0 +1,212 @@ +'; +$js_dn_list = ''; +foreach( $servers as $id => $server ) { + $base_dn = $server['base'] ? $server['base'] : try_to_get_root_dn( $id ); + $js_dn_list .= '"' . $server['base'] . '",'; + 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 = utf8_encode($filter); +$attr = stripslashes( $_GET['attribute'] ); + +// grab the base dn for the search +if( isset( $_GET['base_dn'] ) ) + $base_dn = $_GET['base_dn']; +elseif( '' != $servers[$server_id]['base'] ) + $base_dn = $servers[$server_id]['base']; +else + $base_dn = try_to_get_root_dn( $server_id ); + +$criterion = stripslashes( $_GET['criterion'] ); +$form = stripslashes( $_GET['form'] ); +$scope = $_GET['scope'] ? $_GET['scope'] : 'sub'; +//echo "
";print_r( $_GET );echo "
"; +?> + + + + +
+ + + +
+ + + + +
+
+ You haven't logged into server + yet. Go to the login form to do so. +
+ + +
+
Found . + + +
Filter performed:
+ + +
+ + + + $attrs ) { ?> + + +
+ + + +
+ + + + + + + + + +
+ + +
+ + + + +
+ + + +

+
Search happily performed by phpLDAPAdmin in + seconds.
+ + + + + + diff --git a/search_form_advanced.php b/search_form_advanced.php new file mode 100644 index 0000000..230d63a --- /dev/null +++ b/search_form_advanced.php @@ -0,0 +1,50 @@ + + + diff --git a/search_form_simple.php b/search_form_simple.php new file mode 100644 index 0000000..3a23006 --- /dev/null +++ b/search_form_simple.php @@ -0,0 +1,42 @@ + + diff --git a/server_info.php b/server_info.php new file mode 100644 index 0000000..af4762f --- /dev/null +++ b/server_info.php @@ -0,0 +1,49 @@ +"; print_r( $attrs ); echo "
"; + +include 'header.php'; +?> + +

Server info for

+

Server reports the following information about itself

+ + + +

This server has nothing to report.
+ + + + + +
"; + echo htmlspecialchars($attr) . ""; + for( $j=0; $j<$attrs[ $attr ][ 'count' ]; $j++ ) + echo htmlspecialchars( $attrs[ $attr ][ $j ] ) . "
\n"; +} +?> + +
diff --git a/style.css b/style.css new file mode 100644 index 0000000..6303a18 --- /dev/null +++ b/style.css @@ -0,0 +1,360 @@ +table.schema_oclasses td { + vertical-align: top; + text-align: left; +} + +table.schema_attr th { + background-color: #016; + padding: 5px; + color: white; + font-weight: normal; +} + +table.schema_attr td { + padding: 5px; +} + +table.schema_attr tr.even { + background-color: #eee; +} + +table.schema_attr tr.odd { + background-color: #ccc; +} + +div.error { + background-color: #eec; + border: solid black 1px; + padding: 15px; + padding-top: 0px; + width: 380px; + text-align: left; +} + +table.confirm th { + background-color: #016; + padding: 5px; + color: white; + font-weight: normal; +} + +table.confirm tr.spacer { + background-color: #ddd; +} + +table.confirm tr.even { + background-color: #ccc; +} + +table.confirm tr.odd{ + background-color: #eee; +} + +table.confirm tr td { + padding: 4px; + vertical-align: top; +} + +table.confirm tr td.heading { + font-size: 75%; +} + +table.templates tr td { + text-align: left; + vertical-align: center; +} + +table.templates tr { + height: 25px; +} + + +a img { + border: 0px; +} + +body { + font-family: arial, helvetica, sans-serif; + background-color: white; + font-size: 12pt; +} + +table.tree { + border: 0px; +} + +table.tree img { + border: 0px; +} + +table.tree td { + padding: 2px; + border: 0px solid black; +} + +table.tree tr { +} + +table.tree tr.server { + vertical-align: top; +} + +table.tree td.icon { + text-align: center; + padding: 0px; + width: 22px; +} + +table.tree td.rdn a { + text-decoration: none; + color: black; +} + +table.tree td.rdn a:hover { + text-decoration: underline; + color: blue; +} + +table.tree td.create a { + text-decoration: none; + color: black; +} + +table.tree td.create a:hover { + text-decoration: underline; + color: blue; +} + + +table.tree td.spacer { + width: 22px; +} + +table.tree td.expander { + text-align: center; + width: 22px; + min-width: 22px; +} + +table.tree td span.count { + color: gray; + font-size: 85%; +} + +h3.title { + text-align: center; + margin: 0px; + padding: 10px; + color: white; + background-color: #018; + border: 1px solid black; + font-weight: normal; + font-size: 150%; +} + +h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + font-size: 75%; + color: white; + border-bottom: 1px solid black; + border-left: 1px solid black; + border-right: 1px solid black; + background: #018; + padding: 4px; + font-weight: normal; +} + +table.edit_dn tr.spacer td { + height: 20px; +} + +table.edit_dn { + width: 100%; +} + +table.edit_dn th { + background: #777; + color: white; + font-weight: normal; + font-size: 125%; + padding: 5px; +} + +table.edit_dn tr td { + padding: 4px; +} + +table.edit_dn tr td.attr { + vertical-align: top; +} + +table.edit_dn tr td.heading { + border-top: 3px solid #ccc; + font-weight: bold; +} + +table.edit_dn tr td.val { + text-align: right; + vertical-align: center; +} + +table.edit_dn tr.updated_attr { + background: #def; +} + +table.edit_dn tr.updated_attr td { + border-top: 1px solid black; + border-bottom: 1px solid black; + color: #005; +} + +table.edit_dn tr.updated_attr a { +} + +table.edit_dn tr.mod_dn { + background: #def; +} + +table.edit_dn tr.row1 { + background: #eee; +} + +table.edit_dn tr.row2 { + background: #ccc; +} + +input.update_dn { + font-size: 65%; +} + +small { + font-size: 10pt; +} + +form.edit_dn { + margin: 0px; + padding: 0px; +} + +h4.oclass { + background: #88b; + padding: 5px; + margin: 0px; + margin-top: 8px; + font-weight: normal; + border: 1px solid black; + font-size: 140%; + color: white; +} + +h4.oclass_sub { + background: #dde; + border: 1px solid black; + border-top: 0px; + font-weight: normal; + margin: 0px; + padding: 2px; + padding-left: 5px; + font-size: 80%; +} + +ul.schema { + margin: 5px; +} + +ul.schema li { + margin-left: 10px; +} + +ul.current_values { + padding: 5px; + padding-left: 25px; + width: 200px; + margin-left: 50px; +} + +form.new_value { + margin-left: 70px; +} + +ul.search { + font-weight: bold; +} + +div.search_result { + list-style-type: none; + background: #ffb; + padding: 6px; + padding-left: 10px; + margin-right: 40px; +} + +table.attrs { + font-weight: normal; + font-size: 75%; + margin: 0px; +} + +table.attrs td { + padding-right: 10px; +} + +table.attrs td.attr { + color: #aaa; + padding-left: 15px; +} + +form.search { + width: 500px; + background-color: #ddf; + padding: 5px; +} + +table.edit_dn_menu { + font-size: 75%; +} + +input.scary { + background: red; + font-weight: bold; + color: white; +} + +input.cancel { + padding-left: 10px; + padding-right: 10px; + font-weight: bold; +} + +input.happy { + background: green; + font-weight: bold; + color: white; +} + +table.delete_confirm { + width: 76%; + background-color: #ddf; + padding: 20px; + text-align: left; +} + +table.login { + background-color: #ddf; + padding: 10px; +} + +table.login td { + padding: 5px; +} + +table.create { + font-size: 75%; +} + +table.create td.heading { + vertical-align: top; + padding: 10px; +} diff --git a/templates/creation/custom.php b/templates/creation/custom.php new file mode 100644 index 0000000..68de800 --- /dev/null +++ b/templates/creation/custom.php @@ -0,0 +1,186 @@ + + +

Step 1 of 2: Name and ObjectClass(es)

+ +
+ + + + + + + + + + + + + + + + + + + + + +
RDN: (example: cn=MyNewObject)
Container: +
ObjectClass(es): + +
+
+ + $attr_display\n"; + } + + // add the required attribute based on the RDN provided by the user + // (ie, if the user specifies "cn=Bob" for their RDN, make sure "cn" is + // 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 ) ) + $required_attrs[] = $rdn_attr; + + ?> + + +

Step 2 of 2: Specify attributes and values

+ + + + + + + +
+ Creating entry with DN: + + Instrucions: Enter values for the + required attributes. Then create any optional attributes. You + can specify multi-valued attributes as well.
+
+ +
+ + + + + + + + + + $attr ) { ?> + + + + + + + + + + + + + + + + + + + + +
Required Attributes
" . + htmlspecialchars( $friendly_attrs[ strtolower( $attr ) ] ) . ""; + } else { + $attr_display = htmlspecialchars( $attr ); + } + + echo $attr_display; + + ?> +
Optional Attributes
+
+ +
+ +
+ + + diff --git a/templates/creation/new_address_template.php b/templates/creation/new_address_template.php new file mode 100755 index 0000000..681e420 --- /dev/null +++ b/templates/creation/new_address_template.php @@ -0,0 +1,210 @@ + + + + +

New Address Book Entry
+(InetOrgPerson)

+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name: + + +
Common name:
Organization:
Address:
City:
Postal code:
Work phone:
Fax:
Mobile:
Email:
Container: +

+
+ + +

Confirm entry creation:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
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 new file mode 100755 index 0000000..ec9689f --- /dev/null +++ b/templates/creation/new_dns_entry.php @@ -0,0 +1,91 @@ + + +

New DNS Entry

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
DC Name: (hint: don't include "dc=")
Associated Domain:
Container DN: +

+
+ + + + + + + + + + + + + + + + + + +
+ Really create this new DC entry?
+
+ + + + + +
Name
Domain
Container
+
+
+ + diff --git a/templates/creation/new_nt_machine.php b/templates/creation/new_nt_machine.php new file mode 100644 index 0000000..dc6fc7e --- /dev/null +++ b/templates/creation/new_nt_machine.php @@ -0,0 +1,128 @@ + + +

New Samba NT Machine

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Machine Name: (hint: don't include "$" at the end)
UID Number:
Container: +

+





+ This will create a new NT machine with:
+ +
    +
  • gidNumber
  • +
  • acctFlags
  • +
  • cn
  • +
  • in container
  • +
+ To change these values, edit the template file: + templates/creation/new_nt_machine.php
+ Note: You must have the samba schema installed on your LDAP server. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Realy create this new Samba machine?
+
+ + + + +
Name
UID
Container
+
+
+ + diff --git a/templates/creation/new_ou_template.php b/templates/creation/new_ou_template.php new file mode 100644 index 0000000..c7f572c --- /dev/null +++ b/templates/creation/new_ou_template.php @@ -0,0 +1,84 @@ + + +

New Organizational Unit

+ + + + + + + + +
+ + + + + + + + + + + + + + + +
OU Name: (hint: don't include "ou=")
Container DN: +

+
+ + + + + + + + + + + + + + + + +
+ Really create this new OU?
+
+ + + + +
Name
Container
+
+
+ + + diff --git a/templates/creation/new_user_template.php b/templates/creation/new_user_template.php new file mode 100644 index 0000000..d2845f1 --- /dev/null +++ b/templates/creation/new_user_template.php @@ -0,0 +1,242 @@ + + + + +

New User Account

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First name:
Last name:
User name:
Password:
Password:
Encryption:
Login Shell: + +
Container: +
UID Number:
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/tree.php b/tree.php new file mode 100644 index 0000000..c45093c --- /dev/null +++ b/tree.php @@ -0,0 +1,281 @@ +_, so if I wanted to scroll to + * dc=example,dc=com for server 3, the URL would be: + * tree.php#3_dc%3Dexample%2Cdc%3Dcom + */ + +require 'config.php'; +require_once 'functions.php'; + +// no expire header stuff +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: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +// The entire visible tree is stored in the session. +session_start(); + +// do we not have a tree yet? Build a new one. +if( ! session_is_registered( 'tree' ) ) { + session_register( 'tree' ); + $_SESSION['tree'] = build_initial_tree(); + session_register( 'tree_icons' ); + $_SESSION['tree_icons'] = build_initial_tree_icons(); +} + +// grab the tree out of the session variable +$tree = $_SESSION['tree']; +$tree_icons = $_SESSION['tree_icons']; +?> + + + + + + + +

phpLDAPAdmin -

+ + + + + + + + + +
Request a new feature + (see open requests)
Report a bug + (see open bugs)
+
+ + + $server_tree ) { + + if( $servers[$server_id]['host'] != '' ) { + + $server_name = $servers[$server_id]['name']; + echo ''; + echo ''; + echo ''; + + $rdn = utf8_decode( $dn ); + if( null == $servers[ $server_id ]['base'] ) { + $base_dn = try_to_get_root_dn( $server_id ); + } else { + $base_dn = $servers[ $server_id ]['base']; + } + + // Did we get a base_dn for this server somehow? + if( $base_dn ) { + // is the root of the tree expanded already? + if( isset( $tree[$server_id][$base_dn] ) ) { + $expand_href = "collapse.php?server_id=$server_id&" . + "dn=" . rawurlencode( $base_dn ); + $expand_img = "images/minus.png"; + } else { + $expand_href = "expand.php?server_id=$server_id&" . + "dn=" . rawurlencode( $base_dn ); + $expand_img = "images/plus.png"; + } + + $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 "\n"; + } else { + if( "" === $base_dn || null === $base_dn ) { + // The server refuses to give out the base dn + 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 ""; + // Proceed to the next server. We cannot draw anything else for this server. + continue; + } + } + + flush(); + + // 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 ''; + } + } + else // have_auth_info() returned false. + { + // We don't have enough information to login to this server + $login_href = "login_form.php?server_id=$server_id"; + echo '   '; + echo 'login '; + echo 'login...'; + echo ''; + } + + } +} + +?> + +
server' . htmlspecialchars( $server_name ) . '
'; + + + // 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)? + if( have_auth_info( $server_id ) ) + { + $schema_href = 'schema.php?server_id=' . $server_id . '" target="right_frame'; + $search_href= 'search.php?server_id=' . $server_id . '" target="right_frame'; + $refresh_href = 'refresh.php?server_id=' . $server_id; + $create_href = 'create_form.php?server_id=' . $server_id . '&container=' . + rawurlencode( $servers[$server_id]['base'] ); + $logout_href = 'logout.php?server_id=' . $server_id; + $info_href = 'server_info.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 'create | '; + echo 'info'; + if( $servers[ $server_id ][ 'auth_type' ] == 'form' ) + echo ' | logout'; + 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 "
Could not determine "; + echo "the root of your LDAP tree.
Please specify it in config.php"; + echo "
Create New
+ + + +'; + + for( $i=0; $i<=$level; $i++ ) { + echo ''; + } + + // is this node expanded? + if( isset( $tree[$server_id][$dn] ) ) { ?> + + + plus + + + (' . count( $tree[$server_id][$dn] ) . ')'; ?> + + + + minus + + + + + + + + + + + + + + + + + '; + for( $i=0; $i<=$level; $i++ ) { + echo ''; + } + echo ''; + echo ''; + echo 'Create New'; + } + + echo ''; + +} + +?> diff --git a/update.php b/update.php new file mode 100644 index 0000000..8c58bf7 --- /dev/null +++ b/update.php @@ -0,0 +1,49 @@ +"; 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." ); + +foreach( $update_array as $attr => $val ) + if( ! is_array( $val ) ) + if( $val == '' ) + $update_array[ $attr ] = array(); + +$ds = pla_ldap_connect( $server_id ); +$res = @ldap_modify( $ds, $dn, $update_array ); +if( $res ) +{ + $redirect_url = "edit.php?server_id=$server_id&dn=$encoded_dn"; + foreach( $update_array as $attr => $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/update_confirm.php b/update_confirm.php new file mode 100644 index 0000000..4c32cff --- /dev/null +++ b/update_confirm.php @@ -0,0 +1,143 @@ + + + + +

+

Server:     Distinguished Name:

+ + $new_val ) +{ + // did the user change the field? + 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 ); + } + + $update_array[ $attr ] = $new_val; + } +} + +//echo "
"; print_r( $update_array ); echo "
"; + +?> + 0 ) { ?> + +
+
+ Do you want to make these changes? +
+
+ + + + $new_val ) { $counter++ ?> + + + + \n\n"; + } + + ?> + +
AttributeOld ValueNew Value
+ "; + else + echo htmlspecialchars( $old_values[ $attr ] ) . "
"; + echo "
"; + 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 + if( $new_val != '' ) + echo htmlspecialchars( $new_val ) . "
"; + echo "
+
+ + + + + + +
+ + + + + $val ) { ?> + + $v ) { ?> + + + + + + + + + + +
+ + + +
+
+
+ + + + +
+ You made no changes. + Go back. +
+ + + + + + + diff --git a/view_jpeg_photo.php b/view_jpeg_photo.php new file mode 100644 index 0000000..f524716 --- /dev/null +++ b/view_jpeg_photo.php @@ -0,0 +1,28 @@ +