commit c98521571432a52064e7df43c89c1b88457ffb0b Author: Timothy J Warren Date: Fri Feb 8 13:44:52 2019 -0500 First commit, 'forked' from https://sourceforge.net/projects/phpldapadmin/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac7db53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +config/config.php +queries/custom_* +templates/*/custom_* diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e079b12 --- /dev/null +++ b/INSTALL @@ -0,0 +1,23 @@ +For install instructions in non-English languages, see the wiki: + http://phpldapadmin.sourceforge.net + +* Requirements + + phpLDAPadmin requires the following: + a. A web server (Apache, IIS, etc). + b. PHP 5.0.0 or newer (with LDAP support) + +* To install + + 1. Unpack the archive (if you're reading this, you already did that). + 2. Put the resulting 'phpldapadmin' directory somewhere in your webroot. + 3. Copy 'config.php.example' to 'config.php' and edit to taste (this is in the config/ directory). + 4. Then, point your browser to the phpldapadmin directory. + +* For additional help + + See the wiki: + http://phpldapadmin.sourceforge.net + + Join our mailing list: + https://lists.sourceforge.net/lists/listinfo/phpldapadmin-devel 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..e0a90a8 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +RELEASE-1.2.3 diff --git a/config/config.php.example b/config/config.php.example new file mode 100644 index 0000000..5b6fdb8 --- /dev/null +++ b/config/config.php.example @@ -0,0 +1,576 @@ +custom variable to do so. + * For example, the default for defining the language in config_default.php + * + * $this->default->appearance['language'] = array( + * 'desc'=>'Language', + * 'default'=>'auto'); + * + * to override this, use $config->custom->appearance['language'] = 'en_EN'; + * + * This file is also used to configure your LDAP server connections. + * + * You must specify at least one LDAP server there. You may add + * as many as you like. You can also specify your language, and + * many other options. + * + * NOTE: Commented out values in this file prefixed by //, represent the + * defaults that have been defined in config_default.php. + * Commented out values prefixed by #, dont reflect their default value, you can + * check config_default.php if you want to see what the default is. + * + * DONT change config_default.php, you changes will be lost by the next release + * of PLA. Instead change this file - as it will NOT be replaced by a new + * version of phpLDAPadmin. + */ + +/********************************************* + * Useful important configuration overrides * + *********************************************/ + +/* If you are asked to put PLA in debug mode, this is how you do it: */ +# $config->custom->debug['level'] = 255; +# $config->custom->debug['syslog'] = true; +# $config->custom->debug['file'] = '/tmp/pla_debug.log'; + +/* phpLDAPadmin can encrypt the content of sensitive cookies if you set this + to a big random string. */ +// $config->custom->session['blowfish'] = null; + +/* If your auth_type is http, you can override your HTTP Authentication Realm. */ +// $config->custom->session['http_realm'] = sprintf('%s %s',app_name(),'login'); + +/* The language setting. If you set this to 'auto', phpLDAPadmin will attempt + to determine your language automatically. + If PLA doesnt show (all) strings in your language, then you can do some + translation at http://translations.launchpad.net/phpldapadmin and download + the translation files, replacing those provided with PLA. + (We'll pick up the translations before making the next release too!) */ +// $config->custom->appearance['language'] = 'auto'; + +/* The temporary storage directory where we will put jpegPhoto data + This directory must be readable and writable by your web server. */ +// $config->custom->jpeg['tmpdir'] = '/tmp'; // Example for Unix systems +# $config->custom->jpeg['tmpdir'] = 'c:\\temp'; // Example for Windows systems + +/* Set this to (bool)true if you do NOT want a random salt used when + calling crypt(). Instead, use the first two letters of the user's + password. This is insecure but unfortunately needed for some older + environments. */ +# $config->custom->password['no_random_crypt_salt'] = true; + +/* PHP script timeout control. If php runs longer than this many seconds then + PHP will stop with an Maximum Execution time error. Increase this value from + the default if queries to your LDAP server are slow. The default is either + 30 seconds or the setting of max_exection_time if this is null. */ +// $config->custom->session['timelimit'] = 30; + +/* Our local timezone + This is to make sure that when we ask the system for the current time, we + get the right local time. If this is not set, all time() calculations will + assume UTC if you have not set PHP date.timezone. */ +// $config->custom->appearance['timezone'] = null; +# $config->custom->appearance['timezone'] = 'Australia/Melbourne'; + +/********************************************* + * Commands * + *********************************************/ + +/* Command availability ; if you don't authorize a command the command + links will not be shown and the command action will not be permitted. + For better security, set also ACL in your ldap directory. */ +/* +$config->custom->commands['cmd'] = array( + 'entry_internal_attributes_show' => true, + 'entry_refresh' => true, + 'oslinks' => true, + 'switch_template' => true +); + +$config->custom->commands['script'] = array( + 'add_attr_form' => true, + 'add_oclass_form' => true, + 'add_value_form' => true, + 'collapse' => true, + 'compare' => true, + 'compare_form' => true, + 'copy' => true, + 'copy_form' => true, + 'create' => true, + 'create_confirm' => true, + 'delete' => true, + 'delete_attr' => true, + 'delete_form' => true, + 'draw_tree_node' => true, + 'expand' => true, + 'export' => true, + 'export_form' => true, + 'import' => true, + 'import_form' => true, + 'login' => true, + 'logout' => true, + 'login_form' => true, + 'mass_delete' => true, + 'mass_edit' => true, + 'mass_update' => true, + 'modify_member_form' => true, + 'monitor' => true, + 'purge_cache' => true, + 'query_engine' => true, + 'rename' => true, + 'rename_form' => true, + 'rdelete' => true, + 'refresh' => true, + 'schema' => true, + 'server_info' => true, + 'show_cache' => true, + 'template_engine' => true, + 'update_confirm' => true, + 'update' => true +); +*/ + +/********************************************* + * Appearance * + *********************************************/ + +/* If you want to choose the appearance of the tree, specify a class name which + inherits from the Tree class. */ +// $config->custom->appearance['tree'] = 'AJAXTree'; +# $config->custom->appearance['tree'] = 'HTMLTree'; + +/* Just show your custom templates. */ +// $config->custom->appearance['custom_templates_only'] = false; + +/* Disable the default template. */ +// $config->custom->appearance['disable_default_template'] = false; + +/* Hide the warnings for invalid objectClasses/attributes in templates. */ +// $config->custom->appearance['hide_template_warning'] = false; + +/* Set to true if you would like to hide header and footer parts. */ +// $config->custom->appearance['minimalMode'] = false; + +/* Configure what objects are shown in left hand tree */ +// $config->custom->appearance['tree_filter'] = '(objectclass=*)'; + +/* The height and width of the tree. If these values are not set, then + no tree scroll bars are provided. */ +// $config->custom->appearance['tree_height'] = null; +# $config->custom->appearance['tree_height'] = 600; +// $config->custom->appearance['tree_width'] = null; +# $config->custom->appearance['tree_width'] = 250; + +/* Confirm create and update operations, allowing you to review the changes + and optionally skip attributes during the create/update operation. */ +// $config->custom->confirm['create'] = true; +// $config->custom->confirm['update'] = true; + +/* Confirm copy operations, and treat them like create operations. This allows + you to edit the attributes (thus changing any that might conflict with + uniqueness) before creating the new entry. */ +// $config->custom->confirm['copy'] = true; + +/********************************************* + * User-friendly attribute translation * + *********************************************/ + +/* Use this array to map attribute names to user friendly names. For example, if + you don't want to see "facsimileTelephoneNumber" but rather "Fax". */ +// $config->custom->appearance['friendly_attrs'] = array(); +$config->custom->appearance['friendly_attrs'] = array( + 'facsimileTelephoneNumber' => 'Fax', + 'gid' => 'Group', + 'mail' => 'Email', + 'telephoneNumber' => 'Telephone', + 'uid' => 'User Name', + 'userPassword' => 'Password' +); + +/********************************************* + * Hidden attributes * + *********************************************/ + +/* You may want to hide certain attributes from being edited. If you want to + hide attributes from the user, you should use your LDAP servers ACLs. + NOTE: The user must be able to read the hide_attrs_exempt entry to be + excluded. */ +// $config->custom->appearance['hide_attrs'] = array(); +# $config->custom->appearance['hide_attrs'] = array('objectClass'); + +/* Members of this list will be exempt from the hidden attributes. */ +// $config->custom->appearance['hide_attrs_exempt'] = null; +# $config->custom->appearance['hide_attrs_exempt'] = 'cn=PLA UnHide,ou=Groups,c=AU'; + +/********************************************* + * Read-only attributes * + *********************************************/ + +/* You may want to phpLDAPadmin to display certain attributes as read only, + meaning that users will not be presented a form for modifying those + attributes, and they will not be allowed to be modified on the "back-end" + either. You may configure this list here: + NOTE: The user must be able to read the readonly_attrs_exempt entry to be + excluded. */ +// $config->custom->appearance['readonly_attrs'] = array(); + +/* Members of this list will be exempt from the readonly attributes. */ +// $config->custom->appearance['readonly_attrs_exempt'] = null; +# $config->custom->appearance['readonly_attrs_exempt'] = 'cn=PLA ReadWrite,ou=Groups,c=AU'; + +/********************************************* + * Group attributes * + *********************************************/ + +/* Add "modify group members" link to the attribute. */ +// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid'); + +/* Configure filter for member search. This only applies to "modify group members" feature */ +// $config->custom->modify_member['filter'] = '(objectclass=Person)'; + +/* Attribute that is added to the group member attribute. */ +// $config->custom->modify_member['attr'] = 'dn'; + +/* For Posix attributes */ +// $config->custom->modify_member['posixattr'] = 'uid'; +// $config->custom->modify_member['posixfilter'] = '(uid=*)'; +// $config->custom->modify_member['posixgroupattr'] = 'memberUid'; + +/********************************************* + * Support for attrs display order * + *********************************************/ + +/* Use this array if you want to have your attributes displayed in a specific + order. You can use default attribute names or their fridenly names. + For example, "sn" will be displayed right after "givenName". All the other + attributes that are not specified in this array will be displayed after in + alphabetical order. */ +// $config->custom->appearance['attr_display_order'] = array(); +# $config->custom->appearance['attr_display_order'] = array( +# 'givenName', +# 'sn', +# 'cn', +# 'displayName', +# 'uid', +# 'uidNumber', +# 'gidNumber', +# 'homeDirectory', +# 'mail', +# 'userPassword' +# ); + +/********************************************* + * Define your LDAP servers in this section * + *********************************************/ + +$servers = new Datastore(); + +/* $servers->NewServer('ldap_pla') must be called before each new LDAP server + declaration. */ +$servers->newServer('ldap_pla'); + +/* A convenient name that will appear in the tree viewer and throughout + phpLDAPadmin to identify this LDAP server to users. */ +$servers->setValue('server','name','My LDAP Server'); + +/* Examples: + 'ldap.example.com', + 'ldaps://ldap.example.com/', + 'ldapi://%2fusr%local%2fvar%2frun%2fldapi' + (Unix socket at /usr/local/var/run/ldap) */ +// $servers->setValue('server','host','127.0.0.1'); + +/* The port your LDAP server listens on (no quotes). 389 is standard. */ +// $servers->setValue('server','port',389); + +/* Array of base DNs of your LDAP server. Leave this blank to have phpLDAPadmin + auto-detect it for you. */ +// $servers->setValue('server','base',array('')); + +/* Five options for auth_type: + 1. 'cookie': you will login via a web form, and a client-side cookie will + store your login dn and password. + 2. 'session': same as cookie but your login dn and password are stored on the + web server in a persistent session variable. + 3. 'http': same as session but your login dn and password are retrieved via + HTTP authentication. + 4. 'config': specify your login dn and password here in this config file. No + login will be required to use phpLDAPadmin for this server. + 5. 'sasl': login will be taken from the webserver's kerberos authentication. + Currently only GSSAPI has been tested (using mod_auth_kerb). + + Choose wisely to protect your authentication information appropriately for + your situation. If you choose 'cookie', your cookie contents will be + encrypted using blowfish and the secret your specify above as + session['blowfish']. */ +// $servers->setValue('login','auth_type','session'); + +/* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or + 'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS + BLANK. If you specify a login_attr in conjunction with a cookie or session + auth_type, then you can also specify the bind_id/bind_pass here for searching + the directory for users (ie, if your LDAP server does not allow anonymous + binds. */ +// $servers->setValue('login','bind_id',''); +# $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com'); + +/* Your LDAP password. If you specified an empty bind_id above, this MUST also + be blank. */ +// $servers->setValue('login','bind_pass',''); +# $servers->setValue('login','bind_pass','secret'); + +/* Use TLS (Transport Layer Security) to connect to the LDAP server. */ +// $servers->setValue('server','tls',false); + +/************************************ + * SASL Authentication * + ************************************/ + +/* Enable SASL authentication LDAP SASL authentication requires PHP 5.x + configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to + false), then all other sasl options are ignored. */ +// $servers->setValue('login','auth_type','sasl'); + +/* SASL auth mechanism */ +// $servers->setValue('sasl','mech','GSSAPI'); + +/* SASL authentication realm name */ +// $servers->setValue('sasl','realm',''); +# $servers->setValue('sasl','realm','EXAMPLE.COM'); + +/* SASL authorization ID name + If this option is undefined, authorization id will be computed from bind DN, + using authz_id_regex and authz_id_replacement. */ +// $servers->setValue('sasl','authz_id', null); + +/* SASL authorization id regex and replacement + When authz_id property is not set (default), phpLDAPAdmin will try to + figure out authorization id by itself from bind distinguished name (DN). + + This procedure is done by calling preg_replace() php function in the + following way: + + $authz_id = preg_replace($sasl_authz_id_regex,$sasl_authz_id_replacement, + $bind_dn); + + For info about pcre regexes, see: + - pcre(3), perlre(3) + - http://www.php.net/preg_replace */ +// $servers->setValue('sasl','authz_id_regex',null); +// $servers->setValue('sasl','authz_id_replacement',null); +# $servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i'); +# $servers->setValue('sasl','authz_id_replacement','$1'); + +/* SASL auth security props. + See http://beepcore-tcl.sourceforge.net/tclsasl.html#anchor5 for explanation. */ +// $servers->setValue('sasl','props',null); + +/* Default password hashing algorithm. One of md5, ssha, sha, md5crpyt, smd5, + blowfish, crypt or leave blank for now default algorithm. */ +// $servers->setValue('appearance','password_hash','md5'); + +/* If you specified 'cookie' or 'session' as the auth_type above, you can + optionally specify here an attribute to use when logging in. If you enter + 'uid' and login as 'dsmith', phpLDAPadmin will search for (uid=dsmith) + and log in as that user. + Leave blank or specify 'dn' to use full DN for logging in. Note also that if + your LDAP server requires you to login to perform searches, you can enter the + DN to use when searching in 'bind_id' and 'bind_pass' above. */ +// $servers->setValue('login','attr','dn'); + +/* Base DNs to used for logins. If this value is not set, then the LDAP server + Base DNs are used. */ +// $servers->setValue('login','base',array()); + +/* If 'login,attr' is used above such that phpLDAPadmin will search for your DN + at login, you may restrict the search to a specific objectClasses. EG, set this + to array('posixAccount') or array('inetOrgPerson',..), depending upon your + setup. */ +// $servers->setValue('login','class',array()); + +/* If you specified something different from 'dn', for example 'uid', as the + login_attr above, you can optionally specify here to fall back to + authentication with dn. + This is useful, when users should be able to log in with their uid, but + the ldap administrator wants to log in with his root-dn, that does not + necessarily have the uid attribute. + When using this feature, login_class is ignored. */ +// $servers->setValue('login','fallback_dn',false); + +/* Specify true If you want phpLDAPadmin to not display or permit any + modification to the LDAP server. */ +// $servers->setValue('server','read_only',false); + +/* Specify false if you do not want phpLDAPadmin to draw the 'Create new' links + in the tree viewer. */ +// $servers->setValue('appearance','show_create',true); + +/* Set to true if you would like to initially open the first level of each tree. */ +// $servers->setValue('appearance','open_tree',false); + +/* This feature allows phpLDAPadmin to automatically determine the next + available uidNumber for a new entry. */ +// $servers->setValue('auto_number','enable',true); + +/* The mechanism to use when finding the next available uidNumber. Two possible + values: 'uidpool' or 'search'. + The 'uidpool' mechanism uses an existing uidPool entry in your LDAP server to + blindly lookup the next available uidNumber. The 'search' mechanism searches + for entries with a uidNumber value and finds the first available uidNumber + (slower). */ +// $servers->setValue('auto_number','mechanism','search'); + +/* The DN of the search base when the 'search' mechanism is used above. */ +# $servers->setValue('auto_number','search_base','ou=People,dc=example,dc=com'); + +/* The minimum number to use when searching for the next available number + (only when 'search' is used for auto_number. */ +// $servers->setValue('auto_number','min',array('uidNumber'=>1000,'gidNumber'=>500)); + +/* If you set this, then phpldapadmin will bind to LDAP with this user ID when + searching for the uidnumber. The idea is, this user id would have full + (readonly) access to uidnumber in your ldap directory (the logged in user + may not), so that you can be guaranteed to get a unique uidnumber for your + directory. */ +// $servers->setValue('auto_number','dn',null); + +/* The password for the dn above. */ +// $servers->setValue('auto_number','pass',null); + +/* Enable anonymous bind login. */ +// $servers->setValue('login','anon_bind',true); + +/* Use customized page with prefix when available. */ +# $servers->setValue('custom','pages_prefix','custom_'); + +/* If you set this, then only these DNs are allowed to log in. This array can + contain individual users, groups or ldap search filter(s). Keep in mind that + the user has not authenticated yet, so this will be an anonymous search to + the LDAP server, so make your ACLs allow these searches to return results! */ +# $servers->setValue('login','allowed_dns',array( +# 'uid=stran,ou=People,dc=example,dc=com', +# '(&(gidNumber=811)(objectClass=groupOfNames))', +# '(|(uidNumber=200)(uidNumber=201))', +# 'cn=callcenter,ou=Group,dc=example,dc=com')); + +/* Set this if you dont want this LDAP server to show in the tree */ +// $servers->setValue('server','visible',true); + +/* Set this if you want to hide the base DNs that dont exist instead of + displaying the message "The base entry doesnt exist, create it?" +// $servers->setValue('server','hide_noaccess_base',false); +# $servers->setValue('server','hide_noaccess_base',true); + +/* This is the time out value in minutes for the server. After as many minutes + of inactivity you will be automatically logged out. If not set, the default + value will be ( session_cache_expire()-1 ) */ +# $servers->setValue('login','timeout',30); + +/* Set this if you want phpldapadmin to perform rename operation on entry which + has children. Certain servers are known to allow it, certain are not. */ +// $servers->setValue('server','branch_rename',false); + +/* If you set this, then phpldapadmin will show these attributes as + internal attributes, even if they are not defined in your schema. */ +// $servers->setValue('server','custom_sys_attrs',array('')); +# $servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime')); + +/* If you set this, then phpldapadmin will show these attributes on + objects, even if they are not defined in your schema. */ +// $servers->setValue('server','custom_attrs',array('')); +# $servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock')); + +/* These attributes will be forced to MAY attributes and become option in the + templates. If they are not defined in the templates, then they wont appear + as per normal template processing. You may want to do this because your LDAP + server may automatically calculate a default value. + In Fedora Directory Server using the DNA Plugin one could ignore uidNumber, + gidNumber and sambaSID. */ +// $servers->setValue('server','force_may',array('')); +# $servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID')); + +/********************************************* + * Unique attributes * + *********************************************/ + +/* You may want phpLDAPadmin to enforce some attributes to have unique values + (ie: not belong to other entries in your tree. This (together with + 'unique','dn' and 'unique','pass' option will not let updates to + occur with other attributes have the same value. */ +# $servers->setValue('unique','attrs',array('mail','uid','uidNumber')); + +/* If you set this, then phpldapadmin will bind to LDAP with this user ID when + searching for attribute uniqueness. The idea is, this user id would have full + (readonly) access to your ldap directory (the logged in user may not), so + that you can be guaranteed to get a unique uidnumber for your directory. */ +// $servers->setValue('unique','dn',null); + +/* The password for the dn above. */ +// $servers->setValue('unique','pass',null); + +/************************************************************************** + * If you want to configure additional LDAP servers, do so below. * + * Remove the commented lines and use this section as a template for all * + * your other LDAP servers. * + **************************************************************************/ + +/* +$servers->newServer('ldap_pla'); +$servers->setValue('server','name','LDAP Server'); +$servers->setValue('server','host','127.0.0.1'); +$servers->setValue('server','port',389); +$servers->setValue('server','base',array('')); +$servers->setValue('login','auth_type','cookie'); +$servers->setValue('login','bind_id',''); +$servers->setValue('login','bind_pass',''); +$servers->setValue('server','tls',false); + +# SASL auth +$servers->setValue('login','auth_type','sasl'); +$servers->setValue('sasl','mech','GSSAPI'); +$servers->setValue('sasl','realm','EXAMPLE.COM'); +$servers->setValue('sasl','authz_id',null); +$servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i'); +$servers->setValue('sasl','authz_id_replacement','$1'); +$servers->setValue('sasl','props',null); + +$servers->setValue('appearance','password_hash','md5'); +$servers->setValue('login','attr','dn'); +$servers->setValue('login','fallback_dn',false); +$servers->setValue('login','class',null); +$servers->setValue('server','read_only',false); +$servers->setValue('appearance','show_create',true); + +$servers->setValue('auto_number','enable',true); +$servers->setValue('auto_number','mechanism','search'); +$servers->setValue('auto_number','search_base',null); +$servers->setValue('auto_number','min',array('uidNumber'=>1000,'gidNumber'=>500)); +$servers->setValue('auto_number','dn',null); +$servers->setValue('auto_number','pass',null); + +$servers->setValue('login','anon_bind',true); +$servers->setValue('custom','pages_prefix','custom_'); +$servers->setValue('unique','attrs',array('mail','uid','uidNumber')); +$servers->setValue('unique','dn',null); +$servers->setValue('unique','pass',null); + +$servers->setValue('server','visible',true); +$servers->setValue('login','timeout',30); +$servers->setValue('server','branch_rename',false); +$servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime')); +$servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock')); +$servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID')); +*/ +?> diff --git a/doc/README-translation.txt b/doc/README-translation.txt new file mode 100644 index 0000000..3bf340a --- /dev/null +++ b/doc/README-translation.txt @@ -0,0 +1,2 @@ +Please see http://phpldapadmin.sourceforge.net/Translate now for information on +translating PLA. diff --git a/doc/certs/ca-bundle.crt b/doc/certs/ca-bundle.crt new file mode 100644 index 0000000..dea4c9f --- /dev/null +++ b/doc/certs/ca-bundle.crt @@ -0,0 +1,4567 @@ +## +## Extracted from the mod_ssl-2.7.1-1.3.14 source tree 25 October 2000. +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## Last Modified: Thu Mar 2 09:32:46 CET 2000 +## +## This is a bundle of X.509 certificates of public +## Certificate Authorities (CA). These were automatically +## extracted from Netscape Communicator 4.72's certificate database +## (the file `cert7.db'). It contains the certificates in both +## plain text and PEM format and therefore can be directly used +## with an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## (SKIPME) +## + +ABAecom (sub., Am. Bankers Assn.) Root CA +========================================= +MD5 Fingerprint: 82:12:F7:89:E1:0B:91:60:A4:B6:22:9F:94:68:11:92 +PEM Data: +-----BEGIN CERTIFICATE----- +MIID+DCCAuCgAwIBAgIRANAeQJAAACdLAAAAAQAAAAQwDQYJKoZIhvcNAQEFBQAw +gYwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExh +a2UgQ2l0eTEYMBYGA1UEChMPWGNlcnQgRVogYnkgRFNUMRgwFgYDVQQDEw9YY2Vy +dCBFWiBieSBEU1QxITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAe +Fw05OTA3MTQxNjE0MThaFw0wOTA3MTExNjE0MThaMIGMMQswCQYDVQQGEwJVUzEN +MAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxGDAWBgNVBAoT +D1hjZXJ0IEVaIGJ5IERTVDEYMBYGA1UEAxMPWGNlcnQgRVogYnkgRFNUMSEwHwYJ +KoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCtVBjetL/3reh0qu2LfI/C1HUa1YS5tmL8ie/kl2GS+x24 +4VpHNJ6eBiL70+o4y7iLB/caoBd3B1owHNQpOCDXJ0DYUJNDv9IYoil2BXKqa7Zp +mKt5Hhxl9WqL/MUWqqJy2mDtTm4ZJXoKHTDjUJtCPETrobAgHtsCfv49H7/QAIrb +QHamGKUVp1e2UsIBF5h3j4qBxhq0airmr6nWAKzP2BVJfNsbof6B+of505DBAsD5 +0ELpkWglX8a/hznplQBgKL+DLMDnXrbXNhbnYId26OcnsiUNi3rlqh3lWc3OCw5v +xsic4xDZhTnTt5v6xrp8dNJddVardKSiUb9SfO5xAgMBAAGjUzBRMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAUCCBsZuuBCmxc1bWmPEHdHJaRJ3cwHQYDVR0O +BBYEFAggbGbrgQpsXNW1pjxB3RyWkSd3MA0GCSqGSIb3DQEBBQUAA4IBAQBah1iP +Lat2IWtUDNnxQfZOzSue4x+boy1/2St9WMhnpCn16ezVvZY/o3P4xFs2fNBjLDQ5 +m0i4PW/2FMWeY+anNG7T6DOzxzwYbiOuQ5KZP5jFaTDxNjutuTCC1rZZFpYCCykS +YbQRifcML5SQhZgonFNsfmPdc/QZ/0qB0bJSI/08SjTOWhvgUIrtT4GV2GDn5MQN +u1g+WPdOaG8+Z8nLepcWJ+xCYRR2uwDF6wg9FX9LtiJdhzuQ9PPA/jez6dliDMDD +Wa9gvR8N26E0HzDEPYutsB0Ek+1f1eS/IDAE9EjpMwHRLpAnUrOb3jocq6mXf5vr +wo3CbezcE9NGxXl8 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + d0:1e:40:90:00:00:27:4b:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=ca@digsigtrust.com + Validity + Not Before: Jul 14 16:14:18 1999 GMT + Not After : Jul 11 16:14:18 2009 GMT + Subject: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:54:18:de:b4:bf:f7:ad:e8:74:aa:ed:8b:7c: + 8f:c2:d4:75:1a:d5:84:b9:b6:62:fc:89:ef:e4:97: + 61:92:fb:1d:b8:e1:5a:47:34:9e:9e:06:22:fb:d3: + ea:38:cb:b8:8b:07:f7:1a:a0:17:77:07:5a:30:1c: + d4:29:38:20:d7:27:40:d8:50:93:43:bf:d2:18:a2: + 29:76:05:72:aa:6b:b6:69:98:ab:79:1e:1c:65:f5: + 6a:8b:fc:c5:16:aa:a2:72:da:60:ed:4e:6e:19:25: + 7a:0a:1d:30:e3:50:9b:42:3c:44:eb:a1:b0:20:1e: + db:02:7e:fe:3d:1f:bf:d0:00:8a:db:40:76:a6:18: + a5:15:a7:57:b6:52:c2:01:17:98:77:8f:8a:81:c6: + 1a:b4:6a:2a:e6:af:a9:d6:00:ac:cf:d8:15:49:7c: + db:1b:a1:fe:81:fa:87:f9:d3:90:c1:02:c0:f9:d0: + 42:e9:91:68:25:5f:c6:bf:87:39:e9:95:00:60:28: + bf:83:2c:c0:e7:5e:b6:d7:36:16:e7:60:87:76:e8: + e7:27:b2:25:0d:8b:7a:e5:aa:1d:e5:59:cd:ce:0b: + 0e:6f:c6:c8:9c:e3:10:d9:85:39:d3:b7:9b:fa:c6: + ba:7c:74:d2:5d:75:56:ab:74:a4:a2:51:bf:52:7c: + ee:71 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77 + + X509v3 Subject Key Identifier: + 08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77 + Signature Algorithm: sha1WithRSAEncryption + 5a:87:58:8f:2d:ab:76:21:6b:54:0c:d9:f1:41:f6:4e:cd:2b: + 9e:e3:1f:9b:a3:2d:7f:d9:2b:7d:58:c8:67:a4:29:f5:e9:ec: + d5:bd:96:3f:a3:73:f8:c4:5b:36:7c:d0:63:2c:34:39:9b:48: + b8:3d:6f:f6:14:c5:9e:63:e6:a7:34:6e:d3:e8:33:b3:c7:3c: + 18:6e:23:ae:43:92:99:3f:98:c5:69:30:f1:36:3b:ad:b9:30: + 82:d6:b6:59:16:96:02:0b:29:12:61:b4:11:89:f7:0c:2f:94: + 90:85:98:28:9c:53:6c:7e:63:dd:73:f4:19:ff:4a:81:d1:b2: + 52:23:fd:3c:4a:34:ce:5a:1b:e0:50:8a:ed:4f:81:95:d8:60: + e7:e4:c4:0d:bb:58:3e:58:f7:4e:68:6f:3e:67:c9:cb:7a:97: + 16:27:ec:42:61:14:76:bb:00:c5:eb:08:3d:15:7f:4b:b6:22: + 5d:87:3b:90:f4:f3:c0:fe:37:b3:e9:d9:62:0c:c0:c3:59:af: + 60:bd:1f:0d:db:a1:34:1f:30:c4:3d:8b:ad:b0:1d:04:93:ed: + 5f:d5:e4:bf:20:30:04:f4:48:e9:33:01:d1:2e:90:27:52:b3: + 9b:de:3a:1c:ab:a9:97:7f:9b:eb:c2:8d:c2:6d:ec:dc:13:d3: + 46:c5:79:7c + +ANX Network CA by DST +===================== +MD5 Fingerprint: A8:ED:DE:EB:93:88:66:D8:2F:C3:BD:1D:BE:45:BE:4D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDTTCCAragAwIBAgIENm6ibzANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMR0wGwYDVQQL +ExREU1QgKEFOWCBOZXR3b3JrKSBDQTAeFw05ODEyMDkxNTQ2NDhaFw0xODEyMDkx +NjE2NDhaMFIxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVy +ZSBUcnVzdCBDby4xHTAbBgNVBAsTFERTVCAoQU5YIE5ldHdvcmspIENBMIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEbaI +IwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ce +InYTBLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04 +JrBvQ24JfQIBA6OCATAwggEsMBEGCWCGSAGG+EIBAQQEAwIABzB0BgNVHR8EbTBr +MGmgZ6BlpGMwYTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjEdMBsGA1UECxMURFNUIChBTlggTmV0d29yaykgQ0ExDTAL +BgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxNTQ2NDhagQ8yMDE4MTIw +OTE1NDY0OFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFIwWVXDMFgpTZMKlhKqz +ZBdDP4I2MB0GA1UdDgQWBBSMFlVwzBYKU2TCpYSqs2QXQz+CNjAMBgNVHRMEBTAD +AQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEklyWCxDF+pORDTxTRVfc95wynr3vnCQPnoVsXwL+z02exIUbhjOF6TbhiWhbnK +UJykuOpmJmiThW9vTHHQvnoLPDG5975pnhDX0UDorBZxq66rOOFwscqSFuBdhaYY +gAYAnOGmGEJRp2hoWe8mlF+tMQz+KR4XAYQ3W+gSMqNd +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913220207 (0x366ea26f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA + Validity + Not Before: Dec 9 15:46:48 1998 GMT + Not After : Dec 9 16:16:48 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:48:11:80:58:a0:d5:a5:99:0f:f6:37:2c:44: + b6:6e:d1:7c:f3:2a:6b:9e:11:b6:88:23:04:5c:71: + 25:9e:6a:12:77:11:6e:bf:68:39:65:a8:f6:b2:f6: + a2:18:b2:89:15:a0:67:b7:7a:8c:22:48:6b:f6:84: + 34:1f:b6:ca:f7:1b:72:cb:f2:5b:48:d3:87:1e:22: + 76:13:04:b4:ac:6c:96:7f:e7:0e:08:c9:32:51:30: + 2d:d5:80:e8:21:67:ba:f3:5e:08:24:2c:07:59:9d: + 90:1a:ee:46:c9:b5:a4:1e:96:b4:41:91:d4:7f:d2: + 8d:38:26:b0:6f:43:6e:09:7d + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DST (ANX Network) CA/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 15:46:48 1998 GMT, Not After: Dec 9 15:46:48 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36 + + X509v3 Subject Key Identifier: + 8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 49:25:c9:60:b1:0c:5f:a9:39:10:d3:c5:34:55:7d:cf:79:c3: + 29:eb:de:f9:c2:40:f9:e8:56:c5:f0:2f:ec:f4:d9:ec:48:51: + b8:63:38:5e:93:6e:18:96:85:b9:ca:50:9c:a4:b8:ea:66:26: + 68:93:85:6f:6f:4c:71:d0:be:7a:0b:3c:31:b9:f7:be:69:9e: + 10:d7:d1:40:e8:ac:16:71:ab:ae:ab:38:e1:70:b1:ca:92:16: + e0:5d:85:a6:18:80:06:00:9c:e1:a6:18:42:51:a7:68:68:59: + ef:26:94:5f:ad:31:0c:fe:29:1e:17:01:84:37:5b:e8:12:32: + a3:5d + +American Express CA +=================== +MD5 Fingerprint: 1C:D5:8E:82:BE:70:55:8E:39:61:DF:AD:51:DB:6B:A0 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICkDCCAfkCAgCNMA0GCSqGSIb3DQEBBAUAMIGPMQswCQYDVQQGEwJVUzEnMCUG +A1UEChMeQW1lcmljYW4gRXhwcmVzcyBDb21wYW55LCBJbmMuMSYwJAYDVQQLEx1B +bWVyaWNhbiBFeHByZXNzIFRlY2hub2xvZ2llczEvMC0GA1UEAxMmQW1lcmljYW4g +RXhwcmVzcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgwODE0MjIwMTAwWhcN +MDYwODE0MjM1OTAwWjCBjzELMAkGA1UEBhMCVVMxJzAlBgNVBAoTHkFtZXJpY2Fu +IEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1lcmljYW4gRXhwcmVz +cyBUZWNobm9sb2dpZXMxLzAtBgNVBAMTJkFtZXJpY2FuIEV4cHJlc3MgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ8kmS +hcr9FSm1BrZE7PyIo/KGzv8UTyQckvnCI8HOQ99dNMi4FOzVKnCRSZXXVs2U8amT +0Ggi3E19oApyKkfqJfCFAF82VGHPC/k3Wmed6R/pZD9wlWGn0DAC3iYopGYDBOkw ++48zB/lvYYeictvzaHhjZlmpybdm4RWySDYs+QIDAQABMA0GCSqGSIb3DQEBBAUA +A4GBAGgXYrhzi0xs60qlPqvlnS7SzYoHV/PGWZd2Fxf4Uo4nk9hY2Chs9KIEeorC +diSxArTfKPL386infiNIYYj0EWiuJl32oUtTJWrYKhQCDuCHIG6eGVxzkAsj4jGX +Iz/VIqLTBnvaN/XXtUFEF3pFAtmFRWbWjsfwegyZYiJpW+3S +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 141 (0x8d) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority + Validity + Not Before: Aug 14 22:01:00 1998 GMT + Not After : Aug 14 23:59:00 2006 GMT + Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:f2:49:92:85:ca:fd:15:29:b5:06:b6:44:ec: + fc:88:a3:f2:86:ce:ff:14:4f:24:1c:92:f9:c2:23: + c1:ce:43:df:5d:34:c8:b8:14:ec:d5:2a:70:91:49: + 95:d7:56:cd:94:f1:a9:93:d0:68:22:dc:4d:7d:a0: + 0a:72:2a:47:ea:25:f0:85:00:5f:36:54:61:cf:0b: + f9:37:5a:67:9d:e9:1f:e9:64:3f:70:95:61:a7:d0: + 30:02:de:26:28:a4:66:03:04:e9:30:fb:8f:33:07: + f9:6f:61:87:a2:72:db:f3:68:78:63:66:59:a9:c9: + b7:66:e1:15:b2:48:36:2c:f9 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 68:17:62:b8:73:8b:4c:6c:eb:4a:a5:3e:ab:e5:9d:2e:d2:cd: + 8a:07:57:f3:c6:59:97:76:17:17:f8:52:8e:27:93:d8:58:d8: + 28:6c:f4:a2:04:7a:8a:c2:76:24:b1:02:b4:df:28:f2:f7:f3: + a8:a7:7e:23:48:61:88:f4:11:68:ae:26:5d:f6:a1:4b:53:25: + 6a:d8:2a:14:02:0e:e0:87:20:6e:9e:19:5c:73:90:0b:23:e2: + 31:97:23:3f:d5:22:a2:d3:06:7b:da:37:f5:d7:b5:41:44:17: + 7a:45:02:d9:85:45:66:d6:8e:c7:f0:7a:0c:99:62:22:69:5b: + ed:d2 + +American Express Global CA +========================== +MD5 Fingerprint: 63:1B:66:93:8C:F3:66:CB:3C:79:57:DC:05:49:EA:DB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgICAIUwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAlVT +MScwJQYDVQQKEx5BbWVyaWNhbiBFeHByZXNzIENvbXBhbnksIEluYy4xJjAkBgNV +BAsTHUFtZXJpY2FuIEV4cHJlc3MgVGVjaG5vbG9naWVzMTYwNAYDVQQDEy1BbWVy +aWNhbiBFeHByZXNzIEdsb2JhbCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgw +ODE0MTkwNjAwWhcNMTMwODE0MjM1OTAwWjCBljELMAkGA1UEBhMCVVMxJzAlBgNV +BAoTHkFtZXJpY2FuIEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1l +cmljYW4gRXhwcmVzcyBUZWNobm9sb2dpZXMxNjA0BgNVBAMTLUFtZXJpY2FuIEV4 +cHJlc3MgR2xvYmFsIENlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAPAkJmYu++tKc3FTiUfLJjxTkpRMysKFtQ34w1e9 +Lyofahi3V68MABb6oLaQpvcaoS5mJsdoo4qTaWa1RlYtHYLqkAwKIsKJUI0F89Sr +c0HwzxKsKLRvFJSWWUuekHWG3+JH6+HpT0N+h8onGGaetcFAZX38YW+tm3LPqV7Y +8/nabpEQ+ky16n4g3qk5L/WI5IpvNcYgnCuGRjMK/DFVpWusFkDpzTVZbzIEw3u1 +D3t3cPNIuypSgs6vKW3xEW9t5gcAAe+a8yYNpnkTZ6/4qxx1rJG1a75AsN6cDLFp +hRlxkRNFyt/R/eayypaDedvFuKpbepALeFY+xteflEgR9a0CAwEAAaNaMFgwEgYD +VR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgoq +hkiG+Q8KAQUBMBkGA1UdDgQSBBBXRzV7NicRqAj8L0Yl6yRpMA0GCSqGSIb3DQEB +BQUAA4IBAQDHYUWoinG5vjTpIXshzVYTmNUwY+kYqkuSFb8LHbvskmnFLsNhi+gw +RcsQRsFzOFyLGdIr80DrfHKzLh4n43WVihybLsSVBYZy0FX0oZJSeVzb9Pjc5dcS +sUDHPIbkMWVKyjfG3nZXGWlMRmn8Kq0WN3qTrPchSy3766lQy8HRQAjaA2mHpzde +VcHF7cTjjgwml5tcV0ty4/IDBdACOyYDQJCevgtbSQx48dVMVSng9v1MA6lUAjLR +V1qFrEPtWzsWX6C/NdtLnnvo/+cNPDuom0lBRvVzTv+SZSGDE1Vx60k8f4gawhIo +JaFGS0E3l3/sjvHUoZbCILZerakcHhGg +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 133 (0x85) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority + Validity + Not Before: Aug 14 19:06:00 1998 GMT + Not After : Aug 14 23:59:00 2013 GMT + Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:f0:24:26:66:2e:fb:eb:4a:73:71:53:89:47:cb: + 26:3c:53:92:94:4c:ca:c2:85:b5:0d:f8:c3:57:bd: + 2f:2a:1f:6a:18:b7:57:af:0c:00:16:fa:a0:b6:90: + a6:f7:1a:a1:2e:66:26:c7:68:a3:8a:93:69:66:b5: + 46:56:2d:1d:82:ea:90:0c:0a:22:c2:89:50:8d:05: + f3:d4:ab:73:41:f0:cf:12:ac:28:b4:6f:14:94:96: + 59:4b:9e:90:75:86:df:e2:47:eb:e1:e9:4f:43:7e: + 87:ca:27:18:66:9e:b5:c1:40:65:7d:fc:61:6f:ad: + 9b:72:cf:a9:5e:d8:f3:f9:da:6e:91:10:fa:4c:b5: + ea:7e:20:de:a9:39:2f:f5:88:e4:8a:6f:35:c6:20: + 9c:2b:86:46:33:0a:fc:31:55:a5:6b:ac:16:40:e9: + cd:35:59:6f:32:04:c3:7b:b5:0f:7b:77:70:f3:48: + bb:2a:52:82:ce:af:29:6d:f1:11:6f:6d:e6:07:00: + 01:ef:9a:f3:26:0d:a6:79:13:67:af:f8:ab:1c:75: + ac:91:b5:6b:be:40:b0:de:9c:0c:b1:69:85:19:71: + 91:13:45:ca:df:d1:fd:e6:b2:ca:96:83:79:db:c5: + b8:aa:5b:7a:90:0b:78:56:3e:c6:d7:9f:94:48:11: + f5:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 1.2.840.113807.10.1.5.1 + + X509v3 Subject Key Identifier: + 57:47:35:7B:36:27:11:A8:08:FC:2F:46:25:EB:24:69 + Signature Algorithm: sha1WithRSAEncryption + c7:61:45:a8:8a:71:b9:be:34:e9:21:7b:21:cd:56:13:98:d5: + 30:63:e9:18:aa:4b:92:15:bf:0b:1d:bb:ec:92:69:c5:2e:c3: + 61:8b:e8:30:45:cb:10:46:c1:73:38:5c:8b:19:d2:2b:f3:40: + eb:7c:72:b3:2e:1e:27:e3:75:95:8a:1c:9b:2e:c4:95:05:86: + 72:d0:55:f4:a1:92:52:79:5c:db:f4:f8:dc:e5:d7:12:b1:40: + c7:3c:86:e4:31:65:4a:ca:37:c6:de:76:57:19:69:4c:46:69: + fc:2a:ad:16:37:7a:93:ac:f7:21:4b:2d:fb:eb:a9:50:cb:c1: + d1:40:08:da:03:69:87:a7:37:5e:55:c1:c5:ed:c4:e3:8e:0c: + 26:97:9b:5c:57:4b:72:e3:f2:03:05:d0:02:3b:26:03:40:90: + 9e:be:0b:5b:49:0c:78:f1:d5:4c:55:29:e0:f6:fd:4c:03:a9: + 54:02:32:d1:57:5a:85:ac:43:ed:5b:3b:16:5f:a0:bf:35:db: + 4b:9e:7b:e8:ff:e7:0d:3c:3b:a8:9b:49:41:46:f5:73:4e:ff: + 92:65:21:83:13:55:71:eb:49:3c:7f:88:1a:c2:12:28:25:a1: + 46:4b:41:37:97:7f:ec:8e:f1:d4:a1:96:c2:20:b6:5e:ad:a9: + 1c:1e:11:a0 + +BelSign Object Publishing CA +============================ +MD5 Fingerprint: 8A:02:F8:DF:B8:E1:84:9F:5A:C2:60:24:65:D1:73:FB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAzCCAmygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBuzELMAkGA1UEBhMCQkUx +ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQL +Ey9CZWxTaWduIE9iamVjdCBQdWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0 +eTElMCMGA1UEAxMcQmVsU2lnbiBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqG +SIb3DQEJARYUd2VibWFzdGVyQGJlbHNpZ24uYmUwHhcNOTcwOTE5MjIwMzAwWhcN +MDcwOTE5MjIwMzAwWjCBuzELMAkGA1UEBhMCQkUxETAPBgNVBAcTCEJydXNzZWxz +MRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQLEy9CZWxTaWduIE9iamVjdCBQ +dWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0eTElMCMGA1UEAxMcQmVsU2ln +biBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqGSIb3DQEJARYUd2VibWFzdGVy +QGJlbHNpZ24uYmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQuH7a/7oJA +3fm3LkHVngWxWtAmfGJVA5v8y2HeS+/+6Jn+h7mIz5DaDwk8dt8Xl7bLPyVF/bS8 +WAC+sFq2FIeP7mdkrR2Ig7tnn2VhAFgIgFCfgMkx9iqQHC33SmwQ9iNDXTgJYIhX +As0WbBj8zfuSKnfQnpOjXYhk0Mj4XVRRAgMBAAGjFTATMBEGCWCGSAGG+EIBAQQE +AwIABzANBgkqhkiG9w0BAQQFAAOBgQBjdhd8lvBTpV0BHFPOKcJ+daxMDaIIc7Rq +Mf0CBhSZ3FQEpL/IloafMUMyJVf2hfYluze+oXkjyVcGJXFrRU/49AJAFoIir1Tq +Mij2De6ZuksIUQ9uhiMhTC0liIHELg7xEyw4ipUCJMM6lWPkk45IuwhHcl+u5jpa +R9Zxxp6aUg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmaster@belsign.be + Validity + Not Before: Sep 19 22:03:00 1997 GMT + Not After : Sep 19 22:03:00 2007 GMT + Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmaster@belsign.be + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:2e:1f:b6:bf:ee:82:40:dd:f9:b7:2e:41:d5: + 9e:05:b1:5a:d0:26:7c:62:55:03:9b:fc:cb:61:de: + 4b:ef:fe:e8:99:fe:87:b9:88:cf:90:da:0f:09:3c: + 76:df:17:97:b6:cb:3f:25:45:fd:b4:bc:58:00:be: + b0:5a:b6:14:87:8f:ee:67:64:ad:1d:88:83:bb:67: + 9f:65:61:00:58:08:80:50:9f:80:c9:31:f6:2a:90: + 1c:2d:f7:4a:6c:10:f6:23:43:5d:38:09:60:88:57: + 02:cd:16:6c:18:fc:cd:fb:92:2a:77:d0:9e:93:a3: + 5d:88:64:d0:c8:f8:5d:54:51 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 63:76:17:7c:96:f0:53:a5:5d:01:1c:53:ce:29:c2:7e:75:ac: + 4c:0d:a2:08:73:b4:6a:31:fd:02:06:14:99:dc:54:04:a4:bf: + c8:96:86:9f:31:43:32:25:57:f6:85:f6:25:bb:37:be:a1:79: + 23:c9:57:06:25:71:6b:45:4f:f8:f4:02:40:16:82:22:af:54: + ea:32:28:f6:0d:ee:99:ba:4b:08:51:0f:6e:86:23:21:4c:2d: + 25:88:81:c4:2e:0e:f1:13:2c:38:8a:95:02:24:c3:3a:95:63: + e4:93:8e:48:bb:08:47:72:5f:ae:e6:3a:5a:47:d6:71:c6:9e: + 9a:52 + +BelSign Secure Server CA +======================== +MD5 Fingerprint: 3D:5E:82:C6:D9:AD:D9:8B:93:6B:0C:10:B9:49:0A:B1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC8zCCAlygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBszELMAkGA1UEBhMCQkUx +ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTQwMgYDVQQL +EytCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSEw +HwYDVQQDExhCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ0ExIzAhBgkqhkiG9w0BCQEW +FHdlYm1hc3RlckBiZWxzaWduLmJlMB4XDTk3MDcxNjIyMDA1NFoXDTA3MDcxNjIy +MDA1NFowgbMxCzAJBgNVBAYTAkJFMREwDwYDVQQHEwhCcnVzc2VsczETMBEGA1UE +ChMKQmVsU2lnbiBOVjE0MDIGA1UECxMrQmVsU2lnbiBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRlIEF1dGhvcml0eTEhMB8GA1UEAxMYQmVsU2lnbiBTZWN1cmUgU2Vy +dmVyIENBMSMwIQYJKoZIhvcNAQkBFhR3ZWJtYXN0ZXJAYmVsc2lnbi5iZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1gESeJL4BEJ/yccig/x8R3AwK0kLPjZA +kCjaIXODU/LE0RZAwFP/rqbGJLMnbaWzPTl3XagG9ubpvGMRTgZlcAqdk/miQIt/ +SoQOjRax1swIZBIM4ChLyKWEkBf7EUYu1qeFGMsYrmOasFgG9ADP+MQJGjUMofnu +Sv1t3v4mpTsCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgCgMA0GCSqGSIb3DQEB +BAUAA4GBAGw9mcMF4h3K5S2qaIWLQDEgZhNo5lg6idCNdbLFYth9go/32TKBd/Y1 +W4UpzmeyubwrGXjP84f9RvGVdbIJVwMwwXrNckdxgMp9ncllPEcRIn36BwsoeKGT +6AVFSOIyMko96FMcELfHc4wHUOH5yStTQfWDjeUJOUqOA2KqQGOL +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmaster@belsign.be + Validity + Not Before: Jul 16 22:00:54 1997 GMT + Not After : Jul 16 22:00:54 2007 GMT + Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmaster@belsign.be + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:01:12:78:92:f8:04:42:7f:c9:c7:22:83:fc: + 7c:47:70:30:2b:49:0b:3e:36:40:90:28:da:21:73: + 83:53:f2:c4:d1:16:40:c0:53:ff:ae:a6:c6:24:b3: + 27:6d:a5:b3:3d:39:77:5d:a8:06:f6:e6:e9:bc:63: + 11:4e:06:65:70:0a:9d:93:f9:a2:40:8b:7f:4a:84: + 0e:8d:16:b1:d6:cc:08:64:12:0c:e0:28:4b:c8:a5: + 84:90:17:fb:11:46:2e:d6:a7:85:18:cb:18:ae:63: + 9a:b0:58:06:f4:00:cf:f8:c4:09:1a:35:0c:a1:f9: + ee:4a:fd:6d:de:fe:26:a5:3b + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL Client, S/MIME + Signature Algorithm: md5WithRSAEncryption + 6c:3d:99:c3:05:e2:1d:ca:e5:2d:aa:68:85:8b:40:31:20:66: + 13:68:e6:58:3a:89:d0:8d:75:b2:c5:62:d8:7d:82:8f:f7:d9: + 32:81:77:f6:35:5b:85:29:ce:67:b2:b9:bc:2b:19:78:cf:f3: + 87:fd:46:f1:95:75:b2:09:57:03:30:c1:7a:cd:72:47:71:80: + ca:7d:9d:c9:65:3c:47:11:22:7d:fa:07:0b:28:78:a1:93:e8: + 05:45:48:e2:32:32:4a:3d:e8:53:1c:10:b7:c7:73:8c:07:50: + e1:f9:c9:2b:53:41:f5:83:8d:e5:09:39:4a:8e:03:62:aa:40: + 63:8b + +Deutsche Telekom AG Root CA +=========================== +MD5 Fingerprint: 77:DE:04:94:77:D0:0C:5F:A7:B1:F4:30:18:87:FB:55 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICjjCCAfegAwIBAgIBBjANBgkqhkiG9w0BAQQFADBtMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEdMBsGA1UECxMUVGVsZVNlYyBU +cnVzdCBDZW50ZXIxITAfBgNVBAMTGERldXRzY2hlIFRlbGVrb20gUm9vdCBDQTAe +Fw05ODEyMDkwOTExMDBaFw0wNDEyMDkyMzU5MDBaMG0xCzAJBgNVBAYTAkRFMRww +GgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR0wGwYDVQQLExRUZWxlU2VjIFRy +dXN0IENlbnRlcjEhMB8GA1UEAxMYRGV1dHNjaGUgVGVsZWtvbSBSb290IENBMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdBSz5BbO5EtdpcffqVjAIVxRDe7sa +nG0vV2HX4vVEa+42QZb2ZM7hwbK5pBQEmFDocPiONZp9ScFhHVmu2gYYlX2tzuyp +vtEYD0CRdiqj5f3+iRX0V/fgVdp1rQD0LME1zLRDJlViRC4BJZyKW/DB0AA1eP41 +3pRAZHiDocw5iQIDAQABoz4wPDAPBgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQE +AwIBBjAZBgNVHQ4EEgQQLIdZH4sTgLL5hp0+En5YljANBgkqhkiG9w0BAQQFAAOB +gQAP/nO1B4hvoAuJ6spQH5TelCsLJ15P9RyVJtqMllStGZE3Q12ryYuzzW+YOT3t +3TXjcbftE5OD6IblKTMTE7w1e/0oL3BZ1dO0jSgTWTvI1XT5RcIHYKq4GFT5pWj/ +1wXVj7YFMS5BSvQQH2BHGguLGU2SVyDS71AZ6M3QcLy8Ng== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA + Validity + Not Before: Dec 9 09:11:00 1998 GMT + Not After : Dec 9 23:59:00 2004 GMT + Subject: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:dd:05:2c:f9:05:b3:b9:12:d7:69:71:f7:ea:56: + 30:08:57:14:43:7b:bb:1a:9c:6d:2f:57:61:d7:e2: + f5:44:6b:ee:36:41:96:f6:64:ce:e1:c1:b2:b9:a4: + 14:04:98:50:e8:70:f8:8e:35:9a:7d:49:c1:61:1d: + 59:ae:da:06:18:95:7d:ad:ce:ec:a9:be:d1:18:0f: + 40:91:76:2a:a3:e5:fd:fe:89:15:f4:57:f7:e0:55: + da:75:ad:00:f4:2c:c1:35:cc:b4:43:26:55:62:44: + 2e:01:25:9c:8a:5b:f0:c1:d0:00:35:78:fe:35:de: + 94:40:64:78:83:a1:cc:39:89 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 2C:87:59:1F:8B:13:80:B2:F9:86:9D:3E:12:7E:58:96 + Signature Algorithm: md5WithRSAEncryption + 0f:fe:73:b5:07:88:6f:a0:0b:89:ea:ca:50:1f:94:de:94:2b: + 0b:27:5e:4f:f5:1c:95:26:da:8c:96:54:ad:19:91:37:43:5d: + ab:c9:8b:b3:cd:6f:98:39:3d:ed:dd:35:e3:71:b7:ed:13:93: + 83:e8:86:e5:29:33:13:13:bc:35:7b:fd:28:2f:70:59:d5:d3: + b4:8d:28:13:59:3b:c8:d5:74:f9:45:c2:07:60:aa:b8:18:54: + f9:a5:68:ff:d7:05:d5:8f:b6:05:31:2e:41:4a:f4:10:1f:60: + 47:1a:0b:8b:19:4d:92:57:20:d2:ef:50:19:e8:cd:d0:70:bc: + bc:36 + +Digital Signature Trust Co. Global CA 1 +======================================= +MD5 Fingerprint: 25:7A:BA:83:2E:B6:A2:0B:DA:FE:F5:02:0F:08:D7:AD +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg +bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ +j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV +Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw +MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 +fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i ++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN +QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ +gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913315222 (0x36701596) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Validity + Not Before: Dec 10 18:10:23 1998 GMT + Not After : Dec 10 18:40:23 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a0:6c:81:a9:cf:34:1e:24:dd:fe:86:28:cc:de: + 83:2f:f9:5e:d4:42:d2:e8:74:60:66:13:98:06:1c: + a9:51:12:69:6f:31:55:b9:49:72:00:08:7e:d3:a5: + 62:44:37:24:99:8f:d9:83:48:8f:99:6d:95:13:bb: + 43:3b:2e:49:4e:88:37:c1:bb:58:7f:fe:e1:bd:f8: + bb:61:cd:f3:47:c0:99:a6:f1:f3:91:e8:78:7c:00: + cb:61:c9:44:27:71:69:55:4a:7e:49:4d:ed:a2:a3: + be:02:4c:00:ca:02:a8:ee:01:02:31:64:0f:52:2d: + 13:74:76:36:b5:7a:b4:2d:71 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E1/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 10 18:10:23 1998 GMT, Not After: Dec 10 18:10:23 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + + X509v3 Subject Key Identifier: + 6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 22:12:d8:7a:1d:dc:81:06:b6:09:65:b2:87:c8:1f:5e:b4:2f: + e9:c4:1e:f2:3c:c1:bb:04:90:11:4a:83:4e:7e:93:b9:4d:42: + c7:92:26:a0:5c:34:9a:38:72:f8:fd:6b:16:3e:20:ee:82:8b: + 31:2a:93:36:85:23:88:8a:3c:03:68:d3:c9:09:0f:4d:fc:6c: + a4:da:28:72:93:0e:89:80:b0:7d:fe:80:6f:65:6d:18:33:97: + 8b:c2:6b:89:ee:60:3d:c8:9b:ef:7f:2b:32:62:73:93:cb:3c: + e3:7b:e2:76:78:45:bc:a1:93:04:bb:86:9f:3a:5b:43:7a:c3: + 8a:65 + +Digital Signature Trust Co. Global CA 2 +======================================= +MD5 Fingerprint: 6C:C9:A7:6E:47:F1:0C:E3:53:3B:78:4C:4D:C2:6A:C5 +PEM Data: +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx +ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf +WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK +xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE +zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F +5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv +OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz +ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME +lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG +Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q +gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k +Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:02:7c:00:00:00:02:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=ca@digsigtrust.com + Validity + Not Before: Dec 1 18:18:55 1998 GMT + Not After : Nov 28 18:18:55 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:c6:26:b6:e7:a5:3d:c1:c4:68:d5:50:6f:53: + c5:6f:49:13:09:b8:af:2c:48:8d:14:6a:a3:17:5f: + 5a:f9:d3:2e:75:2f:d8:28:62:d1:93:2f:fc:4d:d4: + ab:87:e5:08:c7:99:e7:92:3f:75:bd:eb:25:b4:15: + c1:9b:19:3d:d2:44:8d:d7:74:20:6d:37:02:8f:69: + 93:5b:8a:c4:19:9d:f4:b2:0e:fc:16:6c:b9:b1:05: + 92:83:d1:85:2c:60:94:3e:45:55:a0:d9:ab:08:21: + e6:60:e8:3b:74:f2:99:50:51:68:d0:03:2d:b1:80: + be:a3:d8:52:b0:44:cd:43:4a:70:8e:58:85:95:e1: + 4e:2c:d6:2d:41:6f:d6:84:e7:c8:98:44:ca:47:db: + 2c:24:a5:69:26:cf:6b:b8:27:62:c3:f4:c9:7a:92: + 23:ed:13:67:82:ae:45:2e:45:e5:7e:72:3f:85:9d: + 94:62:10:e6:3c:91:a1:ad:77:00:e0:15:ec:f3:84: + 80:72:7a:8e:6e:60:97:c7:24:59:10:34:83:5b:e1: + a5:a4:69:b6:57:35:1c:78:59:c6:d3:2f:3a:73:67: + ee:94:ca:04:13:05:62:06:70:23:b3:f4:7c:ee:45: + d9:64:0b:5b:49:aa:a4:43:ce:26:c4:44:12:6c:b8: + dd:79 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + a2:37:b2:3f:69:fb:d7:86:79:54:49:31:95:33:2b:f3:d1:09: + 14:49:62:60:86:a5:b0:11:e2:50:c2:1d:06:57:3e:2d:e8:33: + 64:be:9b:aa:ad:5f:1b:4d:d4:99:95:a2:8b:9a:c9:62:72:b5: + 69:ea:d9:58:ab:35:ed:15:a2:43:d6:b6:bc:07:79:65:64:73: + 7d:d7:79:ca:7b:d5:5a:51:c6:e1:53:04:96:8d:38:cf:a3:17: + ac:39:71:6b:01:c3:8b:53:3c:63:e9:ee:79:c0:e4:be:92:32: + 64:7a:b3:1f:97:94:62:bd:ea:b2:20:15:95:fb:97:f2:78:2f: + 63:36:40:38:e3:46:0f:1d:dd:ac:95:ca:e7:4b:90:7b:b1:4b: + a9:d4:c5:eb:9a:da:aa:d5:a3:94:14:46:8d:2d:1f:f3:3a:d6: + 93:3a:f6:3e:79:fc:e8:e6:b0:75:ed:ee:3d:c9:70:c7:5d:aa: + 81:4b:46:25:1c:c7:6c:15:e3:95:4e:0f:aa:32:37:94:0a:17: + 24:92:13:84:58:d2:63:6f:2b:f7:e6:5b:62:0b:13:17:b0:0d: + 52:4c:fe:fe:6f:5c:e2:91:6e:1d:fd:a4:62:d7:68:fa:8e:7a: + 4f:d2:08:da:93:dc:f0:92:11:7a:d0:dc:72:93:0c:73:93:62: + 85:68:d0:f4 + +Digital Signature Trust Co. Global CA 3 +======================================= +MD5 Fingerprint: 93:C2:8E:11:7B:D4:F3:03:19:BD:28:75:13:4A:45:4A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ +k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso +LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o +TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 +MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C +TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 +WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR +xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL +B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913232846 (0x366ed3ce) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Validity + Not Before: Dec 9 19:17:26 1998 GMT + Not After : Dec 9 19:47:26 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:93:8f:17:92:ef:33:13:18:eb:10:7f:4e:16: + bf:ff:06:8f:2a:85:bc:5e:f9:24:a6:24:88:b6:03: + b7:c1:c3:5f:03:5b:d1:6f:ae:7e:42:ea:66:23:b8: + 63:83:56:fb:28:2d:e1:38:8b:b4:ee:a8:01:e1:ce: + 1c:b6:88:2a:22:46:85:fb:9f:a7:70:a9:47:14:3f: + ce:de:65:f0:a8:71:f7:4f:26:6c:8c:bc:c6:b5:ef: + de:49:27:ff:48:2a:7d:e8:4d:03:cc:c7:b2:52:c6: + 17:31:13:3b:b5:4d:db:c8:c4:f6:c3:0f:24:2a:da: + 0c:9d:e7:91:5b:80:cd:94:9d + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E2/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 19:17:26 1998 GMT, Not After: Dec 9 19:17:26 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + + X509v3 Subject Key Identifier: + 1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 47:8d:83:ad:62:f2:db:b0:9e:45:22:05:b9:a2:d6:03:0e:38: + 72:e7:9e:fc:7b:e6:93:b6:9a:a5:a2:94:c8:34:1d:91:d1:c5: + d7:f4:0a:25:0f:3d:78:81:9e:0f:b1:67:c4:90:4c:63:dd:5e: + a7:e2:ba:9f:f5:f7:4d:a5:31:7b:9c:29:2d:4c:fe:64:3e:ec: + b6:53:fe:ea:9b:ed:82:db:74:75:4b:07:79:6e:1e:d8:19:83: + 73:de:f5:3e:d0:b5:de:e7:4b:68:7d:43:2e:2a:20:e1:7e:a0: + 78:44:9e:08:f5:98:f9:c7:7f:1b:1b:d6:06:20:02:58:a1:c3: + a2:03 + +Digital Signature Trust Co. Global CA 4 +======================================= +MD5 Fingerprint: CD:3B:3D:62:5B:09:B8:09:36:87:9E:12:2F:71:64:BA +PEM Data: +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy +MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV +p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw +BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl +5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi +3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+ +QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ +2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN +I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL +553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q +10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN +uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:77:6d:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=ca@digsigtrust.com + Validity + Not Before: Nov 30 22:46:16 1998 GMT + Not After : Nov 27 22:46:16 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dc:75:f0:8c:c0:75:96:9a:c0:62:1f:26:f7:c4: + e1:9a:ea:e0:56:73:5b:99:cd:01:44:a8:08:b6:d5: + a7:da:1a:04:18:39:92:4a:78:a3:81:c2:f5:77:7a: + 50:b4:70:ff:9a:ab:c6:c7:ca:6e:83:4f:42:98:fb: + 26:0b:da:dc:6d:d6:a9:99:55:52:67:e9:28:03:92: + dc:e5:b0:05:9a:0f:15:f9:6b:59:72:56:f2:fa:39: + fc:aa:68:ee:0f:1f:10:83:2f:fc:9d:fa:17:96:dd: + 82:e3:e6:45:7d:c0:4b:80:44:1f:ed:2c:e0:84:fd: + 91:5c:92:54:69:25:e5:62:69:dc:e5:ee:00:52:bd: + 33:0b:ad:75:02:85:a7:64:50:2d:c5:19:19:30:c0: + 26:db:c9:d3:fd:2e:99:ad:59:b5:0b:4d:d4:41:ae: + 85:48:43:59:dc:b7:a8:e2:a2:de:c3:8f:d7:b8:a1: + 62:a6:68:50:52:e4:cf:31:a7:94:85:da:9f:46:32: + 17:56:e5:f2:eb:66:3d:12:ff:43:db:98:ef:77:cf: + cb:81:8d:34:b1:c6:50:4a:26:d1:e4:3e:41:50:af: + 6c:ae:22:34:2e:d5:6b:6e:83:ba:79:b8:76:65:48: + da:09:29:64:63:22:b9:fb:47:76:85:8c:86:44:cb: + 09:db + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + b5:36:0e:5d:e1:61:28:5a:11:65:c0:3f:83:03:79:4d:be:28: + a6:0b:07:02:52:85:cd:f8:91:d0:10:6c:b5:6a:20:5b:1c:90: + d9:30:3c:c6:48:9e:8a:5e:64:f9:a1:71:77:ef:04:27:1f:07: + eb:e4:26:f7:73:74:c9:44:18:1a:66:d3:e0:43:af:91:3b:d1: + cb:2c:d8:74:54:3a:1c:4d:ca:d4:68:cd:23:7c:1d:10:9e:45: + e9:f6:00:6e:a6:cd:19:ff:4f:2c:29:8f:57:4d:c4:77:92:be: + e0:4c:09:fb:5d:44:86:66:21:a8:b9:32:a2:56:d5:e9:8c:83: + 7c:59:3f:c4:f1:0b:e7:9d:ec:9e:bd:9c:18:0e:3e:c2:39:79: + 28:b7:03:0d:08:cb:c6:e7:d9:01:37:50:10:ec:cc:61:16:40: + d4:af:31:74:7b:fc:3f:31:a7:d0:47:73:33:39:1b:cc:4e:6a: + d7:49:83:11:06:fe:eb:82:58:33:32:4c:f0:56:ac:1e:9c:2f: + 56:9a:7b:c1:4a:1c:a5:fd:55:36:ce:fc:96:4d:f4:b0:f0:ec: + b7:6c:82:ed:2f:31:99:42:4c:a9:b2:0d:b8:15:5d:f1:df:ba: + c9:b5:4a:d4:64:98:b3:26:a9:30:c8:fd:a6:ec:ab:96:21:ad: + 7f:c2:78:b6 + +Entrust Worldwide by DST +======================== +MD5 Fingerprint: B4:65:22:0A:7C:AD:DF:41:B7:D5:44:D5:AD:FA:9A:75 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDRzCCArCgAwIBAgIENm3FGDANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRswGQYDVQQL +ExJEU1QtRW50cnVzdCBHVEkgQ0EwHhcNOTgxMjA5MDAwMjI0WhcNMTgxMjA5MDAz +MjI0WjBQMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg +VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0EwgZ0wDQYJKoZI +hvcNAQEBBQADgYsAMIGHAoGBALYd90uNDxPjEvUJ/gYyDq9MQfV91Ec9KgrfgwXe +3n3mAxb2UTrLRxpKrX7E/R20vnSKeN0Lg460hBPE+/htKa6h4Q8PQ+O1XmBp+oOU +/Hnm3Hbt0UQrjv0Su/4XdxcMie2n71F9xO04wzujevviTaBgtfL9E2XTxuw/vjWc +PSLvAgEDo4IBLjCCASowEQYJYIZIAYb4QgEBBAQDAgAHMHIGA1UdHwRrMGkwZ6Bl +oGOkYTBfMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg +VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0ExDTALBgNVBAMT +BENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkwMDAyMjRagQ8yMDE4MTIwOTAwMDIy +NFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFJOaRMrQeFOAKUkE38evMz+ZdV+u +MB0GA1UdDgQWBBSTmkTK0HhTgClJBN/HrzM/mXVfrjAMBgNVHRMEBTADAQH/MBkG +CSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GBAGSJzAOn +3AryWCDn/RegKHLNh7DNmLUkR2MzMRAQsu+KV3KuTAPgZ5+sYEOEIsGpo+Wxp94J +1M8NeEYjW49Je/4TIpeU6nJI4SwgeJbpZkUZywllY2E/0UmYsXYQVdVjSmZLpAdr +3nt/ueaTWxoCW4AO3Y0Y1Iqjwmjxo+AY0U5M +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913163544 (0x366dc518) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA + Validity + Not Before: Dec 9 00:02:24 1998 GMT + Not After : Dec 9 00:32:24 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:1d:f7:4b:8d:0f:13:e3:12:f5:09:fe:06:32: + 0e:af:4c:41:f5:7d:d4:47:3d:2a:0a:df:83:05:de: + de:7d:e6:03:16:f6:51:3a:cb:47:1a:4a:ad:7e:c4: + fd:1d:b4:be:74:8a:78:dd:0b:83:8e:b4:84:13:c4: + fb:f8:6d:29:ae:a1:e1:0f:0f:43:e3:b5:5e:60:69: + fa:83:94:fc:79:e6:dc:76:ed:d1:44:2b:8e:fd:12: + bb:fe:17:77:17:0c:89:ed:a7:ef:51:7d:c4:ed:38: + c3:3b:a3:7a:fb:e2:4d:a0:60:b5:f2:fd:13:65:d3: + c6:ec:3f:be:35:9c:3d:22:ef + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DST-Entrust GTI CA/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 00:02:24 1998 GMT, Not After: Dec 9 00:02:24 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE + + X509v3 Subject Key Identifier: + 93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 64:89:cc:03:a7:dc:0a:f2:58:20:e7:fd:17:a0:28:72:cd:87: + b0:cd:98:b5:24:47:63:33:31:10:10:b2:ef:8a:57:72:ae:4c: + 03:e0:67:9f:ac:60:43:84:22:c1:a9:a3:e5:b1:a7:de:09:d4: + cf:0d:78:46:23:5b:8f:49:7b:fe:13:22:97:94:ea:72:48:e1: + 2c:20:78:96:e9:66:45:19:cb:09:65:63:61:3f:d1:49:98:b1: + 76:10:55:d5:63:4a:66:4b:a4:07:6b:de:7b:7f:b9:e6:93:5b: + 1a:02:5b:80:0e:dd:8d:18:d4:8a:a3:c2:68:f1:a3:e0:18:d1: + 4e:4c + +Entrust.net Premium 2048 Secure Server CA +========================================= +MD5 Fingerprint: BA:21:EA:20:D6:DD:DB:8F:C1:57:8B:40:AD:A1:FC:FC +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy +MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA +vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G +CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA +WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ +h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 +f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN +B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy +vUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 946059622 (0x3863b966) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Validity + Not Before: Dec 24 17:50:51 1999 GMT + Not After : Dec 24 18:20:51 2019 GMT + Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64: + 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7: + 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76: + 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf: + e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1: + 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29: + b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64: + ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c: + e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89: + a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90: + 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2: + cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a: + fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55: + 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86: + 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26: + 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e: + 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0: + 07:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Authority Key Identifier: + keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + + X509v3 Subject Key Identifier: + 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 59:47:ac:21:84:8a:17:c9:9c:89:53:1e:ba:80:85:1a:c6:3c: + 4e:3e:b1:9c:b6:7c:c6:92:5d:18:64:02:e3:d3:06:08:11:61: + 7c:63:e3:2b:9d:31:03:70:76:d2:a3:28:a0:f4:bb:9a:63:73: + ed:6d:e5:2a:db:ed:14:a9:2b:c6:36:11:d0:2b:eb:07:8b:a5: + da:9e:5c:19:9d:56:12:f5:54:29:c8:05:ed:b2:12:2a:8d:f4: + 03:1b:ff:e7:92:10:87:b0:3a:b5:c3:9d:05:37:12:a3:c7:f4: + 15:b9:d5:a4:39:16:9b:53:3a:23:91:f1:a8:82:a2:6a:88:68: + c1:79:02:22:bc:aa:a6:d6:ae:df:b0:14:5f:b8:87:d0:dd:7c: + 7f:7b:ff:af:1c:cf:e6:db:07:ad:5e:db:85:9d:d0:2b:0d:33: + db:04:d1:e6:49:40:13:2b:76:fb:3e:e9:9c:89:0f:15:ce:18: + b0:85:78:21:4f:6b:4f:0e:fa:36:67:cd:07:f2:ff:08:d0:e2: + de:d9:bf:2a:af:b8:87:86:21:3c:04:ca:b7:94:68:7f:cf:3c: + e9:98:d7:38:ff:ec:c0:d9:50:f0:2e:4b:58:ae:46:6f:d0:2e: + c3:60:da:72:55:72:bd:4c:45:9e:61:ba:bf:84:81:92:03:d1: + d2:69:7c:c5 + +Entrust.net Secure Personal CA +============================== +MD5 Fingerprint: 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u +ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh +Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D +bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq +RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo +6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux +5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm +AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC +ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 +cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m +by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp +IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg +Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg +KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV +HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E +BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE +FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 +pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz +wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a +EkP/TOYGJqibGapEPHayXOw= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 939758062 (0x380391ee) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Validity + Not Before: Oct 12 19:24:30 1999 GMT + Not After : Oct 12 19:54:30 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:3a:99:5e:31:17:df:ac:27:6f:90:7b:e4:19: + ff:45:a3:34:c2:db:c1:a8:4f:f0:68:ea:84:fd:9f: + 75:79:cf:c1:8a:51:94:af:c7:57:03:47:64:9e:ad: + 82:1b:5a:da:7f:37:78:47:bb:37:98:12:96:ce:c6: + 13:7d:ef:d2:0c:30:51:a9:39:9e:55:f8:fb:b1:e7: + 30:de:83:b2:ba:3e:f1:d5:89:3b:3b:85:ba:aa:74: + 2c:fe:3f:31:6e:af:91:95:6e:06:d4:07:4d:4b:2c: + 56:47:18:04:52:da:0e:10:93:bf:63:90:9b:e1:df: + 8c:e6:02:a4:e6:4f:5e:f7:8b + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab./OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Client Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/Client1.crl + + X509v3 Private Key Usage Period: + Not Before: Oct 12 19:24:30 1999 GMT, Not After: Oct 12 19:24:30 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + + X509v3 Subject Key Identifier: + C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: md5WithRSAEncryption + 3f:ae:8a:f1:d7:66:03:05:9e:3e:fa:ea:1c:46:bb:a4:5b:8f: + 78:9a:12:48:99:f9:f4:35:de:0c:36:07:02:6b:10:3a:89:14: + 81:9c:31:a6:7c:b2:41:b2:6a:e7:07:01:a1:4b:f9:9f:25:3b: + 96:ca:99:c3:3e:a1:51:1c:f3:c3:2e:44:f7:b0:67:46:aa:92: + e5:3b:da:1c:19:14:38:30:d5:e2:a2:31:25:2e:f1:ec:45:38: + ed:f8:06:58:03:73:62:b0:10:31:8f:40:bf:64:e0:5c:3e:c5: + 4f:1f:da:12:43:ff:4c:e6:06:26:a8:9b:19:aa:44:3c:76:b2: + 5c:ec + +Entrust.net Secure Server CA +============================ +MD5 Fingerprint: DF:F2:80:73:CC:F1:E6:61:73:FC:F5:42:E9:C5:7C:EE +PEM Data: +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 927650371 (0x374ad243) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Validity + Not Before: May 25 16:09:40 1999 GMT + Not After : May 25 16:39:40 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff: + af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1: + 0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81: + 26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71: + d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24: + da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29: + 92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8: + ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81: + b1:16:19:61:b9:54:b6:e6:43 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/net1.crl + + X509v3 Private Key Usage Period: + Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + + X509v3 Subject Key Identifier: + F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb: + 47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d: + f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31: + c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb: + a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58: + 0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54: + 73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06: + f9:b2 + +Equifax Premium CA +================== +MD5 Fingerprint: A9:E9:A8:9D:0E:73:E3:B1:2F:37:0D:E8:48:3F:86:ED +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDIzCCAoygAwIBAgIENeHvHjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEuMCwGA1UECxMlRXF1aWZheCBQcmVtaXVtIENl +cnRpZmljYXRlIEF1dGhvcml0eTAeFw05ODA4MjQyMjU0MjNaFw0xODA4MjQyMjU0 +MjNaME8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVF +cXVpZmF4IFByZW1pdW0gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDOoQaOBswIC8GGqN4g1Q0O0Q3En+pq2bPCMkdAb4qI +pAm9OCwd5svmpPM269rrvPxkswf2Lbyqzp8ZSGhK/PWiRX4JEPWPs0lcIwY56hOL +uAvNkR12X9k3oUT7X5DyZ7PNGJlDH3YSawLylYM4Q8L2YjTKyXhdX9LYupr/vhBg +WwIDAQABo4IBCjCCAQYwcQYDVR0fBGowaDBmoGSgYqRgMF4xCzAJBgNVBAYTAlVT +MRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVFcXVpZmF4IFByZW1pdW0gQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIw +MTgwODI0MjI1NDIzWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUFe6yKFmrbuX4 +z4uB9CThrj91G5gwHQYDVR0OBBYEFBXusihZq27l+M+LgfQk4a4/dRuYMAwGA1Ud +EwQFMAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEB +BQUAA4GBAL0LnCepA9so3JipS9DRjqeoGlqR4Jzx9xh8LiKeNh/JqLXNRkpu+jUH +G4YI65/iqPmdQS06rlxctl80BOv8KmCw+3TkhellOJbuFcfGd2MSvYpoH6tsfdrK +XBPO6snrCVzFc+cSAdXZUwee4A+W8Iu0u0VIn4bFGVWgy5bFA/xI +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 903999262 (0x35e1ef1e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax, OU=Equifax Premium Certificate Authority + Validity + Not Before: Aug 24 22:54:23 1998 GMT + Not After : Aug 24 22:54:23 2018 GMT + Subject: C=US, O=Equifax, OU=Equifax Premium Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:a1:06:8e:06:cc:08:0b:c1:86:a8:de:20:d5: + 0d:0e:d1:0d:c4:9f:ea:6a:d9:b3:c2:32:47:40:6f: + 8a:88:a4:09:bd:38:2c:1d:e6:cb:e6:a4:f3:36:eb: + da:eb:bc:fc:64:b3:07:f6:2d:bc:aa:ce:9f:19:48: + 68:4a:fc:f5:a2:45:7e:09:10:f5:8f:b3:49:5c:23: + 06:39:ea:13:8b:b8:0b:cd:91:1d:76:5f:d9:37:a1: + 44:fb:5f:90:f2:67:b3:cd:18:99:43:1f:76:12:6b: + 02:f2:95:83:38:43:c2:f6:62:34:ca:c9:78:5d:5f: + d2:d8:ba:9a:ff:be:10:60:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax/OU=Equifax Premium Certificate Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Aug 24 22:54:23 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98 + + X509v3 Subject Key Identifier: + 15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + bd:0b:9c:27:a9:03:db:28:dc:98:a9:4b:d0:d1:8e:a7:a8:1a: + 5a:91:e0:9c:f1:f7:18:7c:2e:22:9e:36:1f:c9:a8:b5:cd:46: + 4a:6e:fa:35:07:1b:86:08:eb:9f:e2:a8:f9:9d:41:2d:3a:ae: + 5c:5c:b6:5f:34:04:eb:fc:2a:60:b0:fb:74:e4:85:e9:65:38: + 96:ee:15:c7:c6:77:63:12:bd:8a:68:1f:ab:6c:7d:da:ca:5c: + 13:ce:ea:c9:eb:09:5c:c5:73:e7:12:01:d5:d9:53:07:9e:e0: + 0f:96:f0:8b:b4:bb:45:48:9f:86:c5:19:55:a0:cb:96:c5:03: + fc:48 + +Equifax Secure CA +================= +MD5 Fingerprint: 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 903804111 (0x35def4cf) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Validity + Not Before: Aug 22 16:41:51 1998 GMT + Not After : Aug 22 16:41:51 2018 GMT + Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c1:5d:b1:58:67:08:62:ee:a0:9a:2d:1f:08:6d: + 91:14:68:98:0a:1e:fe:da:04:6f:13:84:62:21:c3: + d1:7c:ce:9f:05:e0:b8:01:f0:4e:34:ec:e2:8a:95: + 04:64:ac:f1:6b:53:5f:05:b3:cb:67:80:bf:42:02: + 8e:fe:dd:01:09:ec:e1:00:14:4f:fc:fb:f0:0c:dd: + 43:ba:5b:2b:e1:1f:80:70:99:15:57:93:16:f1:0f: + 97:6a:b7:c2:68:23:1c:cc:4d:59:30:ac:51:1e:3b: + af:2b:d6:ee:63:45:7b:c5:d9:5f:50:d2:e3:50:0f: + 3a:88:e7:bf:14:fd:e0:c7:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Aug 22 16:41:51 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + + X509v3 Subject Key Identifier: + 48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + 58:ce:29:ea:fc:f7:de:b5:ce:02:b9:17:b5:85:d1:b9:e3:e0: + 95:cc:25:31:0d:00:a6:92:6e:7f:b6:92:63:9e:50:95:d1:9a: + 6f:e4:11:de:63:85:6e:98:ee:a8:ff:5a:c8:d3:55:b2:66:71: + 57:de:c0:21:eb:3d:2a:a7:23:49:01:04:86:42:7b:fc:ee:7f: + a2:16:52:b5:67:67:d3:40:db:3b:26:58:b2:28:77:3d:ae:14: + 77:61:d6:fa:2a:66:27:a0:0d:fa:a7:73:5c:ea:70:f1:94:21: + 65:44:5f:fa:fc:ef:29:68:a9:a2:87:79:ef:79:ef:4f:ac:07: + 77:38 + +GTE CyberTrust Global Root +========================== +MD5 Fingerprint: CA:3D:D3:68:F1:03:5C:D0:32:FA:B8:2B:59:E8:5A:DB +PEM Data: +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 421 (0x1a5) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Validity + Not Before: Aug 13 00:29:00 1998 GMT + Not After : Aug 13 23:59:00 2018 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:95:0f:a0:b6:f0:50:9c:e8:7a:c7:88:cd:dd:17: + 0e:2e:b0:94:d0:1b:3d:0e:f6:94:c0:8a:94:c7:06: + c8:90:97:c8:b8:64:1a:7a:7e:6c:3c:53:e1:37:28: + 73:60:7f:b2:97:53:07:9f:53:f9:6d:58:94:d2:af: + 8d:6d:88:67:80:e6:ed:b2:95:cf:72:31:ca:a5:1c: + 72:ba:5c:02:e7:64:42:e7:f9:a9:2c:d6:3a:0d:ac: + 8d:42:aa:24:01:39:e6:9c:3f:01:85:57:0d:58:87: + 45:f8:d3:85:aa:93:69:26:85:70:48:80:3f:12:15: + c7:79:b4:1f:05:2f:3b:62:99 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 6d:eb:1b:09:e9:5e:d9:51:db:67:22:61:a4:2a:3c:48:77:e3: + a0:7c:a6:de:73:a2:14:03:85:3d:fb:ab:0e:30:c5:83:16:33: + 81:13:08:9e:7b:34:4e:df:40:c8:74:d7:b9:7d:dc:f4:76:55: + 7d:9b:63:54:18:e9:f0:ea:f3:5c:b1:d9:8b:42:1e:b9:c0:95: + 4e:ba:fa:d5:e2:7c:f5:68:61:bf:8e:ec:05:97:5f:5b:b0:d7: + a3:85:34:c4:24:a7:0d:0f:95:93:ef:cb:94:d8:9e:1f:9d:5c: + 85:6d:c7:aa:ae:4f:1f:22:b5:cd:95:ad:ba:a7:cc:f9:ab:0b: + 7a:7f + + +GTE CyberTrust Root 2 +===================== +MD5 Fingerprint: BA:ED:17:57:9A:4B:FF:7C:F9:C9:1F:A2:CD:1A:D6:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICUDCCAbkCAgGbMA0GCSqGSIb3DQEBBAUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAyMB4X +DTk4MDgxMTExMzUwN1oXDTA4MDgxMTExMjIxNlowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDIw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANksTE4vaRoj41a6886EwAnAefFE +XzMfFZF/iogouCRFzI8YzR900bWPcUzWMfZzloSUQMWpg2Akfa9vNLdLTMIJgDtF +BJ7EPMQndXsADKFkR7UUXYJLUTpYu0RMPdPlBjjoYVyYeLuAs5zacoJioN+cX+v5 +T3fCzGAYAGs0giWzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAo2SRbxDt526iQkCU +eM74FAjR+kOF60bNkhTQ7y4tNjkY2brJJ4gp6UgXb/jBqshhbS39QC11QzCXOfgU +ZL1v72OoK0LfsloNJex7N9jOkSmCFvnoYqLhdsQCfd0li5jh9g1gjPZZkEBRRNHC ++xkkHhc5a3QhFTPWVdeCHnAsJ6g= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 411 (0x19b) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2 + Validity + Not Before: Aug 11 11:35:07 1998 GMT + Not After : Aug 11 11:22:16 2008 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:2c:4c:4e:2f:69:1a:23:e3:56:ba:f3:ce:84: + c0:09:c0:79:f1:44:5f:33:1f:15:91:7f:8a:88:28: + b8:24:45:cc:8f:18:cd:1f:74:d1:b5:8f:71:4c:d6: + 31:f6:73:96:84:94:40:c5:a9:83:60:24:7d:af:6f: + 34:b7:4b:4c:c2:09:80:3b:45:04:9e:c4:3c:c4:27: + 75:7b:00:0c:a1:64:47:b5:14:5d:82:4b:51:3a:58: + bb:44:4c:3d:d3:e5:06:38:e8:61:5c:98:78:bb:80: + b3:9c:da:72:82:62:a0:df:9c:5f:eb:f9:4f:77:c2: + cc:60:18:00:6b:34:82:25:b3 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + a3:64:91:6f:10:ed:e7:6e:a2:42:40:94:78:ce:f8:14:08:d1: + fa:43:85:eb:46:cd:92:14:d0:ef:2e:2d:36:39:18:d9:ba:c9: + 27:88:29:e9:48:17:6f:f8:c1:aa:c8:61:6d:2d:fd:40:2d:75: + 43:30:97:39:f8:14:64:bd:6f:ef:63:a8:2b:42:df:b2:5a:0d: + 25:ec:7b:37:d8:ce:91:29:82:16:f9:e8:62:a2:e1:76:c4:02: + 7d:dd:25:8b:98:e1:f6:0d:60:8c:f6:59:90:40:51:44:d1:c2: + fb:19:24:1e:17:39:6b:74:21:15:33:d6:55:d7:82:1e:70:2c: + 27:a8 + +GTE CyberTrust Root 3 +===================== +MD5 Fingerprint: DB:81:96:57:AE:64:61:EF:77:A7:83:C4:51:24:3C:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICUDCCAbkCAgGXMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAzMB4X +DTk4MDgxMDE5NTkwOFoXDTA4MDgxMDE5MzYzOVowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHzsSsLztwU2TSXYlASVmOETFP6 +wIXP+sHdD955E39T+6oOYN3iYr/G7k6ZNKpoQzWZ+KP982O9AVRqnrI6lix7eCjG +WrWNGhUY/eOMLqJQCVtx1g21GB8ZjgQpk5N4q18U53NC8gMMV6IbUDsLu1ngoDoD +7icbWky5sAjKuRqJAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAheutlCAG6bKiazvy +ZuvjS7gSJgXl9JGo3IfcmPSUwfRhvdWcbFFzlV7QvdfmRdw8z0aE1ee57ORnY24A +KHdxXUoF6bl8hszCRLveKUja6t29F58dUQGo6BResVf3/9qPzpX+Le0yEnf/fGph +la4xcgYI8PnzDY7i76hTXZEDg94= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 407 (0x197) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3 + Validity + Not Before: Aug 10 19:59:08 1998 GMT + Not After : Aug 10 19:36:39 2008 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e1:f3:b1:2b:0b:ce:dc:14:d9:34:97:62:50:12: + 56:63:84:4c:53:fa:c0:85:cf:fa:c1:dd:0f:de:79: + 13:7f:53:fb:aa:0e:60:dd:e2:62:bf:c6:ee:4e:99: + 34:aa:68:43:35:99:f8:a3:fd:f3:63:bd:01:54:6a: + 9e:b2:3a:96:2c:7b:78:28:c6:5a:b5:8d:1a:15:18: + fd:e3:8c:2e:a2:50:09:5b:71:d6:0d:b5:18:1f:19: + 8e:04:29:93:93:78:ab:5f:14:e7:73:42:f2:03:0c: + 57:a2:1b:50:3b:0b:bb:59:e0:a0:3a:03:ee:27:1b: + 5a:4c:b9:b0:08:ca:b9:1a:89 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 85:eb:ad:94:20:06:e9:b2:a2:6b:3b:f2:66:eb:e3:4b:b8:12: + 26:05:e5:f4:91:a8:dc:87:dc:98:f4:94:c1:f4:61:bd:d5:9c: + 6c:51:73:95:5e:d0:bd:d7:e6:45:dc:3c:cf:46:84:d5:e7:b9: + ec:e4:67:63:6e:00:28:77:71:5d:4a:05:e9:b9:7c:86:cc:c2: + 44:bb:de:29:48:da:ea:dd:bd:17:9f:1d:51:01:a8:e8:14:5e: + b1:57:f7:ff:da:8f:ce:95:fe:2d:ed:32:12:77:ff:7c:6a:61: + 95:ae:31:72:06:08:f0:f9:f3:0d:8e:e2:ef:a8:53:5d:91:03: + 83:de + +GTE CyberTrust Root 4 +===================== +MD5 Fingerprint: 33:43:02:B1:B9:E0:73:B1:B1:20:CA:CB:C7:84:03:50 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDVTCCAj0CAgGoMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCA0MB4X +DTk4MDgxMzEzNTEwMFoXDTEzMDgxMzIzNTkwMFowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6nSJuf9pmPDlCsaMqb9P3 +vK6sMVrXEZBHuZ0ZLvnzGyKgw+GnusT8XgqUS5haSybkH/Tc8/6OiNxsLXx3hyZQ +wF5OqCih6hdpT03GAQ7amg0GViYVtqRdejWvje14Uob5OKuzAdPaBZaxtlCrwKGu +F1P6QzkgcWUj223Etu2YRYPX0vbiqWv7+XXM78WrcZY16N+OkZuoEHUft84Tjmuz +lneXGpEvxyxpmfAPKmgAmHZEG4wo0uuO9IO0f6QlXmw72cZo1WG41F4xB7VbkDVS +V3sXIO0tuB6OiDk+Usvf8FyxZbulErSQY79xnTLB2r9QSpW+BjrEK+vNmHZETQvl +AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEOvHIfJSbpliTRJPOoHO0eiedSgO5Bs +3n+oVMPoTEAyvMjsHOXZrEC6/Iw/wnOc9GTq36ntTlvIAWDuOW1DJ/N/qgjS/k5v +FDJNfeQ0gKU1xNZGULQ7oC1lH09lfjQoLcCndn0xyQ0zFvYgGSARULsDzHBtlrfv +TKfaNhXPu03UltyITWyY7blz/ihXoO1k+AqBKXP29pcyhzm0ge/ZTRoHNPe6QjXe +V9xc1vfF6wonDIGmwtBoTv2SW0iD9haKjzZb7TFsP0F6cfeSPzGkCkBM84biYcE8 +SYEtpbjvupcPvCsdm4ny0o4eTYbywqv2LZnAGyoNobZP+SxYTT19Nwo= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 424 (0x1a8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4 + Validity + Not Before: Aug 13 13:51:00 1998 GMT + Not After : Aug 13 23:59:00 2013 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ba:9d:22:6e:7f:da:66:3c:39:42:b1:a3:2a:6f: + d3:f7:bc:ae:ac:31:5a:d7:11:90:47:b9:9d:19:2e: + f9:f3:1b:22:a0:c3:e1:a7:ba:c4:fc:5e:0a:94:4b: + 98:5a:4b:26:e4:1f:f4:dc:f3:fe:8e:88:dc:6c:2d: + 7c:77:87:26:50:c0:5e:4e:a8:28:a1:ea:17:69:4f: + 4d:c6:01:0e:da:9a:0d:06:56:26:15:b6:a4:5d:7a: + 35:af:8d:ed:78:52:86:f9:38:ab:b3:01:d3:da:05: + 96:b1:b6:50:ab:c0:a1:ae:17:53:fa:43:39:20:71: + 65:23:db:6d:c4:b6:ed:98:45:83:d7:d2:f6:e2:a9: + 6b:fb:f9:75:cc:ef:c5:ab:71:96:35:e8:df:8e:91: + 9b:a8:10:75:1f:b7:ce:13:8e:6b:b3:96:77:97:1a: + 91:2f:c7:2c:69:99:f0:0f:2a:68:00:98:76:44:1b: + 8c:28:d2:eb:8e:f4:83:b4:7f:a4:25:5e:6c:3b:d9: + c6:68:d5:61:b8:d4:5e:31:07:b5:5b:90:35:52:57: + 7b:17:20:ed:2d:b8:1e:8e:88:39:3e:52:cb:df:f0: + 5c:b1:65:bb:a5:12:b4:90:63:bf:71:9d:32:c1:da: + bf:50:4a:95:be:06:3a:c4:2b:eb:cd:98:76:44:4d: + 0b:e5 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 43:af:1c:87:c9:49:ba:65:89:34:49:3c:ea:07:3b:47:a2:79: + d4:a0:3b:90:6c:de:7f:a8:54:c3:e8:4c:40:32:bc:c8:ec:1c: + e5:d9:ac:40:ba:fc:8c:3f:c2:73:9c:f4:64:ea:df:a9:ed:4e: + 5b:c8:01:60:ee:39:6d:43:27:f3:7f:aa:08:d2:fe:4e:6f:14: + 32:4d:7d:e4:34:80:a5:35:c4:d6:46:50:b4:3b:a0:2d:65:1f: + 4f:65:7e:34:28:2d:c0:a7:76:7d:31:c9:0d:33:16:f6:20:19: + 20:11:50:bb:03:cc:70:6d:96:b7:ef:4c:a7:da:36:15:cf:bb: + 4d:d4:96:dc:88:4d:6c:98:ed:b9:73:fe:28:57:a0:ed:64:f8: + 0a:81:29:73:f6:f6:97:32:87:39:b4:81:ef:d9:4d:1a:07:34: + f7:ba:42:35:de:57:dc:5c:d6:f7:c5:eb:0a:27:0c:81:a6:c2: + d0:68:4e:fd:92:5b:48:83:f6:16:8a:8f:36:5b:ed:31:6c:3f: + 41:7a:71:f7:92:3f:31:a4:0a:40:4c:f3:86:e2:61:c1:3c:49: + 81:2d:a5:b8:ef:ba:97:0f:bc:2b:1d:9b:89:f2:d2:8e:1e:4d: + 86:f2:c2:ab:f6:2d:99:c0:1b:2a:0d:a1:b6:4f:f9:2c:58:4d: + 3d:7d:37:0a + +GTE CyberTrust Root 5 +===================== +MD5 Fingerprint: 7D:6C:86:E4:FC:4D:D1:0B:00:BA:22:BB:4E:7C:6A:8E +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgICAbYwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1 +c3QgU29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290 +IDUwHhcNOTgwODE0MTQ1MDAwWhcNMTMwODE0MjM1OTAwWjBwMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xHjAcBgNVBAMTFUdURSBDeWJlclRydXN0IFJv +b3QgNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwSbj+KfHqXAewe +uzlaAvR4RKJIG457SVJ6uHtHs6+Um2+7lvoramVcuByUc76/iQoigO5X/IwFu3Cf +lzkE2qOHXKjlyq/AM5rVN1xLrOSA0KYjYPv9ci6UncfOwgQy73hgXe2thw9FZR48 +mgqavl0dmezn8tHGehfZrZtUln/EfGC/haoVNR1A2hG87FQhKC0joajwzy3N3fx+ +D17hZQdWywe00lboXjHMGGPEhtIthc+Tkqtt/mg5+95zvYb45EZ66p8My/QZ/mO8 +0Sx7iDM29uThnAxTgWAc2i6rlqkWiBNQmbK9Vd8VMH7o5Zj7cH5stQf8/Ea30O03 +ln4y/iECAwEAAaNaMFgwEgYDVR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMC +AQYwFwYDVR0gBBAwDjAMBgoqhkiG+GMBAgEDMBkGA1UdDgQSBBB2CkkhOEyf3vjE +ScdxcZGdMA0GCSqGSIb3DQEBBQUAA4IBAQBBOtQYW9q43iEc4Y4J5fFoNP/elvQH +9ac886xKsZv6kvqb7eYyIapKdsXcTzjl39WG5NXIdn2Y17HNj021kSNsi4rr6nzv +FJTExvAfSi0ycWMrY5EmAgm2gB3t4sy4f9uHY8jh0GwmsTUdQGYQG82VVBgzYewT +T9oT95mvPtDPjqZyorPDBZrJJ32SzH5SjbOrcG2eiZ9N6xp1wpiq1QIW1wyKvyXk +6y28mOlYOBl8uTf+2+KZCHMGx5eDan0QAS8yuRcFSmXmL86+XlOmgumaUwqEdC2D +ysiUFnZflGEo8IWnObvXi9moshMdVAk0JH0ggX1mfqKQdFwQxr3sqxvC +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 438 (0x1b6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5 + Validity + Not Before: Aug 14 14:50:00 1998 GMT + Not After : Aug 14 23:59:00 2013 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bc:12:6e:3f:8a:7c:7a:97:01:ec:1e:bb:39:5a: + 02:f4:78:44:a2:48:1b:8e:7b:49:52:7a:b8:7b:47: + b3:af:94:9b:6f:bb:96:fa:2b:6a:65:5c:b8:1c:94: + 73:be:bf:89:0a:22:80:ee:57:fc:8c:05:bb:70:9f: + 97:39:04:da:a3:87:5c:a8:e5:ca:af:c0:33:9a:d5: + 37:5c:4b:ac:e4:80:d0:a6:23:60:fb:fd:72:2e:94: + 9d:c7:ce:c2:04:32:ef:78:60:5d:ed:ad:87:0f:45: + 65:1e:3c:9a:0a:9a:be:5d:1d:99:ec:e7:f2:d1:c6: + 7a:17:d9:ad:9b:54:96:7f:c4:7c:60:bf:85:aa:15: + 35:1d:40:da:11:bc:ec:54:21:28:2d:23:a1:a8:f0: + cf:2d:cd:dd:fc:7e:0f:5e:e1:65:07:56:cb:07:b4: + d2:56:e8:5e:31:cc:18:63:c4:86:d2:2d:85:cf:93: + 92:ab:6d:fe:68:39:fb:de:73:bd:86:f8:e4:46:7a: + ea:9f:0c:cb:f4:19:fe:63:bc:d1:2c:7b:88:33:36: + f6:e4:e1:9c:0c:53:81:60:1c:da:2e:ab:96:a9:16: + 88:13:50:99:b2:bd:55:df:15:30:7e:e8:e5:98:fb: + 70:7e:6c:b5:07:fc:fc:46:b7:d0:ed:37:96:7e:32: + fe:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 1.2.840.113763.1.2.1.3 + + X509v3 Subject Key Identifier: + 76:0A:49:21:38:4C:9F:DE:F8:C4:49:C7:71:71:91:9D + Signature Algorithm: sha1WithRSAEncryption + 41:3a:d4:18:5b:da:b8:de:21:1c:e1:8e:09:e5:f1:68:34:ff: + de:96:f4:07:f5:a7:3c:f3:ac:4a:b1:9b:fa:92:fa:9b:ed:e6: + 32:21:aa:4a:76:c5:dc:4f:38:e5:df:d5:86:e4:d5:c8:76:7d: + 98:d7:b1:cd:8f:4d:b5:91:23:6c:8b:8a:eb:ea:7c:ef:14:94: + c4:c6:f0:1f:4a:2d:32:71:63:2b:63:91:26:02:09:b6:80:1d: + ed:e2:cc:b8:7f:db:87:63:c8:e1:d0:6c:26:b1:35:1d:40:66: + 10:1b:cd:95:54:18:33:61:ec:13:4f:da:13:f7:99:af:3e:d0: + cf:8e:a6:72:a2:b3:c3:05:9a:c9:27:7d:92:cc:7e:52:8d:b3: + ab:70:6d:9e:89:9f:4d:eb:1a:75:c2:98:aa:d5:02:16:d7:0c: + 8a:bf:25:e4:eb:2d:bc:98:e9:58:38:19:7c:b9:37:fe:db:e2: + 99:08:73:06:c7:97:83:6a:7d:10:01:2f:32:b9:17:05:4a:65: + e6:2f:ce:be:5e:53:a6:82:e9:9a:53:0a:84:74:2d:83:ca:c8: + 94:16:76:5f:94:61:28:f0:85:a7:39:bb:d7:8b:d9:a8:b2:13: + 1d:54:09:34:24:7d:20:81:7d:66:7e:a2:90:74:5c:10:c6:bd: + ec:ab:1b:c2 + +GTE CyberTrust Root CA +====================== +MD5 Fingerprint: C4:D7:F0:B2:A3:C5:7D:61:67:F0:04:CD:43:D3:BA:58 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv +b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU +cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv +RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M +ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5 +1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz +dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl +IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy +bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 419 (0x1a3) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Validity + Not Before: Feb 23 23:01:00 1996 GMT + Not After : Feb 23 23:59:00 2006 GMT + Subject: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b8:e6:4f:ba:db:98:7c:71:7c:af:44:b7:d3:0f: + 46:d9:64:e5:93:c1:42:8e:c7:ba:49:8d:35:2d:7a: + e7:8b:bd:e5:05:31:59:c6:b1:2f:0a:0c:fb:9f:a7: + 3f:a2:09:66:84:56:1e:37:29:1b:87:e9:7e:0c:ca: + 9a:9f:a5:7f:f5:15:94:a3:d5:a2:46:82:d8:68:4c: + d1:37:15:06:68:af:bd:f8:b0:b3:f0:29:f5:95:5a: + 09:16:61:77:0a:22:25:d4:4f:45:aa:c7:bd:e5:96: + df:f9:d4:a8:8e:42:cc:24:c0:1e:91:27:4a:b5:6d: + 06:80:63:39:c4:a2:5e:38:03 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 12:b3:75:c6:5f:1d:e1:61:55:80:00:d4:81:4b:7b:31:0f:23: + 63:e7:3d:f3:03:f9:f4:36:a8:bb:d9:e3:a5:97:4d:ea:2b:29: + e0:d6:6a:73:81:e6:c0:89:a3:d3:f1:e0:a5:a5:22:37:9a:63: + c2:48:20:b4:db:72:e3:c8:f6:d9:7c:be:b1:af:53:da:14:b4: + 21:b8:d6:d5:96:e3:fe:4e:0c:59:62:b6:9a:4a:f9:42:dd:8c: + 6f:81:a9:71:ff:f4:0a:72:6d:6d:44:0e:9d:f3:74:74:a8:d5: + 34:49:e9:5e:9e:e9:b4:7a:e1:e5:5a:1f:84:30:9c:d3:9f:a5: + 25:d8 + +GlobalSign Partners CA +====================== +MD5 Fingerprint: 3C:75:CD:4C:BD:A9:D0:8A:79:4F:50:16:37:84:F4:2B +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDnjCCAoagAwIBAgILAgAAAAAA1ni50a8wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xv +YmFsU2lnbiBQYXJ0bmVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBANIs+DKsShJ6N8gpkaWujG4eDsA0M4jlM3EWHHiEaMMYNFAuFj6xlIJPsZqf +APjGETXGaXuYAq0ABohs50wzKACIJ0Yfh7NxdWO8MruI3mYYDlAGk7T2vBQ3MD0i +3z3/dX7ZChrFn7P80KyzCHqJ0wHoAFznSgs9TXsmordiBovaRt2TFz8/WwJLC7aI +IBGSAK27xy7U40Wu9YlafI2krYVkMsAnjMbyioCShiRWWY10aKKDQrOePVBBhm8g +bvb9ztMZ4zLMj+2aXm0fKPVSrG4YXvg90ZLlumwBiEsK8i3eZTMFQqBMqjF2vv2/ +gXj5cRxGXi0VlS0wWY5MQdFiqz0CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgAGMB0G +A1UdDgQWBBRDJI1wFQhiVZxPDEAXXYZeD6JM+zAfBgNVHSMEGDAWgBRge2YaRQ2X +yolQL30EzTSo//z9SzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IB +AQBm7bSIaRGZgiGDrKFti5uErQ8tyB6Mynt+rarUjt4H1p5Fx6W4nAc5YCVVGsBP +GeXPFylJiRg1ZuXrKEBOV8mvs+S4IAWjO5VQkUmUKX0s5YhBpUWIXp2CJ/fS71u1 +T5++/jVlLFVkn+FR2iJhd7pYTo/GeVlZbjCAok+QbiELrdBoOZAQm+0iZW8eETjm +f4zS8zltR9Uh6Op1OkHRrfYWnV0LIb3zH2MGJR3BHzVxLOsgGdXBsOw95W/tAgc/ +E3tmktZEwZj3X1CLelvCb22w0fjldKBAN6MlD+Q9ymQxk5BcMHu5OTGaXkzNuUFP +UOQ9OK7IZtnHO11RR6ybq/Kt +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b9:d1:af + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Partners CA, CN=GlobalSign Partners CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:2c:f8:32:ac:4a:12:7a:37:c8:29:91:a5:ae: + 8c:6e:1e:0e:c0:34:33:88:e5:33:71:16:1c:78:84: + 68:c3:18:34:50:2e:16:3e:b1:94:82:4f:b1:9a:9f: + 00:f8:c6:11:35:c6:69:7b:98:02:ad:00:06:88:6c: + e7:4c:33:28:00:88:27:46:1f:87:b3:71:75:63:bc: + 32:bb:88:de:66:18:0e:50:06:93:b4:f6:bc:14:37: + 30:3d:22:df:3d:ff:75:7e:d9:0a:1a:c5:9f:b3:fc: + d0:ac:b3:08:7a:89:d3:01:e8:00:5c:e7:4a:0b:3d: + 4d:7b:26:a2:b7:62:06:8b:da:46:dd:93:17:3f:3f: + 5b:02:4b:0b:b6:88:20:11:92:00:ad:bb:c7:2e:d4: + e3:45:ae:f5:89:5a:7c:8d:a4:ad:85:64:32:c0:27: + 8c:c6:f2:8a:80:92:86:24:56:59:8d:74:68:a2:83: + 42:b3:9e:3d:50:41:86:6f:20:6e:f6:fd:ce:d3:19: + e3:32:cc:8f:ed:9a:5e:6d:1f:28:f5:52:ac:6e:18: + 5e:f8:3d:d1:92:e5:ba:6c:01:88:4b:0a:f2:2d:de: + 65:33:05:42:a0:4c:aa:31:76:be:fd:bf:81:78:f9: + 71:1c:46:5e:2d:15:95:2d:30:59:8e:4c:41:d1:62: + ab:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 43:24:8D:70:15:08:62:55:9C:4F:0C:40:17:5D:86:5E:0F:A2:4C:FB + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 66:ed:b4:88:69:11:99:82:21:83:ac:a1:6d:8b:9b:84:ad:0f: + 2d:c8:1e:8c:ca:7b:7e:ad:aa:d4:8e:de:07:d6:9e:45:c7:a5: + b8:9c:07:39:60:25:55:1a:c0:4f:19:e5:cf:17:29:49:89:18: + 35:66:e5:eb:28:40:4e:57:c9:af:b3:e4:b8:20:05:a3:3b:95: + 50:91:49:94:29:7d:2c:e5:88:41:a5:45:88:5e:9d:82:27:f7: + d2:ef:5b:b5:4f:9f:be:fe:35:65:2c:55:64:9f:e1:51:da:22: + 61:77:ba:58:4e:8f:c6:79:59:59:6e:30:80:a2:4f:90:6e:21: + 0b:ad:d0:68:39:90:10:9b:ed:22:65:6f:1e:11:38:e6:7f:8c: + d2:f3:39:6d:47:d5:21:e8:ea:75:3a:41:d1:ad:f6:16:9d:5d: + 0b:21:bd:f3:1f:63:06:25:1d:c1:1f:35:71:2c:eb:20:19:d5: + c1:b0:ec:3d:e5:6f:ed:02:07:3f:13:7b:66:92:d6:44:c1:98: + f7:5f:50:8b:7a:5b:c2:6f:6d:b0:d1:f8:e5:74:a0:40:37:a3: + 25:0f:e4:3d:ca:64:31:93:90:5c:30:7b:b9:39:31:9a:5e:4c: + cd:b9:41:4f:50:e4:3d:38:ae:c8:66:d9:c7:3b:5d:51:47:ac: + 9b:ab:f2:ad + +GlobalSign Primary Class 1 CA +============================= +MD5 Fingerprint: 5C:AC:59:01:A4:86:53:CB:10:66:B5:D6:D6:71:FF:01 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4N88wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MTUxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDEgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAxIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAvSA1R9Eo1gijEjkjRw29cCFSDlcxlaY0V2vsfkN5 +wwZSSM28taGZvdgfMrzP125ybS53IpCCTkuPmgwBQprZcFm2nR/mY9EMrR1O+IWB ++a7vn6ZSYUR5GnVF4GFWRW1CjD1yy6akErea9dZg0GBQs46mpuy09BLNf6jO77Ph +hTD+csTm53eznlhB1lGDiAfGtmlPNt7RC0g/vdafIXRkbycGPkv9Dqabv6RIV4yQ +7okYCwKBGL5n/lNgiCe6o3M0S1pWtN5zBe2Yll3sSudA/EsJYuvQ4zFPhdF6q1ln +K/uID+uqg701/WEn7GYOQlf3acIM7/xqwm5J2o9BOK5IqQIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFPzgZvZaNZnrQB7SuB5DvJiOH4rDMB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAJujCETO8pCdcfMyswVqterPKZjeVT6gFn0GekTWr9L6 +E1iM+BzHqx20G+9paJhcCDmP4Pf7SMwh57gz2wWqNCRsSuXpe2Deg7MfCr5BdfzM +MEi3wSYdBDOqtnjtKsu6VpcybvcxlS5G8hTuJ8f3Yom5XFrTOIpk9Te08bM0ctXV +IT1L13iT1zFmNR6j2EdJbxyt4YB/+JgkbHOsDsIadwKjJge3x2tdvILVKkgdY89Q +Mqb7HBhHFQpbDFw4JJoEmKgISF98NIdjqy2NTAB3lBt2uvUWGKMVry+U9ikAdsEV +F9PpN0121MtLKVkkrNpKoOpj3l9Usfrz0UXLxWS0cyE= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:37:cf + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 15 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 1 CA, CN=GlobalSign Primary Class 1 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bd:20:35:47:d1:28:d6:08:a3:12:39:23:47:0d: + bd:70:21:52:0e:57:31:95:a6:34:57:6b:ec:7e:43: + 79:c3:06:52:48:cd:bc:b5:a1:99:bd:d8:1f:32:bc: + cf:d7:6e:72:6d:2e:77:22:90:82:4e:4b:8f:9a:0c: + 01:42:9a:d9:70:59:b6:9d:1f:e6:63:d1:0c:ad:1d: + 4e:f8:85:81:f9:ae:ef:9f:a6:52:61:44:79:1a:75: + 45:e0:61:56:45:6d:42:8c:3d:72:cb:a6:a4:12:b7: + 9a:f5:d6:60:d0:60:50:b3:8e:a6:a6:ec:b4:f4:12: + cd:7f:a8:ce:ef:b3:e1:85:30:fe:72:c4:e6:e7:77: + b3:9e:58:41:d6:51:83:88:07:c6:b6:69:4f:36:de: + d1:0b:48:3f:bd:d6:9f:21:74:64:6f:27:06:3e:4b: + fd:0e:a6:9b:bf:a4:48:57:8c:90:ee:89:18:0b:02: + 81:18:be:67:fe:53:60:88:27:ba:a3:73:34:4b:5a: + 56:b4:de:73:05:ed:98:96:5d:ec:4a:e7:40:fc:4b: + 09:62:eb:d0:e3:31:4f:85:d1:7a:ab:59:67:2b:fb: + 88:0f:eb:aa:83:bd:35:fd:61:27:ec:66:0e:42:57: + f7:69:c2:0c:ef:fc:6a:c2:6e:49:da:8f:41:38:ae: + 48:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + FC:E0:66:F6:5A:35:99:EB:40:1E:D2:B8:1E:43:BC:98:8E:1F:8A:C3 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 9b:a3:08:44:ce:f2:90:9d:71:f3:32:b3:05:6a:b5:ea:cf:29: + 98:de:55:3e:a0:16:7d:06:7a:44:d6:af:d2:fa:13:58:8c:f8: + 1c:c7:ab:1d:b4:1b:ef:69:68:98:5c:08:39:8f:e0:f7:fb:48: + cc:21:e7:b8:33:db:05:aa:34:24:6c:4a:e5:e9:7b:60:de:83: + b3:1f:0a:be:41:75:fc:cc:30:48:b7:c1:26:1d:04:33:aa:b6: + 78:ed:2a:cb:ba:56:97:32:6e:f7:31:95:2e:46:f2:14:ee:27: + c7:f7:62:89:b9:5c:5a:d3:38:8a:64:f5:37:b4:f1:b3:34:72: + d5:d5:21:3d:4b:d7:78:93:d7:31:66:35:1e:a3:d8:47:49:6f: + 1c:ad:e1:80:7f:f8:98:24:6c:73:ac:0e:c2:1a:77:02:a3:26: + 07:b7:c7:6b:5d:bc:82:d5:2a:48:1d:63:cf:50:32:a6:fb:1c: + 18:47:15:0a:5b:0c:5c:38:24:9a:04:98:a8:08:48:5f:7c:34: + 87:63:ab:2d:8d:4c:00:77:94:1b:76:ba:f5:16:18:a3:15:af: + 2f:94:f6:29:00:76:c1:15:17:d3:e9:37:4d:76:d4:cb:4b:29: + 59:24:ac:da:4a:a0:ea:63:de:5f:54:b1:fa:f3:d1:45:cb:c5: + 64:b4:73:21 + +GlobalSign Primary Class 2 CA +============================= +MD5 Fingerprint: A9:A9:42:59:7E:BE:5A:94:E4:2C:C6:8B:1C:2A:44:B6 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4jY0wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDIgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAyIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAkoz+7/RFjhdBbvzYvyFvqwadUsEsAJ0/joW4f0qP +vaBjKspJJ65agvR04lWS/8LRqnmitvrVnYIET8ayxl5jpzq62O7rim+ftrsoQcAi ++05IGgaS17/Xz7nZvThPOw1EblVB/vwJ29i/844h8egStfYTpdPGTJMisAL/7h0M +xKhrT3VoVujcKBJQ96gknS4kOfsJBd7lo2RJIdBofnEwkbFg4Dn0UPh6TZgAa3x5 +uk7OSuK6Nh23xTYVlZxkQupfxLr1QAW+4TpZvYSnGbjeTVNQzgfR0lHT7w2BbObn +bctdfD98zOxPgycl/3BQ9oNZdYQGZlgs3omNAKZJ+aVDdwIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFHznsrEs3rGna+l2DOGj/U5sx7n2MB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAGPdWc6KeaqYnU7FiWQ3foqTZy8Q6m8nw413bfJcVpQZ +GmlgMEZdj/JtRTyONZd8L7hR4uiJvYjPJxwINFyIwWgk25GF5M/7+0ON6CUBG8QO +9wBCSIYfJAhYWoyN8mtHLGiRsWlC/Q2NySbmkoamZG6Sxc4+PH1x4yOkq8fVqKnf +gqc76IbVw08Y40TQ4NzzxWgu/qUvBYTIfkdCU2uHSv4y/14+cIy3qBXMF8L/RuzQ +7C20bhIoqflA6evUZpdTqWlVwKmqsi7N0Wn0vvi7fGnuVKbbnvtapj7+mu+UUUt1 +7tjU4ZrxAlYTiQ6nQouWi4UMG4W+Jq6rppm8IvFz30I= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:8d:8d + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 2 CA, CN=GlobalSign Primary Class 2 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:92:8c:fe:ef:f4:45:8e:17:41:6e:fc:d8:bf:21: + 6f:ab:06:9d:52:c1:2c:00:9d:3f:8e:85:b8:7f:4a: + 8f:bd:a0:63:2a:ca:49:27:ae:5a:82:f4:74:e2:55: + 92:ff:c2:d1:aa:79:a2:b6:fa:d5:9d:82:04:4f:c6: + b2:c6:5e:63:a7:3a:ba:d8:ee:eb:8a:6f:9f:b6:bb: + 28:41:c0:22:fb:4e:48:1a:06:92:d7:bf:d7:cf:b9: + d9:bd:38:4f:3b:0d:44:6e:55:41:fe:fc:09:db:d8: + bf:f3:8e:21:f1:e8:12:b5:f6:13:a5:d3:c6:4c:93: + 22:b0:02:ff:ee:1d:0c:c4:a8:6b:4f:75:68:56:e8: + dc:28:12:50:f7:a8:24:9d:2e:24:39:fb:09:05:de: + e5:a3:64:49:21:d0:68:7e:71:30:91:b1:60:e0:39: + f4:50:f8:7a:4d:98:00:6b:7c:79:ba:4e:ce:4a:e2: + ba:36:1d:b7:c5:36:15:95:9c:64:42:ea:5f:c4:ba: + f5:40:05:be:e1:3a:59:bd:84:a7:19:b8:de:4d:53: + 50:ce:07:d1:d2:51:d3:ef:0d:81:6c:e6:e7:6d:cb: + 5d:7c:3f:7c:cc:ec:4f:83:27:25:ff:70:50:f6:83: + 59:75:84:06:66:58:2c:de:89:8d:00:a6:49:f9:a5: + 43:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 7C:E7:B2:B1:2C:DE:B1:A7:6B:E9:76:0C:E1:A3:FD:4E:6C:C7:B9:F6 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 63:dd:59:ce:8a:79:aa:98:9d:4e:c5:89:64:37:7e:8a:93:67: + 2f:10:ea:6f:27:c3:8d:77:6d:f2:5c:56:94:19:1a:69:60:30: + 46:5d:8f:f2:6d:45:3c:8e:35:97:7c:2f:b8:51:e2:e8:89:bd: + 88:cf:27:1c:08:34:5c:88:c1:68:24:db:91:85:e4:cf:fb:fb: + 43:8d:e8:25:01:1b:c4:0e:f7:00:42:48:86:1f:24:08:58:5a: + 8c:8d:f2:6b:47:2c:68:91:b1:69:42:fd:0d:8d:c9:26:e6:92: + 86:a6:64:6e:92:c5:ce:3e:3c:7d:71:e3:23:a4:ab:c7:d5:a8: + a9:df:82:a7:3b:e8:86:d5:c3:4f:18:e3:44:d0:e0:dc:f3:c5: + 68:2e:fe:a5:2f:05:84:c8:7e:47:42:53:6b:87:4a:fe:32:ff: + 5e:3e:70:8c:b7:a8:15:cc:17:c2:ff:46:ec:d0:ec:2d:b4:6e: + 12:28:a9:f9:40:e9:eb:d4:66:97:53:a9:69:55:c0:a9:aa:b2: + 2e:cd:d1:69:f4:be:f8:bb:7c:69:ee:54:a6:db:9e:fb:5a:a6: + 3e:fe:9a:ef:94:51:4b:75:ee:d8:d4:e1:9a:f1:02:56:13:89: + 0e:a7:42:8b:96:8b:85:0c:1b:85:be:26:ae:ab:a6:99:bc:22: + f1:73:df:42 + +GlobalSign Primary Class 3 CA +============================= +MD5 Fingerprint: 98:12:A3:4B:95:A9:96:64:94:E7:50:8C:3E:E1:83:5A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni41sMwDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDMgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAzIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAkV5WZdbAwAScv0fEXHt6MQH5WJaZ4xyEL9xWj631 +WYHVQ2ZdWpOMdcqp5xHBURAUYMks1HuvxneGq3onrm+VuQvKtkb7fhr0DRRt0slO +sq7wVPZcQEw2SHToVIxlZhCnvSu3II0FSa14fdIkI1Dj8LR5mwE5/6870y3u4UmN +jS88akFFL5vjPeES5JF1ns+gPjySgW+KLhjc4PKMjP2H2Qf0QJTJTk9D32dWb70D +UHyZZ6S5PJFsAm6E1vxG98xvGD4X8O8LZBZX5qyG8UiqQ8HJJ3hzREXihX26/7Ph ++xsFpEs7mRIlAVAUaq9d6sgM7uTa7EuLXGgTldzDtTA61wIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFMw2zBe0RZEv7c87MEh3+7UUmb7jMB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAFeyVMy9lRdkYIm2U5EMRZLDPahsw8yyGPV4QXTYfaMn +r3cNWT6UHWn6idMMvRoB9D/o4Hcagiha5mLXt+M2yQ6feuPC08xZiQzvFovwNnci +yqS2t8FCZwFAY8znOGSHWxSWZnstFO69SW3/d9DiTlvTgMJND8q4nYGXpzRux+Oc +SOW0qkX19mVMSPISwtKTjMIVJPMrUv/jCK64btYsEs85yxIq56l7X5g9o+HMpmOJ +XH0xdfnV1l3y0NQ9355xqA7c5CCXeOZ/U6QNUU+OOwOuow1aTcN55zVYcELJXqFe +tNkio0RTNaTQz3OAxc+fVph2+RRMd4eCydx+XTTVNnU= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:d6:c3 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 3 CA, CN=GlobalSign Primary Class 3 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:91:5e:56:65:d6:c0:c0:04:9c:bf:47:c4:5c:7b: + 7a:31:01:f9:58:96:99:e3:1c:84:2f:dc:56:8f:ad: + f5:59:81:d5:43:66:5d:5a:93:8c:75:ca:a9:e7:11: + c1:51:10:14:60:c9:2c:d4:7b:af:c6:77:86:ab:7a: + 27:ae:6f:95:b9:0b:ca:b6:46:fb:7e:1a:f4:0d:14: + 6d:d2:c9:4e:b2:ae:f0:54:f6:5c:40:4c:36:48:74: + e8:54:8c:65:66:10:a7:bd:2b:b7:20:8d:05:49:ad: + 78:7d:d2:24:23:50:e3:f0:b4:79:9b:01:39:ff:af: + 3b:d3:2d:ee:e1:49:8d:8d:2f:3c:6a:41:45:2f:9b: + e3:3d:e1:12:e4:91:75:9e:cf:a0:3e:3c:92:81:6f: + 8a:2e:18:dc:e0:f2:8c:8c:fd:87:d9:07:f4:40:94: + c9:4e:4f:43:df:67:56:6f:bd:03:50:7c:99:67:a4: + b9:3c:91:6c:02:6e:84:d6:fc:46:f7:cc:6f:18:3e: + 17:f0:ef:0b:64:16:57:e6:ac:86:f1:48:aa:43:c1: + c9:27:78:73:44:45:e2:85:7d:ba:ff:b3:e1:fb:1b: + 05:a4:4b:3b:99:12:25:01:50:14:6a:af:5d:ea:c8: + 0c:ee:e4:da:ec:4b:8b:5c:68:13:95:dc:c3:b5:30: + 3a:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CC:36:CC:17:B4:45:91:2F:ED:CF:3B:30:48:77:FB:B5:14:99:BE:E3 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 57:b2:54:cc:bd:95:17:64:60:89:b6:53:91:0c:45:92:c3:3d: + a8:6c:c3:cc:b2:18:f5:78:41:74:d8:7d:a3:27:af:77:0d:59: + 3e:94:1d:69:fa:89:d3:0c:bd:1a:01:f4:3f:e8:e0:77:1a:82: + 28:5a:e6:62:d7:b7:e3:36:c9:0e:9f:7a:e3:c2:d3:cc:59:89: + 0c:ef:16:8b:f0:36:77:22:ca:a4:b6:b7:c1:42:67:01:40:63: + cc:e7:38:64:87:5b:14:96:66:7b:2d:14:ee:bd:49:6d:ff:77: + d0:e2:4e:5b:d3:80:c2:4d:0f:ca:b8:9d:81:97:a7:34:6e:c7: + e3:9c:48:e5:b4:aa:45:f5:f6:65:4c:48:f2:12:c2:d2:93:8c: + c2:15:24:f3:2b:52:ff:e3:08:ae:b8:6e:d6:2c:12:cf:39:cb: + 12:2a:e7:a9:7b:5f:98:3d:a3:e1:cc:a6:63:89:5c:7d:31:75: + f9:d5:d6:5d:f2:d0:d4:3d:df:9e:71:a8:0e:dc:e4:20:97:78: + e6:7f:53:a4:0d:51:4f:8e:3b:03:ae:a3:0d:5a:4d:c3:79:e7: + 35:58:70:42:c9:5e:a1:5e:b4:d9:22:a3:44:53:35:a4:d0:cf: + 73:80:c5:cf:9f:56:98:76:f9:14:4c:77:87:82:c9:dc:7e:5d: + 34:d5:36:75 + +GlobalSign Root CA +================== +MD5 Fingerprint: AB:BF:EA:E3:6B:29:A6:CC:A6:78:35:99:EF:AD:2B:80 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU +YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7 +5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q +gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR +rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7 +ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o +Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b7:94:05 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 1 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2014 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b: + 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0: + 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89: + 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c: + 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50: + 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0: + 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2: + 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7: + 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c: + 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2: + 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9: + c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b: + bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91: + ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51: + 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa: + 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a: + 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93: + 90:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + ae:aa:9f:fc:b7:d2:cb:1f:5f:39:29:28:18:9e:34:c9:6c:4f: + 6f:1a:f0:64:a2:70:4a:4f:13:86:9b:60:28:9e:e8:81:49:98: + 7d:0a:bb:e5:b0:9d:3d:36:db:8f:05:51:ff:09:31:2a:1f:dd: + 89:77:9e:0f:2e:6c:95:04:ed:86:cb:b4:00:3f:84:02:4d:80: + 6a:2a:2d:78:0b:ae:6f:2b:a2:83:44:83:1f:cd:50:82:4c:24: + af:bd:f7:a5:b4:c8:5a:0f:f4:e7:47:5e:49:8e:37:96:fe:9a: + 88:05:3a:d9:c0:db:29:87:e6:19:96:47:a7:3a:a6:8c:8b:3c: + 77:fe:46:63:a7:53:da:21:d1:ac:7e:49:a2:4b:e6:c3:67:59: + 2f:b3:8a:0e:bb:2c:bd:a9:aa:42:7c:35:c1:d8:7f:d5:a7:31: + 3a:4e:63:43:39:af:08:b0:61:34:8c:d3:98:a9:43:34:f6:0f: + 87:29:3b:9d:c2:56:58:98:77:c3:f7:1b:ac:f6:9d:f8:3e:aa: + a7:54:45:f0:f5:f9:d5:31:65:fe:6b:58:9c:71:b3:1e:d7:52: + ea:32:17:fc:40:60:1d:c9:79:24:b2:f6:6c:fd:a8:66:0e:82: + dd:98:cb:da:c2:44:4f:2e:a0:7b:f2:f7:6b:2c:76:11:84:46: + 8a:78:a3:e3 + +National Retail Federation by DST +================================= +MD5 Fingerprint: AD:8E:0F:9E:01:6B:A0:C5:74:D5:0C:D3:68:65:4F:1E +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEAjCCAuoCEQDQHkCKAAACfAAAAAMAAAABMA0GCSqGSIb3DQEBBQUAMIG+MQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UE +CxMaTmF0aW9uYWwgUmV0YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJG +KSBSb290Q0ExITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05 +ODEyMTExNjE0MTZaFw0wODEyMDgxNjE0MTZaMIG+MQswCQYDVQQGEwJ1czENMAsG +A1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0Rp +Z2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UECxMaTmF0aW9uYWwgUmV0 +YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJGKSBSb290Q0ExITAfBgkq +hkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBANmsm3f6UNPM3LlArLlyagCHI/wPliHQJq/k4rVf+tOmfSEw +LswXgo+YdPxnpKbfiJeiQin1p9sRk/teIzDCqrwi50Eb5e0l3sg/295XRXhARoOy +1Ro93w9FbdVjAnXYL8Zuq5WRdDcNy00JXNHUWzra3Q7Ia5nY1TnM34VVxJJTAqPh +94DJcKPa3DPEf6JHCBw1lh+hAxwwg/TEzP+Yw7BGRKLAv63b0oH2TJgsp14k84bK +Y9W6ffCawErQG1ju7Klnz2kCbCLAYCws0cgg6sgt+92cu8tRTNznVwQ7VJsRpTJ0 +7HQB85AVWy98LJNluWZntIGINeWekRh/gahByMsCAwEAATANBgkqhkiG9w0BAQUF +AAOCAQEAhF4LO+ygjRyb0DwdcWnkGn9kvoFlYcWMatd8AHTgemJV7SR84GHj8t0U +5hFugw7h6qmegK2aIL/gV37V0LWEYy3ZGOS9GzUsXq5hdqpnhTs44TGBHzF/5tf4 +W9K7Y3mGxIzF3gqu19H8AXT/trYNYoFnHLsm+CSA4Fxe2KSKOo99y/+So/18qTJp +B1hYYUKZUgOxOD3GcW9s8uh9BqrBfFPLGi2IT8mpp6xpb/ekH9h0gfVKv7FVt9N3 +OKdvwkrI4nOJ01dy4UMvcjz2H7f4BEpuwemUF+SXF/QOE4ZvjavoXy20/2zWorQf +7LmUaqoSTxrd9Xe1JYzyigrx/FJbWA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8a:00:00:02:7c:00:00:00:03:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=ca@digsigtrust.com + Validity + Not Before: Dec 11 16:14:16 1998 GMT + Not After : Dec 8 16:14:16 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d9:ac:9b:77:fa:50:d3:cc:dc:b9:40:ac:b9:72: + 6a:00:87:23:fc:0f:96:21:d0:26:af:e4:e2:b5:5f: + fa:d3:a6:7d:21:30:2e:cc:17:82:8f:98:74:fc:67: + a4:a6:df:88:97:a2:42:29:f5:a7:db:11:93:fb:5e: + 23:30:c2:aa:bc:22:e7:41:1b:e5:ed:25:de:c8:3f: + db:de:57:45:78:40:46:83:b2:d5:1a:3d:df:0f:45: + 6d:d5:63:02:75:d8:2f:c6:6e:ab:95:91:74:37:0d: + cb:4d:09:5c:d1:d4:5b:3a:da:dd:0e:c8:6b:99:d8: + d5:39:cc:df:85:55:c4:92:53:02:a3:e1:f7:80:c9: + 70:a3:da:dc:33:c4:7f:a2:47:08:1c:35:96:1f:a1: + 03:1c:30:83:f4:c4:cc:ff:98:c3:b0:46:44:a2:c0: + bf:ad:db:d2:81:f6:4c:98:2c:a7:5e:24:f3:86:ca: + 63:d5:ba:7d:f0:9a:c0:4a:d0:1b:58:ee:ec:a9:67: + cf:69:02:6c:22:c0:60:2c:2c:d1:c8:20:ea:c8:2d: + fb:dd:9c:bb:cb:51:4c:dc:e7:57:04:3b:54:9b:11: + a5:32:74:ec:74:01:f3:90:15:5b:2f:7c:2c:93:65: + b9:66:67:b4:81:88:35:e5:9e:91:18:7f:81:a8:41: + c8:cb + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 84:5e:0b:3b:ec:a0:8d:1c:9b:d0:3c:1d:71:69:e4:1a:7f:64: + be:81:65:61:c5:8c:6a:d7:7c:00:74:e0:7a:62:55:ed:24:7c: + e0:61:e3:f2:dd:14:e6:11:6e:83:0e:e1:ea:a9:9e:80:ad:9a: + 20:bf:e0:57:7e:d5:d0:b5:84:63:2d:d9:18:e4:bd:1b:35:2c: + 5e:ae:61:76:aa:67:85:3b:38:e1:31:81:1f:31:7f:e6:d7:f8: + 5b:d2:bb:63:79:86:c4:8c:c5:de:0a:ae:d7:d1:fc:01:74:ff: + b6:b6:0d:62:81:67:1c:bb:26:f8:24:80:e0:5c:5e:d8:a4:8a: + 3a:8f:7d:cb:ff:92:a3:fd:7c:a9:32:69:07:58:58:61:42:99: + 52:03:b1:38:3d:c6:71:6f:6c:f2:e8:7d:06:aa:c1:7c:53:cb: + 1a:2d:88:4f:c9:a9:a7:ac:69:6f:f7:a4:1f:d8:74:81:f5:4a: + bf:b1:55:b7:d3:77:38:a7:6f:c2:4a:c8:e2:73:89:d3:57:72: + e1:43:2f:72:3c:f6:1f:b7:f8:04:4a:6e:c1:e9:94:17:e4:97: + 17:f4:0e:13:86:6f:8d:ab:e8:5f:2d:b4:ff:6c:d6:a2:b4:1f: + ec:b9:94:6a:aa:12:4f:1a:dd:f5:77:b5:25:8c:f2:8a:0a:f1: + fc:52:5b:58 + +TC TrustCenter, Germany, Class 1 CA +=================================== +MD5 Fingerprint: 64:3F:F8:3E:52:14:4A:59:BA:93:56:04:0B:23:02:D1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTYzM1oX +DTA1MTIzMTEzNTYzM1owgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCnrtHaz +rte2W7Re573jsZxJBFdboavZfxMb/bphq9jncd8tAJRdUUh9I+91YoSQPAofWRF0 +L46Apf0wAj0pUs1yGkkhnLzLUo5IoWOWyBCFMGlXdEXAWobG1T3gaFd9MWokjUWX +PjF+aGYybiRt7DI2yUHK8DFEyKNhyhugNh8CAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAx +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQAFQlImpAwn +AUSsXCUowkRCVAi5HcU+bFlmxLNOUKf4+JZ1oZZ16BY4oM1dbvp5pxt7HR7DALlm +vlrWYg/n8nu470zgwD9Zrjm3hAmeq/GpLmtp4q3M8up4CQUgOEJxGH7Hspfm1QIF +BlajX/GqwsRP/vfvFg+d7KqFzz0pJPEEzQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:56:33 1998 GMT + Not After : Dec 31 13:56:33 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:29:eb:b4:76:b3:ae:d7:b6:5b:b4:5e:e7:bd: + e3:b1:9c:49:04:57:5b:a1:ab:d9:7f:13:1b:fd:ba: + 61:ab:d8:e7:71:df:2d:00:94:5d:51:48:7d:23:ef: + 75:62:84:90:3c:0a:1f:59:11:74:2f:8e:80:a5:fd: + 30:02:3d:29:52:cd:72:1a:49:21:9c:bc:cb:52:8e: + 48:a1:63:96:c8:10:85:30:69:57:74:45:c0:5a:86: + c6:d5:3d:e0:68:57:7d:31:6a:24:8d:45:97:3e:31: + 7e:68:66:32:6e:24:6d:ec:32:36:c9:41:ca:f0:31: + 44:c8:a3:61:ca:1b:a0:36:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 1 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 05:42:52:26:a4:0c:27:01:44:ac:5c:25:28:c2:44:42:54:08: + b9:1d:c5:3e:6c:59:66:c4:b3:4e:50:a7:f8:f8:96:75:a1:96: + 75:e8:16:38:a0:cd:5d:6e:fa:79:a7:1b:7b:1d:1e:c3:00:b9: + 66:be:5a:d6:62:0f:e7:f2:7b:b8:ef:4c:e0:c0:3f:59:ae:39: + b7:84:09:9e:ab:f1:a9:2e:6b:69:e2:ad:cc:f2:ea:78:09:05: + 20:38:42:71:18:7e:c7:b2:97:e6:d5:02:05:06:56:a3:5f:f1: + aa:c2:c4:4f:fe:f7:ef:16:0f:9d:ec:aa:85:cf:3d:29:24:f1: + 04:cd + +TC TrustCenter, Germany, Class 2 CA +=================================== +MD5 Fingerprint: E1:E9:96:53:77:E1:F0:38:A0:02:AB:94:C6:95:7B:FC +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTc0NFoX +DTA1MTIzMTEzNTc0NFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2jjo7TIA +KXGDAQ2/jAHc2satOaSpii/Vi1xoX1DGYvVmvcqRIuyqHVHXPbNRsoNOXctJsPBM +VeVrLceFCzAckk6C1MoC7fdvvtzg4xS4BVPymvRWi1qehZPRtIJWrk27qEtXFrz+ ++Fie+CmNsHvNeMlPrItnDPGc+/xXm1dcTw0CAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAy +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCJG/Tv6Tji +bAz2zW9JzinM+6YP+Y0+lUbW/EcyibLIBmF60ucNEwKUC9mLVkf0u+fFX3v0Y0yu +fDTqDaKpsyyF8+P+J1QQkrCPksGYQhhwSNtOLOsNJGjk0fe+Cakph7vo2tw+o4hC +MfXR43+u2I4AWnSYsE/G/yN7XHMAeMnbTg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:57:44 1998 GMT + Not After : Dec 31 13:57:44 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:38:e8:ed:32:00:29:71:83:01:0d:bf:8c:01: + dc:da:c6:ad:39:a4:a9:8a:2f:d5:8b:5c:68:5f:50: + c6:62:f5:66:bd:ca:91:22:ec:aa:1d:51:d7:3d:b3: + 51:b2:83:4e:5d:cb:49:b0:f0:4c:55:e5:6b:2d:c7: + 85:0b:30:1c:92:4e:82:d4:ca:02:ed:f7:6f:be:dc: + e0:e3:14:b8:05:53:f2:9a:f4:56:8b:5a:9e:85:93: + d1:b4:82:56:ae:4d:bb:a8:4b:57:16:bc:fe:f8:58: + 9e:f8:29:8d:b0:7b:cd:78:c9:4f:ac:8b:67:0c:f1: + 9c:fb:fc:57:9b:57:5c:4f:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 2 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 89:1b:f4:ef:e9:38:e2:6c:0c:f6:cd:6f:49:ce:29:cc:fb:a6: + 0f:f9:8d:3e:95:46:d6:fc:47:32:89:b2:c8:06:61:7a:d2:e7: + 0d:13:02:94:0b:d9:8b:56:47:f4:bb:e7:c5:5f:7b:f4:63:4c: + ae:7c:34:ea:0d:a2:a9:b3:2c:85:f3:e3:fe:27:54:10:92:b0: + 8f:92:c1:98:42:18:70:48:db:4e:2c:eb:0d:24:68:e4:d1:f7: + be:09:a9:29:87:bb:e8:da:dc:3e:a3:88:42:31:f5:d1:e3:7f: + ae:d8:8e:00:5a:74:98:b0:4f:c6:ff:23:7b:5c:73:00:78:c9: + db:4e + +TC TrustCenter, Germany, Class 3 CA +=================================== +MD5 Fingerprint: 62:AB:B6:15:4A:B4:B0:16:77:FF:AE:CF:16:16:2B:8C +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTg0OVoX +DTA1MTIzMTEzNTg0OVowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrTBNQUu +DY3soEBqHA4nplCSa1AbB94u53bM4Nr8hKhejGNqK03ZTgJ2EcEL8o15ygC28bAO +1/ukFz2vq2l6lie/rzOhmipZqsS1NwjyEqUxtkP1MpZxKCirjSiG37vu4wx9MNbD +UquPXSeca8Cj5wVrV0lEs27qZM/SjnpQd3cCAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAz +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCEhlBieaAn +4SW6CbE0DxMJ7S3Ko+aV+TCszRelzj2Xnex8jyZ/wGHKIveR3Tw2WZqbdfe85Mjt +7AK2IqfzLPHIknhttu7FKOyAIE+5awjnL6eGHn2xCJ9UuQA3PKDYGsiWHPQyFJw5 +lbfu8ENJwl7oy3lvU7/7SYos2EvZVfIScA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:58:49 1998 GMT + Not After : Dec 31 13:58:49 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:b4:c1:35:05:2e:0d:8d:ec:a0:40:6a:1c:0e: + 27:a6:50:92:6b:50:1b:07:de:2e:e7:76:cc:e0:da: + fc:84:a8:5e:8c:63:6a:2b:4d:d9:4e:02:76:11:c1: + 0b:f2:8d:79:ca:00:b6:f1:b0:0e:d7:fb:a4:17:3d: + af:ab:69:7a:96:27:bf:af:33:a1:9a:2a:59:aa:c4: + b5:37:08:f2:12:a5:31:b6:43:f5:32:96:71:28:28: + ab:8d:28:86:df:bb:ee:e3:0c:7d:30:d6:c3:52:ab: + 8f:5d:27:9c:6b:c0:a3:e7:05:6b:57:49:44:b3:6e: + ea:64:cf:d2:8e:7a:50:77:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 3 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 84:86:50:62:79:a0:27:e1:25:ba:09:b1:34:0f:13:09:ed:2d: + ca:a3:e6:95:f9:30:ac:cd:17:a5:ce:3d:97:9d:ec:7c:8f:26: + 7f:c0:61:ca:22:f7:91:dd:3c:36:59:9a:9b:75:f7:bc:e4:c8: + ed:ec:02:b6:22:a7:f3:2c:f1:c8:92:78:6d:b6:ee:c5:28:ec: + 80:20:4f:b9:6b:08:e7:2f:a7:86:1e:7d:b1:08:9f:54:b9:00: + 37:3c:a0:d8:1a:c8:96:1c:f4:32:14:9c:39:95:b7:ee:f0:43: + 49:c2:5e:e8:cb:79:6f:53:bf:fb:49:8a:2c:d8:4b:d9:55:f2: + 12:70 + +TC TrustCenter, Germany, Class 4 CA +=================================== +MD5 Fingerprint: BF:AF:EC:C4:DA:F9:30:F9:CA:35:CA:25:E4:3F:8D:89 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBBTANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTE0MDAyMFoX +DTA1MTIzMTE0MDAyMFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyA0IENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvy9j1jZ7 +sg3TVfVkbOYlXca0yBS6JTiD61ZipVWpZaP0I5nCS7nQzVRnpqOgo6kzK3bkva13 +su1cEnTDxbYPUppyk0OQYmYVD0Wl3eDduG9AblfBeXKjYKq6dh0SiVNa/AK+4QkT +xUov3D2LGa3XiyRF+0z0zVw1HSlMUfPybFUCAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyA0 +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCUaBQbJZ4p +mbGyI9JEs5Wf0Z5VBN3jL4IzVZZ3GZ0rnmUc+orjx48l/LEeVUYPj/9PNy+kdlmm +ZOvVFnC93ZUzDKQNJOtkULRDEfJDvg1xmCLsAa/s98dcccN1kVgZ6N2g9LTxvBBK +85O0Bkm7H2bSvXRH4Zr569erbR+64R0s2g== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 5 (0x5) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 14:00:20 1998 GMT + Not After : Dec 31 14:00:20 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:2f:63:d6:36:7b:b2:0d:d3:55:f5:64:6c:e6: + 25:5d:c6:b4:c8:14:ba:25:38:83:eb:56:62:a5:55: + a9:65:a3:f4:23:99:c2:4b:b9:d0:cd:54:67:a6:a3: + a0:a3:a9:33:2b:76:e4:bd:ad:77:b2:ed:5c:12:74: + c3:c5:b6:0f:52:9a:72:93:43:90:62:66:15:0f:45: + a5:dd:e0:dd:b8:6f:40:6e:57:c1:79:72:a3:60:aa: + ba:76:1d:12:89:53:5a:fc:02:be:e1:09:13:c5:4a: + 2f:dc:3d:8b:19:ad:d7:8b:24:45:fb:4c:f4:cd:5c: + 35:1d:29:4c:51:f3:f2:6c:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 4 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 94:68:14:1b:25:9e:29:99:b1:b2:23:d2:44:b3:95:9f:d1:9e: + 55:04:dd:e3:2f:82:33:55:96:77:19:9d:2b:9e:65:1c:fa:8a: + e3:c7:8f:25:fc:b1:1e:55:46:0f:8f:ff:4f:37:2f:a4:76:59: + a6:64:eb:d5:16:70:bd:dd:95:33:0c:a4:0d:24:eb:64:50:b4: + 43:11:f2:43:be:0d:71:98:22:ec:01:af:ec:f7:c7:5c:71:c3: + 75:91:58:19:e8:dd:a0:f4:b4:f1:bc:10:4a:f3:93:b4:06:49: + bb:1f:66:d2:bd:74:47:e1:9a:f9:eb:d7:ab:6d:1f:ba:e1:1d: + 2c:da + +Thawte Personal Basic CA +======================== +MD5 Fingerprint: E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj +IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X +DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw +EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE +ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD +QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 +dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK +wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 +G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF +AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 +c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P +9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basic@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basic@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:bc:93:53:6d:c0:50:4f:82:15:e6:48:94:35: + a6:5a:be:6f:42:fa:0f:47:ee:77:75:72:dd:8d:49: + 9b:96:57:a0:78:d4:ca:3f:51:b3:69:0b:91:76:17: + 22:07:97:6a:c4:51:93:4b:e0:8d:ef:37:95:a1:0c: + 4d:da:34:90:1d:17:89:97:e0:35:38:57:4a:c0:f4: + 08:70:e9:3c:44:7b:50:7e:61:9a:90:e3:23:d3:88: + 11:46:27:f5:0b:07:0e:bb:dd:d1:7f:20:0a:88:b9: + 56:0b:2e:1c:80:da:f1:e3:9e:29:ef:14:bd:0a:44: + fb:1b:5b:18:d1:bf:23:93:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 2d:e2:99:6b:b0:3d:7a:89:d7:59:a2:94:01:1f:2b:dd:12:4b: + 53:c2:ad:7f:aa:a7:00:5c:91:40:57:25:4a:38:aa:84:70:b9: + d9:80:0f:a5:7b:5c:fb:73:c6:bd:d7:8a:61:5c:03:e3:2d:27: + a8:17:e0:84:85:42:dc:5e:9b:c6:b7:b2:6d:bb:74:af:e4:3f: + cb:a7:b7:b0:e0:5d:be:78:83:25:94:d2:db:81:0f:79:07:6d: + 4f:f4:39:15:5a:52:01:7b:de:32:d6:4d:38:f6:12:5c:06:50: + df:05:5b:bd:14:4b:a1:df:29:ba:3b:41:8d:f7:63:56:a1:df: + 22:b1 + +Thawte Personal Freemail CA +=========================== +MD5 Fingerprint: 1E:74:C3:86:3C:0C:35:C5:3E:C2:7F:EF:3C:AA:3C:D9 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt +YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu +Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa +MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG +cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh +d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY +DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E +rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq +uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN +BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP +MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa +/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei +gQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemail@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemail@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d4:69:d7:d4:b0:94:64:5b:71:e9:47:d8:0c:51: + b6:ea:72:91:b0:84:5e:7d:2d:0d:8f:7b:12:df:85: + 25:75:28:74:3a:42:2c:63:27:9f:95:7b:4b:ef:7e: + 19:87:1d:86:ea:a3:dd:b9:ce:96:64:1a:c2:14:6e: + 44:ac:7c:e6:8f:e8:4d:0f:71:1f:40:38:a6:00:a3: + 87:78:f6:f9:94:86:5e:ad:ea:c0:5e:76:eb:d9:14: + a3:5d:6e:7a:7c:0c:a5:4b:55:7f:06:19:29:7f:9e: + 9a:26:d5:6a:bb:38:24:08:6a:98:c7:b1:da:a3:98: + 91:fd:79:db:e5:5a:c4:1c:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + c7:ec:92:7e:4e:f8:f5:96:a5:67:62:2a:a4:f0:4d:11:60:d0: + 6f:8d:60:58:61:ac:26:bb:52:35:5c:08:cf:30:fb:a8:4a:96: + 8a:1f:62:42:23:8c:17:0f:f4:ba:64:9c:17:ac:47:29:df:9d: + 98:5e:d2:6c:60:71:5c:a2:ac:dc:79:e3:e7:6e:00:47:1f:b5: + 0d:28:e8:02:9d:e4:9a:fd:13:f4:a6:d9:7c:b1:f8:dc:5f:23: + 26:09:91:80:73:d0:14:1b:de:43:a9:83:25:f2:e6:9c:2f:15: + ca:fe:a6:ab:8a:07:75:8b:0c:dd:51:84:6b:e4:f8:d1:ce:77: + a2:81 + +Thawte Personal Premium CA +========================== +MD5 Fingerprint: 3A:B2:DE:22:9A:20:93:49:F9:ED:C8:D2:8A:E7:68:0D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p +dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv +bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa +QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY +BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u +IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl +bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu +Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs +Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI +Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD +ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH +b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh +KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premium@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premium@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:66:d9:f8:07:44:cf:b9:8c:2e:f0:a1:ef:13: + 45:6c:05:df:de:27:16:51:36:41:11:6c:6c:3b:ed: + fe:10:7d:12:9e:e5:9b:42:9a:fe:60:31:c3:66:b7: + 73:3a:48:ae:4e:d0:32:37:94:88:b5:0d:b6:d9:f3: + f2:44:d9:d5:88:12:dd:76:4d:f2:1a:fc:6f:23:1e: + 7a:f1:d8:98:45:4e:07:10:ef:16:42:d0:43:75:6d: + 4a:de:e2:aa:c9:31:ff:1f:00:70:7c:66:cf:10:25: + 08:ba:fa:ee:00:e9:46:03:66:27:11:15:3b:aa:5b: + f2:98:dd:36:42:b2:da:88:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 69:36:89:f7:34:2a:33:72:2f:6d:3b:d4:22:b2:b8:6f:9a:c5: + 36:66:0e:1b:3c:a1:b1:75:5a:e6:fd:35:d3:f8:a8:f2:07:6f: + 85:67:8e:de:2b:b9:e2:17:b0:3a:a0:f0:0e:a2:00:9a:df:f3: + 14:15:6e:bb:c8:85:5a:98:80:f9:ff:be:74:1d:3d:f3:fe:30: + 25:d1:37:34:67:fa:a5:71:79:30:61:29:72:c0:e0:2c:4c:fb: + 56:e4:3a:a8:6f:e5:32:59:52:db:75:28:50:59:0c:f8:0b:19: + e4:ac:d9:af:96:8d:2f:50:db:07:c3:ea:1f:ab:33:e0:f5:2b: + 31:89 + +Thawte Premium Server CA +======================== +MD5 Fingerprint: 06:9F:69:79:16:66:90:02:1B:8C:8C:A2:C3:07:6F:3A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-server@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-server@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:36:36:6a:8b:d7:c2:5b:9e:da:81:41:62:8f: + 38:ee:49:04:55:d6:d0:ef:1c:1b:95:16:47:ef:18: + 48:35:3a:52:f4:2b:6a:06:8f:3b:2f:ea:56:e3:af: + 86:8d:9e:17:f7:9e:b4:65:75:02:4d:ef:cb:09:a2: + 21:51:d8:9b:d0:67:d0:ba:0d:92:06:14:73:d4:93: + cb:97:2a:00:9c:5c:4e:0c:bc:fa:15:52:fc:f2:44: + 6e:da:11:4a:6e:08:9f:2f:2d:e3:f9:aa:3a:86:73: + b6:46:53:58:c8:89:05:bd:83:11:b8:73:3f:aa:07: + 8d:f4:42:4d:e7:40:9d:1c:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 26:48:2c:16:c2:58:fa:e8:16:74:0c:aa:aa:5f:54:3f:f2:d7: + c9:78:60:5e:5e:6e:37:63:22:77:36:7e:b2:17:c4:34:b9:f5: + 08:85:fc:c9:01:38:ff:4d:be:f2:16:42:43:e7:bb:5a:46:fb: + c1:c6:11:1f:f1:4a:b0:28:46:c9:c3:c4:42:7d:bc:fa:ab:59: + 6e:d5:b7:51:88:11:e3:a4:85:19:6b:82:4c:a4:0c:12:ad:e9: + a4:ae:3f:f1:c3:49:65:9a:8c:c5:c8:3e:25:b7:94:99:bb:92: + 32:71:07:f0:86:5e:ed:50:27:a6:0d:a6:23:f9:bb:cb:a6:07: + 14:42 + +Thawte Server CA +================ +MD5 Fingerprint: C5:70:C4:A2:ED:53:78:0C:C8:10:53:81:64:CB:D0:1D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certs@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certs@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:a4:50:6e:c8:ff:56:6b:e6:cf:5d:b6:ea:0c: + 68:75:47:a2:aa:c2:da:84:25:fc:a8:f4:47:51:da: + 85:b5:20:74:94:86:1e:0f:75:c9:e9:08:61:f5:06: + 6d:30:6e:15:19:02:e9:52:c0:62:db:4d:99:9e:e2: + 6a:0c:44:38:cd:fe:be:e3:64:09:70:c5:fe:b1:6b: + 29:b6:2f:49:c8:3b:d4:27:04:25:10:97:2f:e7:90: + 6d:c0:28:42:99:d7:4c:43:de:c3:f5:21:6d:54:9f: + 5d:c3:58:e1:c0:e4:d9:5b:b0:b8:dc:b4:7b:df:36: + 3a:c2:b5:66:22:12:d6:87:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 07:fa:4c:69:5c:fb:95:cc:46:ee:85:83:4d:21:30:8e:ca:d9: + a8:6f:49:1a:e6:da:51:e3:60:70:6c:84:61:11:a1:1a:c8:48: + 3e:59:43:7d:4f:95:3d:a1:8b:b7:0b:62:98:7a:75:8a:dd:88: + 4e:4e:9e:40:db:a8:cc:32:74:b9:6f:0d:c6:e3:b3:44:0b:d9: + 8a:6f:9a:29:9b:99:18:28:3b:d1:e3:40:28:9a:5a:3c:d5:b5: + e7:20:1b:8b:ca:a4:ab:8d:e9:51:d9:e2:4c:2c:59:a9:da:b9: + b2:75:1b:f6:42:f2:ef:c7:f2:18:f9:89:bc:a3:ff:8a:23:2e: + 70:47 + +Thawte Universal CA Root +======================== +MD5 Fingerprint: 17:AF:71:16:52:7B:73:65:22:05:29:28:84:71:9D:13 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIRIjCCCQoCAQAwDQYJKoZIhvcNAQEFBQAwVzEPMA0GA1UEChMGVGhhd3RlMSEw +HwYDVQQLExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3QxITAfBgNVBAMTGFRoYXd0 +ZSBVbml2ZXJzYWwgQ0EgUm9vdDAeFw05OTEyMDUxMzU2MDVaFw0zNzA0MDMxMzU2 +MDVaMFcxDzANBgNVBAoTBlRoYXd0ZTEhMB8GA1UECxMYVGhhd3RlIFVuaXZlcnNh +bCBDQSBSb290MSEwHwYDVQQDExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3Qwgggi +MA0GCSqGSIb3DQEBAQUAA4IIDwAwgggKAoIIAQDiiQVtw3+tpok6/7vHzZ03seHS +IR6bYSoV53tXT1U80Lv52T0+przstK1TmhYC6wty/Yryj0QFxevT5b22RDnm+0e/ +ap4KlRjiaOLWltYhrYj99Rf109pCpZDtKZWWdTrah6HU9dOH3gVipuNmdJLPpby7 +32j/cXVWQVk16zNaZlHy0qMKwYzOc1wRby2MlYyRsf3P5a1WlcyFkoOQVUHJwnft ++aN0QgpoCPPQ0WX9Zyw0/yR/53nIBzslV92kDJg9vuDMGWXb8lSir0LUneKuhCMl +CTMStWoedsSL2UkAbF66H/Ib2mfKJ6qjRCMbg4LO8qsz7VSk3MmrWWXROA7BPhtn +j9Z1AeBVIt12d+yO3fTPeSJtuVcD9ZkIpzw+NPvEF64jWM0k8yPKagIolAGBNLRs +a66LGsOj0gk8FlT1Nl8k459KoeJkxhbDpoF6JDZHjsFeDvv5FXgE1g5Z2Z1YZmLS +lCkyMsh4uWb2tVbhbMYUS5ZSWZECJGpVR9c/tiMaYHeXLuJAr54EV56tEcXJQ3Dv +SLRerBxpLi6C1VuLvoK+GRRe5w0ix1Eb/x6b8TCPcTEGszQnj196ZoJPii0Tq0LP +IVael45mNg+Wm+Ur9AKpKmqMLMTDuHAsLSkeP1B3Hm0qVORVCpE4ocW1ZqJ2Wu4P +v7Rn4ShuD+E2oYLRv9R34cRnMpN4yOdUU/4jeeZozCaQ9hBjXSpvkS2kczJRIfK7 +Fd+qJAhIBt6hnia/uoO/fKTIoIy90v+8hGknEyQYxEUYIyZeGBTKLoiHYqNT5iG3 +uIV7moW7FSZy+Ln3anQPST+SvqkFt5knv78JF0uZTK0REHzfdDH2jyZfqoiuOFfI +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 +yJTuQFv5QgLC/7DYLOsof17JJgGZpw== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root + Validity + Not Before: Dec 5 13:56:05 1999 GMT + Not After : Apr 3 13:56:05 2037 GMT + Subject: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (16384 bit) + Modulus (16384 bit): + 00:e2:89:05:6d:c3:7f:ad:a6:89:3a:ff:bb:c7:cd: + 9d:37:b1:e1:d2:21:1e:9b:61:2a:15:e7:7b:57:4f: + 55:3c:d0:bb:f9:d9:3d:3e:a6:bc:ec:b4:ad:53:9a: + 16:02:eb:0b:72:fd:8a:f2:8f:44:05:c5:eb:d3:e5: + bd:b6:44:39:e6:fb:47:bf:6a:9e:0a:95:18:e2:68: + e2:d6:96:d6:21:ad:88:fd:f5:17:f5:d3:da:42:a5: + 90:ed:29:95:96:75:3a:da:87:a1:d4:f5:d3:87:de: + 05:62:a6:e3:66:74:92:cf:a5:bc:bb:df:68:ff:71: + 75:56:41:59:35:eb:33:5a:66:51:f2:d2:a3:0a:c1: + 8c:ce:73:5c:11:6f:2d:8c:95:8c:91:b1:fd:cf:e5: + ad:56:95:cc:85:92:83:90:55:41:c9:c2:77:ed:f9: + a3:74:42:0a:68:08:f3:d0:d1:65:fd:67:2c:34:ff: + 24:7f:e7:79:c8:07:3b:25:57:dd:a4:0c:98:3d:be: + e0:cc:19:65:db:f2:54:a2:af:42:d4:9d:e2:ae:84: + 23:25:09:33:12:b5:6a:1e:76:c4:8b:d9:49:00:6c: + 5e:ba:1f:f2:1b:da:67:ca:27:aa:a3:44:23:1b:83: + 82:ce:f2:ab:33:ed:54:a4:dc:c9:ab:59:65:d1:38: + 0e:c1:3e:1b:67:8f:d6:75:01:e0:55:22:dd:76:77: + ec:8e:dd:f4:cf:79:22:6d:b9:57:03:f5:99:08:a7: + 3c:3e:34:fb:c4:17:ae:23:58:cd:24:f3:23:ca:6a: + 02:28:94:01:81:34:b4:6c:6b:ae:8b:1a:c3:a3:d2: + 09:3c:16:54:f5:36:5f:24:e3:9f:4a:a1:e2:64:c6: + 16:c3:a6:81:7a:24:36:47:8e:c1:5e:0e:fb:f9:15: + 78:04:d6:0e:59:d9:9d:58:66:62:d2:94:29:32:32: + c8:78:b9:66:f6:b5:56:e1:6c:c6:14:4b:96:52:59: + 91:02:24:6a:55:47:d7:3f:b6:23:1a:60:77:97:2e: + e2:40:af:9e:04:57:9e:ad:11:c5:c9:43:70:ef:48: + b4:5e:ac:1c:69:2e:2e:82:d5:5b:8b:be:82:be:19: + 14:5e:e7:0d:22:c7:51:1b:ff:1e:9b:f1:30:8f:71: + 31:06:b3:34:27:8f:5f:7a:66:82:4f:8a:2d:13:ab: + 42:cf:21:56:9e:97:8e:66:36:0f:96:9b:e5:2b:f4: + 02:a9:2a:6a:8c:2c:c4:c3:b8:70:2c:2d:29:1e:3f: + 50:77:1e:6d:2a:54:e4:55:0a:91:38:a1:c5:b5:66: + a2:76:5a:ee:0f:bf:b4:67:e1:28:6e:0f:e1:36:a1: + 82:d1:bf:d4:77:e1:c4:67:32:93:78:c8:e7:54:53: + fe:23:79:e6:68:cc:26:90:f6:10:63:5d:2a:6f:91: + 2d:a4:73:32:51:21:f2:bb:15:df:aa:24:08:48:06: + de:a1:9e:26:bf:ba:83:bf:7c:a4:c8:a0:8c:bd:d2: + ff:bc:84:69:27:13:24:18:c4:45:18:23:26:5e:18: + 14:ca:2e:88:87:62:a3:53:e6:21:b7:b8:85:7b:9a: + 85:bb:15:26:72:f8:b9:f7:6a:74:0f:49:3f:92:be: + a9:05:b7:99:27:bf:bf:09:17:4b:99:4c:ad:11:10: + 7c:df:74:31:f6:8f:26:5f:aa:88:ae:38:57:c8:55: + 2d:d3:fb:d8:1b:51:99:be:25:1b:3a:ba:c0:7d:1b: + ed:ce:d2:49:b9:cf:f3:c5:7d:89:90:81:d8:69:48: + 20:10:a3:f8:ef:92:51:18:32:8b:11:18:c0:3f:1b: + 85:56:ce:57:c9:f2:82:64:c6:df:02:09:2e:4a:11: + 2f:b1:27:6d:37:52:f0:f0:16:61:f1:67:8d:df:87: + 72:af:87:da:cf:fb:50:94:6e:d4:94:85:eb:8a:2c: + ea:21:f5:96:4a:44:d5:e0:ce:6a:74:44:4d:d0:05: + d3:87:15:ed:36:d0:a4:8b:66:55:70:93:ee:47:06: + c1:7e:2e:a5:18:79:67:f3:28:85:f1:70:f7:0e:83: + a4:7e:54:9e:5a:76:32:cb:65:1b:b8:cd:fb:c8:28: + 03:d2:54:91:d1:a7:c5:85:43:08:17:76:a5:e6:2f: + 67:08:d8:a1:a2:82:2d:0c:f8:c1:af:63:d4:50:77: + 6d:6b:46:4a:41:85:d5:90:5f:79:2d:c4:ec:d7:11: + 87:40:8a:e1:68:e2:64:f8:55:32:fb:6f:93:2c:da: + 77:d9:21:c1:17:e5:36:2c:4e:7e:90:7f:ac:94:2b: + 32:67:be:38:50:76:b8:ae:41:b9:d7:21:c5:09:4c: + 60:c8:a3:51:c4:34:9b:57:37:df:cb:c9:33:57:8b: + eb:fb:76:9f:19:4d:c5:6a:1f:2a:45:ae:2b:ed:2f: + 8d:a7:a5:00:cb:04:fa:25:62:2e:74:48:1b:ca:2a: + 8c:ba:db:b6:7e:f6:bb:02:7c:a9:c3:db:58:78:a1: + bf:f0:fe:1a:10:55:11:ce:e8:69:4e:96:65:c6:17: + 03:d6:07:68:8c:54:82:ae:1c:22:55:3f:f1:f4:09: + 97:28:c0:46:f7:4e:0b:25:1d:f7:07:d7:09:1d:3a: + 18:57:38:3b:e8:33:06:e7:8f:78:46:1e:5b:f5:06: + b6:ec:b8:a6:0d:f1:ba:13:4b:d6:18:20:dd:69:33: + 4a:33:15:ae:b8:c8:98:8a:27:2c:93:bc:2d:fb:ee: + 33:bf:66:e6:4d:ba:b6:9b:06:55:60:97:4b:bc:44: + cd:7e:f4:a1:d8:aa:2f:c0:02:28:21:16:62:78:db: + 08:54:f2:fc:f4:34:e3:c6:8f:1c:43:57:ce:90:1a: + 4b:dc:2e:3b:28:91:89:3f:7a:da:35:1d:8e:2c:ee: + 49:ec:f4:33:ad:c9:53:a8:8c:9f:04:53:3e:24:1c: + 52:c9:12:f9:62:57:a3:bc:ee:2c:eb:40:7c:20:23: + 70:2b:95:f9:73:17:8a:d1:c1:1c:69:a6:b7:38:9a: + 67:f7:70:1d:7a:5a:0c:40:cf:62:0f:85:3c:c2:02: + 4e:7e:b5:f6:c5:2a:29:84:b3:1f:37:2a:e1:aa:72: + 42:c4:ed:6b:1a:8f:92:1c:5d:be:d1:f2:5b:f2:ab: + aa:a9:d2:f5:b8:a4:41:2b:2b:91:6e:12:48:ca:98: + d8:37:8d:c8:ed:00:30:b5:b6:04:4e:7e:9c:da:84: + ec:c0:fa:7b:e5:1d:88:a4:53:46:b0:94:e4:5c:1b: + a1:25:2c:0f:48:52:77:97:09:6c:ec:5b:18:33:83: + 02:e5:82:7e:cd:85:21:30:11:fd:27:4f:cf:e4:1e: + ec:3f:a5:57:6c:e9:2a:30:19:2a:88:e5:c3:69:38: + ab:6f:39:71:7f:84:e1:41:c3:e1:cc:2a:89:20:52: + 2e:83:0f:6c:39:3f:4b:2d:16:ac:2d:f0:24:ac:00: + 73:f4:9b:b3:06:3f:05:b8:14:85:1f:ab:9e:5c:3c: + 9e:62:9d:0e:6d:3b:80:09:fc:02:ea:a2:97:74:ca: + c7:f9:e3:56:e1:c3:ca:a5:a6:9a:c0:90:e0:24:12: + 53:d2:c2:8b:da:be:ed:02:43:5e:67:e1:89:98:79: + ee:cb:aa:ca:c3:1b:dc:e7:a5:46:a5:7c:6b:16:87: + b6:5a:28:d7:db:27:3c:5e:a5:bd:b6:51:dd:1f:43: + cf:3b:26:c8:3a:8d:25:61:c1:49:f4:3c:1b:c9:44: + ea:af:1c:c2:2b:94:01:2a:0e:30:d1:5b:8b:2b:47: + e5:c3:d1:04:03:9b:0e:39:2c:d6:27:d4:e6:70:5a: + d9:75:cf:2a:d8:c9:00:05:e4:13:88:ec:c3:39:fb: + 87:61:30:36:43:03:c8:9e:9c:a2:06:c2:2f:c5:fc: + f0:80:63:b1:54:04:a0:4c:a9:2e:c6:f5:76:7a:d8: + d0:e4:d4:94:11:e5:15:b5:78:06:dc:b8:80:8f:99: + a9:20:33:3d:10:85:4c:65:09:ca:3e:58:5e:60:93: + 9a:aa:62:5d:c0:51:06:1c:5d:60:a0:0d:9c:4b:43: + f6:a7:16:21:a4:87:aa:f2:c1:2e:ee:92:30:b8:9e: + df:df:10:01:8b:86:09:70:d8:6c:a8:b7:50:1e:16: + 96:b4:f7:67:fd:35:3a:21:90:2a:32:c7:00:7b:4d: + 07:10:09:b9:2f:73:d8:18:7e:67:99:04:4f:06:fc: + 50:c7:85:9b:9d:40:9d:b3:96:37:fa:a5:dc:b2:72: + 4e:ef:4e:09:2c:fd:91:fd:4d:f7:bb:a6:a1:3e:ab: + 7b:a2:03:40:a6:a9:55:27:e2:fa:f9:19:ce:87:75: + aa:f1:75:36:f3:f3:b8:91:f8:91:c3:8b:75:13:8e: + 4c:65:9a:16:39:6a:e5:34:e8:7a:96:59:7f:35:b0: + 00:fd:5b:69:fc:43:26:fa:f5:28:6e:fe:87:d9:7e: + 24:fb:b4:a0:82:6e:54:a2:ff:ae:bf:62:b4:f4:72: + 01:c2:cb:98:47:98:e1:4c:b5:17:80:80:ce:8f:a6: + 28:ee:1e:45:6a:fb:df:f1:1d:fc:5a:3b:d6:ea:f4: + 6c:1d:62:49:57:3b:8a:8f:86:ea:f0:53:04:ce:9c: + 16:68:ff:ba:b9:fc:88:0f:47:f7:02:44:72:40:b8: + ca:3b:2d:53:9d:dc:3c:56:8c:59:7b:68:1a:2c:8d: + 71:bb:6c:00:c7:1a:ce:6f:40:92:b1:a3:2f:0f:d9: + 44:f2:a3:70:2e:9e:ee:0e:ae:32:d0:3b:3e:8b:07: + ea:e6:79:b3:5c:29:e2:7d:6b:a8:5e:f9:5a:31:e8: + 08:96:a2:8c:03:98:46:f1:b8:7d:90:54:26:ed:76: + 62:fe:9e:e9:9a:6e:5e:c9:49:c7:5c:34:53:29:54: + d9:ec:e4:46:e1:80:3b:75:d9:df:fb:79:d5:87:f1: + ba:9e:eb:19:ce:4c:52:73:e6:5b:87:ae:25:4f:39: + 79:cc:c6:b8:f9:10:7b:ec:f0:9b:71:a4:05:a0:d3: + 29:d3:4e:7f:1f:f4:2d:28:78:cc:55:95:7b:1e:91: + 2f:cc:56:18:73:8b:b2:db:bc:69:07:e6:d0:d8:4f: + ed:a2:ff:58:85:a3:6d:e0:4a:53:b7:67:7d:8d:0c: + 5c:5b:7b:77:28:02:35:44:7a:04:d3:28:43:c8:6b: + 30:17:5d:32:b8:29:35:ba:76:da:3b:14:4a:76:18: + 58:a4:f8:92:3c:9e:4d:33:6f:46:6b:08:d9:31:48: + 68:dd:f4:fb:24:56:34:b2:cf:69:66:be:48:d2:8a: + 66:22:cd:f2:69:cd:c2:53:13:45:29:41:22:d6:5d: + 98:1f:b6:a4:b2:a3:c2:ee:02:2f:51:1b:dc:83:a4: + ec:70:25:a8:d4:08:61:32:6f:e4:a1:81:2e:7c:63: + 72:fa:29:65:bc:70:44:cf:5d + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 55:9a:34:6a:22:06:69:09:45:33:c7:ae:a9:5c:c7:09:4e:9b: + 86:bc:41:90:d4:94:52:f6:cd:23:29:94:4b:22:cd:e8:bd:fe: + 9d:cd:52:f2:bd:ed:ab:87:c9:ab:ab:46:04:b4:bd:a2:3f:22: + 30:47:50:c0:4b:8c:76:0f:03:f5:92:d2:b1:2d:c4:7a:35:9c: + c9:73:87:eb:a6:9f:de:0f:73:8d:d3:7f:99:d8:ba:8f:6f:c4: + f3:be:1a:ae:8b:a2:94:36:90:e2:e5:eb:8d:05:f4:fc:65:df: + 95:f1:c4:94:4d:17:56:d7:9f:3c:8f:50:3c:e7:77:bf:95:86: + 26:64:fb:6a:ff:c6:da:e9:8c:ae:42:bb:69:e5:33:c6:d8:e9: + 0d:c6:55:21:49:c1:0c:b4:a3:f9:9b:4b:5c:de:83:4f:41:03: + ce:2a:79:68:38:7d:f0:54:49:20:f5:b6:10:ff:08:dc:33:66: + 96:9b:ff:06:de:00:9e:d7:ce:56:43:9a:51:fc:70:cd:f6:f0: + 51:a3:b7:cd:b4:5c:85:62:cd:71:b7:c6:2b:23:2b:dd:c3:6e: + 40:42:fa:37:ff:37:1c:f6:7a:57:94:87:85:23:d7:d4:c9:c7: + 5f:c1:4d:2f:c9:0d:d7:5c:ec:9c:25:ee:9e:30:82:91:96:72: + b8:75:1d:f8:09:68:57:97:b2:2d:4b:ee:25:ec:7a:24:29:ee: + 72:d4:9c:13:db:ab:dc:03:0a:d8:4a:14:c9:08:57:44:5d:a1: + b5:53:80:34:f2:14:97:cf:52:de:a2:0e:8a:10:e9:14:ef:d0: + 60:be:61:a1:f1:25:5d:d5:18:73:3f:93:10:ca:96:ee:b3:40: + d2:db:a3:55:cf:57:5a:a5:0e:4f:75:47:df:ea:f7:90:9a:6d: + f5:70:2e:1d:14:1c:37:64:04:59:50:b0:dc:72:86:6f:9c:37: + 3d:5d:28:af:73:55:ef:d2:ee:24:74:74:13:ef:dc:db:31:49: + fb:3f:63:f5:d3:08:3e:33:a5:e7:9d:0a:de:53:2c:51:8e:67: + db:9b:41:65:41:50:bd:d4:a4:96:6c:87:bc:12:e0:94:c7:d3: + c0:e4:cb:73:58:00:83:e1:ac:27:85:d6:9d:53:9d:5c:bd:0a: + 3e:03:43:9c:0c:91:f5:6d:7b:f8:40:72:75:ab:11:76:91:2b: + e1:c6:aa:1f:70:69:76:70:15:09:fe:93:d0:d6:2d:b7:15:6a: + 9b:67:5c:b4:69:9f:25:a6:7d:8a:fb:7d:22:a9:71:f2:ce:4e: + 8c:b8:21:2d:de:fe:41:71:0d:ff:9d:ec:73:a6:bb:07:4f:88: + 0e:58:47:2e:7e:a9:c2:c7:78:dd:ba:7a:9e:4e:e0:30:4e:63: + 6f:85:d4:20:41:e9:fa:fe:43:45:e7:fb:af:7a:b2:ce:a4:05: + 1d:22:9a:58:86:df:e4:ce:4c:a9:fe:d8:16:a5:6f:fb:d8:ce: + 56:7b:f5:d6:20:ef:e4:47:cd:63:24:ff:b9:be:f1:48:a3:c1: + 01:72:e6:bd:c0:ad:ed:26:0d:ca:34:9f:fc:02:2d:20:4f:05: + 20:ae:21:3d:0c:c2:20:3c:3f:f0:04:84:dc:cf:89:fd:b9:25: + 91:8e:d0:43:e6:b3:20:ab:5c:2d:d5:40:9e:a0:4b:d8:f4:b2: + cc:7d:f1:58:0a:8e:87:ed:88:ac:36:96:e4:56:a0:11:8a:f2: + 9a:d0:b3:57:a3:34:bb:19:ab:38:e1:74:6b:22:c4:31:ce:01: + d5:1b:36:e3:1e:38:4c:33:93:df:40:e3:59:57:4e:ac:6e:7b: + 1e:5a:3d:c5:1d:5b:ac:c8:10:82:35:02:22:b2:fc:75:e8:10: + 91:8d:c4:7d:78:93:47:9e:1c:9d:ac:6b:62:02:58:8c:d6:1c: + 23:d6:af:78:c2:80:9c:a4:aa:24:54:14:b5:14:98:c6:f8:2b: + 1a:24:cb:71:32:0a:e2:9b:0e:69:6b:dd:7e:8c:64:d1:2e:63: + ef:0e:7f:b1:3e:88:4c:9d:55:e5:c9:6e:17:04:b7:41:ff:bd: + 8a:41:cb:25:31:6f:44:77:3f:47:b1:fc:81:88:07:8e:05:49: + 20:b7:11:d9:69:03:2a:03:9d:b9:33:84:9a:df:df:7a:e3:46: + 73:a3:d8:a2:8c:53:19:88:55:4c:74:b8:f6:44:84:2b:d1:14: + 2d:4e:39:2e:92:68:ff:69:fc:85:62:1b:eb:55:4f:ef:25:84: + 62:45:99:d6:d8:4e:6f:3f:53:08:7d:1d:06:95:81:80:7f:4f: + 4e:74:36:98:b5:e2:87:70:98:dc:d7:f5:dc:52:15:e6:c6:d6: + 79:96:39:7f:8f:95:cf:ab:80:53:ad:1b:0b:45:40:0e:d4:18: + bd:2c:de:8a:77:76:fd:f2:44:47:c6:21:d0:e4:74:f0:d8:18: + 05:c8:7c:30:72:c7:df:f1:bb:fc:02:30:a9:f4:42:26:59:0d: + 93:05:82:a1:73:ed:34:e5:38:5d:cd:50:90:fe:94:fc:13:bc: + bd:fc:a8:a2:88:a7:73:c4:b2:a8:d1:5d:88:c4:02:a2:7a:f1: + 04:c9:fe:8c:74:c9:ef:1d:64:41:9f:ac:1e:96:67:64:ac:ab: + 28:41:c7:9d:f7:c0:98:1b:6e:07:c2:64:7d:5a:83:66:56:28: + 36:9c:e7:fb:1c:77:0e:28:a0:c4:f7:6b:79:39:04:20:84:c7: + 57:93:bc:1b:a0:ea:bc:eb:42:e5:a8:11:fe:fc:ac:65:cc:fd: + f8:28:88:f4:a5:9a:e5:73:51:e0:a8:9b:0d:03:77:4e:e5:e0: + 98:b3:88:da:7d:e6:c6:9e:7c:14:66:c1:2e:53:4a:92:07:37: + a0:7e:e9:3d:09:e4:15:7c:cf:fd:b8:41:a5:ef:9e:66:9d:c4: + 5e:07:1d:87:f8:41:ad:ea:e7:2f:d2:41:63:18:37:f9:14:e3: + 4d:d0:e5:f7:43:fd:15:e3:f9:36:73:06:26:df:01:4f:a9:c3: + 4e:de:20:46:77:98:b4:7a:24:2b:3b:75:2b:4e:58:8d:9b:5d: + a4:c7:16:a0:bc:32:88:3f:a1:83:f3:00:c8:f8:d8:58:e9:63: + 5d:4c:2b:b5:f0:72:41:d8:ab:77:37:d6:72:74:ae:b6:36:9c: + c8:a6:83:49:4b:e0:c9:56:0b:29:be:00:30:cb:dd:d6:c8:42: + 8a:00:d9:ec:15:d1:34:71:f2:5b:64:87:f6:27:d2:b7:eb:86: + b0:90:bf:29:db:21:9e:36:8c:e3:20:2f:95:23:51:6c:1b:c2: + a4:d5:e6:d8:02:43:67:a0:fe:9b:50:03:44:7f:bb:e4:72:d5: + d1:e4:da:8f:92:14:64:fb:5d:14:10:12:4a:95:06:c9:65:08: + 29:ca:21:a3:26:38:11:c9:27:df:70:67:04:fd:ca:48:32:7f: + 63:b2:45:74:31:50:4f:87:d9:20:70:d2:21:70:b1:d6:10:9d: + 33:5d:78:83:91:6d:55:82:ec:da:e4:62:63:c7:81:46:d7:19: + 65:72:2a:43:19:90:b8:d7:23:4d:4c:1c:e0:44:a9:66:67:ac: + ee:71:79:27:26:78:6d:72:0e:f5:5d:4b:23:b5:7c:7c:65:e9: + 17:c6:3a:0b:0d:dd:5e:1e:51:c3:86:b8:ec:7f:c7:27:4a:a5: + 46:e8:6a:2d:19:c1:87:a3:cb:99:93:87:64:a2:55:14:4c:b7: + 43:a5:93:d7:e7:d2:4e:79:40:ca:65:99:46:3d:3f:7a:80:7a: + 88:6a:cc:1e:e5:6b:33:46:f4:50:c0:d5:1f:09:b8:cd:8a:2e: + a1:27:eb:5d:73:a7:e8:6b:0a:e5:57:82:2a:b0:fc:e2:54:52: + 56:f0:ab:a9:12:c6:23:96:07:24:9c:e0:bc:46:a5:b4:20:04: + da:09:93:63:e5:d4:2e:c2:7e:c5:31:ed:b5:15:74:86:17:b9: + b3:f3:26:8a:1d:02:6a:da:1a:3f:e8:ba:f1:04:6d:94:51:54: + e2:5a:b4:59:83:1d:60:d0:2d:73:cc:07:b5:26:8c:f9:d7:c6: + 88:91:ef:80:cf:5d:0f:a1:60:cb:45:d4:42:22:d1:b1:70:1d: + fd:d0:b7:30:90:3a:c6:48:6d:67:e5:32:da:8f:db:e3:a8:e3: + 1d:20:25:a2:1c:e1:4c:b9:a4:f6:c6:3f:5c:58:0d:bb:c6:b2: + 77:01:16:91:9f:17:06:0d:b7:40:3e:cc:8f:8e:9c:4b:e0:9d: + 7e:9b:1e:05:ab:88:22:fa:d3:28:1b:57:14:64:4a:3e:24:2c: + 38:4d:21:69:00:73:2e:d0:55:2d:74:f2:15:e8:94:43:3e:40: + 2a:c6:c6:b9:6a:5b:de:a2:cc:18:50:54:5d:4e:2a:85:6c:f6: + 92:8b:29:19:7e:e7:ea:4a:e0:22:2b:25:bc:f7:66:cf:77:9a: + 41:74:f2:3c:14:0d:74:69:f5:50:83:cd:cd:2f:21:db:22:46: + 8a:d0:f7:51:1a:95:57:f2:05:8b:1a:19:ed:3b:45:e8:36:c2: + 6e:7e:fb:57:22:00:1f:06:53:a9:ae:93:c6:8f:71:2a:31:45: + 92:e7:8e:6d:e6:99:22:c0:83:fc:ef:dc:57:66:77:4f:a2:36: + 31:fb:a1:13:8d:e5:ca:a3:95:7d:01:0c:64:70:3b:53:42:68: + 80:c7:bb:9d:a8:00:35:69:98:0c:a8:67:d8:43:e5:aa:cf:95: + e0:51:95:a4:17:3f:42:9d:b8:04:ce:d3:79:79:c8:d3:8a:16: + 32:92:e0:d7:a2:ee:d7:37:4c:2f:ac:b8:7b:be:45:f6:f1:18: + 33:9c:7b:37:a6:24:d9:bc:40:ab:00:e9:c3:37:8b:ab:d8:b6: + f3:5e:81:4e:b0:14:6b:07:3e:1f:ec:c2:f6:44:22:95:bb:b3: + e6:6f:d6:f9:70:65:ba:0a:83:65:aa:0e:13:2f:83:13:23:53: + 8b:40:16:fa:ce:2f:fc:4d:04:f8:eb:d8:ac:c5:36:c2:15:57: + 48:38:ec:55:b3:b4:1e:ba:ad:d2:42:06:17:0d:73:c8:57:a6: + be:96:4d:a9:f2:c0:fb:7a:21:1c:f5:c9:70:a9:82:90:b5:f1: + 0c:d4:79:10:be:81:a6:e9:5c:61:9c:77:79:9a:a4:c3:37:26: + 57:37:c9:52:2c:fa:08:ff:d0:5f:c6:61:c0:f4:76:be:fc:de: + 4e:cf:ab:51:99:71:c7:df:7e:f4:d6:cf:06:56:19:13:53:0b: + 6d:74:59:48:19:9b:53:05:2d:9d:32:54:d3:e5:2c:53:8b:64: + 3e:d4:64:7b:e3:80:09:14:cc:fe:16:46:63:6b:71:69:f8:f9: + cb:27:f6:88:54:bc:45:b3:ce:02:c8:94:ee:40:5b:f9:42:02: + c2:ff:b0:d8:2c:eb:28:7f:5e:c9:26:01:99:a7 + +UPS Document Exchange by DST +============================ +MD5 Fingerprint: 78:A5:FB:10:4B:E4:63:2E:D2:6B:FB:F2:B6:C2:4B:8E +PEM Data: +-----BEGIN CERTIFICATE----- +MIID+DCCAuACEQDQHkCLAAACfAAAAAcAAAABMA0GCSqGSIb3DQEBBQUAMIG5MQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEeMBwGA1UE +CxMVVW5pdGVkIFBhcmNlbCBTZXJ2aWNlMRkwFwYDVQQDExBEU1QgKFVQUykgUm9v +dENBMSEwHwYJKoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wHhcNOTgxMjEw +MDAyNTQ2WhcNMDgxMjA3MDAyNTQ2WjCBuTELMAkGA1UEBhMCdXMxDTALBgNVBAgT +BFV0YWgxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xHjAcBgNVBAsTFVVuaXRlZCBQYXJjZWwgU2Vy +dmljZTEZMBcGA1UEAxMQRFNUIChVUFMpIFJvb3RDQTEhMB8GCSqGSIb3DQEJARYS +Y2FAZGlnc2lndHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA7xfsrynm2SsnwNt7JJ9m9ASjwq0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3Svb +YbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQjk4xuiVNtgym8eWvDOHlb1IDFcHf +vn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQUZPJViuhwt+yiM0ciekjxb +EVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXFY/23YhRtFx7MioCF +QjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZNqbuxx3sExd +5sjo9X15LVckP8zjPSyYzxKfFwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQC7OI4E +IiZYDiFEVsy9WXwpaMtcD8iGVD+BeKetj8xG9xxUuHktW3IFaugh0OwdHf6kNFG+ +7u3OzJwWaOJddXMIQzGRahArEMJLafjJrZio/bjv9qvwXyHvy4VrCe0vSGa1YHLA +6KDHmNsO9xtzjTQICnvFd2KqMCObsB6LgJhU3AWHs6liWfyLtxWarETszzUa9w8u +XZJLAch77qA37eQdgg2ZQUMXrdTVyuP5fReiAdAwD0C53LkEgmmDtvkP+gaS96j0 +1hcc8F5/xCnI5uHi/zZoIVGu/6m6hJKtinsz2JDSwXltMzM5dKwbOHGfLAeQ6h3g +04lfy+8UjSdUpb1G +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:02:7c:00:00:00:07:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=ca@digsigtrust.com + Validity + Not Before: Dec 10 00:25:46 1998 GMT + Not After : Dec 7 00:25:46 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ef:17:ec:af:29:e6:d9:2b:27:c0:db:7b:24:9f: + 66:f4:04:a3:c2:ad:0a:ca:b0:cd:84:2b:aa:37:f3: + 80:a1:60:ef:42:8f:e5:5d:77:5f:57:42:54:dd:2b: + db:61:b2:71:5e:93:7b:6f:5f:eb:24:2b:e7:a4:f2: + eb:f1:73:b3:0b:8d:f5:59:d7:32:df:ac:90:8e:4e: + 31:ba:25:4d:b6:0c:a6:f1:e5:af:0c:e1:e5:6f:52: + 03:15:c1:df:be:7e:4a:a6:a6:18:46:70:3f:ef:a7: + 4d:a8:dc:f5:74:d9:61:7a:40:3c:a1:94:28:ea:c2: + 94:88:cb:37:15:05:19:3c:95:62:ba:1c:2d:fb:28: + 8c:d1:c8:9e:92:3c:5b:11:54:3b:78:d9:47:3b:9b: + 2d:4a:e6:3e:7b:6b:df:f4:f6:05:cf:28:f6:ba:98: + 36:00:9e:3c:37:85:0a:9c:de:b7:a4:85:c5:63:fd: + b7:62:14:6d:17:1e:cc:8a:80:85:42:32:11:b0:21: + e2:9d:77:c9:80:16:41:9e:eb:e5:14:89:7f:b7:c3: + bc:4f:c1:9f:87:9b:96:ec:63:f6:f9:90:56:0e:95: + a3:23:0a:8c:64:da:9b:bb:1c:77:b0:4c:5d:e6:c8: + e8:f5:7d:79:2d:57:24:3f:cc:e3:3d:2c:98:cf:12: + 9f:17 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + bb:38:8e:04:22:26:58:0e:21:44:56:cc:bd:59:7c:29:68:cb: + 5c:0f:c8:86:54:3f:81:78:a7:ad:8f:cc:46:f7:1c:54:b8:79: + 2d:5b:72:05:6a:e8:21:d0:ec:1d:1d:fe:a4:34:51:be:ee:ed: + ce:cc:9c:16:68:e2:5d:75:73:08:43:31:91:6a:10:2b:10:c2: + 4b:69:f8:c9:ad:98:a8:fd:b8:ef:f6:ab:f0:5f:21:ef:cb:85: + 6b:09:ed:2f:48:66:b5:60:72:c0:e8:a0:c7:98:db:0e:f7:1b: + 73:8d:34:08:0a:7b:c5:77:62:aa:30:23:9b:b0:1e:8b:80:98: + 54:dc:05:87:b3:a9:62:59:fc:8b:b7:15:9a:ac:44:ec:cf:35: + 1a:f7:0f:2e:5d:92:4b:01:c8:7b:ee:a0:37:ed:e4:1d:82:0d: + 99:41:43:17:ad:d4:d5:ca:e3:f9:7d:17:a2:01:d0:30:0f:40: + b9:dc:b9:04:82:69:83:b6:f9:0f:fa:06:92:f7:a8:f4:d6:17: + 1c:f0:5e:7f:c4:29:c8:e6:e1:e2:ff:36:68:21:51:ae:ff:a9: + ba:84:92:ad:8a:7b:33:d8:90:d2:c1:79:6d:33:33:39:74:ac: + 1b:38:71:9f:2c:07:90:ea:1d:e0:d3:89:5f:cb:ef:14:8d:27: + 54:a5:bd:46 + +ValiCert Class 1 VA +=================== +MD5 Fingerprint: 65:58:AB:15:AD:57:6C:1E:A8:A7:B5:69:AC:BF:FF:EB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 25 22:23:48 1999 GMT + Not After : Jun 25 22:23:48 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d8:59:82:7a:89:b8:96:ba:a6:2f:68:6f:58:2e: + a7:54:1c:06:6e:f4:ea:8d:48:bc:31:94:17:f0:f3: + 4e:bc:b2:b8:35:92:76:b0:d0:a5:a5:01:d7:00:03: + 12:22:19:08:f8:ff:11:23:9b:ce:07:f5:bf:69:1a: + 26:fe:4e:e9:d1:7f:9d:2c:40:1d:59:68:6e:a6:f8: + 58:b0:9d:1a:8f:d3:3f:f1:dc:19:06:81:a8:0e:e0: + 3a:dd:c8:53:45:09:06:e6:0f:70:c3:fa:40:a6:0e: + e2:56:05:0f:18:4d:fc:20:82:d1:73:55:74:8d:76: + 72:a0:1d:9d:1d:c0:dd:3f:71 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 50:68:3d:49:f4:2c:1c:06:94:df:95:60:7f:96:7b:17:fe:4f: + 71:ad:64:c8:dd:77:d2:ef:59:55:e8:3f:e8:8e:05:2a:21:f2: + 07:d2:b5:a7:52:fe:9c:b1:b6:e2:5b:77:17:40:ea:72:d6:23: + cb:28:81:32:c3:00:79:18:ec:59:17:89:c9:c6:6a:1e:71:c9: + fd:b7:74:a5:25:45:69:c5:48:ab:19:e1:45:8a:25:6b:19:ee: + e5:bb:12:f5:7f:f7:a6:8d:51:c3:f0:9d:74:b7:a9:3e:a0:a5: + ff:b6:49:03:13:da:22:cc:ed:71:82:2b:99:cf:3a:b7:f5:2d: + 72:c8 + +ValiCert Class 2 VA +=================== +MD5 Fingerprint: A9:23:75:9B:BA:49:36:6E:31:C2:DB:F2:E7:66:BA:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 26 00:19:54 1999 GMT + Not After : Jun 26 00:19:54 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:3a:71:ca:e5:ab:c8:59:92:55:d7:ab:d8:74: + 0e:f9:ee:d9:f6:55:47:59:65:47:0e:05:55:dc:eb: + 98:36:3c:5c:53:5d:d3:30:cf:38:ec:bd:41:89:ed: + 25:42:09:24:6b:0a:5e:b3:7c:dd:52:2d:4c:e6:d4: + d6:7d:5a:59:a9:65:d4:49:13:2d:24:4d:1c:50:6f: + b5:c1:85:54:3b:fe:71:e4:d3:5c:42:f9:80:e0:91: + 1a:0a:5b:39:36:67:f3:3f:55:7c:1b:3f:b4:5f:64: + 73:34:e3:b4:12:bf:87:64:f8:da:12:ff:37:27:c1: + b3:43:bb:ef:7b:6e:2e:69:f7 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 3b:7f:50:6f:6f:50:94:99:49:62:38:38:1f:4b:f8:a5:c8:3e: + a7:82:81:f6:2b:c7:e8:c5:ce:e8:3a:10:82:cb:18:00:8e:4d: + bd:a8:58:7f:a1:79:00:b5:bb:e9:8d:af:41:d9:0f:34:ee:21: + 81:19:a0:32:49:28:f4:c4:8e:56:d5:52:33:fd:50:d5:7e:99: + 6c:03:e4:c9:4c:fc:cb:6c:ab:66:b3:4a:21:8c:e5:b5:0c:32: + 3e:10:b2:cc:6c:a1:dc:9a:98:4c:02:5b:f3:ce:b9:9e:a5:72: + 0e:4a:b7:3f:3c:e6:16:68:f8:be:ed:74:4c:bc:5b:d5:62:1f: + 43:dd + +ValiCert Class 3 VA +=================== +MD5 Fingerprint: A2:6F:53:B7:EE:40:DB:4A:68:E7:FA:18:D9:10:4B:72 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 26 00:22:33 1999 GMT + Not After : Jun 26 00:22:33 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e3:98:51:96:1c:e8:d5:b1:06:81:6a:57:c3:72: + 75:93:ab:cf:9e:a6:fc:f3:16:52:d6:2d:4d:9f:35: + 44:a8:2e:04:4d:07:49:8a:38:29:f5:77:37:e7:b7: + ab:5d:df:36:71:14:99:8f:dc:c2:92:f1:e7:60:92: + 97:ec:d8:48:dc:bf:c1:02:20:c6:24:a4:28:4c:30: + 5a:76:6d:b1:5c:f3:dd:de:9e:10:71:a1:88:c7:5b: + 9b:41:6d:ca:b0:b8:8e:15:ee:ad:33:2b:cf:47:04: + 5c:75:71:0a:98:24:98:29:a7:49:59:a5:dd:f8:b7: + 43:62:61:f3:d3:e2:d0:55:3f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 56:bb:02:58:84:67:08:2c:df:1f:db:7b:49:33:f5:d3:67:9d: + f4:b4:0a:10:b3:c9:c5:2c:e2:92:6a:71:78:27:f2:70:83:42: + d3:3e:cf:a9:54:f4:f1:d8:92:16:8c:d1:04:cb:4b:ab:c9:9f: + 45:ae:3c:8a:a9:b0:71:33:5d:c8:c5:57:df:af:a8:35:b3:7f: + 89:87:e9:e8:25:92:b8:7f:85:7a:ae:d6:bc:1e:37:58:2a:67: + c9:91:cf:2a:81:3e:ed:c6:39:df:c0:3e:19:9c:19:cc:13:4d: + 82:41:b5:8c:de:e0:3d:60:08:20:0f:45:7e:6b:a2:7f:a3:8c: + 15:ee + +VeriSign Class 4 Primary CA +=========================== +MD5 Fingerprint: 1B:D1:AD:17:8B:7F:22:13:24:F5:26:E2:5D:4E:B9:10 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICMTCCAZoCBQKmAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBa +Fw05OTEyMzEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln +biwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LJ1 +9njQrlpQ9OlQqZ+M1++RlHDo0iSQdomF1t+s5gEXMoDwnZNHvJplnR+Xrr/phnVj +IIm9gFidBAydqMEk6QvlMXi9/C0MN2qeeIDpRnX57aP7E3vIwUzSo+/1PLBij0pd +O92VZ48TucE81qcmm+zDO3rZTbxtm+gVAePwR6kCAwEAATANBgkqhkiG9w0BAQIF +AAOBgQBT3dPwnCR+QKri/AAa19oM/DJhuBUNlvP6Vxt/M3yv6ZiaYch6s7f/sdyZ +g9ysEvxwyR84Qu1E9oAuW2szaayc01znX1oYx7EteQSWQZGZQbE8DbqEOcY7l/Am +yY7uvcxClf8exwI/VAx49byqYHwCaejcrOICdmHEPgPq0ook0Q== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:a6:00:00:01 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 1999 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d0:b2:75:f6:78:d0:ae:5a:50:f4:e9:50:a9:9f: + 8c:d7:ef:91:94:70:e8:d2:24:90:76:89:85:d6:df: + ac:e6:01:17:32:80:f0:9d:93:47:bc:9a:65:9d:1f: + 97:ae:bf:e9:86:75:63:20:89:bd:80:58:9d:04:0c: + 9d:a8:c1:24:e9:0b:e5:31:78:bd:fc:2d:0c:37:6a: + 9e:78:80:e9:46:75:f9:ed:a3:fb:13:7b:c8:c1:4c: + d2:a3:ef:f5:3c:b0:62:8f:4a:5d:3b:dd:95:67:8f: + 13:b9:c1:3c:d6:a7:26:9b:ec:c3:3b:7a:d9:4d:bc: + 6d:9b:e8:15:01:e3:f0:47:a9 + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 53:dd:d3:f0:9c:24:7e:40:aa:e2:fc:00:1a:d7:da:0c:fc:32: + 61:b8:15:0d:96:f3:fa:57:1b:7f:33:7c:af:e9:98:9a:61:c8: + 7a:b3:b7:ff:b1:dc:99:83:dc:ac:12:fc:70:c9:1f:38:42:ed: + 44:f6:80:2e:5b:6b:33:69:ac:9c:d3:5c:e7:5f:5a:18:c7:b1: + 2d:79:04:96:41:91:99:41:b1:3c:0d:ba:84:39:c6:3b:97:f0: + 26:c9:8e:ee:bd:cc:42:95:ff:1e:c7:02:3f:54:0c:78:f5:bc: + aa:60:7c:02:69:e8:dc:ac:e2:02:76:61:c4:3e:03:ea:d2:8a: + 24:d1 + +Verisign Class 1 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: 97:60:E8:57:5F:D3:50:47:E5:43:0C:94:36:8A:B0:62 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 +NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD +VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp +bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N +H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR +4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN +BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo +EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 +FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx +lA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + cd:ba:7f:56:f0:df:e4:bc:54:fe:22:ac:b3:72:aa:55 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:19:bf:6d:a3:56:61:2d:99:48:71:f6:67:de: + b9:8d:eb:b7:9e:86:80:0a:91:0e:fa:38:25:af:46: + 88:82:e5:73:a8:a0:9b:24:5d:0d:1f:cc:65:6e:0c: + b0:d0:56:84:18:87:9a:06:9b:10:a1:73:df:b4:58: + 39:6b:6e:c1:f6:15:d5:a8:a8:3f:aa:12:06:8d:31: + ac:7f:b0:34:d7:8f:34:67:88:09:cd:14:11:e2:4e: + 45:56:69:1f:78:02:80:da:dc:47:91:29:bb:36:c9: + 63:5c:c5:e0:d7:2d:87:7b:a1:b7:32:b0:7b:30:ba: + 2a:2f:31:aa:ee:a3:67:da:db + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 4c:3f:b8:8b:c6:68:df:ee:43:33:0e:5d:e9:a6:cb:07:84:4d: + 7a:33:ff:92:1b:f4:36:ad:d8:95:22:36:68:11:6c:7c:42:cc: + f3:9c:2e:c4:07:3f:14:b0:0f:4f:ff:90:92:76:f9:e2:bc:4a: + e9:8f:cd:a0:80:0a:f7:c5:29:f1:82:22:5d:b8:b1:dd:81:23: + a3:7b:25:15:46:30:79:16:f8:ea:05:4b:94:7f:1d:c2:1c:c8: + e3:b7:f4:10:40:3c:13:c3:5f:1f:53:e8:48:e4:86:b4:7b:a1: + 35:b0:7b:25:ba:b8:d3:8e:ab:3f:38:9d:00:34:00:98:f3:d1: + 71:94 + +Verisign Class 1 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: F2:7D:E9:54:E4:A3:22:0D:76:9F:E7:0B:BB:B3:24:2B +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDnKVIn+UCIy/jLZ2/sbhBkwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTE4MDUxODIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK +VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm +Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIv3GhDOdlwHq4OZ3BeAbzQ5XZg+a3Is4cei +e0ApuXiIukzFo2penm574/ICQQxmvq37rqIUzpLzojSLtLK2JPLl1eDI5WJthHvL +vrsDi3xXyvA3qZCviu4Dvh0onNkmdqDNxJ1O8K4HFtW+r1cIatCgQkJCHvQgzKV4 +gpUmOIpH +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 39:ca:54:89:fe:50:22:32:fe:32:d9:db:fb:1b:84:19 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : May 18 23:59:59 2018 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:aa:d0:ba:be:16:2d:b8:83:d4:ca:d2:0f:bc:76: + 31:ca:94:d8:1d:93:8c:56:02:bc:d9:6f:1a:6f:52: + 36:6e:75:56:0a:55:d3:df:43:87:21:11:65:8a:7e: + 8f:bd:21:de:6b:32:3f:1b:84:34:95:05:9d:41:35: + eb:92:eb:96:dd:aa:59:3f:01:53:6d:99:4f:ed:e5: + e2:2a:5a:90:c1:b9:c4:a6:15:cf:c8:45:eb:a6:5d: + 8e:9c:3e:f0:64:24:76:a5:cd:ab:1a:6f:b6:d8:7b: + 51:61:6e:a6:7f:87:c8:e2:b7:e5:34:dc:41:88:ea: + 09:40:be:73:92:3d:6b:e7:75 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 8b:f7:1a:10:ce:76:5c:07:ab:83:99:dc:17:80:6f:34:39:5d: + 98:3e:6b:72:2c:e1:c7:a2:7b:40:29:b9:78:88:ba:4c:c5:a3: + 6a:5e:9e:6e:7b:e3:f2:02:41:0c:66:be:ad:fb:ae:a2:14:ce: + 92:f3:a2:34:8b:b4:b2:b6:24:f2:e5:d5:e0:c8:e5:62:6d:84: + 7b:cb:be:bb:03:8b:7c:57:ca:f0:37:a9:90:af:8a:ee:03:be: + 1d:28:9c:d9:26:76:a0:cd:c4:9d:4e:f0:ae:07:16:d5:be:af: + 57:08:6a:d0:a0:42:42:42:1e:f4:20:cc:a5:78:82:95:26:38: + 8a:47 + +Verisign Class 1 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: B1:47:BC:18:57:D1:18:A0:78:2D:EC:71:E8:2A:95:73 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 8b:5b:75:56:84:54:85:0b:00:cf:af:38:48:ce:b1:a4 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dd:84:d4:b9:b4:f9:a7:d8:f3:04:78:9c:de:3d: + dc:6c:13:16:d9:7a:dd:24:51:66:c0:c7:26:59:0d: + ac:06:08:c2:94:d1:33:1f:f0:83:35:1f:6e:1b:c8: + de:aa:6e:15:4e:54:27:ef:c4:6d:1a:ec:0b:e3:0e: + f0:44:a5:57:c7:40:58:1e:a3:47:1f:71:ec:60:f6: + 6d:94:c8:18:39:ed:fe:42:18:56:df:e4:4c:49:10: + 78:4e:01:76:35:63:12:36:dd:66:bc:01:04:36:a3: + 55:68:d5:a2:36:09:ac:ab:21:26:54:06:ad:3f:ca: + 14:e0:ac:ca:ad:06:1d:95:e2:f8:9d:f1:e0:60:ff: + c2:7f:75:2b:4c:cc:da:fe:87:99:21:ea:ba:fe:3e: + 54:d7:d2:59:78:db:3c:6e:cf:a0:13:00:1a:b8:27: + a1:e4:be:67:96:ca:a0:c5:b3:9c:dd:c9:75:9e:eb: + 30:9a:5f:a3:cd:d9:ae:78:19:3f:23:e9:5c:db:29: + bd:ad:55:c8:1b:54:8c:63:f6:e8:a6:ea:c7:37:12: + 5c:a3:29:1e:02:d9:db:1f:3b:b4:d7:0f:56:47:81: + 15:04:4a:af:83:27:d1:c5:58:88:c1:dd:f6:aa:a7: + a3:18:da:68:aa:6d:11:51:e1:bf:65:6b:9f:96:76: + d1:3d + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + ab:66:8d:d7:b3:ba:c7:9a:b6:e6:55:d0:05:f1:9f:31:8d:5a: + aa:d9:aa:46:26:0f:71:ed:a5:ad:53:56:62:01:47:2a:44:e9: + fe:3f:74:0b:13:9b:b9:f4:4d:1b:b2:d1:5f:b2:b6:d2:88:5c: + b3:9f:cd:cb:d4:a7:d9:60:95:84:3a:f8:c1:37:1d:61:ca:e7: + b0:c5:e5:91:da:54:a6:ac:31:81:ae:97:de:cd:08:ac:b8:c0: + 97:80:7f:6e:72:a4:e7:69:13:95:65:1f:c4:93:3c:fd:79:8f: + 04:d4:3e:4f:ea:f7:9e:ce:cd:67:7c:4f:65:02:ff:91:85:54: + 73:c7:ff:36:f7:86:2d:ec:d0:5e:4f:ff:11:9f:72:06:d6:b8: + 1a:f1:4c:0d:26:65:e2:44:80:1e:c7:9f:e3:dd:e8:0a:da:ec: + a5:20:80:69:68:a1:4f:7e:e1:6b:cf:07:41:fa:83:8e:bc:38: + dd:b0:2e:11:b1:6b:b2:42:cc:9a:bc:f9:48:22:79:4a:19:0f: + b2:1c:3e:20:74:d9:6a:c3:be:f2:28:78:13:56:79:4f:6d:50: + ea:1b:b0:b5:57:b1:37:66:58:23:f3:dc:0f:df:0a:87:c4:ef: + 86:05:d5:38:14:60:99:a3:4b:de:06:96:71:2c:f2:db:b6:1f: + a4:ef:3f:ee + +Verisign Class 2 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: B3:9C:25:B1:C3:2E:32:53:80:15:30:9D:4D:02:77:3E +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg +J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc +r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 2d:1b:fc:4a:17:8d:a3:91:eb:e7:ff:f5:8b:45:be:0b + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:5a:8b:a3:0d:6a:23:83:80:6b:cf:39:87:f4: + 21:13:33:06:4c:25:a2:ed:55:12:97:c5:a7:80:b9: + fa:83:c1:20:a0:fa:2f:15:0d:7c:a1:60:6b:7e:79: + 2c:fa:06:0f:3a:ae:f6:1b:6f:b1:d2:ff:2f:28:52: + 5f:83:7d:4b:c4:7a:b7:f8:66:1f:80:54:fc:b7:c2: + 8e:59:4a:14:57:46:d1:9a:93:be:41:91:03:bb:15: + 80:93:5c:eb:e7:cc:08:6c:3f:3e:b3:4a:fc:ff:4b: + 6c:23:d5:50:82:26:44:19:8e:23:c3:71:ea:19:24: + 47:04:9e:75:bf:c8:a6:00:1f + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 8a:1b:2b:fa:39:c1:74:d7:5e:d8:19:64:a2:58:4a:2d:37:e0: + 33:47:0f:ac:ed:f7:aa:db:1e:e4:8b:06:5c:60:27:ca:45:52: + ce:16:ef:3f:06:64:e7:94:68:7c:60:33:15:11:69:af:9d:62: + 8d:a3:03:54:6b:a6:be:e5:ee:05:18:60:04:bf:42:80:fd:d0: + a8:a8:1e:01:3b:f7:a3:5c:af:a3:dc:e6:26:80:23:3c:b8:44: + 74:f7:0a:ae:49:8b:61:78:cc:24:bf:88:8a:a7:0e:ea:73:19: + 41:fd:4d:03:f0:88:d1:e5:78:8d:a5:2a:4f:f6:97:0d:17:77: + ca:d8 + +Verisign Class 2 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: 2D:BB:E5:25:D3:D1:65:82:3A:B7:0E:FA:E6:EB:E2:E1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns +YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe +Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj +IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx +KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM +HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw +DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji +nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX +rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn +jBJ7xUS0rg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + b9:2f:60:cc:88:9f:a1:7a:46:09:b8:5b:70:6c:8a:af + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:88:01:21:74:2c:e7:1a:03:f0:98:e1:97:3c: + 0f:21:08:f1:9c:db:97:e9:9a:fc:c2:04:06:13:be: + 5f:52:c8:cc:1e:2c:12:56:2c:b8:01:69:2c:cc:99: + 1f:ad:b0:96:ae:79:04:f2:13:39:c1:7b:98:ba:08: + 2c:e8:c2:84:13:2c:aa:69:e9:09:f4:c7:a9:02:a4: + 42:c2:23:4f:4a:d8:f0:0e:a2:fb:31:6c:c9:e6:6f: + 99:27:07:f5:e6:f4:4c:78:9e:6d:eb:46:86:fa:b9: + 86:c9:54:f2:b2:c4:af:d4:46:1c:5a:c9:15:30:ff: + 0d:6c:f5:2d:0e:6d:ce:7f:77 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 72:2e:f9:7f:d1:f1:71:fb:c4:9e:f6:c5:5e:51:8a:40:98:b8: + 68:f8:9b:1c:83:d8:e2:9d:bd:ff:ed:a1:e6:66:ea:2f:09:f4: + ca:d7:ea:a5:2b:95:f6:24:60:86:4d:44:2e:83:a5:c4:2d:a0: + d3:ae:78:69:6f:72:da:6c:ae:08:f0:63:92:37:e6:bb:c4:30: + 17:ad:77:cc:49:35:aa:cf:d8:8f:d1:be:b7:18:96:47:73:6a: + 54:22:34:64:2d:b6:16:9b:59:5b:b4:51:59:3a:b3:0b:14:f4: + 12:df:67:a0:f4:ad:32:64:5e:b1:46:72:27:8c:12:7b:c5:44: + b4:ae + +Verisign Class 2 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 61:70:cb:49:8c:5f:98:45:29:e7:b0:a6:d9:50:5b:7a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:af:0a:0d:c2:d5:2c:db:67:b9:2d:e5:94:27:dd: + a5:be:e0:b0:4d:8f:b3:61:56:3c:d6:7c:c3:f4:cd: + 3e:86:cb:a2:88:e2:e1:d8:a4:69:c5:b5:e2:bf:c1: + a6:47:50:5e:46:39:8b:d5:96:ba:b5:6f:14:bf:10: + ce:27:13:9e:05:47:9b:31:7a:13:d8:1f:d9:d3:02: + 37:8b:ad:2c:47:f0:8e:81:06:a7:0d:30:0c:eb:f7: + 3c:0f:20:1d:dc:72:46:ee:a5:02:c8:5b:c3:c9:56: + 69:4c:c5:18:c1:91:7b:0b:d5:13:00:9b:bc:ef:c3: + 48:3e:46:60:20:85:2a:d5:90:b6:cd:8b:a0:cc:32: + dd:b7:fd:40:55:b2:50:1c:56:ae:cc:8d:77:4d:c7: + 20:4d:a7:31:76:ef:68:92:8a:90:1e:08:81:56:b2: + ad:69:a3:52:d0:cb:1c:c4:23:3d:1f:99:fe:4c:e8: + 16:63:8e:c6:08:8e:f6:31:f6:d2:fa:e5:76:dd:b5: + 1c:92:a3:49:cd:cd:01:cd:68:cd:a9:69:ba:a3:eb: + 1d:0d:9c:a4:20:a6:c1:a0:c5:d1:46:4c:17:6d:d2: + ac:66:3f:96:8c:e0:84:d4:36:ff:22:59:c5:f9:11: + 60:a8:5f:04:7d:f2:1a:f6:25:42:61:0f:c4:4a:b8: + 3e:89 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 34:26:15:3c:c0:8d:4d:43:49:1d:bd:e9:21:92:d7:66:9c:b7: + de:c5:b8:d0:e4:5d:5f:76:22:c0:26:f9:84:3a:3a:f9:8c:b5: + fb:ec:60:f1:e8:ce:04:b0:c8:dd:a7:03:8f:30:f3:98:df:a4: + e6:a4:31:df:d3:1c:0b:46:dc:72:20:3f:ae:ee:05:3c:a4:33: + 3f:0b:39:ac:70:78:73:4b:99:2b:df:30:c2:54:b0:a8:3b:55: + a1:fe:16:28:cd:42:bd:74:6e:80:db:27:44:a7:ce:44:5d:d4: + 1b:90:98:0d:1e:42:94:b1:00:2c:04:d0:74:a3:02:05:22:63: + 63:cd:83:b5:fb:c1:6d:62:6b:69:75:fd:5d:70:41:b9:f5:bf: + 7c:df:be:c1:32:73:22:21:8b:58:81:7b:15:91:7a:ba:e3:64: + 48:b0:7f:fb:36:25:da:95:d0:f1:24:14:17:dd:18:80:6b:46: + 23:39:54:f5:8e:62:09:04:1d:94:90:a6:9b:e6:25:e2:42:45: + aa:b8:90:ad:be:08:8f:a9:0b:42:18:94:cf:72:39:e1:b1:43: + e0:28:cf:b7:e7:5a:6c:13:6b:49:b3:ff:e3:18:7c:89:8b:33: + 5d:ac:33:d7:a7:f9:da:3a:55:c9:58:10:f9:aa:ef:5a:b6:cf: + 4b:4b:df:2a + +Verisign Class 3 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: 10:FC:63:5D:F6:26:3E:0D:F3:25:BE:5F:79:CD:67:67 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:5c:59:9e:f2:1b:8a:01:14:b4:10:df:04:40: + db:e3:57:af:6a:45:40:8f:84:0c:0b:d1:33:d9:d9: + 11:cf:ee:02:58:1f:25:f7:2a:a8:44:05:aa:ec:03: + 1f:78:7f:9e:93:b9:9a:00:aa:23:7d:d6:ac:85:a2: + 63:45:c7:72:27:cc:f4:4c:c6:75:71:d2:39:ef:4f: + 42:f0:75:df:0a:90:c6:8e:20:6f:98:0f:f8:ac:23: + 5f:70:29:36:a4:c9:86:e7:b1:9a:20:cb:53:a5:85: + e7:3d:be:7d:9a:fe:24:45:33:dc:76:15:ed:0f:a2: + 71:64:4c:65:2e:81:68:45:a7 + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + bb:4c:12:2b:cf:2c:26:00:4f:14:13:dd:a6:fb:fc:0a:11:84: + 8c:f3:28:1c:67:92:2f:7c:b6:c5:fa:df:f0:e8:95:bc:1d:8f: + 6c:2c:a8:51:cc:73:d8:a4:c0:53:f0:4e:d6:26:c0:76:01:57: + 81:92:5e:21:f1:d1:b1:ff:e7:d0:21:58:cd:69:17:e3:44:1c: + 9c:19:44:39:89:5c:dc:9c:00:0f:56:8d:02:99:ed:a2:90:45: + 4c:e4:bb:10:a4:3d:f0:32:03:0e:f1:ce:f8:e8:c9:51:8c:e6: + 62:9f:e6:9f:c0:7d:b7:72:9c:c9:36:3a:6b:9f:4e:a8:ff:64: + 0d:64 + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 7d:d9:fe:07:cf:a8:1e:b7:10:79:67:fb:a7:89:34:c6 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cc:5e:d1:11:5d:5c:69:d0:ab:d3:b9:6a:4c:99: + 1f:59:98:30:8e:16:85:20:46:6d:47:3f:d4:85:20: + 84:e1:6d:b3:f8:a4:ed:0c:f1:17:0f:3b:f9:a7:f9: + 25:d7:c1:cf:84:63:f2:7c:63:cf:a2:47:f2:c6:5b: + 33:8e:64:40:04:68:c1:80:b9:64:1c:45:77:c7:d8: + 6e:f5:95:29:3c:50:e8:34:d7:78:1f:a8:ba:6d:43: + 91:95:8f:45:57:5e:7e:c5:fb:ca:a4:04:eb:ea:97: + 37:54:30:6f:bb:01:47:32:33:cd:dc:57:9b:64:69: + 61:f8:9b:1d:1c:89:4f:5c:67 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 51:4d:cd:be:5c:cb:98:19:9c:15:b2:01:39:78:2e:4d:0f:67: + 70:70:99:c6:10:5a:94:a4:53:4d:54:6d:2b:af:0d:5d:40:8b: + 64:d3:d7:ee:de:56:61:92:5f:a6:c4:1d:10:61:36:d3:2c:27: + 3c:e8:29:09:b9:11:64:74:cc:b5:73:9f:1c:48:a9:bc:61:01: + ee:e2:17:a6:0c:e3:40:08:3b:0e:e7:eb:44:73:2a:9a:f1:69: + 92:ef:71:14:c3:39:ac:71:a7:91:09:6f:e4:71:06:b3:ba:59: + 57:26:79:00:f6:f8:0d:a2:33:30:28:d4:aa:58:a0:9d:9d:69: + 91:fd + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:cb:ba:9c:52:fc:78:1f:1a:1e:6f:1b:37:73:bd: + f8:c9:6b:94:12:30:4f:f0:36:47:f5:d0:91:0a:f5: + 17:c8:a5:61:c1:16:40:4d:fb:8a:61:90:e5:76:20: + c1:11:06:7d:ab:2c:6e:a6:f5:11:41:8e:fa:2d:ad: + 2a:61:59:a4:67:26:4c:d0:e8:bc:52:5b:70:20:04: + 58:d1:7a:c9:a4:69:bc:83:17:64:ad:05:8b:bc:d0: + 58:ce:8d:8c:f5:eb:f0:42:49:0b:9d:97:27:67:32: + 6e:e1:ae:93:15:1c:70:bc:20:4d:2f:18:de:92:88: + e8:6c:85:57:11:1a:e9:7e:e3:26:11:54:a2:45:96: + 55:83:ca:30:89:e8:dc:d8:a3:ed:2a:80:3f:7f:79: + 65:57:3e:15:20:66:08:2f:95:93:bf:aa:47:2f:a8: + 46:97:f0:12:e2:fe:c2:0a:2b:51:e6:76:e6:b7:46: + b7:e2:0d:a6:cc:a8:c3:4c:59:55:89:e6:e8:53:5c: + 1c:ea:9d:f0:62:16:0b:a7:c9:5f:0c:f0:de:c2:76: + ce:af:f7:6a:f2:fa:41:a6:a2:33:14:c9:e5:7a:63: + d3:9e:62:37:d5:85:65:9e:0e:e6:53:24:74:1b:5e: + 1d:12:53:5b:c7:2c:e7:83:49:3b:15:ae:8a:68:b9: + 57:97 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 11:14:96:c1:ab:92:08:f7:3f:2f:c9:b2:fe:e4:5a:9f:64:de: + db:21:4f:86:99:34:76:36:57:dd:d0:15:2f:c5:ad:7f:15:1f: + 37:62:73:3e:d4:e7:5f:ce:17:03:db:35:fa:2b:db:ae:60:09: + 5f:1e:5f:8f:6e:bb:0b:3d:ea:5a:13:1e:0c:60:6f:b5:c0:b5: + 23:22:2e:07:0b:cb:a9:74:cb:47:bb:1d:c1:d7:a5:6b:cc:2f: + d2:42:fd:49:dd:a7:89:cf:53:ba:da:00:5a:28:bf:82:df:f8: + ba:13:1d:50:86:82:fd:8e:30:8f:29:46:b0:1e:3d:35:da:38: + 62:16:18:4a:ad:e6:b6:51:6c:de:af:62:eb:01:d0:1e:24:fe: + 7a:8f:12:1a:12:68:b8:fb:66:99:14:14:45:5c:ae:e7:ae:69: + 17:81:2b:5a:37:c9:5e:2a:f4:c6:e2:a1:5c:54:9b:a6:54:00: + cf:f0:f1:c1:c7:98:30:1a:3b:36:16:db:a3:6e:ea:fd:ad:b2: + c2:da:ef:02:47:13:8a:c0:f1:b3:31:ad:4f:1c:e1:4f:9c:af: + 0f:0c:9d:f7:78:0d:d8:f4:35:56:80:da:b7:6d:17:8f:9d:1e: + 81:64:e1:fe:c5:45:ba:ad:6b:b9:0a:7a:4e:4f:4b:84:ee:4b: + f1:7d:dd:11 + +Verisign Class 4 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: 26:6D:2C:19:98:B6:70:68:38:50:54:19:EC:90:34:60 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM +HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK +qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj +cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y +cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP +T8qAkbYp +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 32:88:8e:9a:d2:f5:eb:13:47:f8:7f:c4:20:37:25:f8 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ba:f0:e4:cf:f9:c4:ae:85:54:b9:07:57:f9:8f: + c5:7f:68:11:f8:c4:17:b0:44:dc:e3:30:73:d5:2a: + 62:2a:b8:d0:cc:1c:ed:28:5b:7e:bd:6a:dc:b3:91: + 24:ca:41:62:3c:fc:02:01:bf:1c:16:31:94:05:97: + 76:6e:a2:ad:bd:61:17:6c:4e:30:86:f0:51:37:2a: + 50:c7:a8:62:81:dc:5b:4a:aa:c1:a0:b4:6e:eb:2f: + e5:57:c5:b1:2b:40:70:db:5a:4d:a1:8e:1f:bd:03: + 1f:d8:03:d4:8f:4c:99:71:bc:e2:82:cc:58:e8:98: + 3a:86:d3:86:38:f3:00:29:1f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 85:8c:12:c1:a7:b9:50:15:7a:cb:3e:ac:b8:43:8a:dc:aa:dd: + 14:ba:89:81:7e:01:3c:23:71:21:88:2f:82:dc:63:fa:02:45: + ac:45:59:d7:2a:58:44:5b:b7:9f:81:3b:92:68:3d:e2:37:24: + f5:7b:6c:8f:76:35:96:09:a8:59:9d:b9:ce:23:ab:74:d6:83: + fd:32:73:27:d8:69:3e:43:74:f6:ae:c5:89:9a:e7:53:7c:e9: + 7b:f6:4b:f3:c1:65:83:de:8d:8a:9c:3c:88:8d:39:59:fc:aa: + 3f:22:8d:a1:c1:66:50:81:72:4c:ed:22:64:4f:4f:ca:80:91: + b6:29 + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: DB:C8:F2:27:2E:B1:EA:6A:29:23:5D:FE:56:3E:33:DF +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + ec:a0:a7:8b:6e:75:6a:01:cf:c4:7c:cc:2f:94:5e:d7 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:cb:a5:11:69:c6:59:ab:f1:8f:b5:19:0f:56: + ce:cc:b5:1f:20:e4:9e:26:25:4b:e0:73:65:89:59: + de:d0:83:e4:f5:0f:b5:bb:ad:f1:7c:e8:21:fc:e4: + e8:0c:ee:7c:45:22:19:76:92:b4:13:b7:20:5b:09: + fa:61:ae:a8:f2:a5:8d:85:c2:2a:d6:de:66:36:d2: + 9b:02:f4:a8:92:60:7c:9c:69:b4:8f:24:1e:d0:86: + 52:f6:32:9c:41:58:1e:22:bd:cd:45:62:95:08:6e: + d0:66:dd:53:a2:cc:f0:10:dc:54:73:8b:04:a1:46: + 33:33:5c:17:40:b9:9e:4d:d3:f3:be:55:83:e8:b1: + 89:8e:5a:7c:9a:96:22:90:3b:88:25:f2:d2:53:88: + 02:0c:0b:78:f2:e6:37:17:4b:30:46:07:e4:80:6d: + a6:d8:96:2e:e8:2c:f8:11:b3:38:0d:66:a6:9b:ea: + c9:23:5b:db:8e:e2:f3:13:8e:1a:59:2d:aa:02:f0: + ec:a4:87:66:dc:c1:3f:f5:d8:b9:f4:ec:82:c6:d2: + 3d:95:1d:e5:c0:4f:84:c9:d9:a3:44:28:06:6a:d7: + 45:ac:f0:6b:6a:ef:4e:5f:f8:11:82:1e:38:63:34: + 66:50:d4:3e:93:73:fa:30:c3:66:ad:ff:93:2d:97: + ef:03 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 8f:fa:25:6b:4f:5b:e4:a4:4e:27:55:ab:22:15:59:3c:ca:b5: + 0a:d4:4a:db:ab:dd:a1:5f:53:c5:a0:57:39:c2:ce:47:2b:be: + 3a:c8:56:bf:c2:d9:27:10:3a:b1:05:3c:c0:77:31:bb:3a:d3: + 05:7b:6d:9a:1c:30:8c:80:cb:93:93:2a:83:ab:05:51:82:02: + 00:11:67:6b:f3:88:61:47:5f:03:93:d5:5b:0d:e0:f1:d4:a1: + 32:35:85:b2:3a:db:b0:82:ab:d1:cb:0a:bc:4f:8c:5b:c5:4b: + 00:3b:1f:2a:82:a6:7e:36:85:dc:7e:3c:67:00:b5:e4:3b:52: + e0:a8:eb:5d:15:f9:c6:6d:f0:ad:1d:0e:85:b7:a9:9a:73:14: + 5a:5b:8f:41:28:c0:d5:e8:2d:4d:a4:5e:cd:aa:d9:ed:ce:dc: + d8:d5:3c:42:1d:17:c1:12:5d:45:38:c3:38:f3:fc:85:2e:83: + 46:48:b2:d7:20:5f:92:36:8f:e7:79:0f:98:5e:99:e8:f0:d0: + a4:bb:f5:53:bd:2a:ce:59:b0:af:6e:7f:6c:bb:d2:1e:00:b0: + 21:ed:f8:41:62:82:b9:d8:b2:c4:bb:46:50:f3:31:c5:8f:01: + a8:74:eb:f5:78:27:da:e7:f7:66:43:f3:9e:83:3e:20:aa:c3: + 35:60:91:ce + +Verisign/RSA Commercial CA +========================== +MD5 Fingerprint: 5A:0B:DD:42:9E:B2:B4:62:97:32:7F:7F:0A:AA:9A:39 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICIzCCAZACBQJBAAAWMA0GCSqGSIb3DQEBAgUAMFwxCzAJBgNVBAYTAlVTMSAw +HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVy +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NDExMDQxODU4MzRaFw05 +OTExMDMxODU4MzRaMFwxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBT +ZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVyY2lhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCBmzANBgkqhkiG9w0BAQEFAAOBiQAwgYUCfgCk+4Fie84QJ93o +975sbsZwmdu41QUDaSiCnHJ/lj+O7Kwpkj+KFPhCdr69XQO5kNTQvAayUTNfxMK/ +touPmbZiImDd298ggrTKoi8tUO2UMt7gVY3UaOLgTNLNBRYulWZcYVI4HlGogqHE +7yXpCuaLK44xZtn42f29O2nZ6wIDAQABMA0GCSqGSIb3DQEBAgUAA34AdrW2EP4j +9/dZYkuwX5zBaLxJu7NJbyFHXSudVMQAKD+YufKKg5tgf+tQx6sFEC097TgCwaVI +0v5loMC86qYjFmZsGySp8+x5NRhPJsjjr1BKx6cxa9B8GJ1Qv6km+iYrRpwUqbtb +MJhCKLVLU7tDCZJAuqiqWqTGtotXTcU= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:41:00:00:16 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority + Validity + Not Before: Nov 4 18:58:34 1994 GMT + Not After : Nov 3 18:58:34 1999 GMT + Subject: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1000 bit) + Modulus (1000 bit): + 00:a4:fb:81:62:7b:ce:10:27:dd:e8:f7:be:6c:6e: + c6:70:99:db:b8:d5:05:03:69:28:82:9c:72:7f:96: + 3f:8e:ec:ac:29:92:3f:8a:14:f8:42:76:be:bd:5d: + 03:b9:90:d4:d0:bc:06:b2:51:33:5f:c4:c2:bf:b6: + 8b:8f:99:b6:62:22:60:dd:db:df:20:82:b4:ca:a2: + 2f:2d:50:ed:94:32:de:e0:55:8d:d4:68:e2:e0:4c: + d2:cd:05:16:2e:95:66:5c:61:52:38:1e:51:a8:82: + a1:c4:ef:25:e9:0a:e6:8b:2b:8e:31:66:d9:f8:d9: + fd:bd:3b:69:d9:eb + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 76:b5:b6:10:fe:23:f7:f7:59:62:4b:b0:5f:9c:c1:68:bc:49: + bb:b3:49:6f:21:47:5d:2b:9d:54:c4:00:28:3f:98:b9:f2:8a: + 83:9b:60:7f:eb:50:c7:ab:05:10:2d:3d:ed:38:02:c1:a5:48: + d2:fe:65:a0:c0:bc:ea:a6:23:16:66:6c:1b:24:a9:f3:ec:79: + 35:18:4f:26:c8:e3:af:50:4a:c7:a7:31:6b:d0:7c:18:9d:50: + bf:a9:26:fa:26:2b:46:9c:14:a9:bb:5b:30:98:42:28:b5:4b: + 53:bb:43:09:92:40:ba:a8:aa:5a:a4:c6:b6:8b:57:4d:c5 + +Verisign/RSA Secure Server CA +============================= +MD5 Fingerprint: 74:7B:82:03:43:F0:00:9E:6B:B3:EC:47:BF:85:A5:93 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD +VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 +MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV +BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy +dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ +ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII +0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI +uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI +hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 +YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc +1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:ad:66:7e:4e:45:fe:5e:57:6f:3c:98:19:5e:dd:c0 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Validity + Not Before: Nov 9 00:00:00 1994 GMT + Not After : Jan 7 23:59:59 2010 GMT + Subject: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1000 bit) + Modulus (1000 bit): + 00:92:ce:7a:c1:ae:83:3e:5a:aa:89:83:57:ac:25: + 01:76:0c:ad:ae:8e:2c:37:ce:eb:35:78:64:54:03: + e5:84:40:51:c9:bf:8f:08:e2:8a:82:08:d2:16:86: + 37:55:e9:b1:21:02:ad:76:68:81:9a:05:a2:4b:c9: + 4b:25:66:22:56:6c:88:07:8f:f7:81:59:6d:84:07: + 65:70:13:71:76:3e:9b:77:4c:e3:50:89:56:98:48: + b9:1d:a7:29:1a:13:2e:4a:11:59:9c:1e:15:d5:49: + 54:2c:73:3a:69:82:b1:97:39:9c:6d:70:67:48:e5: + dd:2d:d6:c8:1e:7b + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 65:dd:7e:e1:b2:ec:b0:e2:3a:e0:ec:71:46:9a:19:11:b8:d3: + c7:a0:b4:03:40:26:02:3e:09:9c:e1:12:b3:d1:5a:f6:37:a5: + b7:61:03:b6:5b:16:69:3b:c6:44:08:0c:88:53:0c:6b:97:49: + c7:3e:35:dc:6c:b9:bb:aa:df:5c:bb:3a:2f:93:60:b6:a9:4b: + 4d:f2:20:f7:cd:5f:7f:64:7b:8e:dc:00:5c:d7:fa:77:ca:39: + 16:59:6f:0e:ea:d3:b5:83:7f:4d:4d:42:56:76:b4:c9:5f:04: + f8:38:f8:eb:d2:5f:75:5f:cd:7b:fc:e5:8e:80:7c:fc:50 + + +UTN-USERFirst-Network Applications +================================== +MD5 Fingerprint: BF:60:59:A3:5B:BA:F6:A7:76:42:DA:6F:1A:7B:50:CF +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB +ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt +TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 +NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 +IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD +VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS +Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 +N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH +iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe +YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 +axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g +yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD +AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh +ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V +VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB +BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs +QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 +ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM +YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb +QErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:30:4b:c0:33:77 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Validity + Not Before: Jul 9 18:48:39 1999 GMT + Not After : Jul 9 18:57:49 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b3:fb:91:a1:e4:36:55:85:ac:06:34:5b:a0:9a: + 58:b2:f8:b5:0f:05:77:83:ae:32:b1:76:92:68:ec: + 23:4a:c9:76:3f:e3:9c:b6:37:79:03:b9:ab:69:8d: + 07:25:b6:19:67:e4:b0:1b:18:73:61:4a:e8:7e:cd: + d3:2f:64:e3:a6:7c:0c:fa:17:80:a3:0d:47:89:4f: + 51:71:2f:ee:fc:3f:f9:b8:16:80:87:89:93:25:20: + 9a:43:82:69:24:76:28:59:35:a1:1d:c0:7f:83:06: + 64:16:20:2c:d3:49:a4:85:b4:c0:61:7f:51:08:f8: + 68:15:91:80:cb:a5:d5:ee:3b:3a:f4:84:04:5e:60: + 59:a7:8c:34:72:ee:b8:78:c5:d1:3b:12:4a:6f:7e: + 65:27:b9:a4:55:c5:b9:6f:43:a4:c5:1d:2c:99:c0: + 52:a4:78:4c:15:b3:40:98:08:6b:43:c6:01:b0:7a: + 7b:f5:6b:1c:22:3f:cb:ef:ff:a8:d0:3a:4b:76:15: + 9e:d2:d1:c6:2e:e3:db:57:1b:32:a2:b8:6f:e8:86: + a6:3f:70:ab:e5:70:92:ab:44:1e:40:50:fb:9c:a3: + 62:e4:6c:6e:a0:c8:de:e2:80:42:fa:e9:2f:e8:ce: + 32:04:8f:7c:8d:b7:1c:a3:35:3c:15:dd:9e:c3:ae: + 97:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + FA:86:C9:DB:E0:BA:E9:78:F5:4B:A8:D6:15:DF:F0:D3:E1:6A:14:3C + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-NetworkApplications.crl + + Signature Algorithm: sha1WithRSAEncryption + a4:f3:25:cc:d1:d4:91:83:22:d0:cc:32:ab:9b:96:4e:34:91: + 54:20:25:34:61:5f:2a:02:15:e1:8b:aa:ff:7d:64:51:cf:0a: + ff:bc:7d:d8:21:6a:78:cb:2f:51:6f:f8:42:1d:33:bd:eb:b5: + 7b:94:c3:c3:a9:a0:2d:df:d1:29:1f:1d:fe:8f:3f:bb:a8:45: + 2a:7f:d1:6e:55:24:e2:bb:02:fb:31:3f:be:e8:bc:ec:40:2b: + f8:01:d4:56:38:e4:ca:44:82:b5:61:20:21:67:65:f6:f0:0b: + e7:34:f8:a5:c2:9c:a3:5c:40:1f:85:93:95:06:de:4f:d4:27: + a9:b6:a5:fc:16:cd:73:31:3f:b8:65:27:cf:d4:53:1a:f0:ac: + 6e:9f:4f:05:0c:03:81:a7:84:29:c4:5a:bd:64:57:72:ad:3b: + cf:37:18:a6:98:c6:ad:06:b4:dc:08:a3:04:d5:29:a4:96:9a: + 12:67:4a:8c:60:45:9d:f1:23:9a:b0:00:9c:68:b5:98:50:d3: + ef:8e:2e:92:65:b1:48:3e:21:be:15:30:2a:0d:b5:0c:a3:6b: + 3f:ae:7f:57:f5:1f:96:7c:df:6f:dd:82:30:2c:65:1b:40:4a: + cd:68:b9:72:ec:71:76:ec:54:8e:1f:85:0c:01:6a:fa:a6:38: + ac:1f:c4:84 +# +# RHNS CA certificate. Appended to the ca-bundle at package build-time. +# +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Research Triangle Park, O=Red Hat, Inc., OU=Red Hat Network Services, CN=RHNS Certificate Authority/Email=rhns@redhat.com + Validity + Not Before: Aug 23 22:45:55 2000 GMT + Not After : Aug 28 22:45:55 2003 GMT + Subject: C=US, ST=North Carolina, L=Research Triangle Park, O=Red Hat, Inc., OU=Red Hat Network Services, CN=RHNS Certificate Authority/Email=rhns@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c0:68:2b:12:30:e2:21:2d:22:c6:72:71:5b:bf: + 17:a0:93:10:e9:9b:e3:c9:8d:3b:2d:ac:c4:bb:95: + 3b:e0:ca:55:32:dc:95:c2:10:b3:04:b2:51:fb:e8: + 85:61:16:34:a5:b4:1d:67:5c:a7:77:f4:f0:92:da: + b4:8b:af:95:93:62:f3:66:29:ae:c0:88:b7:64:84: + 0e:48:90:60:f8:60:3e:00:7f:54:dd:17:a6:ac:18: + e0:42:de:7c:be:90:81:f7:f4:05:85:0a:08:cc:d5: + f2:9f:fc:24:8b:77:a5:3d:e9:48:a9:ef:0f:3b:63: + a3:fe:a6:83:4c:e8:dc:0b:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:15:CD:9F:2C:F7:EC:0D:1F:D2:A8:BE:4C:07:AC:88:3E:FB:9B:0A + X509v3 Authority Key Identifier: + keyid:54:15:CD:9F:2C:F7:EC:0D:1F:D2:A8:BE:4C:07:AC:88:3E:FB:9B:0A + DirName:/C=US/ST=North Carolina/L=Research Triangle Park/O=Red Hat, Inc./OU=Red Hat Network Services/CN=RHNS Certificate Authority/Email=rhns@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 93:01:88:88:67:67:91:8c:9e:d0:12:14:90:71:12:87:55:0a: + f2:52:1b:ad:f2:d3:07:1d:af:70:99:bb:b0:cd:80:23:c9:ed: + 2b:73:e9:63:b1:d0:b3:8c:60:c5:42:64:a6:c1:95:56:90:c5: + 35:06:03:58:f5:8e:2b:d9:f9:a9:a0:10:a9:99:f7:15:42:92: + a5:50:d7:11:07:f1:02:d5:e0:70:e4:55:6e:2a:ce:25:f8:5d: + cd:0b:2f:10:61:f8:f6:20:42:cc:c3:89:f8:8a:4f:82:24:12: + cf:39:7f:21:a8:2c:8d:52:97:52:c5:f7:5f:42:a5:87:09:66: + b0:cc +-----BEGIN CERTIFICATE----- +MIIEMDCCA5mgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBxzELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlh +bmdsZSBQYXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQg +SGF0IE5ldHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wHhcNMDAw +ODIzMjI0NTU1WhcNMDMwODI4MjI0NTU1WjCBxzELMAkGA1UEBhMCVVMxFzAVBgNV +BAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlhbmdsZSBQ +YXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQgSGF0IE5l +dHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUgQXV0aG9y +aXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wgZ8wDQYJKoZIhvcN +AQEBBQADgY0AMIGJAoGBAMBoKxIw4iEtIsZycVu/F6CTEOmb48mNOy2sxLuVO+DK +VTLclcIQswSyUfvohWEWNKW0HWdcp3f08JLatIuvlZNi82YprsCIt2SEDkiQYPhg +PgB/VN0XpqwY4ELefL6Qgff0BYUKCMzV8p/8JIt3pT3pSKnvDztjo/6mg0zo3At3 +AgMBAAGjggEoMIIBJDAdBgNVHQ4EFgQUVBXNnyz37A0f0qi+TAesiD77mwowgfQG +A1UdIwSB7DCB6YAUVBXNnyz37A0f0qi+TAesiD77mwqhgc2kgcowgccxCzAJBgNV +BAYTAlVTMRcwFQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEfMB0GA1UEBxMWUmVzZWFy +Y2ggVHJpYW5nbGUgUGFyazEWMBQGA1UEChMNUmVkIEhhdCwgSW5jLjEhMB8GA1UE +CxMYUmVkIEhhdCBOZXR3b3JrIFNlcnZpY2VzMSMwIQYDVQQDExpSSE5TIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYPcmhuc0ByZWRoYXQuY29t +ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAkwGIiGdnkYye0BIU +kHESh1UK8lIbrfLTBx2vcJm7sM2AI8ntK3PpY7HQs4xgxUJkpsGVVpDFNQYDWPWO +K9n5qaAQqZn3FUKSpVDXEQfxAtXgcORVbirOJfhdzQsvEGH49iBCzMOJ+IpPgiQS +zzl/IagsjVKXUsX3X0KlhwlmsMw= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + Validity + Not Before: Sep 5 20:45:16 2002 GMT + Not After : Sep 9 20:45:16 2007 GMT + Subject: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:16:b7:c5:f5:b9:69:51:1f:cd:b4:3d:70:cf: + 60:57:85:a4:2a:a7:5d:28:22:0e:ec:19:e2:92:f7: + 48:97:a6:a6:1f:51:95:83:11:8f:9a:98:a2:90:e0: + cb:4a:24:19:94:a8:8a:4b:88:b4:06:6c:ce:77:d7: + 15:3b:3c:cd:66:83:cf:23:1d:0d:bc:0a:0c:cb:1f: + cb:40:fb:f3:d9:fe:2a:b4:85:2c:7b:c9:a1:fe:f3: + 8f:68:1d:f2:12:b1:a4:16:19:ce:0f:b8:9a:9c:d9: + bc:5f:49:62:b2:95:93:ce:5d:2e:dd:79:3c:f1:5b: + a6:b7:a2:b5:39:0d:8e:12:31 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7F:1B:64:A1:2E:02:C5:A8:7D:B8:D1:B1:8B:06:9D:A3:A9:50:63:92 + X509v3 Authority Key Identifier: + keyid:7F:1B:64:A1:2E:02:C5:A8:7D:B8:D1:B1:8B:06:9D:A3:A9:50:63:92 + DirName:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 28:4d:42:e5:34:22:dd:c6:86:63:04:75:52:67:17:45:72:f2: + 3b:21:2b:45:59:72:73:f7:59:36:9d:57:43:c6:dc:94:0f:0e: + ff:13:5c:4f:50:37:85:b2:e4:c2:1f:35:9f:74:f4:e7:53:fb: + a1:06:b8:39:ce:e4:0a:86:7b:5f:28:5d:c7:11:9e:12:a5:d6: + b9:6c:e9:18:09:d5:f0:42:e7:54:b5:91:9e:23:ad:12:7a:aa: + 72:7c:39:3c:83:f8:75:a4:7b:03:92:ff:2a:d4:c5:76:19:12: + fa:b4:3b:b0:89:2c:95:8c:01:90:0d:d8:ba:06:05:61:00:ac: + 95:da +-----BEGIN CERTIFICATE----- +MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg +BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW +EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMjA5MDUyMDQ1MTZaFw0wNzA5MDkyMDQ1 +MTZaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO +BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT +D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv +cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCzFrfF9blpUR/NtD1wz2BXhaQqp10oIg7sGeKS +90iXpqYfUZWDEY+amKKQ4MtKJBmUqIpLiLQGbM531xU7PM1mg88jHQ28CgzLH8tA ++/PZ/iq0hSx7yaH+849oHfISsaQWGc4PuJqc2bxfSWKylZPOXS7deTzxW6a3orU5 +DY4SMQIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFH8bZKEuAsWofbjRsYsGnaOpUGOS +MIHeBgNVHSMEgdYwgdOAFH8bZKEuAsWofbjRsYsGnaOpUGOSoYG3pIG0MIGxMQsw +CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh +bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg +TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G +CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEEBQADgYEAKE1C5TQi3caGYwR1UmcXRXLyOyErRVlyc/dZNp1X +Q8bclA8O/xNcT1A3hbLkwh81n3T051P7oQa4Oc7kCoZ7XyhdxxGeEqXWuWzpGAnV +8ELnVLWRniOtEnqqcnw5PIP4daR7A5L/KtTFdhkS+rQ7sIkslYwBkA3YugYFYQCs +ldo= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + Validity + Not Before: Aug 29 02:10:55 2003 GMT + Not After : Aug 26 02:10:55 2013 GMT + Subject: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:61:63:eb:3d:8b:2b:45:48:e6:c2:fb:7c:d2: + 21:21:b8:ec:90:93:41:30:7c:2c:8d:79:d5:14:e9: + 0e:7e:3f:ef:d6:0a:9b:0a:a6:02:52:01:2d:26:96: + a4:ed:bd:a9:9e:aa:08:03:c1:61:0a:41:80:ea:ae: + 74:cc:61:26:d0:05:91:55:3e:66:14:a2:20:b3:d6: + 9d:71:0c:ab:77:cc:f4:f0:11:b5:25:33:8a:4e:22: + 9a:10:36:67:fa:11:6d:48:76:3a:1f:d2:e3:44:7b: + 89:66:be:b4:85:fb:2f:a6:aa:13:fa:9a:6d:c9:bb: + 18:c4:04:af:4f:15:69:89:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:44:27:05:DC:2E:ED:A5:F4:81:C4:D7:78:45:E7:44:5D:F8:87:47 + X509v3 Authority Key Identifier: + keyid:69:44:27:05:DC:2E:ED:A5:F4:81:C4:D7:78:45:E7:44:5D:F8:87:47 + DirName:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 23:c9:ca:07:9f:5e:96:39:83:e0:4e:da:dd:47:84:30:ca:d4: + d5:38:86:f9:de:88:83:ca:2c:47:26:36:ab:f4:14:1e:28:29: + de:7d:10:4a:5e:91:3e:5a:99:07:0c:a9:2e:e3:fb:78:44:49: + c5:32:d6:e8:7a:97:ff:29:d0:33:ae:26:ba:76:06:7e:79:97: + 17:0c:4f:2d:2a:8b:8a:ac:41:59:ae:e9:c4:55:2d:b9:88:df: + 9b:7b:41:f8:32:2e:ee:c9:c0:59:e2:30:57:5e:37:47:29:c0: + 2d:78:33:d3:ce:a3:2b:dc:84:da:bf:3b:2e:4b:b6:b3:b6:4e: + 9e:80 +-----BEGIN CERTIFICATE----- +MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg +BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW +EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMzA4MjkwMjEwNTVaFw0xMzA4MjYwMjEw +NTVaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO +BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT +D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv +cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC/YWPrPYsrRUjmwvt80iEhuOyQk0EwfCyNedUU +6Q5+P+/WCpsKpgJSAS0mlqTtvameqggDwWEKQYDqrnTMYSbQBZFVPmYUoiCz1p1x +DKt3zPTwEbUlM4pOIpoQNmf6EW1Idjof0uNEe4lmvrSF+y+mqhP6mm3JuxjEBK9P +FWmJmwIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFGlEJwXcLu2l9IHE13hF50Rd+IdH +MIHeBgNVHSMEgdYwgdOAFGlEJwXcLu2l9IHE13hF50Rd+IdHoYG3pIG0MIGxMQsw +CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh +bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg +TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G +CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEEBQADgYEAI8nKB59eljmD4E7a3UeEMMrU1TiG+d6Ig8osRyY2 +q/QUHigp3n0QSl6RPlqZBwypLuP7eERJxTLW6HqX/ynQM64munYGfnmXFwxPLSqL +iqxBWa7pxFUtuYjfm3tB+DIu7snAWeIwV143RynALXgz086jK9yE2r87Lku2s7ZO +noA= +-----END CERTIFICATE----- diff --git a/doc/certs/slapd.crt b/doc/certs/slapd.crt new file mode 100644 index 0000000..f7a511d --- /dev/null +++ b/doc/certs/slapd.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtTCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQQFADBMMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDAeFw0wNTA5MTUwMjAyMTNaFw0yMTA3MjYxNjM2NTNaMEwx +CzAJBgNVBAYTAkdCMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1 +cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCr6PfdngYTUobwJDwIqY7ywDCWd/IJ+SL2hbe46558oVI7Vw2GbqWn +VZ1fJa0wV2pcy/e10HzZX+RpIwKOZUQvbH1jHJyZ/0bt7on8jmI5o+p+rLVspci5 +yVNcgu1tQttpyKnTrDSDkLVbQ6VX8FKLnKnZ7+dk8SNibt0KbzKnOQIDAQABo4Gm +MIGjMB0GA1UdDgQWBBQ4xLvszjgfXgWht8V6s1eRAZS/OjB0BgNVHSMEbTBrgBQ4 +xLvszjgfXgWht8V6s1eRAZS/OqFQpE4wTDELMAkGA1UEBhMCR0IxEjAQBgNVBAgT +CUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkgQ29tcGFu +eSBMdGSCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAgzaIKI03l +lZmX7IpLN3vqC/PL6QQTUQkdDRXJYGH+DdURx7v0nE/kkb3R3X92BpNxe5jywhHg +A5NaUhjAR76+F3Guk/4XFaWPctJ2PvfJWolS/VrY+KGc3N4zz9A2i8B6SHBzE6V8 +EHkcGJtGXkFvCVp1ZbCyejJhw4PUEYawsQ== +-----END CERTIFICATE----- diff --git a/doc/certs/slapd.key b/doc/certs/slapd.key new file mode 100644 index 0000000..4edd557 --- /dev/null +++ b/doc/certs/slapd.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCr6PfdngYTUobwJDwIqY7ywDCWd/IJ+SL2hbe46558oVI7Vw2G +bqWnVZ1fJa0wV2pcy/e10HzZX+RpIwKOZUQvbH1jHJyZ/0bt7on8jmI5o+p+rLVs +pci5yVNcgu1tQttpyKnTrDSDkLVbQ6VX8FKLnKnZ7+dk8SNibt0KbzKnOQIDAQAB +AoGAdfKYpag3WOiFhpwFyJe1aV5tt79CBI+36lZicHDQw4fXqLkYoYSnCYFXQSHT +ithfNJ4JLeiG0InXaD9KELLwLU2C7rr7mgOBczzmVBGCYUDNuV3bMcNDOQk/drum +GLGqHhxU6W0dlCUnoBZoEHK6dvtDZnxCa+cUBozvFbuLOTUCQQDZJf+Mz7vc78nn +Cc7nnHFfO+79NQi9h0ydW6kb2LLSGB/f3oqwary8eqCs7RVinG21PMWbjrh0lGOJ +DjYP6dLDAkEAyqrs8pgxcxSTcJiaU4/sxGCeaS4fvoeCbYvKLlS5k5Km6DmA3nY+ +KwxQyLHg64g1ImDSuLy3P/E2lZGCPhZGUwJAMVUxpqL3Mi2D+CpBSFtBYnpyRDJN +Rwm6/TD6zWnAznxOmYSsi4HkWQmfAUpnhly1i+w/lKSrAUlJB7Uj0R+1EwJAOADv +pUIFOCXRcGXbD4hQBxwj6jDCuOW9VwQwBImJFoyJ7tYlFFRcbYzjrfHpk2x6MlvL +Hx2XDeZcDQy+juWc3QJAHOpmlHuWqS07i5UIXVl5ohhoWkFd9Qs7/TowyFQF3zpO +BqnwfHZRpySjSUlNE0QpoJRJQPq7p3BWtS3PWMj0/A== +-----END RSA PRIVATE KEY----- diff --git a/doc/demo-reset.sh b/doc/demo-reset.sh new file mode 100644 index 0000000..a23ad5b --- /dev/null +++ b/doc/demo-reset.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +for i in $(grep directory phpldapadmin-demo.conf|awk '{print $2}'); do + if [ -d $i ]; then + rm -f $i/*.dbb $i/*.bdb $i/__db.??? $i/alock $i/log.* + else + mkdir $i + fi +done + +slapadd -b "dc=example.com" -l ldif-example.com +slapadd -b "dc=example,dc=com" -l ldif-example-com +slapadd -b "o=Simpsons" -l ldif-Simpsons +slapadd -b "o=Flintstones" -l ldif-Flintstones + +for i in $(grep directory phpldapadmin-demo.conf|awk '{print $2}'); do + chown -R ldap:ldap $i +done diff --git a/doc/ldif-Flintstones b/doc/ldif-Flintstones new file mode 100644 index 0000000..9453690 --- /dev/null +++ b/doc/ldif-Flintstones @@ -0,0 +1,992 @@ +# LDIF Export for o=Flintstones +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 12 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:03 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: o=Flintstones +dn: o=Flintstones +o: Flintstones +objectclass: organization +objectclass: top + +# Entry 2: cn=Flintstones-PG,o=Flintstones +dn: cn=Flintstones-PG,o=Flintstones +cn: flintstones-pg +gidnumber: 1001 +objectclass: posixGroup +objectclass: top + +# Entry 3: ou=People,o=Flintstones +dn: ou=People,o=Flintstones +objectclass: organizationalUnit +objectclass: top +ou: People + +# Entry 4: cn=Bamm Bamm Rubble,ou=People,o=Flintstones +dn: cn=Bamm Bamm Rubble,ou=People,o=Flintstones +cn: Bamm Bamm Rubble +gidnumber: 1001 +givenname: Bamm Bamm +homedirectory: /home/users/flintstones/bammbamm +jpegphoto:: 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 + s9UUUV6eBRRRQH/9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: bammbamm +uidnumber: 1105 +userpassword: bammbamm + +# Entry 5: cn=Barney Rubble,ou=People,o=Flintstones +dn: cn=Barney Rubble,ou=People,o=Flintstones +cn: Barney Rubble +gidnumber: 1001 +givenname: Barney +homedirectory: /home/users/flintstones/barney +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: barney +uidnumber: 1102 + +# Entry 6: cn=Betty Rubble,ou=People,o=Flintstones +dn: cn=Betty Rubble,ou=People,o=Flintstones +cn: Betty Rubble +gidnumber: 1001 +givenname: Betty +homedirectory: /home/users/flintstones/betty +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: betty +uidnumber: 1103 + +# Entry 7: cn=Fred Flintstone,ou=People,o=Flintstones +dn: cn=Fred Flintstone,ou=People,o=Flintstones +cn: Fred Flintstone +gidnumber: 1001 +givenname: Fred +homedirectory: /home/users/flintstones/fred +jpegphoto:: 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 + EFZAKtieQxViUpTVjGsGGjRQnOLjkpSlK9LC/9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: fred +uidnumber: 1100 +userpassword: yabbadabbado + +# Entry 8: cn=Pebbles Flintstone,ou=People,o=Flintstones +dn: cn=Pebbles Flintstone,ou=People,o=Flintstones +cn: Pebbles Flintstone +gidnumber: 1001 +givenname: Pebbles +homedirectory: /home/users/flintstones/pebbles +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: pebbles +uidnumber: 1104 + +# Entry 9: cn=Wilma Flintstone,ou=People,o=Flintstones +dn: cn=Wilma Flintstone,ou=People,o=Flintstones +cn: Wilma Flintstone +gidnumber: 1001 +givenname: Wilma +homedirectory: /home/users/flintstones/wilma +jpegphoto:: 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 + pHOaGnZKUpWizSlKUIX//Z +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: wilma +uidnumber: 1101 +userpassword: pebble + +# Entry 10: ou=Pets,o=Flintstones +dn: ou=Pets,o=Flintstones +objectclass: organizationalUnit +objectclass: top +ou: Pets + +# Entry 11: cn=Baby Puss Flintstone,ou=Pets,o=Flintstones +dn: cn=Baby Puss Flintstone,ou=Pets,o=Flintstones +cn: Baby Puss Flintstone +gidnumber: 1001 +givenname: Baby Puss +homedirectory: /home/users/flintstones/babypuss +jpegphoto:: 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 + zklF+QxU4BWaKltZeIooor1C//9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +uid: babypuss +uidnumber: 1010 + +# Entry 12: cn=Hoppy Rubble,ou=Pets,o=Flintstones +dn: cn=Hoppy Rubble,ou=Pets,o=Flintstones +cn: Hoppy Rubble +gidnumber: 1001 +givenname: Hoppy +homedirectory: /home/users/flintstones/hoppy +jpegphoto:: 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 + iqfxArbpSvESlKURKUpRF//Z +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: hoppy +uidnumber: 1009 diff --git a/doc/ldif-Simpsons b/doc/ldif-Simpsons new file mode 100644 index 0000000..8b6735f --- /dev/null +++ b/doc/ldif-Simpsons @@ -0,0 +1,496 @@ +# LDIF Export for o=Simpsons +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 11 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:05 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: o=Simpsons +dn: o=Simpsons +o: Simpsons +objectclass: organization +objectclass: top + +# Entry 2: cn=Simpsons-GOUN,o=Simpsons +dn: cn=Simpsons-GOUN,o=Simpsons +cn: simpsons-goun +objectclass: groupOfUniqueNames +objectclass: top +uniquemember: cn=Bart Simpson,ou=People,o=Simpsons +uniquemember: cn=Homer Simpson,ou=People,o=Simpsons +uniquemember: cn=Lisa Simpson,ou=People,o=Simpsons +uniquemember: cn=Maggie Simpson,ou=People,o=Simpsons +uniquemember: cn=Marge Simpson,ou=People,o=Simpsons + +# Entry 3: cn=Simpsons-PG,o=Simpsons +dn: cn=Simpsons-PG,o=Simpsons +cn: simpsons-pg +gidnumber: 1000 +memberuid: maggie +memberuid: marg +memberuid: lisa +memberuid: homer +memberuid: bart +objectclass: posixGroup +objectclass: top + +# Entry 4: ou=People,o=Simpsons +dn: ou=People,o=Simpsons +objectclass: organizationalUnit +objectclass: top +ou: People + +# Entry 5: cn=Bart Simpson,ou=People,o=Simpsons +dn: cn=Bart Simpson,ou=People,o=Simpsons +cn: Bart Simpson +gidnumber: 1000 +givenname: Bart +homedirectory: /home/users/simpsons/bart +jpegphoto:: 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 +l: Springfield +mail: bart.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: bart +uidnumber: 1000 +userpassword: eatmyshorts + +# Entry 6: cn=Homer Simpson,ou=People,o=Simpsons +dn: cn=Homer Simpson,ou=People,o=Simpsons +cn: Homer Simpson +gidnumber: 1000 +givenname: Homer +homedirectory: /home/users/simpsons/homer +jpegphoto:: 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 +l: Springfield +mail: homer.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: homer +uidnumber: 1001 +userpassword: mmm.beer + +# Entry 7: cn=Lisa Simpson,ou=People,o=Simpsons +dn: cn=Lisa Simpson,ou=People,o=Simpsons +cn: Lisa Simpson +gidnumber: 1000 +givenname: Lisa +homedirectory: /home/users/simpsons/lisa +jpegphoto:: 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 + zt1Zj1J/wDtsTcHQxCJtll8Rr3105kOg4DkF//Z +l: Springfield +mail: lisa.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: lisa +uidnumber: 1002 +userpassword: brains + +# Entry 8: cn=Maggie Simpson,ou=People,o=Simpsons +dn: cn=Maggie Simpson,ou=People,o=Simpsons +cn: Maggie Simpson +gidnumber: 1000 +givenname: Maggie +homedirectory: /home/users/simpsons/maggie +jpegphoto:: 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 +l: Springfield +mail: maggie.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: maggie +uidnumber: 1003 +userpassword: dummy + +# Entry 9: cn=Marge Simpson,ou=People,o=Simpsons +dn: cn=Marge Simpson,ou=People,o=Simpsons +cn: Marge Simpson +gidnumber: 1000 +givenname: Marge +homedirectory: /home/users/simpsons/marge +jpegphoto:: R0lGODlhhABwAIcAAAAAAAICBQIEAgUFAQUFBAICCwYICw4EBAsJAgkJCAgJDQ4N + CA0NDQECEgEDGwsMEA4QDhMEAhILAhANARANBBYODhwCARoJARMQAhIQBBURARQRBBcVAhIQCBE + QDRQSDhgSABkUARwTARwVAB0YARISERsbGwIEIgIEKgEENAAEPAQINAQIOiMBASwCAiIbATUDAz + 0CAicgAiogASsjBCskAS0jAS0kAS4oBTEnATQqAjkuATswAz0xATwxBj80BCIiIikpKS8vLzQ0N + Dk5OT09PQIFQwEGTAQJRAMITQEFUQEGWwMIUwMIWgIIYwIIbAAGcQAGfwEIdAEIfEICAksBAVIB + AV8AAEAzAUE1AUU2AUU3BEU4AUw8AVA+AWEBAWsCAnIBAXwBAU5ABFRDAlhGAVxHAltJAWFNAWB + NBGJQBGVRAmpUAW1YAW1YBHFZAHFaBHFcAnRaAnVdAXVeBHleAHdgAntiAURERElJSU1NTVJSUl + lZWV1dXWFhYWVlZWxsbHJycnV1dXt7ewAIg4QBAYwBAZIAAJsCAqICAqsCArQDA7sCAoFlAYRpA + ohqAIptAIxuAo1wApN0AZZ5Bph3AJp7AaB/AYF/f8ECAssBAdMEBNwBAeICAuwBAfIBAf4AAJ6A + AqGAAaODBKaCAKSCBKaEAKqGAayHAK2JAbKMAraRAruTAcKZAcOaBMadAMidAMqgAsugBM2hAc6 + iBM6kAtGlAdOoAdqsAdyuAd6wAOCuAOCxAOK0AOS1AOi3AOm5AO27AO+9AIKCgoWFhYuLi42NjZ + KSkpycnIyapI6cpZCdp5GfqJajrJyosKOjo6qqqqWwt6WwuK23vrS0tLm5ub6+vrnCyLzEysPDw + 8DHzcjIyM3NzcTL0MXM0cjO08nQ1NPT09DW2tfb39fc39jY2N3d3dzg497i5d/k5uHh4eDj5uDk + 5uXl5eHl6OTn6eXo6ufq7Onp6ers7uzs7Ovt8O3u8O3w8fHx8fHz9PP19vX19ff4+Pn5+f39/QA + AACH5BAAAAP8ALAAAAACEAHAAAAj/AAEIHEiwoMGDCBMqXMiwocOHDf1JnEixosWL/p41mEKoo8 + ePIEOKHEmyZEgUgzCqXIlRIMuXF/2gMEmzpk2TUhjQg8nzosuePPGVcHKzqNGaKI4BXervJ9OV+ + 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 + lBDxlFAZlVI5lVIZEAA7 +l: Springfield +mail: marge.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: marge +uidnumber: 1004 +userpassword: homie + +# Entry 10: ou=Pets,o=Simpsons +dn: ou=Pets,o=Simpsons +objectclass: organizationalUnit +objectclass: top +ou: Pets + +# Entry 11: cn=Santas Little Helper,ou=Pets,o=Simpsons +dn: cn=Santas Little Helper,ou=Pets,o=Simpsons +cn: Santas Little Helper +givenname: Santas Little Helper +jpegphoto:: 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 + 0rJcGRsMDnOT1q10pXgAAwJ6SScmf//Z +l: Springfield +o: The Simpsons +objectclass: inetOrgPerson +objectclass: top +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 diff --git a/doc/ldif-example-com b/doc/ldif-example-com new file mode 100644 index 0000000..043136a --- /dev/null +++ b/doc/ldif-example-com @@ -0,0 +1,139 @@ +# LDIF Export for dc=example,dc=com +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 15 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:25 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: dc=example,dc=com +dn: dc=example,dc=com +dc: example +objectclass: dNSDomain + +# Entry 2: c=AU,dc=example,dc=com +dn: c=AU,dc=example,dc=com +c: AU +description: Australia +objectclass: country +objectclass: top + +# Entry 3: c=CN,dc=example,dc=com +dn: c=CN,dc=example,dc=com +c: CN +objectclass: country +objectclass: top + +# Entry 4: cn=你好,c=CN,dc=example,dc=com +dn:: Y2495L2g5aW9LGM9Q04sZGM9ZXhhbXBsZSxkYz1jb20= +cn:: 5L2g5aW9 +gidnumber: 200 +objectclass: posixGroup +objectclass: top + +# Entry 5: c=DE,dc=example,dc=com +dn: c=DE,dc=example,dc=com +c: DE +description: Germany +objectclass: country +objectclass: top + +# Entry 6: c=ES,dc=example,dc=com +dn: c=ES,dc=example,dc=com +c: ES +objectclass: country +objectclass: top + +# Entry 7: c=FR,dc=example,dc=com +dn: c=FR,dc=example,dc=com +c: FR +description: France +objectclass: country +objectclass: top + +# Entry 8: c=GB,dc=example,dc=com +dn: c=GB,dc=example,dc=com +c: GB +description: Great Britain +objectclass: country +objectclass: top + +# Entry 9: c=IT,dc=example,dc=com +dn: c=IT,dc=example,dc=com +c: IT +objectclass: country +objectclass: top + +# Entry 10: c=NO,dc=example,dc=com +dn: c=NO,dc=example,dc=com +c: NO +description: Norway +objectclass: country +objectclass: top + +# Entry 11: c=RU,dc=example,dc=com +dn: c=RU,dc=example,dc=com +c: RU +objectclass: country +objectclass: top + +# Entry 12: cn=Человеки,c=RU,dc=example,dc=com +dn:: Y2490KfQtdC70L7QstC10LrQuCxjPVJVLGRjPWV4YW1wbGUsZGM9Y29t +cn:: 0KfQtdC70L7QstC10LrQuA== +objectclass: inetOrgPerson +objectclass: top +sn:: 0KfQtdC70L7QstC10LrQuA== + +# Entry 13: cn=Дед Логопед,cn=Человеки,c=RU,dc=example,... +dn:: Y2490JTQtdC0INCb0L7Qs9C+0L/QtdC0LGNuPdCn0LXQu9C+0LLQtdC60LgsYz1SVSxkYz1 + leGFtcGxlLGRjPWNvbQ== +cn:: 0JTQtdC0INCb0L7Qs9C+0L/QtdC0 +givenname:: 0JTQtdC0 +jpegphoto:: /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoH + BwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQk + UDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wA + ARCAAwAEADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAA + gEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcY + GRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipK + TlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8v + P09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFB + AQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygp + KjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJm + aoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9 + oADAMBAAIRAxEAPwD9A/gj8Nx8IvhN4V8KPKsr6PpkNnJIv3WZV+Y/QnNc/wCINDutR1Q/Mux2y + xHTFeTaP+17d+IfDN94w02ODW/ANsF+0apZKZHtHOMxyKPmDDK8Ed69G8IfEHR/ij4aTxD4cv47 + 60VMkxEjacdGBAKn2IoA5Txn4KuIzO0v+rToyDjmvlL486HBb2jhdzEdNvrzXtvxB+NsNjeXdpF + M7JFlQpbv6GvlD4qfE6/1Ca4nktWkgI24Tkd+goA+b/ESSRXkoJIwejCuWuZFfOQAfUV1HiC9vN + VuGmj064RJOjvC4HHpxXGXwntZT50Tp6FlIoAy9UQLE5A7VzDJ5h/Guj1aUi1ZvXisTyTGuDwR1 + oA/cX/gnT8CPFfwl/Z21nR/Gugpo9/rOpSXS6df7XdrdoUQCZATtJKt8p5xjPWvefh98HdE8D3d + 3qcNnb2lzPGYXisVaO2EI6IIySOPWvRulYXjjWYvD/hLVdQmfy4oLd3ZvQAUAfjx+0H42kHxR8T + Lajybdb2VY4lPAAY4FefeGbx9Q1yzlu7f+0rbdmSEt8x9QAeK1PiQi614n1LUlbi4neXn3Ymud0 + m9l0G6jlVC6E5OOoPqKAIPFPhq88O+Mr7V9J1i/trC4kMyWaiRHyf4Sn3BjpnJGKpT6yNe0lk1W + 0jN2DgTBAN49T716NqOrXXiC1807dm3rIcV5j4mb7KrZYbsHkUAeW+JIEt7hIYwCqtvwPb/ACKw + XBySec1v39nPc3DTshCNwmR1HrVGfT2jIJHFAH9GkfxQspdds7KKOWaGZtr3CITHEMcMzdAM4/O + uR/aP1qLXPhtqOiaVdQzXV4hQ/PhQMcknFeXeAdRnSzRxG88UxGx9mVJPTnHGcGuk1+4h1LSnij + RHkYlVjk4kVvQHHrQB+f8A4m/Zy8Y380kOnapokEZGS91cvk+wAQ1zq/svfEC5/cp4i0O2KHaR5 + UzsT/3yM19ea9aW8R3y3ElndKSWhdBtkB6HBxj6g1w+tarcxRRXLxS3mmxuE3ohCA9SNwwwP1oA + 8Ksv2WvHGAl143s40xjba6cznn/eYVFrX7LRuYUjbxa817nkTWB2MPqrEj9a9jXxZqt4DEkqoVb + 93DKN3b+8MEHjjI9Kq6j421mwSNL64ESSqytuYOj+gYdvqKAPAvF/wOv9EtR5z2tyEG3fDuX9GU + YryPXfB15axs62ryxhtu+Ebxn6rmvpXW9cilF00+piYDO17cOVK9Mc9vqO1eQ+LNVSOd3g3NAvJ + MmUJ+vP9aAP/9k= +objectclass: inetOrgPerson +objectclass: top +sn:: 0JvQvtCz0L7Qv9C10LQ= + +# Entry 14: c=SE,dc=example,dc=com +dn: c=SE,dc=example,dc=com +c: SE +objectclass: country +objectclass: top + +# Entry 15: c=US,dc=example,dc=com +dn: c=US,dc=example,dc=com +c: US +description: United States of America +objectclass: country +objectclass: top diff --git a/doc/ldif-example.com b/doc/ldif-example.com new file mode 100644 index 0000000..8c6cdfb --- /dev/null +++ b/doc/ldif-example.com @@ -0,0 +1,165 @@ +# LDIF Export for dc=example.com +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 23 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:13 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: dc=example.com +dn: dc=example.com +dc: example.com +objectclass: dNSDomain + +# Entry 2: cn=group,dc=example.com +dn: cn=group,dc=example.com +cn: group +gidnumber: 100 +objectclass: posixGroup +objectclass: top + +# Entry 3: ou=Bad DNs,dc=example.com +dn: ou=Bad DNs,dc=example.com +objectclass: organizationalUnit +ou: Bad DNs + +# Entry 4: c=double plus \2B\2B,ou=Bad DNs,dc=example.com +dn: c=double plus \2B\2B,ou=Bad DNs,dc=example.com +c: double plus ++ +objectclass: country + +# Entry 5: c=end dollar$,ou=Bad DNs,dc=example.com +dn: c=end dollar$,ou=Bad DNs,dc=example.com +c: end dollar$ +objectclass: country + +# Entry 6: sn=sign@at+uid=multi-mixed,ou=Bad DNs,dc=example.com +dn: sn=sign@at+uid=multi-mixed,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: sign@at +uid: multi-mixed + +# Entry 7: uid=angle\3Cleft,ou=Bad DNs,dc=example.com +dn: uid=angle\3Cleft,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: angleright + +# Entry 9: uid=brace(left,ou=Bad DNs,dc=example.com +dn: uid=brace(left,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: brace(left + +# Entry 10: uid=brace)right,ou=Bad DNs,dc=example.com +dn: uid=brace)right,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: brace)right + +# Entry 11: uid=colon:full,ou=Bad DNs,dc=example.com +dn: uid=colon:full,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: colon:full + +# Entry 12: uid=colon\3Bsemi,ou=Bad DNs,dc=example.com +dn: uid=colon\3Bsemi,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: colon;semi + +# Entry 13: uid=multi+uid=sign@at,ou=Bad DNs,dc=example.com +dn: uid=multi+uid=sign@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: multi +uid: sign@at + +# Entry 14: uid=multi+uid=value,ou=Bad DNs,dc=example.com +dn: uid=multi+uid=value,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: multi +uid: value + +# Entry 15: uid=quote\22double,ou=Bad DNs,dc=example.com +dn: uid=quote\22double,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: quote"double + +# Entry 16: uid=quote'single,ou=Bad DNs,dc=example.com +dn: uid=quote'single,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: quote'single + +# Entry 17: uid=sign%percent,ou=Bad DNs,dc=example.com +dn: uid=sign%percent,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign%percent + +# Entry 18: uid=sign\2Bplus,ou=Bad DNs,dc=example.com +dn: uid=sign\2Bplus,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign+plus + +# Entry 19: uid=sign\2Ccomma,ou=Bad DNs,dc=example.com +dn: uid=sign\2Ccomma,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign,comma + +# Entry 20: uid=sign\3Bsemicolon@at,ou=Bad DNs,dc=example.com +dn: uid=sign\3Bsemicolon@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign;semicolon@at + +# Entry 21: uid=sign\3Dequal,ou=Bad DNs,dc=example.com +dn: uid=sign\3Dequal,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign=equal + +# Entry 22: uid=sign?question,ou=Bad DNs,dc=example.com +dn: uid=sign?question,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign?question + +# Entry 23: uid=sign@at,ou=Bad DNs,dc=example.com +dn: uid=sign@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign@at diff --git a/doc/phpldapadmin-demo.conf b/doc/phpldapadmin-demo.conf new file mode 100644 index 0000000..3ed4063 --- /dev/null +++ b/doc/phpldapadmin-demo.conf @@ -0,0 +1,107 @@ +include /etc/openldap/schema/uidpool.schema +include /etc/openldap/schema/sudo.schema +include /etc/openldap/schema/autofs.schema + +TLSCACertificateFile /etc/openldap/pla/ca-bundle.crt +TLSCertificateFile /etc/openldap/pla/slapd.crt +TLSCertificateKeyFile /etc/openldap/pla/slapd.key + +access to dn.regex="o=Simpsons$" attrs=userpassword + by anonymous auth + by self write + by * none + +access to dn.base="" by * read +access to dn.regex="dc=example.com$" + by dn.regex="o=Flintstones$" none + by dn.regex="o=Simpsons$" none + by * write +access to dn.regex="dc=example,dc=com$" + by dn.regex="o=Flintstones$" none + by dn.regex="o=Simpsons$" none + by * write +access to dn.regex="o=Flintstones$" + by dn.regex="o=Simpsons$" none + by self write + by dn.regex="cn=.*,ou=People,o=Flintstones" write + by * read +access to dn.regex="o=Simpsons$" + by dn.regex="o=Flintstones$" none + by self write + by dn.regex="cn=.*,ou=People,o=Simpsons" write + by * read +access to * + by * read + +authz-policy any + +database ldbm +suffix "dc=example.com" +rootdn "cn=Manager,dc=example.com" +rootpw NotAllowed +directory /var/lib/ldap/base-example.com +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database ldbm +suffix "dc=example,dc=com" +rootdn "cn=Manager,dc=example,dc=com" +rootpw NotAllowed +directory /var/lib/ldap/base-example-com +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database ldbm +suffix "o=Simpsons" +rootdn "cn=Manager,o=Simpsons" +rootpw NotAllowed +directory /var/lib/ldap/base-simpsons +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +sasl-regexp uid=(.*),cn=(.*),cn=gssapi,cn=auth + ldap:///dc=example.com??sub?(&(uid=$1)(objectClass=inetOrgPerson)) + +database bdb +suffix "o=Flintstones" +rootdn "cn=Manager,o=Flintstones" +rootpw NotAllowed +directory /var/lib/ldap/base-flintstones +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database monitor +access to * by * read + +database config +access to * by * read +rootdn cn=admin,cn=config +rootpw password diff --git a/doc/pla-test-i18n.ldif b/doc/pla-test-i18n.ldif new file mode 100644 index 0000000..1c9e76f --- /dev/null +++ b/doc/pla-test-i18n.ldif @@ -0,0 +1,66 @@ +# This is a Test-File for characters / encoding +# 1. Change the +# ,dc=example,dc=com +# to avalue for your organisation +# 2. Import it with phpldapadmin +# +# pla-i18n, example.com +# +dn: ou=pla-i18n,dc=example,dc=com +ou: pla-i18n +objectClass: top +objectClass: organizationalUnit + +# pl, pla-i18n, example.com +dn: ou=pl,ou=pla-i18n,dc=example,dc=com +description:: IGRvcMOza2k= +description:: xITFu8WaxbnEhsWDxYHDk8SYIMSFxbzFm8W6xIfFhMWCw7PEmQ== +description:: V3NrYXrDs3drYQ== +objectClass: top +objectClass: organizationalUnit +ou: pl + +# ru, pla-i18n, example.com +dn: ou=ru,ou=pla-i18n,dc=example,dc=com +description:: 0LfQstGD0YfQuNGCINC/0L7QtNC+0LHQvdC+ +description:: 0J/RgNC+0YHRgtCw0Y8g0YTQvtGA0LzQsCDQv9C+0LjRgdC6 +objectClass: top +objectClass: organizationalUnit +ou: ru + +# jp, pla-i18n, example.com +dn: ou=jp,ou=pla-i18n,dc=example,dc=com +ou: jp +objectClass: top +objectClass: organizationalUnit +description:: SVNPLTIwMjItSlDjga7lpJrlm73nsY3oqIDoqp7jgbjjga7mi6HlvLXmgKc= + +# pt-br, pla-i18n, example.com +dn: ou=pt-br,ou=pla-i18n,dc=example,dc=com +ou: pt-br +objectClass: top +objectClass: organizationalUnit +description:: VmVyIGFzIHJlcXVpc2nDp8O1ZXMgZW0gYWJlcnRv + +# de, pla-i18n, example.com +dn: ou=de,ou=pla-i18n,dc=example,dc=com +ou: de +objectClass: top +objectClass: organizationalUnit +description:: U29uZGVyemVpY2hlbiDDtsOkw7zDnyDDlsOEw5w= +description:: w5bDliDDnMOcIMOEw4Q= + +# sv, pla-i18n, example.com +dn: ou=sv,ou=pla-i18n,dc=example,dc=com +ou: sv +objectClass: top +objectClass: organizationalUnit +description:: U8O2a29tZsOlbmc= +description:: bMOldGVyIHNvbQ== + +# ca, pla-i18n, example.com +dn: ou=ca,ou=pla-i18n,dc=example,dc=com +ou: ca +objectClass: top +objectClass: organizationalUnit +description:: RXMgdGluZHLDoSBxdWUgY29uZmlybWFyIGFxdWVzdGEgZGVjaXNpw7M= diff --git a/doc/uidpool.schema b/doc/uidpool.schema new file mode 100644 index 0000000..7154740 --- /dev/null +++ b/doc/uidpool.schema @@ -0,0 +1,11 @@ +## +## Used for storing the next gid and next uid in the the directory +## +objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY + DESC 'Pool for allocating UNIX uids' + MUST ( uidNumber $ cn ) ) + + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY + DESC 'Pool for allocating UNIX gids' + MUST ( gidNumber $ cn ) ) diff --git a/hooks/classes/README b/hooks/classes/README new file mode 100644 index 0000000..1a0f343 --- /dev/null +++ b/hooks/classes/README @@ -0,0 +1,3 @@ +Put your hook class files here. + +A file wich contains "class MyClass" definition must be called "MyClass.php". diff --git a/hooks/functions/README b/hooks/functions/README new file mode 100644 index 0000000..e5b29d7 --- /dev/null +++ b/hooks/functions/README @@ -0,0 +1 @@ +Put your hook function files here. \ No newline at end of file diff --git a/hooks/functions/example.php b/hooks/functions/example.php new file mode 100644 index 0000000..1ba34da --- /dev/null +++ b/hooks/functions/example.php @@ -0,0 +1,402 @@ +sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Global Vars: %s',join('| ',array_keys($GLOBALS))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_session_init','example_post_session_init'); + +/** + * This pre_connect function is called before making a connection to the LDAP server. + * While PLA makes many calls to connect to the LDAP server, this is called only once + * when caching is turned on. + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @see post_connect + */ +function example_pre_connect() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
',$args[0],$args[1]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_connect','example_pre_connect'); + +/** + * This post_connect function is called after making a connection to the LDAP server. + * While PLA makes many calls to connect to the LDAP server, this is called only once + * when caching is turned on. + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string User ID of the user who successfully made the connection. + * @see pre_connect + */ +function example_post_connect() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • User DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_connect','example_post_connect'); + +/** + * This pre_entry_create function is called before an entry is created in ds_ldap_pla::add(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry created + * @param array Attributes for the new DN + * @see post_entry_create + */ +function example_pre_entry_create() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join(',',(array_keys($args[3])))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_create','example_pre_entry_create'); + +/** + * This post_entry_create function is called after an entry is created in ds_ldap_pla::add(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry created + * @param array Attributes for the new DN + * @see pre_entry_create + */ +function example_post_entry_create() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join(',',(array_keys($args[3])))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_create','example_post_entry_create'); + +/** + * This pre_entry_delete function is called before an entry is deleted in ds_ldap_pla::delete(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry deleted + * @see post_entry_delete + */ +function example_pre_entry_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_delete','example_pre_entry_delete'); + +/** + * This post_entry_delete function is called after an entry is deleted in ds_ldap_pla::delete(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry deleted + * @see pre_entry_delete + */ +function example_post_entry_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_delete','example_post_entry_delete'); + +/** + * This pre_entry_rename function is called before an entry is renamed in ds_ldap_pla::rename(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string Old DN of the entry to be renamed + * @param string New RDN for the new entry + * @param string Container for the new entry + * @see post_entry_rename + */ +function example_pre_entry_rename() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • New RDN: %s
  • New Container: %s
',$args[0],$args[1],$args[2],$args[3],$args[4]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_rename','example_pre_entry_rename'); + +/** + * This post_entry_rename function is called after an entry is renamed in ds_ldap_pla::rename(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string Old DN of the entry to be renamed + * @param string New RDN for the new entry + * @param string Container for the new entry + * @see pre_entry_rename + */ +function example_post_entry_rename() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • New RDN: %s
  • New Container: %s
',$args[0],$args[1],$args[2],$args[3],$args[4]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_rename','example_post_entry_rename'); + +/** + * This pre_entry_modify function is called before an entry is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry to be modified + * @param array Attributes to be modified + * @see post_entry_modify + */ +function example_pre_entry_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join('|',array_keys($args[3]))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_modify','example_pre_entry_modify'); + +/** + * This post_entry_modify function is called after an entry is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry to be modified + * @param array Attributes to be modified + * @see pre_entry_modify + */ +function example_post_entry_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join('|',array_keys($args[3]))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_modify','example_post_entry_modify'); + +// pre_attr_add +// post_attr_add +/** + * This pre_attr_add function is called before an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see post_attr_add + */ +function example_pre_attr_add() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_add','example_pre_attr_add'); + +/** + * This post_attr_add function is called after an attribute is added in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be added + * @param string Attribute to be added + * @param array New values + * @see pre_attr_add + */ +function example_post_attr_add() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_add','example_post_attr_add'); + +// pre_attr_modify +// post_attr_modify +/** + * This pre_attr_modify function is called before an attribute is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be modified + * @param string Attribute to be modified + * @param array New values + * @see post_attr_modify + */ +function example_pre_attr_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4]),join('|',$args[5])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_modify','example_pre_attr_modify'); + +/** + * This post_attr_modify function is called after an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see pre_attr_modify + */ +function example_post_attr_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4]),join('|',$args[5])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_modify','example_post_attr_modify'); + +/** + * This pre_attr_delete function is called before an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see post_attr_delete + */ +function example_pre_attr_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_delete','example_pre_attr_delete'); + +/** + * This post_attr_delete function is called after an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see pre_attr_delete + */ +function example_post_attr_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_delete','example_post_attr_delete'); +?> diff --git a/htdocs/add_attr_form.php b/htdocs/add_attr_form.php new file mode 100644 index 0000000..7f72841 --- /dev/null +++ b/htdocs/add_attr_form.php @@ -0,0 +1,185 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +# Render the form +if (get_request('meth','REQUEST') != 'ajax') { + $request['page']->drawTitle(sprintf('%s %s',_('Add new attribute'),get_rdn($request['dn']))); + $request['page']->drawSubTitle(); + + echo '
'; + if (count($request['template']->getAvailAttrs())) { + # If we have more than the configured entries, we'll separate our input to the old ways. + if (count($request['template']->getAvailAttrs()) > $_SESSION[APPCONFIG]->getValue('appearance','max_add_attrs')) { + $attr = array(); + $attr['avail'] = array(); + $attr['binary'] = array(); + + foreach ($request['template']->getAvailAttrs() as $attribute) + if ($app['server']->isAttrBinary($attribute->getName())) + array_push($attr['binary'],$attribute); + else + array_push($attr['avail'],$attribute); + + if (count($attr['avail']) > 0) { + echo '
'; + echo _('Add new attribute'); + echo '
'; + echo '
'; + + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + + echo ''; + + echo ''; + printf('',_('Add')); + echo '
'; + echo '
'; + + } else { + echo '
'; + printf('(%s)',_('no new attributes available for this entry')); + } + + if (count($attr['binary']) > 0) { + echo '
'; + echo _('Add new binary attribute'); + echo '
'; + echo '
'; + + echo ''; + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',$request['dn']); + echo ''; + + echo ''; + + echo ''; + printf('',_('Add')); + + if (! ini_get('file_uploads')) + printf('
%s
', + _('Your PHP configuration has disabled file uploads. Please check php.ini before proceeding.')); + + else + printf('
%s: %s
',_('Maximum file size'),ini_get('upload_max_filesize')); + + echo '
'; + echo '
'; + + } else { + echo '
'; + printf('(%s)',_('no new binary attributes available for this entry')); + } + + } else { + echo '
'; + + $request['page']->drawFormStart(); + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + + echo ''; + + foreach ($request['template']->getAvailAttrs() as $attribute) + $request['page']->draw('Template',$attribute); + + $request['page']->drawFormSubmitButton(); + echo '
'; + + $request['page']->drawFormEnd(); + } + + } else { + printf('(%s)',_('no new attributes available for this entry')); + } + + echo '
'; + +# The ajax addition (it is going into an existing TemplateRendered page +} else { + # Put our DIV there for the callback + echo '
'; + printf('%s',_('Add Attribute')); + echo '
'; + echo ''; + echo ''; + echo '
'; + + printf(''; + + echo '
'; + echo '
'; + echo '
'; +} +?> diff --git a/htdocs/add_oclass_form.php b/htdocs/add_oclass_form.php new file mode 100644 index 0000000..d2353c9 --- /dev/null +++ b/htdocs/add_oclass_form.php @@ -0,0 +1,117 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +$attribute_factory = new AttributeFactory(); + +# Grab the required attributes for the new objectClass +$ldap = array(); +$ldap['attrs']['must'] = array(); + +foreach ($request['template']->getAttribute('objectclass')->getValues() as $oclass_name) { + # Exclude "top" if its there. + if (! strcasecmp('top',$oclass_name)) + continue; + + if ($soc = $app['server']->getSchemaObjectClass($oclass_name)) + $ldap['attrs']['must'] = array_merge($ldap['attrs']['must'],$soc->getMustAttrNames(true)); +} + +$ldap['attrs']['must'] = array_unique($ldap['attrs']['must']); + +/* Build a list of the attributes that this new objectClass requires, + * but that the object does not currently contain */ +$ldap['attrs']['need'] = array(); +foreach ($ldap['attrs']['must'] as $attr) + if (is_null($request['template']->getAttribute($attr))) + array_push($ldap['attrs']['need'],$attribute_factory->newAttribute($attr,array('values'=>array()),$app['server']->getIndex())); + +# Mark all the need attributes as shown +foreach ($ldap['attrs']['need'] as $index => $values) + $ldap['attrs']['need'][$index]->show(); + +if (count($ldap['attrs']['need']) > 0) { + $request['page']->drawTitle(sprintf('%s %s',_('Add new objectClass to'),get_rdn($request['dn']))); + $request['page']->drawSubTitle(); + + echo '
'; + printf('%s: %s %s %s %s', + _('Instructions'), + _('In order to add these objectClass(es) to this entry, you must specify'), + count($ldap['attrs']['need']),_('new attributes'), + _('that this objectClass requires.')); + + echo '

'; + + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + echo '
'; + + echo ''; + printf('',_('New Required Attributes')); + + $counter = 0; + echo ''; + + foreach ($ldap['attrs']['need'] as $count => $attr) + $request['page']->draw('Template',$attr); + + echo '
%s
'; + foreach ($request['template']->getAttribute('objectclass')->getValues() as $value) + $request['page']->draw('HiddenValue',$request['template']->getAttribute('objectclass'),$counter++); + echo '
'; + + printf('

',_('Add ObjectClass and Attributes')); + echo '
'; + echo '
'; + +# There are no other required attributes, so we just need to add the objectclass to the DN. +} else { + $result = $app['server']->modify($request['dn'],$request['template']->getLDAPmodify()); + + if ($result) { + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&modified_attrs[]=objectclass', + $app['server']->getIndex(),rawurlencode($request['dn'])); + + if (get_request('meth','REQUEST') == 'ajax') + $href .= '&meth=ajax'; + + header(sprintf('Location: %s',$href)); + die(); + } +} +?> diff --git a/htdocs/add_value_form.php b/htdocs/add_value_form.php new file mode 100644 index 0000000..c30f348 --- /dev/null +++ b/htdocs/add_value_form.php @@ -0,0 +1,173 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +/* +if ($request['attribute']->isReadOnly()) + error(sprintf(_('The attribute (%s) is in readonly mode.'),$request['attr']),'error','index.php'); +*/ + +# Render the form +if (! strcasecmp($request['attr'],'objectclass') || get_request('meth','REQUEST') != 'ajax') { + # Render the form. + $request['page']->drawTitle(sprintf('%s %s %s %s',_('Add new'),htmlspecialchars($request['attr']),_('value to'),htmlspecialchars(get_rdn($request['dn'])))); + $request['page']->drawSubTitle(); + + if (! strcasecmp($request['attr'],'objectclass')) { + echo '
'; + echo '
'; + echo ''; + + } else { + echo ''; + echo '
'; + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + } + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + echo '
'; + + echo ''; + echo ''; + + $request['attribute'] = $request['template']->getAttribute($request['attr']); + $request['count'] = $request['attribute']->getValueCount(); + + if ($request['count']) { + printf('', + _('Current list of'),$request['count'],_('values for attribute'),$request['attribute']->getFriendlyName()); + + echo ''; + + } else { + printf('', + _('No current value for attribute'),$request['attribute']->getFriendlyName()); + echo ''; + } + + echo ''; + + echo ''; + printf('',_('Enter the value(s) you would like to add:')); + echo ''; + echo ''; + + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) + printf('', + IMGDIR,_('Note: You may be required to enter new attributes that these objectClass(es) require')); + + echo '
%s %s %s %s:'; + + # Display current attribute values + echo '
'; + for ($i=0;$i<$request['count'];$i++) { + if ($i > 0) + echo '
'; + $request['page']->draw('CurrentValue',$request['attribute'],$i); + $request['page']->draw('HiddenValue',$request['attribute'],$i); + } + echo '
'; + + echo '
%s %s.

%s'; + + if (! strcasecmp($request['attr'],'objectclass')) { + # If our attr is an objectClass, fetch all available objectClasses and remove those from the list that are already defined in the entry + $socs = $app['server']->SchemaObjectClasses(); + + foreach ($request['attribute']->getValues() as $oclass) + unset($socs[strtolower($oclass)]); + + # Draw objectClass selection + echo ''; + echo '
'; + echo ''; + echo '
'; + + echo '
'; + printf('', + _('Add new ObjectClass'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'entry_form\'),\'%s\');"',_('Updating Object')) : '')); + echo '
'; + echo '

Hint%s
'; + echo ''; + + } else { + # Draw a blank field + echo '
'; + $request['page']->draw('FormValue',$request['attribute'],$request['count']); + echo '
'; + + $sattr = $app['server']->getSchemaAttribute($request['attr']); + + if ($sattr->getDescription()) + printf('%s: %s
',_('Description'),$sattr->getDescription()); + + if ($sattr->getType()) + printf('%s: %s
',_('Syntax'),$sattr->getType()); + + if ($sattr->getMaxLength()) + printf('%s: %s %s
', + _('Maximum Length'),number_format($sattr->getMaxLength()),_('characters')); + + echo '
'; + printf('',_('Add New Value')); + echo '
'; + + echo ''; + echo ''; + echo ''; + } + +} else { + if (is_null($attribute = $request['template']->getAttribute($request['attr']))) { + $request['template']->addAttribute($request['attr'],array('values'=>array())); + $attribute = $request['template']->getAttribute($request['attr']); + $attribute->show(); + + echo ''; + $request['page']->draw('Template',$attribute); + $request['page']->draw('Javascript',$attribute); + echo '
'; + + } else { + $request['count'] = $attribute->getValueCount(); + $request['page']->draw('FormReadWriteValue',$attribute,$request['count']); + } +} +?> diff --git a/htdocs/cmd.php b/htdocs/cmd.php new file mode 100644 index 0000000..0ddf004 --- /dev/null +++ b/htdocs/cmd.php @@ -0,0 +1,79 @@ +getIndex()); + +# See if we can render the command +if (trim($www['cmd'])) { + # If this is a READ-WRITE operation, the LDAP server must not be in READ-ONLY mode. + if ($app['server']->isReadOnly() && ! in_array(get_request('cmd','REQUEST'),$app['readwrite_cmds'])) + error(_('You cannot perform updates while server is in read-only mode'),'error','index.php'); + + # If this command has been disabled by the config. + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script',$www['cmd'])) { + system_message(array('title'=>_('Command disabled by the server configuration'), + _('Error'),'body'=>sprintf('%s: %s.',_('The command could not be run'),htmlspecialchars($www['cmd'])),'type'=>'error'),'index.php'); + + $app['script_cmd'] = null; + } +} + +if ($app['script_cmd']) + include $app['script_cmd']; + +# Refresh a frame - this is so that one frame can trigger another frame to be refreshed. +if (isAjaxEnabled() && get_request('refresh','REQUEST') && get_request('refresh','REQUEST') != get_request('frame','REQUEST')) { + echo ''; +} + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +if ($www['meth'] == 'ajax') + $www['page']->show(get_request('frame','REQUEST',false,'BODY'),true,get_request('raw','REQUEST',false,false)); +else + $www['page']->display(); +?> diff --git a/htdocs/collapse.php b/htdocs/collapse.php new file mode 100644 index 0000000..8fb2731 --- /dev/null +++ b/htdocs/collapse.php @@ -0,0 +1,27 @@ +getIndex(),'tree'); +$entry = $tree->getEntry($dn); +$entry->close(); +set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s', + $app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param())); +die(); +?> diff --git a/htdocs/common.php b/htdocs/common.php new file mode 100644 index 0000000..de4122c --- /dev/null +++ b/htdocs/common.php @@ -0,0 +1,14 @@ + diff --git a/htdocs/compare.php b/htdocs/compare.php new file mode 100644 index 0000000..47a80db --- /dev/null +++ b/htdocs/compare.php @@ -0,0 +1,188 @@ +getServer(get_request('server_id_src')); +$ldap['DST'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id_dst')); + +if (! $ldap['SRC']->dnExists($request['dnSRC'])) + error(sprintf('%s (%s)',_('No such entry.'),pretty_print_dn($request['dnSRC'])),'error','index.php'); + +if (! $ldap['DST']->dnExists($request['dnDST'])) + error(sprintf('%s (%s)',_('No such entry.'),pretty_print_dn($request['dnDST'])),'error','index.php'); + +$request['pageSRC'] = new PageRender($ldap['SRC']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['pageSRC']->setDN($request['dnSRC']); +$request['pageSRC']->accept(); +$request['templateSRC'] = $request['pageSRC']->getTemplate(); + +$request['pageDST'] = new PageRender($ldap['DST']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['pageDST']->setDN($request['dnDST']); +$request['pageDST']->accept(); +$request['templateDST'] = $request['pageDST']->getTemplate(); + +# Get a list of all attributes. +$attrs_all = array_unique(array_merge($request['templateSRC']->getAttributeNames(),$request['templateDST']->getAttributeNames())); + +$request['pageSRC']->drawTitle(_('Comparing the following DNs')); + +echo '
'; + +echo ''; +echo ''; + +$href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $ldap['SRC']->getIndex(),rawurlencode($request['dnSRC'])); +printf('', + _('Server'),$ldap['SRC']->getName(),_('Distinguished Name'), + htmlspecialchars($href),$request['dnSRC']); + +$href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $ldap['DST']->getIndex(),rawurlencode($request['dnDST'])); +printf('', + _('Server'),$ldap['DST']->getName(),_('Distinguished Name'), + htmlspecialchars($href),$request['dnDST']); + +echo ''; + +echo ''; +echo ''; +echo ''; + +if (! is_array($attrs_all) || ! count($attrs_all)) { + printf('',_('This entry has no attributes')); + print '
%s: %s
%s: %s
%s: %s
%s: %s
'; +echo '
'; +echo '
'; +printf('',$app['server']->getIndex()); +printf('',$ldap['DST']->getIndex()); +printf('',$ldap['SRC']->getIndex()); +printf('',htmlspecialchars($request['dnDST'])); +printf('',htmlspecialchars($request['dnSRC'])); +printf('',_('Switch Entry')); +echo '
'; +echo '
'; +echo '
(%s)
'; + + return; +} + +sort($attrs_all); + +# Work through each of the attributes. +foreach ($attrs_all as $attr) { + # Has the config.php specified that this attribute is to be hidden or shown? + if ($ldap['SRC']->isAttrHidden($attr) || $ldap['DST']->isAttrHidden($attr)) + continue; + + $attributeSRC = $request['templateSRC']->getAttribute($attr); + $attributeDST = $request['templateDST']->getAttribute($attr); + + # Get the values and see if they are the same. + if ($attributeSRC && $attributeDST && ($attributeSRC->getValues() == $attributeDST->getValues())) + echo ''; + else + echo ''; + + foreach (array('src','dst') as $side) { + # If we are on the source side, show the attribute name. + switch ($side) { + case 'src': + if ($attributeSRC) { + echo ''; + $request['pageSRC']->draw('Name',$attributeSRC); + echo ''; + + if ($request['pageSRC']->getServerID() == $request['pageDST']->getServerID()) + echo ' '; + + else { + echo ''; + $request['pageSRC']->draw('Notes',$attributeSRC); + echo ''; + } + + } else { + echo ' '; + } + + break; + + case 'dst': + if ($attributeDST) { + if ($attributeSRC && ($request['pageSRC']->getServerID() == $request['pageDST']->getServerID())) + echo ' '; + + else { + echo ''; + $request['pageDST']->draw('Name',$attributeDST); + echo ''; + } + + echo ''; + $request['pageDST']->draw('Notes',$attributeDST); + echo ''; + + } else { + echo ' '; + } + + break; + } + } + + echo ''; + echo "\n\n"; + + # Get the values and see if they are the same. + if ($attributeSRC && $attributeDST && ($attributeSRC->getValues() == $attributeDST->getValues())) + echo ''; + else + echo ''; + + foreach (array('src','dst') as $side) { + echo ''; + echo ''; + echo '
'; + + switch ($side) { + case 'src': + + if ($attributeSRC && count($attributeSRC->getValues())) + $request['pageSRC']->draw('CurrentValues',$attributeSRC); + else + echo ' '; + + break; + + case 'dst': + if ($attributeDST && count($attributeDST->getValues())) + $request['pageDST']->draw('CurrentValues',$attributeDST); + else + echo ' '; + + break; + } + + echo '
'; + } + + echo ''; +} +echo ''; +?> diff --git a/htdocs/compare_form.php b/htdocs/compare_form.php new file mode 100644 index 0000000..56962bd --- /dev/null +++ b/htdocs/compare_form.php @@ -0,0 +1,65 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Compare another DN with'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('',JSDIR); +echo '
'; +printf('%s %s %s
',_('Compare'),get_rdn($request['dn']),_('with ')); +echo '
'; + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',$app['server']->getIndex()); +printf('',htmlspecialchars($request['dn'])); +echo '
'; +echo "\n"; + +echo ''; + +echo ''; +printf('', + _('Compare this DN with another'),_('Destination DN')); +echo ''; +echo ''; +echo "\n"; + +printf('',_('Destination Server'),server_select_list($app['server']->getIndex(),true,'server_id_dst')); +echo "\n"; + +printf('',_('Compare')); +echo "\n"; + +echo '
%s:'; +echo ''; +draw_chooser_link('compare_form','dn_dst','true',''); +echo '
%s:%s
'; +echo '
'; +?> diff --git a/htdocs/copy.php b/htdocs/copy.php new file mode 100644 index 0000000..34d1512 --- /dev/null +++ b/htdocs/copy.php @@ -0,0 +1,209 @@ +getServer(get_request('server_id_src')); +$ldap['DST'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id_dst')); + +# Error checking +if (! trim($request['dnDST'])) + error(_('You left the destination DN blank.'),'error','index.php'); + +if ($ldap['DST']->isReadOnly()) + error(_('Destination server is currently READ-ONLY.'),'error','index.php'); + +if ($ldap['DST']->dnExists($request['dnDST'])) + error(sprintf(_('The destination entry (%s) already exists.'),pretty_print_dn($request['dnDST'])),'error','index.php'); + +if (! $ldap['DST']->dnExists($ldap['DST']->getContainer($request['dnDST']))) + error(sprintf(_('The destination container (%s) does not exist.'), + pretty_print_dn($ldap['DST']->getContainer($request['dnDST']))),'error','index.php'); + +if (pla_compare_dns($request['dnSRC'],$request['dnDST']) == 0 && $ldap['SRC']->getIndex() == $ldap['DST']->getIndex()) + error(_('The source and destination DN are the same.'),'error','index.php'); + +$request['recursive'] = (get_request('recursive') == 'on') ? true : false; +$request['remove'] = (get_request('remove') == 'yes') ? true : false; + +if ($request['recursive']) { + $filter = get_request('filter','POST',false,'(objectClass=*)'); + + # Build a tree similar to that of the tree browser to give to r_copy_dn + $ldap['tree'] = array(); + printf('

%s%s

',_('Copying '),$request['dnSRC']); + printf('

%s

',_('Recursive copy progress')); + print '

'; + + print ''; + printf ('%s...',_('Building snapshot of tree to copy')); + + $ldap['tree'] = build_tree($ldap['SRC'],$request['dnSRC'],array(),$filter); + printf('%s
',_('Success')); + + # Prevent script from bailing early on a long delete + @set_time_limit(0); + + $copy_result = r_copy_dn($ldap['SRC'],$ldap['DST'],$ldap['tree'],$request['dnSRC'],$request['dnDST'],$request['remove']); + $copy_message = $copy_result; + print '
'; + +} else { + if ($_SESSION[APPCONFIG]->getValue('confirm','copy')) { + $request['pageSRC'] = new TemplateRender($ldap['SRC']->getIndex(),get_request('template','REQUEST',false,null)); + $request['pageSRC']->setDN($request['dnSRC']); + $request['pageSRC']->accept(true); + + $request['pageDST'] = new TemplateRender($ldap['DST']->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageDST']->setContainer($app['server']->getContainer($request['dnDST'])); + $request['pageDST']->accept(true); + + $request['templateSRC'] = $request['pageSRC']->getTemplate(); + $request['templateDST'] = $request['pageDST']->getTemplate(); + + $request['templateDST']->copy($request['templateSRC'],get_rdn($request['dnDST']),true); + + # Set all attributes with a values as shown, and remove the add value options + foreach ($request['templateDST']->getAttributes(true) as $sattribute) + if ($sattribute->getValues() && ! $sattribute->isInternal()) { + $sattribute->show(); + $sattribute->setMaxValueCount(count($sattribute->getValues())); + } + + $request['pageDST']->accept(); + + return; + + } else { + $copy_result = copy_dn($ldap['SRC'],$ldap['DST'],$request['dnSRC'],$request['dnDST'],$request['remove']); + + if ($copy_result) + $copy_message = sprintf('%s %s: %s %s', + $request['remove'] ? _('Move successful') : _('Copy successful'), + _('DN'),$request['dnDST'],_('has been created.')); + else + $copy_message = sprintf('%s %s: %s %s', + $request['remove'] ? _('Move NOT successful') : _('Copy NOT successful'), + _('DN'),$request['dnDST'],_('has NOT been created.')); + } +} + +if ($copy_result) { + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&refresh=SID_%s_nodes&noheader=1', + $ldap['DST']->getIndex(),rawurlencode($request['dnDST']),$ldap['DST']->getIndex()); + + system_message(array( + 'title'=>_('Copy Entry'), + 'body'=>$copy_message, + 'type'=>'info'), + $redirect_url); +} + +function r_copy_dn($serverSRC,$serverDST,$snapshottree,$dnSRC,$dnDST,$remove) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $copy_message = array(); + + $children = isset($snapshottree[$dnSRC]) ? $snapshottree[$dnSRC] : null; + + # If we have children, then we need to copy, then delete for a move + if (is_array($children) && count($children)) { + + $copy_result = copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,false); + + if (! $copy_result) + return false; + + array_push($copy_message,sprintf('%s %s: %s %s',_('Copy successful'),_('DN'),$dnDST,_('has been created.'))); + + $hadError = false; + foreach ($children as $child_dn) { + $dnDST_new = sprintf('%s,%s',get_rdn($child_dn),$dnDST); + $copy_result = r_copy_dn($serverSRC,$serverDST,$snapshottree,$child_dn,$dnDST_new,$remove); + $copy_message = array_merge($copy_message,array_values($copy_result)); + + if (! $copy_result) + $hadError = true; + } + + if (! $hadError && $remove) { + $delete_result = $serverSRC->delete($dnSRC); + + if ($delete_result) + array_push($copy_message,sprintf('%s %s: %s %s',_('Delete successful'),_('DN'),$dnDST,_('has been deleted.'))); + } + + } else { + $copy_result = copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,$remove); + + if ($copy_result) + array_push($copy_message,sprintf('%s %s: %s %s', + $remove ? _('Move successful') : _('Copy successful'), + _('DN'),$dnDST,_('has been created.'))); + else + array_push($copy_message,sprintf('%s %s: %s %s', + $remove ? _('Move NOT successful') : _('Copy NOT successful'), + _('DN'),$dnDST,_('has NOT been created.'))); + } + + return $copy_message; +} + +function copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,$remove) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $request = array(); + $request['pageSRC'] = new PageRender($serverSRC->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageSRC']->setDN($dnSRC); + $request['pageSRC']->accept(); + + $request['pageDST'] = new PageRender($serverDST->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageDST']->setContainer($serverDST->getContainer($dnDST)); + $request['pageDST']->accept(); + + $request['templateSRC'] = $request['pageSRC']->getTemplate(); + $request['templateDST'] = $request['pageDST']->getTemplate(); + $request['templateDST']->copy($request['pageSRC']->getTemplate(),get_rdn($dnDST,0)); + + # Create of move the entry + if ($remove) + return $serverDST->rename($request['templateSRC']->getDN(),$request['templateDST']->getRDN(),$serverDST->getContainer($dnDST),true); + else + return $serverDST->add($request['templateDST']->getDN(),$request['templateDST']->getLDAPadd()); +} + +function build_tree($server,$dn,$buildtree) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # We search all children, not only the visible children in the tree + $children = $server->getContainerContents($dn,null,0); + + if (count($children)) { + $buildtree[$dn] = $children; + foreach ($children as $child_dn) + $buildtree = build_tree($server,$child_dn,$buildtree); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$buildtree); + + return $buildtree; +} +?> diff --git a/htdocs/copy_form.php b/htdocs/copy_form.php new file mode 100644 index 0000000..749b78e --- /dev/null +++ b/htdocs/copy_form.php @@ -0,0 +1,103 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Copy'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('',JSDIR); +echo '
'; +printf('%s %s %s:

',_('Copy'),get_rdn($request['dn']),_('to a new object')); +echo '
'; + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',$app['server']->getIndex()); +printf('',htmlspecialchars($request['dn'])); +echo '
'; +echo "\n"; + +echo ''; + +echo ''; +printf('', + _('The full DN of the new entry to be created when copying the source entry'),_('Destination DN')); +echo ''; +echo ''; +echo "\n"; + +printf('',_('Destination Server'),server_select_list($app['server']->getIndex(),true,'server_id_dst')); +echo "\n"; + +# We search all children, not only the visible children in the tree +$request['children'] = $app['server']->getContainerContents($request['dn']); + +if (count($request['children']) > 0) { + echo ''; + printf('',_('Recursive copy')); + echo '',_('Recursively copy all children of this object as well.')); + echo ''; + echo "\n"; + + echo ''; + printf('', + _('When performing a recursive copy, only copy those entries which match this filter'),_('Filter')); + echo ''; + echo "\n"; + + echo ''; + printf('',_('Delete after copy (move):')); + echo ''; + echo "\n"; + +} else { + printf('',_('Delete after copy (move):')); +} +echo "\n"; + +printf('',_('Copy ')); +echo "\n"; + +echo '
%s:'; +printf('',htmlspecialchars($request['dn'])); +draw_chooser_link('copy_form','dn_dst','true',get_rdn($request['dn'])); +echo '
%s:%s
:'; + printf('(%s)
%s:'; + echo '
%s'; + printf('(%s)',_('Make sure your filter (above) will select all child records.')); + echo '
%s
'; +echo '
'; + +if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) + printf('
Light%s
', + IMGDIR,_('Hint: Copying between different servers only works if there are no schema violations')); + + +# Draw the javascrpt to enable/disable the filter field if this may be a recursive copy +if (count($request['children']) > 0) + printf('',JSDIR); +?> diff --git a/htdocs/create.php b/htdocs/create.php new file mode 100644 index 0000000..0ed5a3c --- /dev/null +++ b/htdocs/create.php @@ -0,0 +1,104 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setContainer(get_request('container','REQUEST',true)); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +if ((! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) && ! get_request('create_base')) + error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); + +# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... +$tree = get_cached_item($app['server']->getIndex(),'tree'); + +$request['container'] = $tree->getEntry($request['template']->getContainer()); +if (! $request['container'] && ! get_request('create_base')) { + $tree->addEntry($request['template']->getContainer()); + $request['container'] = $tree->getEntry($request['template']->getContainer()); +} + +# Check our RDN +if (! count($request['template']->getRDNAttrs())) + error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); +if (! $request['template']->getRDN()) + error(_('The RDN field is empty?'),'error','index.php'); + +# Some other attribute checking... +foreach ($request['template']->getAttributes() as $attribute) { + # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. + # @todo this isIgnoredAttr() function is missing? + if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName())) + error(sprintf(_('You left the value blank for required attribute (%s).'), + $attribute->getName(false)),'error','index.php'); +} + +# Create the entry +$add_result = $app['server']->add($request['template']->getDN(),$request['template']->getLDAPadd()); + +if ($add_result) { + $action_number = $_SESSION[APPCONFIG]->getValue('appearance','action_after_creation'); + $href = sprintf('cmd=template_engine&server_id=%s',$app['server']->getIndex()); + + if ($request['redirect']) + $redirect_url = $request['redirect']; + + else if ($action_number == 2) + $redirect_url = sprintf('cmd.php?%s&template=%s&container=%s', + $href,'default',$request['template']->getContainerEncode()); + + else + $redirect_url = sprintf('cmd.php?%s&template=%s&dn=%s', + $href,'default',$request['template']->getDNEncode()); + + if ($action_number == 1 || $action_number == 2) + printf('',$redirect_url); + + if ($action_number == 1 || $action_number == 2) { + $create_message = sprintf('%s %s: %s %s', + _('Creation successful!'),_('DN'),$request['template']->getDN(),_('has been created.')); + + if (isAjaxEnabled()) + $redirect_url .= sprintf('&refresh=SID_%s_nodes&noheader=1',$app['server']->getIndex()); + + system_message(array( + 'title'=>_('Create Entry'), + 'body'=>$create_message, + 'type'=>'info'), + $redirect_url); + + } else { + $request['page']->drawTitle(_('Entry created')); + $request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', + _('Server'),$app['server']->getName(),_('Distinguished Name'),$request['template']->getDN())); + + echo '
'; + echo '
'; + printf('%s.', + htmlspecialchars($href),rawurlencode($request['template']->getDN()),_('Display the new created entry')); + echo '
'; + printf('%s.', + htmlspecialchars($href),rawurlencode($request['template']->getContainer()),_('Create another entry')); + echo '
'; + } +} +?> diff --git a/htdocs/create_confirm.php b/htdocs/create_confirm.php new file mode 100644 index 0000000..6727fb1 --- /dev/null +++ b/htdocs/create_confirm.php @@ -0,0 +1,143 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setContainer(get_request('container','REQUEST',true)); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +if (! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) + error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); + +# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... +$tree = get_cached_item($app['server']->getIndex(),'tree'); + +$request['container'] = $tree->getEntry($request['template']->getContainer()); +if (! $request['container']) { + $tree->addEntry($request['template']->getContainer()); + $request['container'] = $tree->getEntry($request['template']->getContainer()); +} + +# Check our RDN +if (! count($request['template']->getRDNAttrs())) + error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); +if (! $request['template']->getRDN()) + error(_('The RDN field is empty?'),'error','index.php'); + +# Some other attribute checking... +foreach ($request['template']->getAttributes() as $attribute) { + # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. + # @todo this isIgnoredAttr() function is missing? + if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName())) + error(sprintf(_('You left the value blank for required attribute (%s).'), + $attribute->getName(false)),'error','index.php'); +} + +# Check for unique attributes +$app['server']->checkUniqueAttrs($request['template']->getDN(),$request['template']->getLDAPadd()); + +$request['page']->drawTitle(_('Create LDAP Entry')); +$request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', + _('Server'),$app['server']->getName(),_('Container'),$request['template']->getContainer())); + +# Confirm the creation +if (count($request['template']->getLDAPadd(true))) { + echo '
'; + echo _('Do you want to create this entry?'); + echo '

'; + echo '
'; + + echo "\n\n"; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getContainerEncode(false)); + printf('',$request['template']->getID()); + foreach ($request['template']->getRDNAttrs() as $rdn) + printf('',htmlspecialchars($rdn)); + echo "\n"; + + $request['page']->drawHiddenAttributes(); + echo '
'; + + echo ''; + echo "\n"; + + printf('', + _('Attribute'),_('New Value'),_('Skip')); + echo "\n\n"; + + $counter = 0; + printf('',$counter%2 ? 'even' : 'odd',htmlspecialchars($request['template']->getDN())); + + foreach ($request['template']->getLDAPadd(true) as $attribute) { + $counter++; + + printf('',$counter%2 ? 'even' : 'odd'); + printf('',$attribute->getFriendlyName()); + + # Show NEW Values + echo ''; + + # Show SKIP Option + $input_disabled = ''; + $input_onclick = ''; + + if ($attribute->isRequired()) + $input_disabled = 'disabled="disabled"'; + + printf('', + htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick); + echo ''; + echo "\n\n"; + } + + echo '
%s%s%s
%s
%s'; + $request['page']->draw('CurrentValues',$attribute); + echo '
'; + + echo '
'; + echo '
'; + + printf('', + _('Commit'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'create_form\'),\'%s\');"',_('Updating Object')) : '')); + + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&container=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getContainer(),_('Retrieving DN')) : '')); + + echo '
'; + echo '
'; + echo '
'; + +} else { + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + echo '
'; + echo _('You made no changes'); + + if (isAjaxEnabled()) + printf(' %s.', + htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back')); + else + printf(' %s.',htmlspecialchars($href),_('Go back')); + + echo '
'; +} +?> diff --git a/htdocs/css/default/style.css b/htdocs/css/default/style.css new file mode 100644 index 0000000..7b2a369 --- /dev/null +++ b/htdocs/css/default/style.css @@ -0,0 +1,925 @@ +/* $Header$ */ + +/* Global Page */ +table.page { + font-weight: normal; + color: #000000; + + font-family: "bitstream vera sans","luxi sans",verdana,geneva,arial,helvetica,sans-serif; + background-color: #FFFFFF; + font-size: 13px; + empty-cells: hide; +} + +/* Global Page - Defaults */ +/* A HREF Links */ +table.page a { + color: #0000AA; + text-decoration: none; +} + +table.page a:hover { + text-decoration: none; +} + +table.page a img { + border: 0px; +} + +/* Global Page - Logo & Title */ +table.page tr.head { + text-align: center; + color: #FFFFFF; + background-color: #001188; + font-weight: bold; + font-size: 11px; + height: 25px; +} + +table.page tr.head img.logo { + vertical-align: middle; + text-align: center; + + width: 100px; + height: 60px; +} + +table.page tr.pagehead { +} + +table.page tr.pagehead td.imagetop { + width: 100%; + vertical-align: bottom; + text-align: right; +} + +/* Global Page - Control Line */ +table.page tr.control td { + border-top: 1px solid #AAAACC; + border-bottom: 1px solid #AAAACC; +} + +/* Global Page - Control Line Menu Items */ +table.page table.control { + table-layout: fixed; + width: 100%; +} + +table.page table.control td { + border-top: 0px; + border-bottom: 0px; + padding: 0px; + padding-top: 2px; + padding-bottom: 2px; + text-align: left; + vertical-align: top; + font-size: 11px; + font-weight: bold; +} + +table.page table.control img { + width: 24px; + height: 24px; +} + +table.page table.control a { + color: #000000; +} + +table.page table.control a:hover { + text-decoration: none; + background-color: #FFFFFF; + color: #0000AA; +} + +table.page table.control td.spacer { + width: 20%; +} + +table.page table.control td.logo { + text-align: right; + width: 10%; +} + +table.page table.control td.logo img.logo { + vertical-align: middle; + text-align: right; + + width: 100px; + height: 50px; +} + +/* Global Page - LDAP Tree */ +table.page td.tree { + border-right: 1px solid #AAAACC; + vertical-align: top; + background-color: #FCFCFE; + width: 10%; +} + +/* Global Page - Main Body */ +table.page td.body { + vertical-align: top; + width: 100%; + background-color: #FCFCFE; +} + +/* Global Page - Main Body System Message */ +table.page table.sysmsg { + border-bottom: 2px solid #AAAACC; + width: 100%; +} + +table.page table.sysmsg td.head { + font-size: small; + text-align: left; + font-weight: bold; +} + +table.page table.sysmsg td.body { + font-weight: normal; +} + +table.page table.sysmsg td.icon { + text-align: center; + vertical-align: top; +} + +/* Global Page - Main Body */ +table.page table.body { + font-weight: normal; + background-color: #FCFCFE; + width: 100%; +} + +table.page table.body h3.title { + text-align: center; + margin: 0px; + padding: 10px; + color: #FFFFFF; + background-color: #000088; + border: 1px solid #000000; + font-weight: normal; + font-size: 150%; +} + +table.page table.body h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + font-size: 75%; + color: #FFFFFF; + border-bottom: 1px solid #000000; + border-left: 1px solid #000000; + border-right: 1px solid #000000; + background: #000088; + padding: 4px; + font-weight: normal; +} + +table.page table.body td.spacer { + border-top: 2px solid #AAAACC; + padding: 0px; + font-size: 5px; +} + +table.page table.body td.head { + font-weight: bold; +} + +table.page table.body td.foot { + font-size: small; + border-top: 1px solid #AAAACC; + border-bottom: 1px solid #AAAACC; +} + +/* Global Page Footer */ +table.page tr.foot td { + border-top: 1px solid #AAAACC; + font-weight: bold; + font-size: 12px; + text-align: right; +} + +/* Global Page - Other Layouts */ +/* Server Select */ +table.page table.server_select { + font-weight: bold; + font-size: 13px; + color: #000000; +} + +/* Individual table layouts */ +/* LDAP Tree */ +table.tree { +} + +table.tree tr.server td.icon { + vertical-align: top; +} + +table.tree tr.server td.name { + padding-right: 10px; + vertical-align: top; +} + +table.tree tr.server td { + padding-top: 5px; + font-size: 18px; + text-align: left; + padding-right: 0px; + white-space: nowrap; +} + +table.tree td { + white-space: nowrap; +} + +table.tree td.server_links { + vertical-align: top; + text-align: center; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 3px; + padding-right: 3px; +} + +table.tree td.server_links img { + height: 22px; + width: 22px; +} + +table.tree td.server_links a { + color: #000000; + text-decoration: none; + font-size: 11px; +} + +table.tree td.server_links a:hover { + text-decoration: none; + background-color: #FFFFFF; + color: #000000; +} + +table.tree tr.option td.expander { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree tr.option td.icon { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree td.rdn a { + font-size: 13px; + color: #000000; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +table.tree td.rdn span.count { + font-size: 13px; + color: #000000; +} + +table.tree td.links a { + color: #0000AA; + text-align: center; +} + +table.tree td.link a { + font-size: 13px; + color: #000000; +} + +table.tree td.link a:hover { + font-size: 13px; + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +table.tree td.links a:hover { + text-decoration: none; + color: blue; +} + +table.tree td.links a img { + width: 22px; + height: 22px; +} + +table.tree td.blank { + font-size: 1px; +} + +table.tree td.spacer { + width: 22px; +} + +table.tree td.logged_in { + font-size: 10px; + white-space: nowrap; +} + +table.tree td.logged_in a { + font-size: 11px; +} + +table.tree td.logged_in a:hover { + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +/* Tree Global Defaults */ +table.tree tr td { + padding: 0px; +} + +table.tree a { + text-decoration: none; + color: #000000; +} + +table.tree a:hover { + text-decoration: underline; + color: blue; +} + +table.tree span.dnicon img { + width: 16px; + padding-bottom: 0px; +} + +/* Tree */ +table.tree .treemenudiv { + display: block; + white-space: nowrap; + padding-top: 1px; + padding-bottom: 1px; +} + +table.tree .phplmnormal { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplmnormal:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +table.tree a.phplmselected:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplmselected:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +/* Standard Form */ +table.forminput { + background-color: #F9F9FA; + padding: 10px; + border: 1px solid #AAAACC; +} + +table.forminput td.title { + text-align: center; + font-weight: bold; +} + +table.forminput td.subtitle { + text-align: center; + font-weight: normal; + font-size: small; +} + +table.forminput tr td.heading { + font-weight: bold; +} + +table.forminput td.small { + font-size: 80%; +} + +table.forminput td.top { + vertical-align: top; +} + +table.forminput input.val { + width: 350px; + border: 1px solid #AAAACC; +} + +table.forminput input.roval { + width: 350px; + border: none; +} + +table.forminput td.icon { + width: 16px; + text-align: center; +} + +table.forminput td.icon img { + border: 0px; +} + +table.forminput td.label { + text-align: left; + font-size: 13px; +} + +/* Menu on top of entry form */ +table.menu { + font-size: 14px; +} + +table.menu td.icon { + width: 16px; + text-align: center; +} + +/* Edit DN */ +div.add_value { + font-size: 12px; + margin: 0px; + padding: 0px; +} + +/* Edit Entry */ +table.entry { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; +} + +table.entry input { + margin: 1px; +} + +table.entry input.value { + color: #000000; + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry div.helper { + text-align: left; + white-space: nowrap; + background-color: #FFFFFF; + color: #888; + font-size: 14px; + font-weight: normal; +} + +table.entry input.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; + border: none; +} + +table.entry textarea.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; +} + +table.entry textarea.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; + border: none; +} + +table.entry tr td { + padding: 4px; + padding-right: 0px; +} + +table.entry tr td.heading { + border-top: 3px solid #C0C0C0; + font-weight: bold; +} + +table.entry tr td.note { + text-align: right; + background-color: #E0E0E0; +} + +table.entry tr td.title { + background-color: #E0E0E0; + vertical-align: top; + font-weight: bold; +} + +table.entry tr td.title a { + text-decoration: none; + color: #000000; +} + +table.entry tr td.title a:hover { + text-decoration: underline; + color: #016; +} + +table.entry tr td.value { + text-align: left; + vertical-align: middle; + padding-bottom: 10px; + padding-left: 50px; +} + +/** When an attr is updated, it is highlighted to indicate such */ +table.entry tr.updated td.title { + border-top: 1px dashed #AAAA88; + border-left: 1px dashed #AAAA88; + background-color: #999988; +} + +table.entry tr.updated td.note { + border-top: 1px dashed #AAAA88; + border-right: 1px dashed #AAAA88; + background-color: #999988; +} + +/** An extra row that sits at the bottom of recently modified attrs to encase them in dashes */ +table.entry tr.updated td.bottom { + border-top: 1px dashed #AAAA88; +} + +/** Formatting for the value cell when it is the attribute that has been recently modified */ +table.entry tr.updated td.value { + border-left: 1px dashed #AAAA88; + border-right: 1px dashed #AAAA88; +} + +/* Need to prevent sub-tables (like the one in which jpegPhotos are displayed) + * from drawing borders as well. */ +table.entry tr.updated td table td { + border: 0px; +} + +table.entry tr.noinput { + background: #E0E0E0; +} + +span.hint { + font-size: small; + font-weight: normal; + color: #888; +} + +/* Login Box */ +#login { + background: url('../../images/default/ldap-uid.png') no-repeat 0 1px; + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} + +#login:focus { + background-color: #F0F0FF; + color: #000000; +} + +#login:disabled { + background-color: #DDDDFF; + color: #000000; +} + +#password { + background: url('../../images/default/key.png') no-repeat 0 1px; + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} + +#password:focus { + background-color: #F0F0FF; + color: #000000; +} + +#password:disabled { + background-color: #DDDDFF; + color: #000000; +} + +#generic { + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} +#generic:focus { + background-color: #F0F0FF; + color: #000000; +} + +#generic:disabled { + background-color: #DDDDFF; + color: #000000; +} + +/* After input results */ +div.execution_time { + font-size: 75%; + font-weight: normal; + text-align: left; +} + +table.result { + width: 100%; + vertical-align: top; + empty-cells: show; + border: 1px solid #AAAACC; + border-spacing: 0px; + background-color: #F2F2FF; +} + +table.result tr.heading { + vertical-align: top; +} + +table.result tr.list_title { + background-color: #FFFFFF; +} + +table.result tr.list_title td.icon { + text-align: center; + vertical-align: top; +} + +table.result tr.list_item { + background-color: #FFFFFF; +} + +table.result tr.list_item td.blank { + width: 25px; +} + +table.result tr.list_item td.heading { + vertical-align: top; + color: gray; + width: 10%; + font-size: 12px; +} + +table.result tr.list_item td.value { + color: #000000; + font-size: 12px; +} + +table.result_box { + border: 1px solid #AAAACC; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table { + border: 1px solid #AAAACC; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table td { + font-size: 12px; + vertical-align: top; + border: 1px solid #AAAACC; + padding: 4px; +} + +table.result_table th { + border: 1px solid #AAAACC; + padding: 10px; + padding-left: 20px; + padding-right: 20px; +} + +table.result_table tr.highlight { + background-color: #EEEBBB; +} + +table.result_table tr.highlight td { + border: 1px solid #AAAACC; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table td.heading { + color: #FFFFFF; + background-color: #000088; + font-size: 12px; +} + +table.result_table td.value { + color: #000000; + background-color: #E0E0E0; +} + +table.result_table tr.heading { + color: #FFFFFF; + background-color: #000088; + font-size: 12px; + font-weight: bold; +} + +table.result_table tr.heading a { + color: #FFFFFF; + font-size: 12px; + font-weight: bold; +} + +table.result_table tr.heading td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even { + background-color: #E0E0E0; +} + +table.result_table tr.even td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even td.title { + font-weight: bold; +} + +table.result_table tr.odd { + background-color: #F0F0F0; +} + +table.result_table tr.odd td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.odd td.title { + font-weight: bold; +} + +table.result_table ul.list { + margin: 5px; + margin-left: 0px; + padding-left: 20px; +} + +table.result_table ul.list li { + margin-left: 0px; + padding-left: 0px; +} + +table.result_table ul.list li small { + font-size: 75%; + color: #707070; +} + +table.result_table ul.list li small a { + color: #7070C0; +} + +/* Error Dialog Box */ +table.error { + width: 500px; + border: 1px solid #AA0000; + background-color: #FFF0F0; +} + +table.error th { + background-color: #AA0000; + border: 0px; + color: #FFFFFF; + font-size: 14px; + font-weight: bold; + text-align: center; + vertical-align: middle; + width: 100%; +} + +table.error th.img { + vertical-align: middle; + text-align: center; +} + +table.error td { + border: 0px; + background-color: #FFF0F0; + padding: 2px; + text-align: left; + vertical-align: top; +} + +/* Popup Window */ +div.popup h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + color: #FFFFFF; + border-bottom: 1px solid #000000; + border-left: 1px solid #000000; + border-right: 1px solid #000000; + background: #000088; + padding: 4px; + font-weight: normal; +} + +span.good { + color: green; +} + +span.bad { + color: red; +} diff --git a/htdocs/css/tango/style.css b/htdocs/css/tango/style.css new file mode 100644 index 0000000..fb84aa4 --- /dev/null +++ b/htdocs/css/tango/style.css @@ -0,0 +1,952 @@ +/* $Header$ */ + +/* Global Page */ +table.page { + font-weight: normal; + color: #2E3436; + + font-family: "bitstream vera sans","luxi sans",verdana,geneva,arial,helvetica,sans-serif; + background-color: #FFFFFF; + font-size: 13px; + empty-cells: hide; +} + +/* Global Page - Defaults */ +/* A HREF Links */ +table.page a { + color: #204A87; + text-decoration: none; +} + +table.page a:hover { + text-decoration: none; +} + +table.page a img { + border: 0px; +} + +/* Global Page - Logo & Title */ +table.page tr.head { + text-align: center; + color: #FFFFFF; + background-color: #3465A4; + font-weight: bold; + font-size: 11px; + height: 25px; +} + +table.page tr.head img.logo { + vertical-align: middle; + text-align: center; + + width: 100px; + height: 60px; +} + +table.page tr.pagehead { +} + +table.page tr.pagehead td.imagetop { + width: 100%; + vertical-align: bottom; + text-align: right; +} + +/* Global Page - Control Line */ +table.page tr.control td { + border-top: 1px solid #BABDB6; + border-bottom: 1px solid #BABDB6; +} + +/* Global Page - Control Line Menu Items */ +table.page table.control { + table-layout: fixed; + width: 100%; +} + +table.page table.control td { + border-top: 0px; + border-bottom: 0px; + padding: 0px; + padding-top: 5px; + text-align: left; + vertical-align: top; + font-size: 11px; +} + +table.page table.control img { + width: 24px; + height: 24px; +} + +table.page table.control a { + color: #2E3436; +} + +table.page table.control a:hover { + text-decoration: none; + background-color: #EEEEEC; + color: #CC0000; +} + +table.page table.control td.spacer { + width: 20%; +} + +table.page table.control td.logo { + text-align: right; + width: 10%; +} + +table.page table.control td.logo img.logo { + vertical-align: middle; + text-align: right; + + width: 100px; + height: 60px; +} + +/* Global Page - LDAP Tree */ +table.page td.tree { + border-right: 1px solid #BABDB6; + vertical-align: top; + background-color: #FFFFFF; + width: 10%; +} + +/* Global Page - Main Body */ +table.page td.body { + vertical-align: top; + width: 100%; + background-color: #FFFFFF; +} + +/* Global Page - Main Body System Message */ +table.page table.sysmsg { + border-bottom: 2px solid #BABDB6; + width: 100%; +} + +table.page table.sysmsg td.head { + font-size: small; + text-align: left; + font-weight: bold; +} + +table.page table.sysmsg td.body { + font-weight: normal; +} + +table.page table.sysmsg td.icon { + text-align: center; + vertical-align: top; +} + +/* Global Page - Main Body */ +table.page table.body { + font-weight: normal; + background-color: #FFFFFF; + width: 100%; +} + +table.page table.body h3.title { + text-align: center; + margin: 0px; + padding: 10px; + color: #FFFFFF; + background-color: #3465A4; + border: 1px solid #EEEEEC; + font-weight: normal; + font-size: 150%; +} + +table.page table.body h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + font-size: 75%; + color: #FFFFFF; + border-bottom: 1px solid #EEEEEC; + border-left: 1px solid #EEEEEC; + border-right: 1px solid #EEEEEC; + background: #3465A4; + padding: 4px; + font-weight: normal; +} + +table.page table.body td.spacer { + border-top: 2px solid #BABDB6; + padding: 0px; + font-size: 5px; +} + +table.page table.body td.head { + font-weight: bold; +} + +table.page table.body td.foot { + font-size: small; + border-top: 1px solid #BABDB6; + border-bottom: 1px solid #BABDB6; +} + +/* Global Page Footer */ +table.page tr.foot td { + border-top: 1px solid #BABDB6; + font-weight: bold; + font-size: 12px; + text-align: right; +} + +/* Global Page - Other Layouts */ +/* Server Select */ +table.page table.server_select { + font-weight: bold; + font-size: 13px; + color: #2E3436; +} + +/* Individual table layouts */ +/* LDAP Tree */ +table.tree { +} + +table.tree tr.server td.icon { + vertical-align: top; +} + +table.tree tr.server td.name { + padding-right: 10px; + vertical-align: top; +} + +table.tree tr.server td { + padding-top: 5px; + font-size: 18px; + text-align: left; + padding-right: 0px; + white-space: nowrap; +} + +table.tree td { + white-space: nowrap; +} + +table.tree td.server_links { + vertical-align: top; + text-align: center; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 3px; + padding-right: 3px; +} + +table.tree td.server_links img { + height: 22px; + width: 22px; +} + +table.tree td.server_links a { + color: #2E3436; + text-decoration: none; + font-size: 11px; +} + +table.tree td.server_links a:hover { + text-decoration: none; + background-color: #EEEEEC; + color: #CC0000; +} + +table.tree tr.option td.expander { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree tr.option td.icon { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree td.rdn a { + font-size: 13px; + color: #2E3436; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; +} + +table.tree td.rdn span.count { + font-size: 13px; + color: #2E3436; +} + +table.tree td.links a { + color: #204A87; + text-align: center; +} + +table.tree td.link a { + font-size: 13px; + color: #2E3436; +} + +table.tree td.link a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +table.tree td.links a:hover { + text-decoration: none; + color: #204A87; +} + +table.tree td.links a img { + width: 22px; + height: 22px; +} + +table.tree td.blank { + font-size: 1px; +} + +table.tree td.spacer { + width: 22px; +} + +table.tree td.logged_in { + font-size: 10px; + white-space: nowrap; +} + +table.tree td.logged_in a { + font-size: 11px; +} + +table.tree td.logged_in a:hover { + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +/* Tree Global Defaults */ +table.tree tr td { + padding: 0px; +} + +table.tree a { + text-decoration: none; + color: #2E3436; +} + +table.tree a:hover { + text-decoration: underline; + color: #204A87; +} + +/* Tree */ +table.tree .treemenudiv { + display: block; + white-space: nowrap; + padding-top: 1px; + padding-bottom: 1px; +} + +table.tree .phplmnormal { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplmnormal:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +table.tree a.phplmselected:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplmselected:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +/* Standard Form */ +table.forminput { + background-color: #EEEEEC; + padding: 10px; + border: 1px solid #BABDB6; +} + +table.forminput td.title { + text-align: center; + font-weight: bold; +} + +table.forminput td.subtitle { + text-align: center; + font-weight: normal; + font-size: small; +} + +table.forminput tr td.heading { + font-weight: bold; +} + +table.forminput td.small { + font-size: 80%; +} + +table.forminput td.top { + vertical-align: top; +} + +table.forminput input.val { + width: 350px; + border: 1px solid #BABDB6; +} + +table.forminput input.roval { + width: 350px; + border: none; +} + +table.forminput td.icon { + width: 16px; + text-align: center; +} + +table.forminput td.icon img { + border: 0px; +} + +table.forminput td.label { + text-align: left; + font-size: 13px; +} + +/* Menu on top of entry form */ +table.menu { + font-size: 14px; +} + +table.menu td.icon { + width: 16px; + text-align: center; +} + +/* Edit DN */ +div.add_value { + font-size: 12px; + margin: 0px; + padding: 0px; +} + +/* Edit Entry */ +table.entry { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; +} + +table.entry input { + margin: 1px; +} + +table.entry input.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry div.helper { + text-align: left; + white-space: nowrap; + background-color: #FFFFFF; + font-size: 14px; + font-weight: normal; + color: #888; +} + +table.entry input.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + border: none; +} + +table.entry textarea.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry textarea.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + border: none; +} + +table.entry tr td { + padding: 4px; + padding-right: 0px; +} + +table.entry tr td.heading { + border-top: 3px solid #D3D7CF; + font-weight: bold; +} + +table.entry tr td.note { + text-align: right; + background-color: #EEEEEC; +} + +table.entry tr td.title { + background-color: #EEEEEC; + vertical-align: top; + font-weight: bold; +} + +table.entry tr td.title a { + text-decoration: none; + color: #2E3436; +} + +table.entry tr td.title a:hover { + text-decoration: underline; + color: #204A87; +} + +table.entry tr td.value { + text-align: left; + vertical-align: middle; + padding-bottom: 10px; + padding-left: 50px; +} + +/** When an attr is updated, it is highlighted to indicate such */ +table.entry tr.updated td.title { + border-top: 1px dashed #BABDB6; + border-left: 1px dashed #BABDB6; + background-color: #888A85; +} + +table.entry tr.updated td.note { + border-top: 1px dashed #BABDB6; + border-right: 1px dashed #BABDB6; + background-color: #888A85; +} + +/** An extra row that sits at the bottom of recently modified attrs to encase them in dashes */ +table.entry tr.updated td.bottom { + border-top: 1px dashed #BABDB6; +} + +/** Formatting for the value cell when it is the attribute that has been recently modified */ +table.entry tr.updated td.value { + border-left: 1px dashed #BABDB6; + border-right: 1px dashed #BABDB6; +} + +/* Need to prevent sub-tables (like the one in which jpegPhotos are displayed) + * from drawing borders as well. */ +table.entry tr.updated td table td { + border: 0px; +} + +table.entry tr.noinput { + background: #EEEEEC; +} + +span.hint { + font-size: small; + font-weight: normal; + color: #888; +} + +/* Edit DN - EntryWriter2 */ +table.entry tr.spacer { + background-color: #D3D7CF; +} + +table.entry tr td.ew2_icon { + vertical-align: top; +} + +table.entry tr td.ew2_attr { + vertical-align: top; + text-align: right; + font-size: 75%; + background-color: #FFFFFF; + font-weight: bold; +} + +table.entry tr td.ew2_attr a { + text-decoration: none; + color: #2E3436; +} + +table.entry tr td.ew2_attr a:hover { + text-decoration: underline; + color: #204A87; +} + +table.entry tr td.ew2_val { + text-align: left; + vertical-align: top; + padding-bottom: 10px; + padding-left: 50px; +} + +table.entry tr.updated td.ew2_attr { + text-align: right; + font-size: 75%; + border-top: 1px dashed green; + border-left: 1px dashed green; + border-bottom: 1px dashed green; + background-color: #ded; +} + +table.entry tr.updated td.ew2_val { + border-top: 1px dashed green; + border-left: 1px dashed green; + border-right: 1px dashed green; + border-bottom: 1px dashed green; +} + +/* Login Box */ +#login { + background: url('../../images/tango/ldap-uid.png') no-repeat 0 1px; + background-color: #FFFFFF; + padding-left: 17px; +} + +#login:focus { + background-color: #EEEEEC; +} + +#login:disabled { + background-color: #D3D7CF; +} + +#password { + background: url('../../images/tango/key.png') no-repeat 0 1px; + background-color: #FFFFFF; + padding-left: 17px; +} + +#password:focus { + background-color: #EEEEEC; +} + +#password:disabled { + background-color: #D3D7CF; +} + +#generic { + background-color: #FFFFFF; + padding-left: 17px; +} +#generic:focus { + background-color: #EEEEEC; +} + +#generic:disabled { + background-color: #D3D7CF; +} + +/* After input results */ +div.execution_time { + font-size: 75%; + font-weight: normal; + text-align: center; +} + +table.result { + width: 100%; + vertical-align: top; + empty-cells: show; + border: 1px solid #BABDB6; + border-spacing: 0px; + background-color: #EEEEEC; +} + +table.result tr.heading { + vertical-align: top; +} + +table.result tr.list_title { + background-color: #FFFFFF; +} + +table.result tr.list_title td.icon { + text-align: center; + vertical-align: top; +} + +table.result tr.list_item { + background-color: #FFFFFF; +} + +table.result tr.list_item td.blank { + width: 25px; +} + +table.result tr.list_item td.heading { + vertical-align: top; + color: gray; + width: 10%; + font-size: 12px; +} + +table.result tr.list_item td.value { + color: #2E3436; + font-size: 12px; +} + +table.result_table { + border: 1px solid #BABDB6; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table td { + vertical-align: top; + border: 1px solid #BABDB6; + padding: 4px; +} + +table.result_table th { + border: 1px solid #BABDB6; + padding: 10px; + padding-left: 20px; + padding-right: 20px; +} + +table.result_table tr.highlight { + background-color: #FCE94F; +} + +table.result_table tr.highlight td { + border: 1px solid #BABDB6; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table td.heading { + color: #FFFFFF; + background-color: #3465A4; + font-size: 15px; +} + +table.result_table td.value { + color: #2E3436; + background-color: #EEEEEC; +} + +table.result_table tr.heading { + color: #FFFFFF; + background-color: #3465A4; + font-size: 15px; +} + +table.result_table tr.heading a { + color: #FFFFFF; + font-size: 20px; +} + +table.result_table tr.heading td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even { + background-color: #EEEEEC; +} + +table.result_table tr.even td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even td.title { + font-weight: bold; +} + +table.result_table tr.odd { + background-color: #EEEEEC; +} + +table.result_table tr.odd td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.odd td.title { + font-weight: bold; +} + +table.result_table ul.list { + margin: 5px; + margin-left: 0px; + padding-left: 20px; +} + +table.result_table ul.list li { + margin-left: 0px; + padding-left: 0px; +} + +table.result_table ul.list li small { + font-size: 75%; + color: #707070; +} + +table.result_table ul.list li small a { + color: #7070C0; +} + +/* Error Dialog Box */ +table.error { + width: 500px; + border: 1px solid #AA0000; + background-color: #FFF0F0; +} + +table.error th { + background-color: #AA0000; + border: 0px; + color: #FFFFFF; + font-size: 14px; + font-weight: bold; + text-align: center; + vertical-align: middle; + width: 100%; +} + +table.error th.img { + vertical-align: middle; + text-align: center; +} + +table.error td { + border: 0px; + background-color: #FFF0F0; + padding: 2px; + text-align: left; + vertical-align: top; +} + +/* Popup Window */ +div.popup h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + color: #FFFFFF; + border-bottom: 1px solid #2E3436; + border-left: 1px solid #2E3436; + border-right: 1px solid #2E3436; + background: #3465A4; + padding: 4px; + font-weight: normal; +} + +span.good { + color: green; +} + +span.bad { + color: red; +} diff --git a/htdocs/delete.php b/htdocs/delete.php new file mode 100644 index 0000000..137055c --- /dev/null +++ b/htdocs/delete.php @@ -0,0 +1,40 @@ +dnExists($request['dn'])) + error(sprintf('%s (%s)',_('No such entry.'),''.pretty_print_dn($request['dn']).''),'error','index.php'); + +# Delete the entry. +$result = $app['server']->delete($request['dn']); + +if ($result) { + $redirect_url = ''; + + if (isAjaxEnabled()) + $redirect_url .= sprintf('&refresh=SID_%s_nodes&noheader=1',$app['server']->getIndex()); + + system_message(array( + 'title'=>_('Delete DN'), + 'body'=>_('Successfully deleted DN ').sprintf('%s',$request['dn']), + 'type'=>'info'), + sprintf('index.php?server_id=%s%s',$app['server']->getIndex(),$redirect_url)); +} else + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($request['dn'])), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); +?> diff --git a/htdocs/delete_attr.php b/htdocs/delete_attr.php new file mode 100644 index 0000000..ad323fa --- /dev/null +++ b/htdocs/delete_attr.php @@ -0,0 +1,49 @@ +isAttrReadOnly($request['attr'])) + error(sprintf(_('The attribute "%s" is flagged as read-only in the phpLDAPadmin configuration.'),$request['attr']),'error','index.php'); + +$update_array = array(); +$update_array[$request['attr']] = $app['server']->getDNAttrValue($request['dn'],$request['attr']); + +$redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),rawurlencode($request['dn'])); + +if (! isset($update_array[$request['attr']][$request['index']])) + system_message(array( + 'title'=>_('Could not delete attribute value.'), + 'body'=>sprintf('%s. %s/%s',_('The attribute value does not exist'),$request['attr'],$request['index']), + 'type'=>'warn'),$redirect_url); + +else { + unset($update_array[$request['attr']][$request['index']]); + foreach ($update_array as $key => $values) + $update_array[$key] = array_values($values); + + $result = $app['server']->modify($request['dn'],$update_array); + + if ($result) { + foreach ($update_array as $attr => $junk) + $redirect_url .= sprintf('&modified_attrs[]=%s',$attr); + + header("Location: $redirect_url"); + die(); + } +} +?> diff --git a/htdocs/delete_form.php b/htdocs/delete_form.php new file mode 100644 index 0000000..3f0d44c --- /dev/null +++ b/htdocs/delete_form.php @@ -0,0 +1,157 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +# Check if the entry exists. +if (! $request['dn'] || ! $app['server']->dnExists($request['dn'])) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s)',_('The entry does not exist'),$request['dn']), + 'type'=>'error'),'index.php'); + +# We search all children, not only the visible children in the tree +$request['children'] = $app['server']->getContainerContents($request['dn'],null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + +printf('

%s %s

',_('Delete'),htmlspecialchars(get_rdn($request['dn']))); +printf('

%s: %s     %s: %s

', + _('Server'),$app['server']->getName(),_('Distinguished Name'),$request['dn']); +echo "\n"; + +echo '
'; + +if (count($request['children'])) { + printf('%s

',_('Permanently delete all children also?')); + + $search['href'] = htmlspecialchars(sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&base=%s&scope=sub&query=none&format=list', + $app['server']->getIndex(),rawurlencode('objectClass=*'),rawurlencode($request['dn']))); + + $query = array(); + $query['base'] = $request['dn']; + $query['scope'] = 'sub'; + $query['attrs'] = array('dn'); + $query['size_limit'] = 0; + $query['deref'] = LDAP_DEREF_NEVER; + $request['search'] = $app['server']->query($query,null); + + echo ''; + echo ''; + echo ''; + + echo ''; + + printf('', + sprintf(_('phpLDAPadmin can recursively delete this entry and all %s of its children. See below for a list of all the entries that this action will delete. Do you want to do this?'),count($request['search']))); + + echo ''; + + printf('', + _('Note: this is potentially very dangerous and you do this at your own risk. This operation cannot be undone. Take into consideration aliases, referrals, and other things that may cause problems.')); + echo "\n"; + + echo ''; + echo ''; + + echo ''; + echo ''; + echo "\n"; + + echo '
'; + printf(_('This entry is the root of a sub-tree containing %s entries.'),count($request['search'])); + printf(' (%s)', + $search['href'],_('view entries')); + echo '
 
%s
 
%s
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + //@todo need to refresh the tree after a delete + printf('', + sprintf(_('Delete all %s objects'),count($request['search'])), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'delete_form\'),\'%s\');"',_('Deleting Object(s)')) : '')); + echo '
'; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&dn=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getDNEncode(),_('Retrieving DN')) : '')); + echo '
'; + echo '
'; + echo "\n"; + + echo '

'; + echo _('List of entries to be deleted:'); + echo '
'; + + $i = 0; + printf(''; + echo "\n"; + +} else { + echo ''; + + printf('',_('Are you sure you want to permanently delete this object?')); + echo ''; + + printf('',_('Server'),$app['server']->getName()); + printf('', + _('Distinguished Name'),_('DN'),$request['dn']); + echo ''; + echo "\n"; + + echo ''; + echo ''; + echo ''; + echo ''; + echo '
%s
 
%s:%s
%s%s
 
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + //@todo need to refresh the tree after a delete + printf('', + _('Delete'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'delete_form\'),\'%s\');"',_('Deleting Object(s)')) : '')); + echo '
'; + + echo '
'; + + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&dn=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getDNEncode(),_('Retrieving DN')) : '')); + echo '
'; + + echo '
'; + echo "\n"; +} + +echo '
'; +echo '
'; +?> diff --git a/htdocs/download_binary_attr.php b/htdocs/download_binary_attr.php new file mode 100644 index 0000000..251f2de --- /dev/null +++ b/htdocs/download_binary_attr.php @@ -0,0 +1,49 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$search = $app['server']->getDNAttrValues($request['dn'],null,LDAP_DEREF_NEVER,array($request['attr'])); + +# Dump the binary data to the browser +$obStatus = ob_get_status(); +if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + +if (! isset($search[$request['attr']][$request['index']])) { + # We cant display an error, but we can set a system message, which will be display on the next page render. + system_message(array( + 'title'=>_('No binary data available'), + 'body'=>sprintf(_('Could not fetch binary data from LDAP server for attribute [%s].'),$request['attr']), + 'type'=>'warn')); + + die(); +} + +header(sprintf('Content-type: %s',$request['type'])); +header(sprintf('Content-disposition: attachment; filename="%s"',$request['filename'])); +header(sprintf('Expires: Mon, 26 Jul 1997 05:00:00 GMT',gmdate('r'))); +header(sprintf('Last-Modified: %s',gmdate('r'))); +echo $search[$request['attr']][$request['index']]; +die(); +?> diff --git a/htdocs/draw_tree_node.php b/htdocs/draw_tree_node.php new file mode 100644 index 0000000..7311e2d --- /dev/null +++ b/htdocs/draw_tree_node.php @@ -0,0 +1,61 @@ +getEntry($request['dn']); + + if (! $dnentry) { + $tree->addEntry($request['dn']); + $dnentry = $tree->getEntry($request['dn']); + $treesave = true; + } + + switch ($request['action']) { + case 0: + $dnentry->close(); + + break; + + case 2: + default: + if ($dnentry->isSizeLimited()) { + $tree->readChildren($request['dn'],true); + + $treesave = true; + } + + $dnentry->open(); + } +} + +if ($treesave) + set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +if ($request['dn']) + echo $tree->draw_children($dnentry,$request['code']); +else + $tree->draw($request['noheader']); + +die(); +?> diff --git a/htdocs/entry_chooser.php b/htdocs/entry_chooser.php new file mode 100644 index 0000000..16a4eb6 --- /dev/null +++ b/htdocs/entry_chooser.php @@ -0,0 +1,135 @@ +'; +printf('

%s

',_('Entry Chooser')); + +echo ''; + +echo ''; +if ($request['container']) { + printf('',_('Server'),$app['server']->getName()); + printf('',_('Looking in'),$request['container']); + echo ''; +} + +# Has the user already begun to descend into a specific server tree? +if (isset($app['server']) && ! is_null($request['container'])) { + $tree = get_cached_item($app['server']->getIndex(),'tree'); + + $request['children'] = $app['server']->getContainerContents($request['container'],null,0,'(objectClass=*)',$_SESSION[APPCONFIG]->getValue('deref','tree')); + sort($request['children']); + + foreach ($app['server']->getBaseDN() as $base) { + if (DEBUG_ENABLED) + debug_log('Comparing BaseDN [%s] with container [%s]',64,0,__FILE__,__LINE__,__METHOD__,$base,$request['container']); + + if (! pla_compare_dns($request['container'],$base)) { + $parent_container = false; + $href['up'] = sprintf('entry_chooser.php?form=%s&element=%s&rdn=%s',$request['form'],$request['element'],rawurlencode($request['rdn'])); + break; + + } else { + $parent_container = $app['server']->getContainer($request['container']); + $href['up'] = sprintf('entry_chooser.php?form=%s&element=%s&rdn=%s&server_id=%s&container=%s', + $request['form'],$request['element'],$request['rdn'],$app['server']->getIndex(),rawurlencode($parent_container)); + } + } + + echo ''; + echo ''; + printf('',$href['up'],IMGDIR); + printf('',$href['up'],_('Back Up')); + echo ''; + + if (! count($request['children'])) + printf('',_('no entries')); + + else + foreach ($request['children'] as $dn) { + $href['return'] = sprintf("javascript:returnDN('%s%s')",($request['rdn'] ? sprintf('%s,',$request['rdn']) : ''),str_replace('\\','\\\\',$dn)); + $href['expand'] = sprintf('entry_chooser.php?server_id=%s&form=%s&element=%s&rdn=%s&container=%s', + $app['server']->getIndex(),$request['form'],$request['element'],$request['rdn'],rawurlencode($dn)); + + echo ''; + echo ''; + printf('',$href['expand'],IMGDIR); + + $entry = $tree->getEntry($dn); + if (is_null($entry)) { + $tree->addEntry($dn); + $entry = $tree->getEntry($dn); + } + + if ($entry) + $item = draw_formatted_dn($app['server'], $entry); + else + $item = $dn; + + printf('',$href['return'], $item ); + echo ''; + echo "\n\n"; + } + +# Draw the root of the selection tree (ie, list all the servers) +} else { + foreach ($_SESSION[APPCONFIG]->getServerList() as $index => $server) { + if ($server->isLoggedIn(null)) { + printf('',_('Server'),$server->getName()); + foreach ($server->getBaseDN() as $dn) { + if (! $dn) { + printf('',_('Could not determine base DN')); + + } else { + $href['return'] = sprintf("javascript:returnDN('%s%s')",($request['rdn'] ? sprintf('%s,',$request['rdn']) : ''),rawurlencode($dn)); + $href['expand'] = htmlspecialchars(sprintf('entry_chooser.php?server_id=%s&form=%s&element=%s&rdn=%s&container=%s', + $server->getIndex(),$request['form'],$request['element'],$request['rdn'],rawurlencode($dn))); + + echo ''; + echo ''; + printf('',$href['expand'],IMGDIR); + printf('',$href['return'],$dn); + } + } + + echo ''; + } + } +} + +echo '
%s:%s
%s:%s
 
 Up%s...
 (%s)
 Plus%s
%s:%s
 (%s)
 Plus%s
 
'; +echo '
'; + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +# Render the popup. +$www['page']->display(array('CONTROL'=>false,'FOOT'=>false,'HEAD'=>false,'TREE'=>false)); +?> diff --git a/htdocs/expand.php b/htdocs/expand.php new file mode 100644 index 0000000..d0647d0 --- /dev/null +++ b/htdocs/expand.php @@ -0,0 +1,27 @@ +getIndex(),'tree'); +$entry = $tree->getEntry($dn); +$entry->open(); +set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s', + $app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param())); +die(); +?> diff --git a/htdocs/export.php b/htdocs/export.php new file mode 100644 index 0000000..cc1096b --- /dev/null +++ b/htdocs/export.php @@ -0,0 +1,40 @@ +getIndex(),get_request('exporter_id','REQUEST')); +$request['export'] = $request['exporter']->getTemplate(); +$types = $request['export']->getType(); + +# send the header +if ($request['file']) { + $obStatus = ob_get_status(); + if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + + header('Content-type: application/download'); + header(sprintf('Content-Disposition: inline; filename="%s.%s"','export',$types['extension'].($request['export']->isCompressed() ? '.gz' : ''))); + echo $request['export']->export(); + die(); + +} else { + print '
';
+	echo htmlspecialchars($request['export']->export());
+	print '
'; +} +?> diff --git a/htdocs/export_form.php b/htdocs/export_form.php new file mode 100644 index 0000000..326184e --- /dev/null +++ b/htdocs/export_form.php @@ -0,0 +1,213 @@ + 'Macintosh', + 'unix' => 'UNIX (Linux, BSD)', + 'win' => 'Windows' +); + +$available_scopes = array( + 'base' => _('Base (base dn only)'), + 'one' => _('One (one level beneath base)'), + 'sub' => _('Sub (entire subtree)') +); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Export'))); + +printf('',JSDIR); +printf('',JSDIR); + +echo '
'; +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); + +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; + +echo ''; + +printf('', + htmlspecialchars(_('Proceed >>'))); + +echo '
'; + +echo '
'; +printf('%s',_('Export')); + +echo ''; +printf('',_('Server'),$app['server']->getName()); + +echo ''; +printf('',_('Base DN')); +echo ''; +echo ''; + +echo ''; +printf('',_('Search Scope')); + +echo ''; + +echo ''; + +printf('', + _('Search Filter'),htmlspecialchars($request['filter'])); + +printf('', + _('Show Attributtes'),htmlspecialchars($request['attr'])); + +printf('', + $request['sys_attr'] ? 'checked="checked" ' : '',_('Include system attributes')); + +printf('', + _('Save as file')); + +printf('', + _('Compress')); + +echo '
%s%s
%s'; +printf(' ',htmlspecialchars($request['dn'])); +draw_chooser_link('export_form','dn'); +echo '
%s'; + +foreach ($available_scopes as $id => $desc) + printf('
', + htmlspecialchars($id),$id,($id == $request['scope']) ? 'checked="checked"' : '', + htmlspecialchars($id),$desc); + +echo '
%s
%s
 
 
 
'; +echo '
'; +echo '
'; + +echo ''; +echo ''; + +echo ''; + +echo ''; +echo '
'; +echo '
'; + +printf('%s',_('Export format')); + +foreach (Exporter::types() as $index => $exporter) { + printf('', + htmlspecialchars($exporter['type']),htmlspecialchars($exporter['type']),($exporter['type'] === $request['exporter_id']) ? ' checked="checked"' : ''); + + printf('
', + htmlspecialchars($exporter['type']),$exporter['type']); +} + +echo '
'; +echo '
'; +echo '
'; + +printf('%s',_('Line ends')); +foreach ($available_formats as $id => $desc) + printf('
', + htmlspecialchars($id),htmlspecialchars($id),($request['format']==$id) ? ' checked="checked"' : '', + htmlspecialchars($id),$desc); + +echo '
'; +echo '
'; +echo '
'; + +echo '
'; +echo '
'; + +/** + * Helper function for fetching the line end format. + * + * @return String 'win', 'unix', or 'mac' based on the user's browser.. + */ +function get_line_end_format() { + if (is_browser('win')) + return 'win'; + elseif (is_browser('unix')) + return 'unix'; + elseif (is_browser('mac')) + return 'mac'; + else + return 'unix'; +} + +/** + * Gets the USER_AGENT string from the $_SERVER array, all in lower case in + * an E_NOTICE safe manner. + * + * @return string|false The user agent string as reported by the browser. + */ +function get_user_agent_string() { + if (isset($_SERVER['HTTP_USER_AGENT'])) + return strtolower($_SERVER['HTTP_USER_AGENT']); + else + return ''; +} + +/** + * Determine the OS for the browser + */ +function is_browser($type) { + $agents = array(); + + $agents['unix'] = array( + 'sunos','sunos 4','sunos 5', + 'i86', + 'irix','irix 5','irix 6','irix6', + 'hp-ux','09.','10.', + 'aix','aix 1','aix 2','aix 3','aix 4', + 'inux', + 'sco', + 'unix_sv','unix_system_v','ncr','reliant','dec','osf1', + 'dec_alpha','alphaserver','ultrix','alphastation', + 'sinix', + 'freebsd','bsd', + 'x11','vax','openvms' + ); + + $agents['win'] = array( + 'win','win95','windows 95', + 'win16','windows 3.1','windows 16-bit','windows','win31','win16','winme', + 'win2k','winxp', + 'win98','windows 98','win9x', + 'winnt','windows nt','win32', + '32bit' + ); + + $agents['mac'] = array( + 'mac','68000','ppc','powerpc' + ); + + if (isset($agents[$type])) + return in_array(get_user_agent_string(),$agents[$type]); + else + return false; +} +?> diff --git a/htdocs/images/INFO b/htdocs/images/INFO new file mode 100644 index 0000000..fb46310 --- /dev/null +++ b/htdocs/images/INFO @@ -0,0 +1,6 @@ +PLA's icons come from http://jimmac.musichall.cz/ikony.php3, or the projects that +he drew them for. + +They are open source, either licensed under the GPL or a CC license. + +They are great icons so be sure to let Jakub know :) diff --git a/htdocs/images/ajax-progress.gif b/htdocs/images/ajax-progress.gif new file mode 100644 index 0000000..994bfab Binary files /dev/null and b/htdocs/images/ajax-progress.gif differ diff --git a/htdocs/images/ajax-spinner.gif b/htdocs/images/ajax-spinner.gif new file mode 100644 index 0000000..1ed786f Binary files /dev/null and b/htdocs/images/ajax-spinner.gif differ diff --git a/htdocs/images/countries/af.png b/htdocs/images/countries/af.png new file mode 100644 index 0000000..cda88b0 Binary files /dev/null and b/htdocs/images/countries/af.png differ diff --git a/htdocs/images/countries/al.png b/htdocs/images/countries/al.png new file mode 100644 index 0000000..5925b27 Binary files /dev/null and b/htdocs/images/countries/al.png differ diff --git a/htdocs/images/countries/am.png b/htdocs/images/countries/am.png new file mode 100644 index 0000000..45cd749 Binary files /dev/null and b/htdocs/images/countries/am.png differ diff --git a/htdocs/images/countries/an.png b/htdocs/images/countries/an.png new file mode 100644 index 0000000..2d4d3a7 Binary files /dev/null and b/htdocs/images/countries/an.png differ diff --git a/htdocs/images/countries/ao.png b/htdocs/images/countries/ao.png new file mode 100644 index 0000000..9463d24 Binary files /dev/null and b/htdocs/images/countries/ao.png differ diff --git a/htdocs/images/countries/ar.png b/htdocs/images/countries/ar.png new file mode 100644 index 0000000..bd73382 Binary files /dev/null and b/htdocs/images/countries/ar.png differ diff --git a/htdocs/images/countries/at.png b/htdocs/images/countries/at.png new file mode 100644 index 0000000..2a58c49 Binary files /dev/null and b/htdocs/images/countries/at.png differ diff --git a/htdocs/images/countries/au.png b/htdocs/images/countries/au.png new file mode 100644 index 0000000..b20b048 Binary files /dev/null and b/htdocs/images/countries/au.png differ diff --git a/htdocs/images/countries/aw.png b/htdocs/images/countries/aw.png new file mode 100644 index 0000000..411977e Binary files /dev/null and b/htdocs/images/countries/aw.png differ diff --git a/htdocs/images/countries/az.png b/htdocs/images/countries/az.png new file mode 100644 index 0000000..ced5af0 Binary files /dev/null and b/htdocs/images/countries/az.png differ diff --git a/htdocs/images/countries/ba.png b/htdocs/images/countries/ba.png new file mode 100644 index 0000000..fb7d190 Binary files /dev/null and b/htdocs/images/countries/ba.png differ diff --git a/htdocs/images/countries/bb.png b/htdocs/images/countries/bb.png new file mode 100644 index 0000000..9c07e14 Binary files /dev/null and b/htdocs/images/countries/bb.png differ diff --git a/htdocs/images/countries/bd.png b/htdocs/images/countries/bd.png new file mode 100644 index 0000000..56bba0b Binary files /dev/null and b/htdocs/images/countries/bd.png differ diff --git a/htdocs/images/countries/be.png b/htdocs/images/countries/be.png new file mode 100644 index 0000000..9312218 Binary files /dev/null and b/htdocs/images/countries/be.png differ diff --git a/htdocs/images/countries/bf.png b/htdocs/images/countries/bf.png new file mode 100644 index 0000000..1019379 Binary files /dev/null and b/htdocs/images/countries/bf.png differ diff --git a/htdocs/images/countries/bg.png b/htdocs/images/countries/bg.png new file mode 100644 index 0000000..0f64f7d Binary files /dev/null and b/htdocs/images/countries/bg.png differ diff --git a/htdocs/images/countries/bh.png b/htdocs/images/countries/bh.png new file mode 100644 index 0000000..236693d Binary files /dev/null and b/htdocs/images/countries/bh.png differ diff --git a/htdocs/images/countries/bi.png b/htdocs/images/countries/bi.png new file mode 100644 index 0000000..7fa236a Binary files /dev/null and b/htdocs/images/countries/bi.png differ diff --git a/htdocs/images/countries/bj.png b/htdocs/images/countries/bj.png new file mode 100644 index 0000000..290016a Binary files /dev/null and b/htdocs/images/countries/bj.png differ diff --git a/htdocs/images/countries/bm.png b/htdocs/images/countries/bm.png new file mode 100644 index 0000000..96fb4dc Binary files /dev/null and b/htdocs/images/countries/bm.png differ diff --git a/htdocs/images/countries/bn.png b/htdocs/images/countries/bn.png new file mode 100644 index 0000000..53460dc Binary files /dev/null and b/htdocs/images/countries/bn.png differ diff --git a/htdocs/images/countries/bo.png b/htdocs/images/countries/bo.png new file mode 100644 index 0000000..5025e7f Binary files /dev/null and b/htdocs/images/countries/bo.png differ diff --git a/htdocs/images/countries/br.png b/htdocs/images/countries/br.png new file mode 100644 index 0000000..734ace9 Binary files /dev/null and b/htdocs/images/countries/br.png differ diff --git a/htdocs/images/countries/bs.png b/htdocs/images/countries/bs.png new file mode 100644 index 0000000..36c4cbe Binary files /dev/null and b/htdocs/images/countries/bs.png differ diff --git a/htdocs/images/countries/bt.png b/htdocs/images/countries/bt.png new file mode 100644 index 0000000..3e10663 Binary files /dev/null and b/htdocs/images/countries/bt.png differ diff --git a/htdocs/images/countries/bw.png b/htdocs/images/countries/bw.png new file mode 100644 index 0000000..bd8e293 Binary files /dev/null and b/htdocs/images/countries/bw.png differ diff --git a/htdocs/images/countries/by.png b/htdocs/images/countries/by.png new file mode 100644 index 0000000..8f5b849 Binary files /dev/null and b/htdocs/images/countries/by.png differ diff --git a/htdocs/images/countries/bz.png b/htdocs/images/countries/bz.png new file mode 100644 index 0000000..fb1bd5a Binary files /dev/null and b/htdocs/images/countries/bz.png differ diff --git a/htdocs/images/countries/ca.png b/htdocs/images/countries/ca.png new file mode 100644 index 0000000..d06843f Binary files /dev/null and b/htdocs/images/countries/ca.png differ diff --git a/htdocs/images/countries/cf.png b/htdocs/images/countries/cf.png new file mode 100644 index 0000000..35e6b47 Binary files /dev/null and b/htdocs/images/countries/cf.png differ diff --git a/htdocs/images/countries/cg.png b/htdocs/images/countries/cg.png new file mode 100644 index 0000000..f2db518 Binary files /dev/null and b/htdocs/images/countries/cg.png differ diff --git a/htdocs/images/countries/ch.png b/htdocs/images/countries/ch.png new file mode 100644 index 0000000..9899d78 Binary files /dev/null and b/htdocs/images/countries/ch.png differ diff --git a/htdocs/images/countries/ci.png b/htdocs/images/countries/ci.png new file mode 100644 index 0000000..d536e9b Binary files /dev/null and b/htdocs/images/countries/ci.png differ diff --git a/htdocs/images/countries/ck.png b/htdocs/images/countries/ck.png new file mode 100644 index 0000000..271f568 Binary files /dev/null and b/htdocs/images/countries/ck.png differ diff --git a/htdocs/images/countries/cl.png b/htdocs/images/countries/cl.png new file mode 100644 index 0000000..97db9ec Binary files /dev/null and b/htdocs/images/countries/cl.png differ diff --git a/htdocs/images/countries/cm.png b/htdocs/images/countries/cm.png new file mode 100644 index 0000000..febecad Binary files /dev/null and b/htdocs/images/countries/cm.png differ diff --git a/htdocs/images/countries/cn.png b/htdocs/images/countries/cn.png new file mode 100644 index 0000000..f3f36da Binary files /dev/null and b/htdocs/images/countries/cn.png differ diff --git a/htdocs/images/countries/co.png b/htdocs/images/countries/co.png new file mode 100644 index 0000000..2781663 Binary files /dev/null and b/htdocs/images/countries/co.png differ diff --git a/htdocs/images/countries/cr.png b/htdocs/images/countries/cr.png new file mode 100644 index 0000000..09bb72d Binary files /dev/null and b/htdocs/images/countries/cr.png differ diff --git a/htdocs/images/countries/cu.png b/htdocs/images/countries/cu.png new file mode 100644 index 0000000..9be2138 Binary files /dev/null and b/htdocs/images/countries/cu.png differ diff --git a/htdocs/images/countries/cv.png b/htdocs/images/countries/cv.png new file mode 100644 index 0000000..6204e60 Binary files /dev/null and b/htdocs/images/countries/cv.png differ diff --git a/htdocs/images/countries/cy.png b/htdocs/images/countries/cy.png new file mode 100644 index 0000000..14b2deb Binary files /dev/null and b/htdocs/images/countries/cy.png differ diff --git a/htdocs/images/countries/cz.png b/htdocs/images/countries/cz.png new file mode 100644 index 0000000..36313b4 Binary files /dev/null and b/htdocs/images/countries/cz.png differ diff --git a/htdocs/images/countries/de.png b/htdocs/images/countries/de.png new file mode 100644 index 0000000..67e1bd5 Binary files /dev/null and b/htdocs/images/countries/de.png differ diff --git a/htdocs/images/countries/dk.png b/htdocs/images/countries/dk.png new file mode 100644 index 0000000..9404cf0 Binary files /dev/null and b/htdocs/images/countries/dk.png differ diff --git a/htdocs/images/countries/dz.png b/htdocs/images/countries/dz.png new file mode 100644 index 0000000..26919b1 Binary files /dev/null and b/htdocs/images/countries/dz.png differ diff --git a/htdocs/images/countries/ec.png b/htdocs/images/countries/ec.png new file mode 100644 index 0000000..961e5cd Binary files /dev/null and b/htdocs/images/countries/ec.png differ diff --git a/htdocs/images/countries/ee.png b/htdocs/images/countries/ee.png new file mode 100644 index 0000000..e0a902e Binary files /dev/null and b/htdocs/images/countries/ee.png differ diff --git a/htdocs/images/countries/eg.png b/htdocs/images/countries/eg.png new file mode 100644 index 0000000..f81b276 Binary files /dev/null and b/htdocs/images/countries/eg.png differ diff --git a/htdocs/images/countries/er.png b/htdocs/images/countries/er.png new file mode 100644 index 0000000..f96b315 Binary files /dev/null and b/htdocs/images/countries/er.png differ diff --git a/htdocs/images/countries/es.png b/htdocs/images/countries/es.png new file mode 100644 index 0000000..c85447d Binary files /dev/null and b/htdocs/images/countries/es.png differ diff --git a/htdocs/images/countries/et.png b/htdocs/images/countries/et.png new file mode 100644 index 0000000..48ff7b1 Binary files /dev/null and b/htdocs/images/countries/et.png differ diff --git a/htdocs/images/countries/fi.png b/htdocs/images/countries/fi.png new file mode 100644 index 0000000..d408743 Binary files /dev/null and b/htdocs/images/countries/fi.png differ diff --git a/htdocs/images/countries/fj.png b/htdocs/images/countries/fj.png new file mode 100644 index 0000000..6818444 Binary files /dev/null and b/htdocs/images/countries/fj.png differ diff --git a/htdocs/images/countries/fo.png b/htdocs/images/countries/fo.png new file mode 100644 index 0000000..1e12376 Binary files /dev/null and b/htdocs/images/countries/fo.png differ diff --git a/htdocs/images/countries/fr.png b/htdocs/images/countries/fr.png new file mode 100644 index 0000000..39bed1a Binary files /dev/null and b/htdocs/images/countries/fr.png differ diff --git a/htdocs/images/countries/ga.png b/htdocs/images/countries/ga.png new file mode 100644 index 0000000..8337ab9 Binary files /dev/null and b/htdocs/images/countries/ga.png differ diff --git a/htdocs/images/countries/gb.png b/htdocs/images/countries/gb.png new file mode 100644 index 0000000..30035dd Binary files /dev/null and b/htdocs/images/countries/gb.png differ diff --git a/htdocs/images/countries/ge.png b/htdocs/images/countries/ge.png new file mode 100644 index 0000000..da1ab41 Binary files /dev/null and b/htdocs/images/countries/ge.png differ diff --git a/htdocs/images/countries/gi.png b/htdocs/images/countries/gi.png new file mode 100644 index 0000000..afb539b Binary files /dev/null and b/htdocs/images/countries/gi.png differ diff --git a/htdocs/images/countries/gl.png b/htdocs/images/countries/gl.png new file mode 100644 index 0000000..66cd000 Binary files /dev/null and b/htdocs/images/countries/gl.png differ diff --git a/htdocs/images/countries/gp.png b/htdocs/images/countries/gp.png new file mode 100644 index 0000000..e4a6159 Binary files /dev/null and b/htdocs/images/countries/gp.png differ diff --git a/htdocs/images/countries/gr.png b/htdocs/images/countries/gr.png new file mode 100644 index 0000000..1fb9d52 Binary files /dev/null and b/htdocs/images/countries/gr.png differ diff --git a/htdocs/images/countries/gt.png b/htdocs/images/countries/gt.png new file mode 100644 index 0000000..7d63cb8 Binary files /dev/null and b/htdocs/images/countries/gt.png differ diff --git a/htdocs/images/countries/gu.png b/htdocs/images/countries/gu.png new file mode 100644 index 0000000..4282438 Binary files /dev/null and b/htdocs/images/countries/gu.png differ diff --git a/htdocs/images/countries/gy.png b/htdocs/images/countries/gy.png new file mode 100644 index 0000000..a5d0e8e Binary files /dev/null and b/htdocs/images/countries/gy.png differ diff --git a/htdocs/images/countries/hk.png b/htdocs/images/countries/hk.png new file mode 100644 index 0000000..e5fa24f Binary files /dev/null and b/htdocs/images/countries/hk.png differ diff --git a/htdocs/images/countries/hr.png b/htdocs/images/countries/hr.png new file mode 100644 index 0000000..fda7328 Binary files /dev/null and b/htdocs/images/countries/hr.png differ diff --git a/htdocs/images/countries/ht.png b/htdocs/images/countries/ht.png new file mode 100644 index 0000000..d058c3b Binary files /dev/null and b/htdocs/images/countries/ht.png differ diff --git a/htdocs/images/countries/hu.png b/htdocs/images/countries/hu.png new file mode 100644 index 0000000..dc4eef1 Binary files /dev/null and b/htdocs/images/countries/hu.png differ diff --git a/htdocs/images/countries/id.png b/htdocs/images/countries/id.png new file mode 100644 index 0000000..95e9ce3 Binary files /dev/null and b/htdocs/images/countries/id.png differ diff --git a/htdocs/images/countries/ie.png b/htdocs/images/countries/ie.png new file mode 100644 index 0000000..1943e6b Binary files /dev/null and b/htdocs/images/countries/ie.png differ diff --git a/htdocs/images/countries/il.png b/htdocs/images/countries/il.png new file mode 100644 index 0000000..a9161bb Binary files /dev/null and b/htdocs/images/countries/il.png differ diff --git a/htdocs/images/countries/in.png b/htdocs/images/countries/in.png new file mode 100644 index 0000000..1e404ac Binary files /dev/null and b/htdocs/images/countries/in.png differ diff --git a/htdocs/images/countries/iq.png b/htdocs/images/countries/iq.png new file mode 100644 index 0000000..1374301 Binary files /dev/null and b/htdocs/images/countries/iq.png differ diff --git a/htdocs/images/countries/ir.png b/htdocs/images/countries/ir.png new file mode 100644 index 0000000..a6f4903 Binary files /dev/null and b/htdocs/images/countries/ir.png differ diff --git a/htdocs/images/countries/is.png b/htdocs/images/countries/is.png new file mode 100644 index 0000000..9ce9864 Binary files /dev/null and b/htdocs/images/countries/is.png differ diff --git a/htdocs/images/countries/it.png b/htdocs/images/countries/it.png new file mode 100644 index 0000000..4a4ba95 Binary files /dev/null and b/htdocs/images/countries/it.png differ diff --git a/htdocs/images/countries/jm.png b/htdocs/images/countries/jm.png new file mode 100644 index 0000000..4274119 Binary files /dev/null and b/htdocs/images/countries/jm.png differ diff --git a/htdocs/images/countries/jo.png b/htdocs/images/countries/jo.png new file mode 100644 index 0000000..17e4481 Binary files /dev/null and b/htdocs/images/countries/jo.png differ diff --git a/htdocs/images/countries/jp.png b/htdocs/images/countries/jp.png new file mode 100644 index 0000000..8b52fa8 Binary files /dev/null and b/htdocs/images/countries/jp.png differ diff --git a/htdocs/images/countries/ke.png b/htdocs/images/countries/ke.png new file mode 100644 index 0000000..7bc3858 Binary files /dev/null and b/htdocs/images/countries/ke.png differ diff --git a/htdocs/images/countries/kg.png b/htdocs/images/countries/kg.png new file mode 100644 index 0000000..b176e4f Binary files /dev/null and b/htdocs/images/countries/kg.png differ diff --git a/htdocs/images/countries/kh.png b/htdocs/images/countries/kh.png new file mode 100644 index 0000000..9c94193 Binary files /dev/null and b/htdocs/images/countries/kh.png differ diff --git a/htdocs/images/countries/ki.png b/htdocs/images/countries/ki.png new file mode 100644 index 0000000..fdc58fe Binary files /dev/null and b/htdocs/images/countries/ki.png differ diff --git a/htdocs/images/countries/kp.png b/htdocs/images/countries/kp.png new file mode 100644 index 0000000..405332c Binary files /dev/null and b/htdocs/images/countries/kp.png differ diff --git a/htdocs/images/countries/kr.png b/htdocs/images/countries/kr.png new file mode 100644 index 0000000..0df561a Binary files /dev/null and b/htdocs/images/countries/kr.png differ diff --git a/htdocs/images/countries/ky.png b/htdocs/images/countries/ky.png new file mode 100644 index 0000000..ae2ba3e Binary files /dev/null and b/htdocs/images/countries/ky.png differ diff --git a/htdocs/images/countries/kz.png b/htdocs/images/countries/kz.png new file mode 100644 index 0000000..eb7b9be Binary files /dev/null and b/htdocs/images/countries/kz.png differ diff --git a/htdocs/images/countries/lb.png b/htdocs/images/countries/lb.png new file mode 100644 index 0000000..44f9e1b Binary files /dev/null and b/htdocs/images/countries/lb.png differ diff --git a/htdocs/images/countries/lc.png b/htdocs/images/countries/lc.png new file mode 100644 index 0000000..6b0389a Binary files /dev/null and b/htdocs/images/countries/lc.png differ diff --git a/htdocs/images/countries/lk.png b/htdocs/images/countries/lk.png new file mode 100644 index 0000000..2f2c48b Binary files /dev/null and b/htdocs/images/countries/lk.png differ diff --git a/htdocs/images/countries/lt.png b/htdocs/images/countries/lt.png new file mode 100644 index 0000000..c6252ce Binary files /dev/null and b/htdocs/images/countries/lt.png differ diff --git a/htdocs/images/countries/lu.png b/htdocs/images/countries/lu.png new file mode 100644 index 0000000..6a80e6e Binary files /dev/null and b/htdocs/images/countries/lu.png differ diff --git a/htdocs/images/countries/lv.png b/htdocs/images/countries/lv.png new file mode 100644 index 0000000..925ae28 Binary files /dev/null and b/htdocs/images/countries/lv.png differ diff --git a/htdocs/images/countries/ly.png b/htdocs/images/countries/ly.png new file mode 100644 index 0000000..8741c4c Binary files /dev/null and b/htdocs/images/countries/ly.png differ diff --git a/htdocs/images/countries/ma.png b/htdocs/images/countries/ma.png new file mode 100644 index 0000000..a5d9234 Binary files /dev/null and b/htdocs/images/countries/ma.png differ diff --git a/htdocs/images/countries/mc.png b/htdocs/images/countries/mc.png new file mode 100644 index 0000000..8dd6d29 Binary files /dev/null and b/htdocs/images/countries/mc.png differ diff --git a/htdocs/images/countries/md.png b/htdocs/images/countries/md.png new file mode 100644 index 0000000..9d9d278 Binary files /dev/null and b/htdocs/images/countries/md.png differ diff --git a/htdocs/images/countries/mg.png b/htdocs/images/countries/mg.png new file mode 100644 index 0000000..e93f20e Binary files /dev/null and b/htdocs/images/countries/mg.png differ diff --git a/htdocs/images/countries/mn.png b/htdocs/images/countries/mn.png new file mode 100644 index 0000000..9ce7bc9 Binary files /dev/null and b/htdocs/images/countries/mn.png differ diff --git a/htdocs/images/countries/mo.png b/htdocs/images/countries/mo.png new file mode 100644 index 0000000..21497e9 Binary files /dev/null and b/htdocs/images/countries/mo.png differ diff --git a/htdocs/images/countries/mp.png b/htdocs/images/countries/mp.png new file mode 100644 index 0000000..9523df6 Binary files /dev/null and b/htdocs/images/countries/mp.png differ diff --git a/htdocs/images/countries/ms.png b/htdocs/images/countries/ms.png new file mode 100644 index 0000000..f92b84d Binary files /dev/null and b/htdocs/images/countries/ms.png differ diff --git a/htdocs/images/countries/mt.png b/htdocs/images/countries/mt.png new file mode 100644 index 0000000..7f35e82 Binary files /dev/null and b/htdocs/images/countries/mt.png differ diff --git a/htdocs/images/countries/mx.png b/htdocs/images/countries/mx.png new file mode 100644 index 0000000..5d481f0 Binary files /dev/null and b/htdocs/images/countries/mx.png differ diff --git a/htdocs/images/countries/my.png b/htdocs/images/countries/my.png new file mode 100644 index 0000000..9fa6f81 Binary files /dev/null and b/htdocs/images/countries/my.png differ diff --git a/htdocs/images/countries/mz.png b/htdocs/images/countries/mz.png new file mode 100644 index 0000000..5e6e87b Binary files /dev/null and b/htdocs/images/countries/mz.png differ diff --git a/htdocs/images/countries/na.png b/htdocs/images/countries/na.png new file mode 100644 index 0000000..83d63cf Binary files /dev/null and b/htdocs/images/countries/na.png differ diff --git a/htdocs/images/countries/nc.png b/htdocs/images/countries/nc.png new file mode 100644 index 0000000..32eb190 Binary files /dev/null and b/htdocs/images/countries/nc.png differ diff --git a/htdocs/images/countries/nf.png b/htdocs/images/countries/nf.png new file mode 100644 index 0000000..efdc438 Binary files /dev/null and b/htdocs/images/countries/nf.png differ diff --git a/htdocs/images/countries/nl.png b/htdocs/images/countries/nl.png new file mode 100644 index 0000000..99b5e13 Binary files /dev/null and b/htdocs/images/countries/nl.png differ diff --git a/htdocs/images/countries/no.png b/htdocs/images/countries/no.png new file mode 100644 index 0000000..0199b30 Binary files /dev/null and b/htdocs/images/countries/no.png differ diff --git a/htdocs/images/countries/np.png b/htdocs/images/countries/np.png new file mode 100644 index 0000000..254744a Binary files /dev/null and b/htdocs/images/countries/np.png differ diff --git a/htdocs/images/countries/nr.png b/htdocs/images/countries/nr.png new file mode 100644 index 0000000..7f45229 Binary files /dev/null and b/htdocs/images/countries/nr.png differ diff --git a/htdocs/images/countries/nz.png b/htdocs/images/countries/nz.png new file mode 100644 index 0000000..841bb97 Binary files /dev/null and b/htdocs/images/countries/nz.png differ diff --git a/htdocs/images/countries/om.png b/htdocs/images/countries/om.png new file mode 100644 index 0000000..ad114e3 Binary files /dev/null and b/htdocs/images/countries/om.png differ diff --git a/htdocs/images/countries/pa.png b/htdocs/images/countries/pa.png new file mode 100644 index 0000000..26d5b1a Binary files /dev/null and b/htdocs/images/countries/pa.png differ diff --git a/htdocs/images/countries/pe.png b/htdocs/images/countries/pe.png new file mode 100644 index 0000000..41794a0 Binary files /dev/null and b/htdocs/images/countries/pe.png differ diff --git a/htdocs/images/countries/pf.png b/htdocs/images/countries/pf.png new file mode 100644 index 0000000..cf744fa Binary files /dev/null and b/htdocs/images/countries/pf.png differ diff --git a/htdocs/images/countries/ph.png b/htdocs/images/countries/ph.png new file mode 100644 index 0000000..24007ab Binary files /dev/null and b/htdocs/images/countries/ph.png differ diff --git a/htdocs/images/countries/pk.png b/htdocs/images/countries/pk.png new file mode 100644 index 0000000..ff220ee Binary files /dev/null and b/htdocs/images/countries/pk.png differ diff --git a/htdocs/images/countries/pl.png b/htdocs/images/countries/pl.png new file mode 100644 index 0000000..e275d90 Binary files /dev/null and b/htdocs/images/countries/pl.png differ diff --git a/htdocs/images/countries/pm.png b/htdocs/images/countries/pm.png new file mode 100644 index 0000000..6f9bf90 Binary files /dev/null and b/htdocs/images/countries/pm.png differ diff --git a/htdocs/images/countries/pr.png b/htdocs/images/countries/pr.png new file mode 100644 index 0000000..0671638 Binary files /dev/null and b/htdocs/images/countries/pr.png differ diff --git a/htdocs/images/countries/pt.png b/htdocs/images/countries/pt.png new file mode 100644 index 0000000..8d32759 Binary files /dev/null and b/htdocs/images/countries/pt.png differ diff --git a/htdocs/images/countries/py.png b/htdocs/images/countries/py.png new file mode 100644 index 0000000..bac8948 Binary files /dev/null and b/htdocs/images/countries/py.png differ diff --git a/htdocs/images/countries/qa.png b/htdocs/images/countries/qa.png new file mode 100644 index 0000000..6cf12f1 Binary files /dev/null and b/htdocs/images/countries/qa.png differ diff --git a/htdocs/images/countries/ro.png b/htdocs/images/countries/ro.png new file mode 100644 index 0000000..8d36c04 Binary files /dev/null and b/htdocs/images/countries/ro.png differ diff --git a/htdocs/images/countries/ru.png b/htdocs/images/countries/ru.png new file mode 100644 index 0000000..2b7093c Binary files /dev/null and b/htdocs/images/countries/ru.png differ diff --git a/htdocs/images/countries/sa.png b/htdocs/images/countries/sa.png new file mode 100644 index 0000000..f7982cc Binary files /dev/null and b/htdocs/images/countries/sa.png differ diff --git a/htdocs/images/countries/sb.png b/htdocs/images/countries/sb.png new file mode 100644 index 0000000..37f5c89 Binary files /dev/null and b/htdocs/images/countries/sb.png differ diff --git a/htdocs/images/countries/sd.png b/htdocs/images/countries/sd.png new file mode 100644 index 0000000..32398df Binary files /dev/null and b/htdocs/images/countries/sd.png differ diff --git a/htdocs/images/countries/se.png b/htdocs/images/countries/se.png new file mode 100644 index 0000000..df1775d Binary files /dev/null and b/htdocs/images/countries/se.png differ diff --git a/htdocs/images/countries/sg.png b/htdocs/images/countries/sg.png new file mode 100644 index 0000000..51dc5a8 Binary files /dev/null and b/htdocs/images/countries/sg.png differ diff --git a/htdocs/images/countries/si.png b/htdocs/images/countries/si.png new file mode 100644 index 0000000..e8f8743 Binary files /dev/null and b/htdocs/images/countries/si.png differ diff --git a/htdocs/images/countries/sk.png b/htdocs/images/countries/sk.png new file mode 100644 index 0000000..d605271 Binary files /dev/null and b/htdocs/images/countries/sk.png differ diff --git a/htdocs/images/countries/sl.png b/htdocs/images/countries/sl.png new file mode 100644 index 0000000..beafb9f Binary files /dev/null and b/htdocs/images/countries/sl.png differ diff --git a/htdocs/images/countries/so.png b/htdocs/images/countries/so.png new file mode 100644 index 0000000..d087512 Binary files /dev/null and b/htdocs/images/countries/so.png differ diff --git a/htdocs/images/countries/sr.png b/htdocs/images/countries/sr.png new file mode 100644 index 0000000..e06354f Binary files /dev/null and b/htdocs/images/countries/sr.png differ diff --git a/htdocs/images/countries/sy.png b/htdocs/images/countries/sy.png new file mode 100644 index 0000000..be08e92 Binary files /dev/null and b/htdocs/images/countries/sy.png differ diff --git a/htdocs/images/countries/tc.png b/htdocs/images/countries/tc.png new file mode 100644 index 0000000..e24e1ff Binary files /dev/null and b/htdocs/images/countries/tc.png differ diff --git a/htdocs/images/countries/tg.png b/htdocs/images/countries/tg.png new file mode 100644 index 0000000..74ed93c Binary files /dev/null and b/htdocs/images/countries/tg.png differ diff --git a/htdocs/images/countries/th.png b/htdocs/images/countries/th.png new file mode 100644 index 0000000..5e15d0e Binary files /dev/null and b/htdocs/images/countries/th.png differ diff --git a/htdocs/images/countries/tn.png b/htdocs/images/countries/tn.png new file mode 100644 index 0000000..f05f134 Binary files /dev/null and b/htdocs/images/countries/tn.png differ diff --git a/htdocs/images/countries/to.png b/htdocs/images/countries/to.png new file mode 100644 index 0000000..b53e46f Binary files /dev/null and b/htdocs/images/countries/to.png differ diff --git a/htdocs/images/countries/tp.png b/htdocs/images/countries/tp.png new file mode 100644 index 0000000..f8b4dca Binary files /dev/null and b/htdocs/images/countries/tp.png differ diff --git a/htdocs/images/countries/tr.png b/htdocs/images/countries/tr.png new file mode 100644 index 0000000..0ecd06c Binary files /dev/null and b/htdocs/images/countries/tr.png differ diff --git a/htdocs/images/countries/tt.png b/htdocs/images/countries/tt.png new file mode 100644 index 0000000..927700c Binary files /dev/null and b/htdocs/images/countries/tt.png differ diff --git a/htdocs/images/countries/tv.png b/htdocs/images/countries/tv.png new file mode 100644 index 0000000..433deec Binary files /dev/null and b/htdocs/images/countries/tv.png differ diff --git a/htdocs/images/countries/tw.png b/htdocs/images/countries/tw.png new file mode 100644 index 0000000..2e82e66 Binary files /dev/null and b/htdocs/images/countries/tw.png differ diff --git a/htdocs/images/countries/tz.png b/htdocs/images/countries/tz.png new file mode 100644 index 0000000..c668335 Binary files /dev/null and b/htdocs/images/countries/tz.png differ diff --git a/htdocs/images/countries/ua.png b/htdocs/images/countries/ua.png new file mode 100644 index 0000000..db85d97 Binary files /dev/null and b/htdocs/images/countries/ua.png differ diff --git a/htdocs/images/countries/ug.png b/htdocs/images/countries/ug.png new file mode 100644 index 0000000..5c87b92 Binary files /dev/null and b/htdocs/images/countries/ug.png differ diff --git a/htdocs/images/countries/us.png b/htdocs/images/countries/us.png new file mode 100644 index 0000000..652cb3e Binary files /dev/null and b/htdocs/images/countries/us.png differ diff --git a/htdocs/images/countries/uy.png b/htdocs/images/countries/uy.png new file mode 100644 index 0000000..aec1979 Binary files /dev/null and b/htdocs/images/countries/uy.png differ diff --git a/htdocs/images/countries/va.png b/htdocs/images/countries/va.png new file mode 100644 index 0000000..0fc5b5f Binary files /dev/null and b/htdocs/images/countries/va.png differ diff --git a/htdocs/images/countries/ve.png b/htdocs/images/countries/ve.png new file mode 100644 index 0000000..0a90e47 Binary files /dev/null and b/htdocs/images/countries/ve.png differ diff --git a/htdocs/images/countries/vg.png b/htdocs/images/countries/vg.png new file mode 100644 index 0000000..1ff7ca1 Binary files /dev/null and b/htdocs/images/countries/vg.png differ diff --git a/htdocs/images/countries/vi.png b/htdocs/images/countries/vi.png new file mode 100644 index 0000000..c7e8572 Binary files /dev/null and b/htdocs/images/countries/vi.png differ diff --git a/htdocs/images/countries/vn.png b/htdocs/images/countries/vn.png new file mode 100644 index 0000000..31af3d5 Binary files /dev/null and b/htdocs/images/countries/vn.png differ diff --git a/htdocs/images/countries/ws.png b/htdocs/images/countries/ws.png new file mode 100644 index 0000000..654b842 Binary files /dev/null and b/htdocs/images/countries/ws.png differ diff --git a/htdocs/images/countries/ye.png b/htdocs/images/countries/ye.png new file mode 100644 index 0000000..4c547cc Binary files /dev/null and b/htdocs/images/countries/ye.png differ diff --git a/htdocs/images/countries/yu.png b/htdocs/images/countries/yu.png new file mode 100644 index 0000000..9947f62 Binary files /dev/null and b/htdocs/images/countries/yu.png differ diff --git a/htdocs/images/countries/za.png b/htdocs/images/countries/za.png new file mode 100644 index 0000000..f9745fa Binary files /dev/null and b/htdocs/images/countries/za.png differ diff --git a/htdocs/images/countries/zw.png b/htdocs/images/countries/zw.png new file mode 100644 index 0000000..7e69c9e Binary files /dev/null and b/htdocs/images/countries/zw.png differ diff --git a/htdocs/images/default/add.png b/htdocs/images/default/add.png new file mode 100644 index 0000000..7c04bad Binary files /dev/null and b/htdocs/images/default/add.png differ diff --git a/htdocs/images/default/address-book.png b/htdocs/images/default/address-book.png new file mode 100644 index 0000000..907d939 Binary files /dev/null and b/htdocs/images/default/address-book.png differ diff --git a/htdocs/images/default/bug-big.png b/htdocs/images/default/bug-big.png new file mode 100644 index 0000000..0758a85 Binary files /dev/null and b/htdocs/images/default/bug-big.png differ diff --git a/htdocs/images/default/bug.png b/htdocs/images/default/bug.png new file mode 100644 index 0000000..132f93f Binary files /dev/null and b/htdocs/images/default/bug.png differ diff --git a/htdocs/images/default/calendar.png b/htdocs/images/default/calendar.png new file mode 100644 index 0000000..c3cdf73 Binary files /dev/null and b/htdocs/images/default/calendar.png differ diff --git a/htdocs/images/default/catalog.png b/htdocs/images/default/catalog.png new file mode 100644 index 0000000..907d939 Binary files /dev/null and b/htdocs/images/default/catalog.png differ diff --git a/htdocs/images/default/children.png b/htdocs/images/default/children.png new file mode 100644 index 0000000..6fdc884 Binary files /dev/null and b/htdocs/images/default/children.png differ diff --git a/htdocs/images/default/compare.png b/htdocs/images/default/compare.png new file mode 100644 index 0000000..7d199fc Binary files /dev/null and b/htdocs/images/default/compare.png differ diff --git a/htdocs/images/default/country.png b/htdocs/images/default/country.png new file mode 100644 index 0000000..7640da3 Binary files /dev/null and b/htdocs/images/default/country.png differ diff --git a/htdocs/images/default/create.png b/htdocs/images/default/create.png new file mode 100644 index 0000000..458c730 Binary files /dev/null and b/htdocs/images/default/create.png differ diff --git a/htdocs/images/default/cut.png b/htdocs/images/default/cut.png new file mode 100644 index 0000000..3c21b9b Binary files /dev/null and b/htdocs/images/default/cut.png differ diff --git a/htdocs/images/default/debug-cache.png b/htdocs/images/default/debug-cache.png new file mode 100644 index 0000000..61ae9ef Binary files /dev/null and b/htdocs/images/default/debug-cache.png differ diff --git a/htdocs/images/default/device.png b/htdocs/images/default/device.png new file mode 100644 index 0000000..eb153a3 Binary files /dev/null and b/htdocs/images/default/device.png differ diff --git a/htdocs/images/default/disabled.png b/htdocs/images/default/disabled.png new file mode 100644 index 0000000..1c427c0 Binary files /dev/null and b/htdocs/images/default/disabled.png differ diff --git a/htdocs/images/default/document.png b/htdocs/images/default/document.png new file mode 100644 index 0000000..62ea2ee Binary files /dev/null and b/htdocs/images/default/document.png differ diff --git a/htdocs/images/default/door.png b/htdocs/images/default/door.png new file mode 100644 index 0000000..6720965 Binary files /dev/null and b/htdocs/images/default/door.png differ diff --git a/htdocs/images/default/error-big.png b/htdocs/images/default/error-big.png new file mode 100644 index 0000000..0539ce8 Binary files /dev/null and b/htdocs/images/default/error-big.png differ diff --git a/htdocs/images/default/error.png b/htdocs/images/default/error.png new file mode 100644 index 0000000..a7cdbc7 Binary files /dev/null and b/htdocs/images/default/error.png differ diff --git a/htdocs/images/default/export-big.png b/htdocs/images/default/export-big.png new file mode 100644 index 0000000..6bb2ec6 Binary files /dev/null and b/htdocs/images/default/export-big.png differ diff --git a/htdocs/images/default/export.png b/htdocs/images/default/export.png new file mode 100644 index 0000000..6bb2ec6 Binary files /dev/null and b/htdocs/images/default/export.png differ diff --git a/htdocs/images/default/files.png b/htdocs/images/default/files.png new file mode 100644 index 0000000..ccb1d32 Binary files /dev/null and b/htdocs/images/default/files.png differ diff --git a/htdocs/images/default/find.png b/htdocs/images/default/find.png new file mode 100644 index 0000000..ed5c07e Binary files /dev/null and b/htdocs/images/default/find.png differ diff --git a/htdocs/images/default/folder.png b/htdocs/images/default/folder.png new file mode 100644 index 0000000..cce6d34 Binary files /dev/null and b/htdocs/images/default/folder.png differ diff --git a/htdocs/images/default/forum-big.png b/htdocs/images/default/forum-big.png new file mode 100644 index 0000000..674a8e9 Binary files /dev/null and b/htdocs/images/default/forum-big.png differ diff --git a/htdocs/images/default/hard-drive.png b/htdocs/images/default/hard-drive.png new file mode 100644 index 0000000..f3da3d2 Binary files /dev/null and b/htdocs/images/default/hard-drive.png differ diff --git a/htdocs/images/default/help-big.png b/htdocs/images/default/help-big.png new file mode 100644 index 0000000..bbda895 Binary files /dev/null and b/htdocs/images/default/help-big.png differ diff --git a/htdocs/images/default/help.png b/htdocs/images/default/help.png new file mode 100644 index 0000000..674a8e9 Binary files /dev/null and b/htdocs/images/default/help.png differ diff --git a/htdocs/images/default/home-big.png b/htdocs/images/default/home-big.png new file mode 100644 index 0000000..d40900d Binary files /dev/null and b/htdocs/images/default/home-big.png differ diff --git a/htdocs/images/default/home.png b/htdocs/images/default/home.png new file mode 100644 index 0000000..aa6a5c8 Binary files /dev/null and b/htdocs/images/default/home.png differ diff --git a/htdocs/images/default/host.png b/htdocs/images/default/host.png new file mode 100644 index 0000000..87426e7 Binary files /dev/null and b/htdocs/images/default/host.png differ diff --git a/htdocs/images/default/import-big.png b/htdocs/images/default/import-big.png new file mode 100644 index 0000000..ed62d53 Binary files /dev/null and b/htdocs/images/default/import-big.png differ diff --git a/htdocs/images/default/index.php b/htdocs/images/default/index.php new file mode 100644 index 0000000..0d4445f --- /dev/null +++ b/htdocs/images/default/index.php @@ -0,0 +1,51 @@ + + + + + +

phpLDAPadmin icons

+
+
+The " . count( $files ) . " icons used by phpLDAPadmin
"; +echo ""; +echo ""; +foreach( $files as $file ) { + if( $counter % 6 == 0 ) { + echo "\n"; + flush(); + echo ""; + } + $counter++; + echo '\n"; +} + +?> + + + diff --git a/htdocs/images/default/info-big.png b/htdocs/images/default/info-big.png new file mode 100644 index 0000000..5a2cd96 Binary files /dev/null and b/htdocs/images/default/info-big.png differ diff --git a/htdocs/images/default/info.png b/htdocs/images/default/info.png new file mode 100644 index 0000000..092335a Binary files /dev/null and b/htdocs/images/default/info.png differ diff --git a/htdocs/images/default/invalid.png b/htdocs/images/default/invalid.png new file mode 100644 index 0000000..1c427c0 Binary files /dev/null and b/htdocs/images/default/invalid.png differ diff --git a/htdocs/images/default/key.png b/htdocs/images/default/key.png new file mode 100644 index 0000000..2ecb08d Binary files /dev/null and b/htdocs/images/default/key.png differ diff --git a/htdocs/images/default/ldap-alias.png b/htdocs/images/default/ldap-alias.png new file mode 100644 index 0000000..78dfcf8 Binary files /dev/null and b/htdocs/images/default/ldap-alias.png differ diff --git a/htdocs/images/default/ldap-dc.png b/htdocs/images/default/ldap-dc.png new file mode 100644 index 0000000..2769a47 Binary files /dev/null and b/htdocs/images/default/ldap-dc.png differ diff --git a/htdocs/images/default/ldap-default.png b/htdocs/images/default/ldap-default.png new file mode 100644 index 0000000..a77ff35 Binary files /dev/null and b/htdocs/images/default/ldap-default.png differ diff --git a/htdocs/images/default/ldap-o.png b/htdocs/images/default/ldap-o.png new file mode 100644 index 0000000..dfb89eb Binary files /dev/null and b/htdocs/images/default/ldap-o.png differ diff --git a/htdocs/images/default/ldap-ou.png b/htdocs/images/default/ldap-ou.png new file mode 100644 index 0000000..3e767c7 Binary files /dev/null and b/htdocs/images/default/ldap-ou.png differ diff --git a/htdocs/images/default/ldap-server.png b/htdocs/images/default/ldap-server.png new file mode 100644 index 0000000..d40900d Binary files /dev/null and b/htdocs/images/default/ldap-server.png differ diff --git a/htdocs/images/default/ldap-uid.png b/htdocs/images/default/ldap-uid.png new file mode 100644 index 0000000..7be48fb Binary files /dev/null and b/htdocs/images/default/ldap-uid.png differ diff --git a/htdocs/images/default/ldap-uniquegroup.png b/htdocs/images/default/ldap-uniquegroup.png new file mode 100644 index 0000000..c86d4a1 Binary files /dev/null and b/htdocs/images/default/ldap-uniquegroup.png differ diff --git a/htdocs/images/default/ldap-user.png b/htdocs/images/default/ldap-user.png new file mode 100644 index 0000000..647e429 Binary files /dev/null and b/htdocs/images/default/ldap-user.png differ diff --git a/htdocs/images/default/light-big.png b/htdocs/images/default/light-big.png new file mode 100644 index 0000000..d22f5e9 Binary files /dev/null and b/htdocs/images/default/light-big.png differ diff --git a/htdocs/images/default/light.png b/htdocs/images/default/light.png new file mode 100644 index 0000000..8859899 Binary files /dev/null and b/htdocs/images/default/light.png differ diff --git a/htdocs/images/default/locality.png b/htdocs/images/default/locality.png new file mode 100644 index 0000000..c80540b Binary files /dev/null and b/htdocs/images/default/locality.png differ diff --git a/htdocs/images/default/lock.png b/htdocs/images/default/lock.png new file mode 100644 index 0000000..6af707e Binary files /dev/null and b/htdocs/images/default/lock.png differ diff --git a/htdocs/images/default/login.png b/htdocs/images/default/login.png new file mode 100644 index 0000000..7be48fb Binary files /dev/null and b/htdocs/images/default/login.png differ diff --git a/htdocs/images/default/logo-small.png b/htdocs/images/default/logo-small.png new file mode 100644 index 0000000..6fcdbf9 Binary files /dev/null and b/htdocs/images/default/logo-small.png differ diff --git a/htdocs/images/default/logo.png b/htdocs/images/default/logo.png new file mode 100644 index 0000000..a95539e Binary files /dev/null and b/htdocs/images/default/logo.png differ diff --git a/htdocs/images/default/logout-big.png b/htdocs/images/default/logout-big.png new file mode 100644 index 0000000..393598b Binary files /dev/null and b/htdocs/images/default/logout-big.png differ diff --git a/htdocs/images/default/mail.png b/htdocs/images/default/mail.png new file mode 100644 index 0000000..bd77aff Binary files /dev/null and b/htdocs/images/default/mail.png differ diff --git a/htdocs/images/default/mail_account.png b/htdocs/images/default/mail_account.png new file mode 100644 index 0000000..6d0dc92 Binary files /dev/null and b/htdocs/images/default/mail_account.png differ diff --git a/htdocs/images/default/mail_alias.png b/htdocs/images/default/mail_alias.png new file mode 100644 index 0000000..4edbee4 Binary files /dev/null and b/htdocs/images/default/mail_alias.png differ diff --git a/htdocs/images/default/minus.png b/htdocs/images/default/minus.png new file mode 100644 index 0000000..6ff9066 Binary files /dev/null and b/htdocs/images/default/minus.png differ diff --git a/htdocs/images/default/monitorserver-big.png b/htdocs/images/default/monitorserver-big.png new file mode 100644 index 0000000..d40900d Binary files /dev/null and b/htdocs/images/default/monitorserver-big.png differ diff --git a/htdocs/images/default/move.png b/htdocs/images/default/move.png new file mode 100644 index 0000000..9542d51 Binary files /dev/null and b/htdocs/images/default/move.png differ diff --git a/htdocs/images/default/n.png b/htdocs/images/default/n.png new file mode 100644 index 0000000..a035c34 Binary files /dev/null and b/htdocs/images/default/n.png differ diff --git a/htdocs/images/default/network.png b/htdocs/images/default/network.png new file mode 100644 index 0000000..008b03f Binary files /dev/null and b/htdocs/images/default/network.png differ diff --git a/htdocs/images/default/nogo.png b/htdocs/images/default/nogo.png new file mode 100644 index 0000000..cf1a203 Binary files /dev/null and b/htdocs/images/default/nogo.png differ diff --git a/htdocs/images/default/nt_machine.png b/htdocs/images/default/nt_machine.png new file mode 100644 index 0000000..4d3737a Binary files /dev/null and b/htdocs/images/default/nt_machine.png differ diff --git a/htdocs/images/default/nt_user.png b/htdocs/images/default/nt_user.png new file mode 100644 index 0000000..b69a641 Binary files /dev/null and b/htdocs/images/default/nt_user.png differ diff --git a/htdocs/images/default/paypal-donate.png b/htdocs/images/default/paypal-donate.png new file mode 100644 index 0000000..10d5628 Binary files /dev/null and b/htdocs/images/default/paypal-donate.png differ diff --git a/htdocs/images/default/phone.png b/htdocs/images/default/phone.png new file mode 100644 index 0000000..f319d1a Binary files /dev/null and b/htdocs/images/default/phone.png differ diff --git a/htdocs/images/default/photo.png b/htdocs/images/default/photo.png new file mode 100644 index 0000000..f957404 Binary files /dev/null and b/htdocs/images/default/photo.png differ diff --git a/htdocs/images/default/plus.png b/htdocs/images/default/plus.png new file mode 100644 index 0000000..f66b1a8 Binary files /dev/null and b/htdocs/images/default/plus.png differ diff --git a/htdocs/images/default/process.png b/htdocs/images/default/process.png new file mode 100644 index 0000000..e3495eb Binary files /dev/null and b/htdocs/images/default/process.png differ diff --git a/htdocs/images/default/refresh-big.png b/htdocs/images/default/refresh-big.png new file mode 100644 index 0000000..22fabff Binary files /dev/null and b/htdocs/images/default/refresh-big.png differ diff --git a/htdocs/images/default/refresh.png b/htdocs/images/default/refresh.png new file mode 100644 index 0000000..05fb5f3 Binary files /dev/null and b/htdocs/images/default/refresh.png differ diff --git a/htdocs/images/default/rename.png b/htdocs/images/default/rename.png new file mode 100644 index 0000000..320d2e5 Binary files /dev/null and b/htdocs/images/default/rename.png differ diff --git a/htdocs/images/default/request-feature-big.png b/htdocs/images/default/request-feature-big.png new file mode 100644 index 0000000..b7b1241 Binary files /dev/null and b/htdocs/images/default/request-feature-big.png differ diff --git a/htdocs/images/default/rfc.png b/htdocs/images/default/rfc.png new file mode 100644 index 0000000..531caee Binary files /dev/null and b/htdocs/images/default/rfc.png differ diff --git a/htdocs/images/default/save.png b/htdocs/images/default/save.png new file mode 100644 index 0000000..a7811a4 Binary files /dev/null and b/htdocs/images/default/save.png differ diff --git a/htdocs/images/default/schema-big.png b/htdocs/images/default/schema-big.png new file mode 100644 index 0000000..6248d56 Binary files /dev/null and b/htdocs/images/default/schema-big.png differ diff --git a/htdocs/images/default/search-big.png b/htdocs/images/default/search-big.png new file mode 100644 index 0000000..904b1a8 Binary files /dev/null and b/htdocs/images/default/search-big.png differ diff --git a/htdocs/images/default/server-settings.png b/htdocs/images/default/server-settings.png new file mode 100644 index 0000000..4d8f1a1 Binary files /dev/null and b/htdocs/images/default/server-settings.png differ diff --git a/htdocs/images/default/server-small.png b/htdocs/images/default/server-small.png new file mode 100644 index 0000000..3d1e0f6 Binary files /dev/null and b/htdocs/images/default/server-small.png differ diff --git a/htdocs/images/default/server.png b/htdocs/images/default/server.png new file mode 100644 index 0000000..4f6c2a4 Binary files /dev/null and b/htdocs/images/default/server.png differ diff --git a/htdocs/images/default/smile-big.png b/htdocs/images/default/smile-big.png new file mode 100644 index 0000000..22fba5f Binary files /dev/null and b/htdocs/images/default/smile-big.png differ diff --git a/htdocs/images/default/smile.png b/htdocs/images/default/smile.png new file mode 100644 index 0000000..3eb3152 Binary files /dev/null and b/htdocs/images/default/smile.png differ diff --git a/htdocs/images/default/switch.png b/htdocs/images/default/switch.png new file mode 100644 index 0000000..907d939 Binary files /dev/null and b/htdocs/images/default/switch.png differ diff --git a/htdocs/images/default/terminal.png b/htdocs/images/default/terminal.png new file mode 100644 index 0000000..8f07296 Binary files /dev/null and b/htdocs/images/default/terminal.png differ diff --git a/htdocs/images/default/timeout.png b/htdocs/images/default/timeout.png new file mode 100644 index 0000000..529d8a4 Binary files /dev/null and b/htdocs/images/default/timeout.png differ diff --git a/htdocs/images/default/tools-no.png b/htdocs/images/default/tools-no.png new file mode 100644 index 0000000..96a04d1 Binary files /dev/null and b/htdocs/images/default/tools-no.png differ diff --git a/htdocs/images/default/tools.png b/htdocs/images/default/tools.png new file mode 100644 index 0000000..b391a0e Binary files /dev/null and b/htdocs/images/default/tools.png differ diff --git a/htdocs/images/default/trash-big.png b/htdocs/images/default/trash-big.png new file mode 100644 index 0000000..6b638c5 Binary files /dev/null and b/htdocs/images/default/trash-big.png differ diff --git a/htdocs/images/default/trash.png b/htdocs/images/default/trash.png new file mode 100644 index 0000000..d88ddbb Binary files /dev/null and b/htdocs/images/default/trash.png differ diff --git a/htdocs/images/default/tree_collapse.png b/htdocs/images/default/tree_collapse.png new file mode 100644 index 0000000..1c9be75 Binary files /dev/null and b/htdocs/images/default/tree_collapse.png differ diff --git a/htdocs/images/default/tree_collapse_corner.png b/htdocs/images/default/tree_collapse_corner.png new file mode 100644 index 0000000..b3328ad Binary files /dev/null and b/htdocs/images/default/tree_collapse_corner.png differ diff --git a/htdocs/images/default/tree_collapse_corner_first.png b/htdocs/images/default/tree_collapse_corner_first.png new file mode 100644 index 0000000..122b980 Binary files /dev/null and b/htdocs/images/default/tree_collapse_corner_first.png differ diff --git a/htdocs/images/default/tree_collapse_first.png b/htdocs/images/default/tree_collapse_first.png new file mode 100644 index 0000000..5c43876 Binary files /dev/null and b/htdocs/images/default/tree_collapse_first.png differ diff --git a/htdocs/images/default/tree_corner.png b/htdocs/images/default/tree_corner.png new file mode 100644 index 0000000..541c5b3 Binary files /dev/null and b/htdocs/images/default/tree_corner.png differ diff --git a/htdocs/images/default/tree_expand.png b/htdocs/images/default/tree_expand.png new file mode 100644 index 0000000..e94aecf Binary files /dev/null and b/htdocs/images/default/tree_expand.png differ diff --git a/htdocs/images/default/tree_expand_corner.png b/htdocs/images/default/tree_expand_corner.png new file mode 100644 index 0000000..4293f76 Binary files /dev/null and b/htdocs/images/default/tree_expand_corner.png differ diff --git a/htdocs/images/default/tree_expand_corner_first.png b/htdocs/images/default/tree_expand_corner_first.png new file mode 100644 index 0000000..5de11a6 Binary files /dev/null and b/htdocs/images/default/tree_expand_corner_first.png differ diff --git a/htdocs/images/default/tree_expand_first.png b/htdocs/images/default/tree_expand_first.png new file mode 100644 index 0000000..034b88e Binary files /dev/null and b/htdocs/images/default/tree_expand_first.png differ diff --git a/htdocs/images/default/tree_folder_closed.png b/htdocs/images/default/tree_folder_closed.png new file mode 100644 index 0000000..f1bfd01 Binary files /dev/null and b/htdocs/images/default/tree_folder_closed.png differ diff --git a/htdocs/images/default/tree_folder_open.png b/htdocs/images/default/tree_folder_open.png new file mode 100644 index 0000000..4190b96 Binary files /dev/null and b/htdocs/images/default/tree_folder_open.png differ diff --git a/htdocs/images/default/tree_leaf.png b/htdocs/images/default/tree_leaf.png new file mode 100644 index 0000000..6f999fb Binary files /dev/null and b/htdocs/images/default/tree_leaf.png differ diff --git a/htdocs/images/default/tree_space.png b/htdocs/images/default/tree_space.png new file mode 100644 index 0000000..fbdfa6a Binary files /dev/null and b/htdocs/images/default/tree_space.png differ diff --git a/htdocs/images/default/tree_split.png b/htdocs/images/default/tree_split.png new file mode 100644 index 0000000..1a49fab Binary files /dev/null and b/htdocs/images/default/tree_split.png differ diff --git a/htdocs/images/default/tree_split_first.png b/htdocs/images/default/tree_split_first.png new file mode 100644 index 0000000..e915d03 Binary files /dev/null and b/htdocs/images/default/tree_split_first.png differ diff --git a/htdocs/images/default/tree_vertline.png b/htdocs/images/default/tree_vertline.png new file mode 100644 index 0000000..261ff13 Binary files /dev/null and b/htdocs/images/default/tree_vertline.png differ diff --git a/htdocs/images/default/unknown.png b/htdocs/images/default/unknown.png new file mode 100644 index 0000000..2164ac1 Binary files /dev/null and b/htdocs/images/default/unknown.png differ diff --git a/htdocs/images/default/up.png b/htdocs/images/default/up.png new file mode 100644 index 0000000..865ec15 Binary files /dev/null and b/htdocs/images/default/up.png differ diff --git a/htdocs/images/default/warn-big.png b/htdocs/images/default/warn-big.png new file mode 100644 index 0000000..070b926 Binary files /dev/null and b/htdocs/images/default/warn-big.png differ diff --git a/htdocs/images/favicon.ico b/htdocs/images/favicon.ico new file mode 100644 index 0000000..7865d94 Binary files /dev/null and b/htdocs/images/favicon.ico differ diff --git a/htdocs/images/tango/INFO b/htdocs/images/tango/INFO new file mode 100644 index 0000000..f1426a3 --- /dev/null +++ b/htdocs/images/tango/INFO @@ -0,0 +1,2 @@ +This icons have been sourced from the Tango Icon Library at http://tango.freedesktop.org/Tango_Icon_Library +Please be sure to ackowledge the artists for their great icons :) diff --git a/htdocs/images/tango/add-big.png b/htdocs/images/tango/add-big.png new file mode 100644 index 0000000..2acdd8f Binary files /dev/null and b/htdocs/images/tango/add-big.png differ diff --git a/htdocs/images/tango/add.png b/htdocs/images/tango/add.png new file mode 100644 index 0000000..1aa7f09 Binary files /dev/null and b/htdocs/images/tango/add.png differ diff --git a/htdocs/images/tango/address-book.png b/htdocs/images/tango/address-book.png new file mode 100644 index 0000000..2098cfd Binary files /dev/null and b/htdocs/images/tango/address-book.png differ diff --git a/htdocs/images/tango/bug-big.png b/htdocs/images/tango/bug-big.png new file mode 100644 index 0000000..3d67d9e Binary files /dev/null and b/htdocs/images/tango/bug-big.png differ diff --git a/htdocs/images/tango/bug.png b/htdocs/images/tango/bug.png new file mode 100644 index 0000000..433945d Binary files /dev/null and b/htdocs/images/tango/bug.png differ diff --git a/htdocs/images/tango/children-big.png b/htdocs/images/tango/children-big.png new file mode 100644 index 0000000..2a34a8f Binary files /dev/null and b/htdocs/images/tango/children-big.png differ diff --git a/htdocs/images/tango/children.png b/htdocs/images/tango/children.png new file mode 100644 index 0000000..663cbad Binary files /dev/null and b/htdocs/images/tango/children.png differ diff --git a/htdocs/images/tango/compare-big.png b/htdocs/images/tango/compare-big.png new file mode 100644 index 0000000..5594785 Binary files /dev/null and b/htdocs/images/tango/compare-big.png differ diff --git a/htdocs/images/tango/compare.png b/htdocs/images/tango/compare.png new file mode 100644 index 0000000..d072d3c Binary files /dev/null and b/htdocs/images/tango/compare.png differ diff --git a/htdocs/images/tango/create-big.png b/htdocs/images/tango/create-big.png new file mode 100644 index 0000000..e6d64bb Binary files /dev/null and b/htdocs/images/tango/create-big.png differ diff --git a/htdocs/images/tango/create.png b/htdocs/images/tango/create.png new file mode 100644 index 0000000..4c3efdd Binary files /dev/null and b/htdocs/images/tango/create.png differ diff --git a/htdocs/images/tango/cut-big.png b/htdocs/images/tango/cut-big.png new file mode 100644 index 0000000..217663b Binary files /dev/null and b/htdocs/images/tango/cut-big.png differ diff --git a/htdocs/images/tango/cut.png b/htdocs/images/tango/cut.png new file mode 100644 index 0000000..dc9eb9a Binary files /dev/null and b/htdocs/images/tango/cut.png differ diff --git a/htdocs/images/tango/disabled-big.png b/htdocs/images/tango/disabled-big.png new file mode 100644 index 0000000..e7a8d17 Binary files /dev/null and b/htdocs/images/tango/disabled-big.png differ diff --git a/htdocs/images/tango/disabled.png b/htdocs/images/tango/disabled.png new file mode 100644 index 0000000..ab6808f Binary files /dev/null and b/htdocs/images/tango/disabled.png differ diff --git a/htdocs/images/tango/error-big.png b/htdocs/images/tango/error-big.png new file mode 100644 index 0000000..cdd95ba Binary files /dev/null and b/htdocs/images/tango/error-big.png differ diff --git a/htdocs/images/tango/error.png b/htdocs/images/tango/error.png new file mode 100644 index 0000000..3bbbb4a Binary files /dev/null and b/htdocs/images/tango/error.png differ diff --git a/htdocs/images/tango/export-big.png b/htdocs/images/tango/export-big.png new file mode 100644 index 0000000..bf2e8c8 Binary files /dev/null and b/htdocs/images/tango/export-big.png differ diff --git a/htdocs/images/tango/export.png b/htdocs/images/tango/export.png new file mode 100644 index 0000000..4ced6fe Binary files /dev/null and b/htdocs/images/tango/export.png differ diff --git a/htdocs/images/tango/forum-big.png b/htdocs/images/tango/forum-big.png new file mode 100644 index 0000000..9cb1d3b Binary files /dev/null and b/htdocs/images/tango/forum-big.png differ diff --git a/htdocs/images/tango/forum.png b/htdocs/images/tango/forum.png new file mode 100644 index 0000000..f6e8325 Binary files /dev/null and b/htdocs/images/tango/forum.png differ diff --git a/htdocs/images/tango/help-big.png b/htdocs/images/tango/help-big.png new file mode 100644 index 0000000..4682b36 Binary files /dev/null and b/htdocs/images/tango/help-big.png differ diff --git a/htdocs/images/tango/help.png b/htdocs/images/tango/help.png new file mode 100644 index 0000000..2a63cee Binary files /dev/null and b/htdocs/images/tango/help.png differ diff --git a/htdocs/images/tango/import-big.png b/htdocs/images/tango/import-big.png new file mode 100644 index 0000000..5c9f6b3 Binary files /dev/null and b/htdocs/images/tango/import-big.png differ diff --git a/htdocs/images/tango/import.png b/htdocs/images/tango/import.png new file mode 100644 index 0000000..9bed143 Binary files /dev/null and b/htdocs/images/tango/import.png differ diff --git a/htdocs/images/tango/index.php b/htdocs/images/tango/index.php new file mode 100644 index 0000000..0d4445f --- /dev/null +++ b/htdocs/images/tango/index.php @@ -0,0 +1,51 @@ + + + + + +

phpLDAPadmin icons

+
+
+The " . count( $files ) . " icons used by phpLDAPadmin
"; +echo "

'; + echo "$file
"; +echo ""; +foreach( $files as $file ) { + if( $counter % 6 == 0 ) { + echo "\n"; + flush(); + echo ""; + } + $counter++; + echo '\n"; +} + +?> + + + diff --git a/htdocs/images/tango/info-big.png b/htdocs/images/tango/info-big.png new file mode 100644 index 0000000..d60425f Binary files /dev/null and b/htdocs/images/tango/info-big.png differ diff --git a/htdocs/images/tango/info.png b/htdocs/images/tango/info.png new file mode 100644 index 0000000..f25fc3f Binary files /dev/null and b/htdocs/images/tango/info.png differ diff --git a/htdocs/images/tango/key.png b/htdocs/images/tango/key.png new file mode 100644 index 0000000..486913d Binary files /dev/null and b/htdocs/images/tango/key.png differ diff --git a/htdocs/images/tango/ldap-alias-big.png b/htdocs/images/tango/ldap-alias-big.png new file mode 100644 index 0000000..a68e2db Binary files /dev/null and b/htdocs/images/tango/ldap-alias-big.png differ diff --git a/htdocs/images/tango/ldap-alias.png b/htdocs/images/tango/ldap-alias.png new file mode 100644 index 0000000..6ef8de7 Binary files /dev/null and b/htdocs/images/tango/ldap-alias.png differ diff --git a/htdocs/images/tango/ldap-dc.png b/htdocs/images/tango/ldap-dc.png new file mode 100644 index 0000000..5c140d8 Binary files /dev/null and b/htdocs/images/tango/ldap-dc.png differ diff --git a/htdocs/images/tango/ldap-default.png b/htdocs/images/tango/ldap-default.png new file mode 100644 index 0000000..259ed26 Binary files /dev/null and b/htdocs/images/tango/ldap-default.png differ diff --git a/htdocs/images/tango/ldap-o.png b/htdocs/images/tango/ldap-o.png new file mode 100644 index 0000000..ac5957a Binary files /dev/null and b/htdocs/images/tango/ldap-o.png differ diff --git a/htdocs/images/tango/ldap-ou.png b/htdocs/images/tango/ldap-ou.png new file mode 100644 index 0000000..9d2d500 Binary files /dev/null and b/htdocs/images/tango/ldap-ou.png differ diff --git a/htdocs/images/tango/ldap-uid.png b/htdocs/images/tango/ldap-uid.png new file mode 100644 index 0000000..46573ff Binary files /dev/null and b/htdocs/images/tango/ldap-uid.png differ diff --git a/htdocs/images/tango/ldap-uniquegroup.png b/htdocs/images/tango/ldap-uniquegroup.png new file mode 100644 index 0000000..9d2d500 Binary files /dev/null and b/htdocs/images/tango/ldap-uniquegroup.png differ diff --git a/htdocs/images/tango/ldap-user.png b/htdocs/images/tango/ldap-user.png new file mode 100644 index 0000000..fbea772 Binary files /dev/null and b/htdocs/images/tango/ldap-user.png differ diff --git a/htdocs/images/tango/light-big.png b/htdocs/images/tango/light-big.png new file mode 100644 index 0000000..2ac5747 Binary files /dev/null and b/htdocs/images/tango/light-big.png differ diff --git a/htdocs/images/tango/light.png b/htdocs/images/tango/light.png new file mode 100644 index 0000000..8851b99 Binary files /dev/null and b/htdocs/images/tango/light.png differ diff --git a/htdocs/images/tango/login-big.png b/htdocs/images/tango/login-big.png new file mode 100644 index 0000000..8b10c1e Binary files /dev/null and b/htdocs/images/tango/login-big.png differ diff --git a/htdocs/images/tango/login.png b/htdocs/images/tango/login.png new file mode 100644 index 0000000..46573ff Binary files /dev/null and b/htdocs/images/tango/login.png differ diff --git a/htdocs/images/tango/logo-small.png b/htdocs/images/tango/logo-small.png new file mode 100644 index 0000000..6fcdbf9 Binary files /dev/null and b/htdocs/images/tango/logo-small.png differ diff --git a/htdocs/images/tango/logo.png b/htdocs/images/tango/logo.png new file mode 100644 index 0000000..a95539e Binary files /dev/null and b/htdocs/images/tango/logo.png differ diff --git a/htdocs/images/tango/logout-big.png b/htdocs/images/tango/logout-big.png new file mode 100644 index 0000000..fddbc2b Binary files /dev/null and b/htdocs/images/tango/logout-big.png differ diff --git a/htdocs/images/tango/logout.png b/htdocs/images/tango/logout.png new file mode 100644 index 0000000..0010931 Binary files /dev/null and b/htdocs/images/tango/logout.png differ diff --git a/htdocs/images/tango/mail-big.png b/htdocs/images/tango/mail-big.png new file mode 100644 index 0000000..3f248dc Binary files /dev/null and b/htdocs/images/tango/mail-big.png differ diff --git a/htdocs/images/tango/mail.png b/htdocs/images/tango/mail.png new file mode 100644 index 0000000..a619741 Binary files /dev/null and b/htdocs/images/tango/mail.png differ diff --git a/htdocs/images/tango/minus.png b/htdocs/images/tango/minus.png new file mode 100644 index 0000000..00b654e Binary files /dev/null and b/htdocs/images/tango/minus.png differ diff --git a/htdocs/images/tango/monitorserver-big.png b/htdocs/images/tango/monitorserver-big.png new file mode 100644 index 0000000..b62959e Binary files /dev/null and b/htdocs/images/tango/monitorserver-big.png differ diff --git a/htdocs/images/tango/monitorserver.png b/htdocs/images/tango/monitorserver.png new file mode 100644 index 0000000..8734e77 Binary files /dev/null and b/htdocs/images/tango/monitorserver.png differ diff --git a/htdocs/images/tango/plus.png b/htdocs/images/tango/plus.png new file mode 100644 index 0000000..1aa7f09 Binary files /dev/null and b/htdocs/images/tango/plus.png differ diff --git a/htdocs/images/tango/refresh-big.png b/htdocs/images/tango/refresh-big.png new file mode 100644 index 0000000..606ea9e Binary files /dev/null and b/htdocs/images/tango/refresh-big.png differ diff --git a/htdocs/images/tango/refresh.png b/htdocs/images/tango/refresh.png new file mode 100644 index 0000000..3fd71d6 Binary files /dev/null and b/htdocs/images/tango/refresh.png differ diff --git a/htdocs/images/tango/remove-big.png b/htdocs/images/tango/remove-big.png new file mode 100644 index 0000000..c5524f7 Binary files /dev/null and b/htdocs/images/tango/remove-big.png differ diff --git a/htdocs/images/tango/remove.png b/htdocs/images/tango/remove.png new file mode 100644 index 0000000..00b654e Binary files /dev/null and b/htdocs/images/tango/remove.png differ diff --git a/htdocs/images/tango/rename-big.png b/htdocs/images/tango/rename-big.png new file mode 100644 index 0000000..fd43de3 Binary files /dev/null and b/htdocs/images/tango/rename-big.png differ diff --git a/htdocs/images/tango/rename.png b/htdocs/images/tango/rename.png new file mode 100644 index 0000000..c8d899c Binary files /dev/null and b/htdocs/images/tango/rename.png differ diff --git a/htdocs/images/tango/request-feature-big.png b/htdocs/images/tango/request-feature-big.png new file mode 100644 index 0000000..aadcb91 Binary files /dev/null and b/htdocs/images/tango/request-feature-big.png differ diff --git a/htdocs/images/tango/request-feature.png b/htdocs/images/tango/request-feature.png new file mode 100644 index 0000000..ab8d494 Binary files /dev/null and b/htdocs/images/tango/request-feature.png differ diff --git a/htdocs/images/tango/save-big.png b/htdocs/images/tango/save-big.png new file mode 100644 index 0000000..db5c52b Binary files /dev/null and b/htdocs/images/tango/save-big.png differ diff --git a/htdocs/images/tango/save.png b/htdocs/images/tango/save.png new file mode 100644 index 0000000..22ff495 Binary files /dev/null and b/htdocs/images/tango/save.png differ diff --git a/htdocs/images/tango/schema-big.png b/htdocs/images/tango/schema-big.png new file mode 100644 index 0000000..a896697 Binary files /dev/null and b/htdocs/images/tango/schema-big.png differ diff --git a/htdocs/images/tango/schema.png b/htdocs/images/tango/schema.png new file mode 100644 index 0000000..53014ab Binary files /dev/null and b/htdocs/images/tango/schema.png differ diff --git a/htdocs/images/tango/search-big.png b/htdocs/images/tango/search-big.png new file mode 100644 index 0000000..950d792 Binary files /dev/null and b/htdocs/images/tango/search-big.png differ diff --git a/htdocs/images/tango/search.png b/htdocs/images/tango/search.png new file mode 100644 index 0000000..fd7f0b0 Binary files /dev/null and b/htdocs/images/tango/search.png differ diff --git a/htdocs/images/tango/server-big.png b/htdocs/images/tango/server-big.png new file mode 100644 index 0000000..1d38e4f Binary files /dev/null and b/htdocs/images/tango/server-big.png differ diff --git a/htdocs/images/tango/server.png b/htdocs/images/tango/server.png new file mode 100644 index 0000000..068ffeb Binary files /dev/null and b/htdocs/images/tango/server.png differ diff --git a/htdocs/images/tango/smile-big.png b/htdocs/images/tango/smile-big.png new file mode 100644 index 0000000..a52e44d Binary files /dev/null and b/htdocs/images/tango/smile-big.png differ diff --git a/htdocs/images/tango/smile.png b/htdocs/images/tango/smile.png new file mode 100644 index 0000000..de862b1 Binary files /dev/null and b/htdocs/images/tango/smile.png differ diff --git a/htdocs/images/tango/switch-big.png b/htdocs/images/tango/switch-big.png new file mode 100644 index 0000000..d09995a Binary files /dev/null and b/htdocs/images/tango/switch-big.png differ diff --git a/htdocs/images/tango/switch.png b/htdocs/images/tango/switch.png new file mode 100644 index 0000000..3e4ced5 Binary files /dev/null and b/htdocs/images/tango/switch.png differ diff --git a/htdocs/images/tango/timeout-big.png b/htdocs/images/tango/timeout-big.png new file mode 100644 index 0000000..85daef3 Binary files /dev/null and b/htdocs/images/tango/timeout-big.png differ diff --git a/htdocs/images/tango/timeout.png b/htdocs/images/tango/timeout.png new file mode 100644 index 0000000..18b7c67 Binary files /dev/null and b/htdocs/images/tango/timeout.png differ diff --git a/htdocs/images/tango/tools-big.png b/htdocs/images/tango/tools-big.png new file mode 100644 index 0000000..6e52db7 Binary files /dev/null and b/htdocs/images/tango/tools-big.png differ diff --git a/htdocs/images/tango/tools.png b/htdocs/images/tango/tools.png new file mode 100644 index 0000000..9460dfc Binary files /dev/null and b/htdocs/images/tango/tools.png differ diff --git a/htdocs/images/tango/trash-big.png b/htdocs/images/tango/trash-big.png new file mode 100644 index 0000000..9b7a462 Binary files /dev/null and b/htdocs/images/tango/trash-big.png differ diff --git a/htdocs/images/tango/trash.png b/htdocs/images/tango/trash.png new file mode 100644 index 0000000..0e0953c Binary files /dev/null and b/htdocs/images/tango/trash.png differ diff --git a/htdocs/images/tango/tree_collapse.png b/htdocs/images/tango/tree_collapse.png new file mode 100644 index 0000000..1c9be75 Binary files /dev/null and b/htdocs/images/tango/tree_collapse.png differ diff --git a/htdocs/images/tango/tree_collapse_corner.png b/htdocs/images/tango/tree_collapse_corner.png new file mode 100644 index 0000000..b3328ad Binary files /dev/null and b/htdocs/images/tango/tree_collapse_corner.png differ diff --git a/htdocs/images/tango/tree_collapse_corner_first.png b/htdocs/images/tango/tree_collapse_corner_first.png new file mode 100644 index 0000000..122b980 Binary files /dev/null and b/htdocs/images/tango/tree_collapse_corner_first.png differ diff --git a/htdocs/images/tango/tree_collapse_first.png b/htdocs/images/tango/tree_collapse_first.png new file mode 100644 index 0000000..5c43876 Binary files /dev/null and b/htdocs/images/tango/tree_collapse_first.png differ diff --git a/htdocs/images/tango/tree_corner.png b/htdocs/images/tango/tree_corner.png new file mode 100644 index 0000000..541c5b3 Binary files /dev/null and b/htdocs/images/tango/tree_corner.png differ diff --git a/htdocs/images/tango/tree_expand.png b/htdocs/images/tango/tree_expand.png new file mode 100644 index 0000000..e94aecf Binary files /dev/null and b/htdocs/images/tango/tree_expand.png differ diff --git a/htdocs/images/tango/tree_expand_corner.png b/htdocs/images/tango/tree_expand_corner.png new file mode 100644 index 0000000..4293f76 Binary files /dev/null and b/htdocs/images/tango/tree_expand_corner.png differ diff --git a/htdocs/images/tango/tree_expand_corner_first.png b/htdocs/images/tango/tree_expand_corner_first.png new file mode 100644 index 0000000..5de11a6 Binary files /dev/null and b/htdocs/images/tango/tree_expand_corner_first.png differ diff --git a/htdocs/images/tango/tree_expand_first.png b/htdocs/images/tango/tree_expand_first.png new file mode 100644 index 0000000..034b88e Binary files /dev/null and b/htdocs/images/tango/tree_expand_first.png differ diff --git a/htdocs/images/tango/tree_folder_closed.png b/htdocs/images/tango/tree_folder_closed.png new file mode 100644 index 0000000..f1bfd01 Binary files /dev/null and b/htdocs/images/tango/tree_folder_closed.png differ diff --git a/htdocs/images/tango/tree_folder_open.png b/htdocs/images/tango/tree_folder_open.png new file mode 100644 index 0000000..4190b96 Binary files /dev/null and b/htdocs/images/tango/tree_folder_open.png differ diff --git a/htdocs/images/tango/tree_leaf.png b/htdocs/images/tango/tree_leaf.png new file mode 100644 index 0000000..6f999fb Binary files /dev/null and b/htdocs/images/tango/tree_leaf.png differ diff --git a/htdocs/images/tango/tree_space.png b/htdocs/images/tango/tree_space.png new file mode 100644 index 0000000..fbdfa6a Binary files /dev/null and b/htdocs/images/tango/tree_space.png differ diff --git a/htdocs/images/tango/tree_split.png b/htdocs/images/tango/tree_split.png new file mode 100644 index 0000000..1a49fab Binary files /dev/null and b/htdocs/images/tango/tree_split.png differ diff --git a/htdocs/images/tango/tree_split_first.png b/htdocs/images/tango/tree_split_first.png new file mode 100644 index 0000000..e915d03 Binary files /dev/null and b/htdocs/images/tango/tree_split_first.png differ diff --git a/htdocs/images/tango/tree_vertline.png b/htdocs/images/tango/tree_vertline.png new file mode 100644 index 0000000..261ff13 Binary files /dev/null and b/htdocs/images/tango/tree_vertline.png differ diff --git a/htdocs/images/tango/warn-big.png b/htdocs/images/tango/warn-big.png new file mode 100644 index 0000000..7233d45 Binary files /dev/null and b/htdocs/images/tango/warn-big.png differ diff --git a/htdocs/images/tango/warn.png b/htdocs/images/tango/warn.png new file mode 100644 index 0000000..a9e4ff3 Binary files /dev/null and b/htdocs/images/tango/warn.png differ diff --git a/htdocs/import.php b/htdocs/import.php new file mode 100644 index 0000000..22d7ee2 --- /dev/null +++ b/htdocs/import.php @@ -0,0 +1,111 @@ +getIndex(),'LDIF'); +$request['import'] = $request['importer']->getTemplate(); + +$request['continuous_mode'] = get_request('continuous_mode') ? true : false; + +$type = $request['import']->getType(); + +# Set our timelimit in case we have a lot of importing to do +@set_time_limit(0); + +# String associated to the operation on the ldap server +$actionString = array( + 'add' => _('Adding'), + 'delete' => _('Deleting'), + 'modrdn' => _('Renaming'), + 'moddn' => _('Renaming'), + 'modify' => _('Modifying') + ); + +# String associated with error +$actionErrorMsg = array( + 'add' => _('Could not add object'), + 'delete' => _('Could not delete object'), + 'modrdn' => _('Could not rename object'), + 'moddn' => _('Could not rename object'), + 'modify' => _('Could not modify object') + ); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Import'))); +$request['page']->drawSubTitle(sprintf('%s: %s %s: %s %s %s (%s)', + _('Server'),$app['server']->getName(), + _('File'),$request['import']->getSource('name'),number_format($request['import']->getSource('size')),_('bytes'),$type['description'])); + +echo '
'; + +# @todo When renaming DNs, the hotlink should point to the new entry on success, or the old entry on failure. +while (! $request['import']->eof()) { + while ($request['template'] = $request['import']->readEntry()) { + + $edit_href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$app['server']->getIndex(), + rawurlencode($request['template']->getDN())); + + $changetype = $request['template']->getType(); + printf('%s %s',$actionString[$changetype],$edit_href,$request['template']->getDN()); + + if ($request['import']->LDAPimport()) + printf(' %s
',_('Success')); + + else { + printf(' %s

',_('Failed')); + $errormsg = sprintf('%s %s',$actionErrorMsg[$changetype],$request['template']->getDN()); + $errormsg .= ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)); + + system_message(array( + 'title'=>_('LDIF text import'), + 'body'=>$errormsg, + 'type'=>'warn')); + } + } + + if ($request['import']->error) { + printf('%s: %s
', + _('Error'),$request['import']->error['message']); + + echo '
'; + + display_pla_parse_error($request['import']); + } + + if (! $request['continuous_mode']) + break; +} + +function display_pla_parse_error($request) { + $type = $request->getType(); + + echo '
'; + echo '

'; + echo "$file
'; + echo ''; + printf('',IMGDIR,'error-big.png'); + + printf('',$type['description'],_('Parse Error')); + echo ''; + + printf('',_('Description'),$request->error['message']); + printf('',_('Line'),$request->error['line']); + printf('',_('Data')); + + foreach ($request->error['data'] as $line) + printf('',$line); + + echo '

%s %s

%s:%s
%s:%s
%s:
 %s
'; + echo ''; +} +?> diff --git a/htdocs/import_form.php b/htdocs/import_form.php new file mode 100644 index 0000000..9c6bbbb --- /dev/null +++ b/htdocs/import_form.php @@ -0,0 +1,48 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Import'))); +$request['page']->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +echo '
'; +echo '
'; +printf('',$app['server']->getIndex()); +echo ''; +echo '
'; + +echo ''; + +echo ''; +echo ''; +printf('',_('Select an LDIF file')); +echo ''; + +printf('',_('Maximum file size'),ini_get('upload_max_filesize')); + +echo ''; +printf('',_('Or paste your LDIF here')); +echo ''; +echo ''; +printf('', + _("Don't stop on errors")); +printf('',_('Proceed >>')); +echo '
 
%s'; +echo ''; +echo '
 %s %s
 
%s
 
 %s
 
'; +echo '
'; +?> diff --git a/htdocs/index.php b/htdocs/index.php new file mode 100644 index 0000000..f72840c --- /dev/null +++ b/htdocs/index.php @@ -0,0 +1,148 @@ + + +If you are seeing this in your browser, +PHP is not installed on your web server!!! + + +*******************************************/ + +/** + * We will perform some sanity checking here, since this file is normally loaded first when users + * first access the application. + */ + +# The index we will store our config in $_SESSION +define('APPCONFIG','plaConfig'); + +define('LIBDIR',sprintf('%s/',realpath('../lib/'))); +ini_set('display_errors',1); +error_reporting(-1); + +# General functions needed to proceed. +ob_start(); +if (! file_exists(LIBDIR.'functions.php')) { + if (ob_get_level()) ob_end_clean(); + die(sprintf("Fatal error: Required file '%sfunctions.php' does not exist.",LIBDIR)); +} + +if (! is_readable(LIBDIR.'functions.php')) { + if (ob_get_level()) ob_end_clean(); + die(sprintf("Cannot read the file '%sfunctions.php' its permissions may be too strict.",LIBDIR)); +} + +if (ob_get_level()) + ob_end_clean(); + +# Make sure this PHP install has pcre +if (! extension_loaded('pcre')) + die('

Your install of PHP appears to be missing PCRE support.

Please install PCRE support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)

'); + +require LIBDIR.'functions.php'; +spl_autoload_register("autoload"); + +# Define the path to our configuration file. +if (defined('CONFDIR')) + $app['config_file'] = CONFDIR.'config.php'; +else + $app['config_file'] = 'config.php'; + +# Make sure this PHP install has session support +if (! extension_loaded('session')) + error('

Your install of PHP appears to be missing php-session support.

Please install php-session support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)

','error',null,true); + +# Make sure this PHP install has gettext, we use it for language translation +if (! extension_loaded('gettext')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing GETTEXT support.

GETTEXT is used for language translation.

Please install GETTEXT support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +# Make sure this PHP install has all our required extensions +if (! extension_loaded('ldap')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing LDAP support.

Please install LDAP support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +# Make sure that we have php-xml loaded. +if (! function_exists('xml_parser_create')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing XML support.

Please install XML support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +/** + * Helper functions. + * Our required helper functions are defined in functions.php + */ +if (isset($app['function_files']) && is_array($app['function_files'])) + foreach ($app['function_files'] as $file_name ) { + if (! file_exists($file_name)) + error(sprintf('Fatal error: Required file "%s" does not exist.',$file_name),'error',null,true); + + if (! is_readable($file_name)) + error(sprintf('Fatal error: Cannot read the file "%s", its permissions may be too strict.',$file_name),'error',null,true); + + ob_start(); + require $file_name; + if (ob_get_level()) ob_end_clean(); + } + +# Configuration File check +if (! file_exists($app['config_file'])) { + error(sprintf(_('You need to configure %s. Edit the file "%s" to do so. An example config file is provided in "%s.example".'),app_name(),$app['config_file'],$app['config_file']),'error',null,true); + +} elseif (! is_readable($app['config_file'])) { + error(sprintf('Fatal error: Cannot read your configuration file "%s", its permissions may be too strict.',$app['config_file']),'error',null,true); +} + +# If our config file fails the sanity check, then stop now. +if (! $config = check_config($app['config_file'])) { + $www['page'] = new page(); + $www['body'] = new block(); + $www['page']->block_add('body',$www['body']); + $www['page']->display(); + exit; + +} else { + app_session_start(); + $_SESSION[APPCONFIG] = $config; +} + +if ($uri = get_request('URI','GET')) + header(sprintf('Location: cmd.php?%s',base64_decode($uri))); + +if (! preg_match('/^([0-9]+\.?)+/',app_version())) { + system_message(array( + 'title'=>_('This is a development version of phpLDAPadmin'), + 'body'=>'This is a development version of phpLDAPadmin! You should NOT use it in a production environment (although we dont think it should do any damage).', + 'type'=>'info','special'=>true)); + + if (count($_SESSION[APPCONFIG]->untested())) + system_message(array( + 'title'=>'Untested configuration paramaters', + 'body'=>sprintf('The following parameters have not been tested. If you have configured these parameters, and they are working as expected, please let the developers know, so that they can be removed from this message.
%s',implode(', ',$_SESSION[APPCONFIG]->untested())), + 'type'=>'info','special'=>true)); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + if (count($server->untested())) + system_message(array( + 'title'=>'Untested server configuration paramaters', + 'body'=>sprintf('The following parameters have not been tested. If you have configured these parameters, and they are working as expected, please let the developers know, so that they can be removed from this message.
%s',implode(', ',$server->untested())), + 'type'=>'info','special'=>true)); +} + +include './cmd.php'; +?> diff --git a/htdocs/js/CheckAll.js b/htdocs/js/CheckAll.js new file mode 100644 index 0000000..0f91f10 --- /dev/null +++ b/htdocs/js/CheckAll.js @@ -0,0 +1,22 @@ +function CheckAll(setbgcolor,form,index) { + htmlform = document.getElementById(form+index); + + for (var i=0;i= 0) return component.options[component.selectedIndex].value; + } else if (component.type == "select-multiple") { + if (component.selectedIndex >= 0) return component.options[component.selectedIndex].value; + } else if (component.type == undefined) { // option + if (component.selected) return component.value; + } else { + return component.value; + } + return ""; +} + +function pla_setComponentValue(component,value) { + if (component.type == "checkbox") { + if (component.value == value) component.checked = true; + else component.checked = false; + } else if (component.type == "select-one") { + for (var i = 0; i < component.options.length; i++) { + if (component.options[i].value == value) component.options[i].selected = true; + } + } else if (component.type == "select-multiple") { + for (var i = 0; i < component.options.length; i++) { + if (component.options[i].value == value) component.options[i].selected = true; + } + } else if (component.type == undefined) { // option + if (component.value == value) component.selected = true; + else component.selected = false; + } else { + component.value = value; + } +} + +function getAttributeComponents(prefix,name) { + var components = new Array(); + var i = 0; + var j = 0; + var c = pla_getComponentsByName(prefix + "_values[" + name + "][" + j + "]"); + while (c && (c.length > 0)) { + for (var k = 0; k < c.length; k++) { + components[i++] = c[k]; + } + ++j; + c = pla_getComponentsByName(prefix + "_values[" + name + "][" + j + "]"); + } + c = pla_getComponentsByName(prefix + "_values[" + name + "][]"); + if (c && (c.length > 0)) { + for (var k = 0; k < c.length; k++) { + components[i++] = c[k]; + } + } + return components; +} + +function getAttributeValues(prefix,name) { + var components = getAttributeComponents(prefix,name); + var values = new Array(); + for (var k = 0; k < components.length; k++) { + var val = pla_getComponentValue(components[k]); + if (val) values[values.length] = val; + } + return values; +} + +function submitForm(form) { + for (var i = 0; i < form.elements.length; i++) { + form.elements[i].blur(); + } + return validateForm(true); +} + +function alertError(err,silence) { + if (!silence) alert(err); +} diff --git a/htdocs/js/ajax_functions.js b/htdocs/js/ajax_functions.js new file mode 100644 index 0000000..a812b45 --- /dev/null +++ b/htdocs/js/ajax_functions.js @@ -0,0 +1,253 @@ +/** + * @package phpLDAPadmin + * @author The phpLDAPadmin development team + * @author Xavier Bruyet + */ + +// current request +var http_div = ''; +var http_request = null; +var http_request_success_callback = ''; +var http_request_error_callback = ''; + +function ajSUBMIT(div,obj,display) { + var pageDiv = getDiv(div); + + window.scrollTo(0,95); + + makeHttpRequest('cmd.php',getParameters(obj.parentNode)+'meth=ajax','POST','alertAJ','cancelAJ',div); + + if (pageDiv) + includeHTML(pageDiv,'
'+display+'...'); + else + return true; + + return false; +} + +function ajDISPLAY(div,urlParameters,display,ns) { + var pageDiv = getDiv(div); + + if (! ns) + window.scrollTo(0,95); + + makeHttpRequest('cmd.php',urlParameters+'&meth=ajax','GET','alertAJ','cancelAJ',div); + + if (pageDiv) + includeHTML(pageDiv,'
'+display+'...'); + else + return true; + + return false; +} + +function ajJUMP(url,title,index,prefix) { + var attr = prefix ? document.getElementById(prefix+index).value : index; + + if (attr) + url += '&viewvalue='+attr; + + return ajDISPLAY('BODY',url,'Loading '+title); +} + +function ajSHOWTHIS(key,except,ctl) { + select = document.getElementById(key+except); + + if (select.style.display == '') + return false; + + hideall(key,except,ctl); + + return false; +}; + +function ajSHOWSCHEMA(type,key,value) { + select = document.getElementById(type); + + if (value != null) { + except = value; + select.value = value; + } else { + except = select.value; + } + + if (! except) { + showall(key); + } else { + objectclass = document.getElementById(key+except); + objectclass.style.display = ''; + hideall(key,except); + }; + + return false; +}; + +function hideall(key,except,ctl) { + items = items(); + + for (x in items) { + if (! isNaN(x) && except != items[x]) { + item = document.getElementById(key+items[x]); + item.style.display = 'none'; + + if (ctl && (item = document.getElementById(ctl+items[x]))) { + item.style.background = '#E0E0E0'; + } + + } else if (! isNaN(x) && except == items[x]) { + item = document.getElementById(key+items[x]); + item.style.display = ''; + + if (ctl && (item = document.getElementById(ctl+items[x]))) { + item.style.background = '#F0F0F0'; + } + } + } +} + +function showall(key) { + items = items(); + + for (x in items) { + if (! isNaN(x)) { + item = document.getElementById(key+items[x]); + item.style.display = ''; + } + } +} + +// include html into a component +function includeHTML(component,html) { + if (typeof(component) != 'object' || typeof(html) != 'string') return; + component.innerHTML = html; + + var scripts = component.getElementsByTagName('script'); + if (!scripts) return; + + // load scripts + for (var i = 0; i < scripts.length; i++) { + var scriptclone = document.createElement('script'); + if (scripts[i].attributes.length > 0) { + for (var j in scripts[i].attributes) { + if (typeof(scripts[i].attributes[j]) != 'undefined' + && typeof(scripts[i].attributes[j].nodeName) != 'undefined' + && scripts[i].attributes[j].nodeValue != null + && scripts[i].attributes[j].nodeValue != '') { + scriptclone.setAttribute(scripts[i].attributes[j].nodeName,scripts[i].attributes[j].nodeValue); + } + } + } + scriptclone.text = scripts[i].text; + scripts[i].parentNode.replaceChild(scriptclone,scripts[i]); + eval(scripts[i].innerHTML); + } +} + +// callback function +function alertHttpRequest() { + if (http_request && (http_request.readyState == 4)) { + if (http_request.status == 200 || http_request.status == 401) { + response = http_request.responseText; + http_request = null; + //alert(response); + if (http_request_success_callback) { + eval(http_request_success_callback + '(response,http_div)'); + } + } else { + alert('There was a problem with the request.'); + cancelHttpRequest(); + } + } +} + +function cancelHttpRequest() { + if (http_request) { + http_request = null; + if (http_request_error_callback) { + eval(http_request_error_callback + '(http_div)'); + } + } +} + +function makeHttpRequest(url,parameters,meth,successCallbackFunctionName,errorCallbackFunctionName,div) { + cancelHttpRequest(div); + + http_request_success_callback = successCallbackFunctionName; + http_request_error_callback = errorCallbackFunctionName; + http_div = div; + + if (window.XMLHttpRequest) { // Mozilla, Safari,... + http_request = new XMLHttpRequest(); + if (http_request.overrideMimeType) { + http_request.overrideMimeType('text/html'); + } + + } else if (window.ActiveXObject) { // IE + try { + http_request = new ActiveXObject('Msxml2.XMLHTTP'); + } catch (e) { + try { + http_request = new ActiveXObject('Microsoft.XMLHTTP'); + } catch (e) {} + } + } + + if (!http_request) { + alert('Cannot create XMLHTTP instance.'); + return false; + } + + http_request.onreadystatechange = window['alertHttpRequest']; + if (meth == 'GET') url = url + '?' + parameters; + http_request.open(meth,url,true); + + http_request.setRequestHeader('Content-type','application/x-www-form-urlencoded'); + // http_request.setRequestHeader('Content-length',parameters.length); + // http_request.setRequestHeader('Connection','close'); + + if (meth == 'GET') parameters = null; + http_request.send(parameters); +} + +function getParameters(obj) { + var elements = ['input','select','textarea']; + var getstr = ''; + + for (var j in elements) { + for (i=0; i expand ; (action = 2) => collapse + if (oldimg.indexOf(imgdir+'/tree_expand.png') > -1) { + newimg = imgdir+'/tree_collapse.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_first.png') > -1) { + newimg = imgdir+'/tree_collapse_first.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_corner.png') > -1) { + newimg = imgdir+'/tree_collapse_corner.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_corner_first.png') > -1) { + newimg = imgdir+'/tree_collapse_corner_first.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_collapse.png') > -1) { + newimg = imgdir+'/tree_expand.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_first.png') > -1) { + newimg = imgdir+'/tree_expand_first.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_corner.png') > -1) { + newimg = imgdir+'/tree_expand_corner.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_corner_first.png') > -1) { + newimg = imgdir+'/tree_expand_corner_first.png'; + action = 2; + } + nodeLayer.src = 'images/ajax-spinner.gif'; + + // perform action + if (action == 2) { + newstyle = 'none'; + updateNewStyle(); + addCollapsedNode(nodeid); + } else if (action == 1) { + newstyle = 'block'; + if (sonLayer.innerHTML == '') { + makeHttpRequest('cmd.php',params+'&cmd=draw_tree_node&action=1','GET','alertTreeNodeContents','cancelNewStyle'); + } else { + updateNewStyle(); + } + delCollapsedNode(nodeid); + } + return false; +} + +function getDiv(div) { + if (!IE4) { + return document.getElementById('aj'+div); + } else { + return document.all('aj'+div); + } +} + +function alertAJ(html,div) { + var pageDiv = getDiv(div); + if (pageDiv) includeHTML(pageDiv, html); +} + +function cancelAJ(div) { + var pageDiv = getDiv(div); + if (pageDiv) includeHTML(pageDiv, ''); +} + +// close initial collapsed nodes +// Cant figure out why, but this runs twice in AJAX mode when using "refresh". +// Causing the collapsedNodes to be incorrect. +readCollapsedNodes(); +for (k = 0; k < collapsedNodes.length; k++) { + opencloseTreeNode(collapsedNodes[k],'#','images/default'); +} + +var current; + +function tree_unhide(whichLayer,old) { + if (current == null) current = old; + + var oldtree = document.getElementById('ajSID_'+current).style; + oldtree.display = 'none'; + + if (document.getElementById) { + // this is the way the standards work + var newtree = document.getElementById(whichLayer).value; + var newtree_div = document.getElementById('ajSID_'+newtree).style; + newtree_div.display = 'block'; + } + + current = newtree; +} diff --git a/htdocs/js/date_selector.js b/htdocs/js/date_selector.js new file mode 100644 index 0000000..eed89d6 --- /dev/null +++ b/htdocs/js/date_selector.js @@ -0,0 +1,75 @@ +function dateSelector(id) { + var el = document.getElementById('new_values_'+id); + var format = gettype(el.id); + var epoch; + var parse = false; + + var cal = new Calendar(0, null, onSelect, onClose); + + if (defaults['f_time_'+id]) { + cal.showsTime = true; + } else { + cal.showsTime = false; + } + + cal.weekNumbers = true; + cal.showsOtherMonths = true; + cal.create(); + + // convert to milliseconds (Epoch is usually expressed in seconds, but Javascript uses Milliseconds) + switch (format) { + case '%es' : epoch = el.value * 86400 * 1000; + format = '%s'; + parse = true; + break; + case '%s' : epoch = el.value * 1000; + parse = true; + break; + } + + // Convert the value to the date so that the calendar will display it + if (parse) { + var dDate = new Date(); + dDate.setTime(epoch); + cal.setDateFormat('%a, %d %b %Y'); // set the specified date format + cal.parseDate(dDate.toString()); // try to parse the text in field + cal.setDateFormat(format); // set the specified date format + } else { + cal.setDateFormat(format); // set the specified date format + cal.parseDate(el.value); // try to parse the text in field + } + + cal.sel = el; // inform it what input field we use + cal.showAtElement(el, 'BR'); // show the calendar +} + +function onSelect(calendar,date) { + switch (gettype(calendar.sel.id)) { + case '%es' : date = Math.round(date / 86400); + break; + } + + calendar.sel.value = date; + if (calendar.dateClicked) + onClose(calendar); +} + +function onClose(calendar,date) { + calendar.hide(); +} + +function gettype(attr) { + if (typeof defaults == "undefined") { + return '%s'; + } + + if (typeof defaults[attr] == "undefined") { + if (typeof default_date_format == "undefined") { + return '%s'; + } else { + return default_date_format; + } + } else { + return defaults[attr]; + } +} diff --git a/htdocs/js/dnChooserPopup.js b/htdocs/js/dnChooserPopup.js new file mode 100644 index 0000000..d95b48a --- /dev/null +++ b/htdocs/js/dnChooserPopup.js @@ -0,0 +1,6 @@ +function dnChooserPopup(form,element,rdn) +{ + mywindow=open('entry_chooser.php','myname','resizable=no,width=600,height=370,scrollbars=1'); + mywindow.location.href = 'entry_chooser.php?form=' + form + '&element=' + element + '&rdn=' + rdn; + if (mywindow.opener == null) mywindow.opener = self; +} diff --git a/htdocs/js/form_field_toggle_enable.js b/htdocs/js/form_field_toggle_enable.js new file mode 100644 index 0000000..f26d1eb --- /dev/null +++ b/htdocs/js/form_field_toggle_enable.js @@ -0,0 +1,51 @@ +/** + * This function will provide a enable/disable toggle for a HTML form field + */ +function form_field_toggle_enable(field,disable,focus,rev) { + var i; + var result; + var element; + + switch (field.type) { + case 'checkbox': + if (field.checked) + result = rev ? false : true; + else + result = rev ? true : false; + + for (i=0;i + http://dynarch.com/mishoo/ + + This program is free software published under the + terms of the GNU Lesser General Public License. + + For the entire license text please refer to + http://www.gnu.org/licenses/lgpl.html + +Contents +--------- + + calendar.js -- the main program file + lang/*.js -- internalization files + *.css -- color themes + cal.html -- example usage file + doc/ -- documentation, in PDF and HTML + simple-1.html -- quick setup examples [popup calendars] + simple-2.html -- quick setup example for flat calendar + calendar.php -- PHP wrapper + test.php -- test file for the PHP wrapper + +Homepage +--------- + + For details and latest versions please refer to calendar + homepage, located on my website: + + http://dynarch.com/mishoo/calendar.epl + diff --git a/htdocs/js/jscalendar/calendar-blue.css b/htdocs/js/jscalendar/calendar-blue.css new file mode 100644 index 0000000..ca33cde --- /dev/null +++ b/htdocs/js/jscalendar/calendar-blue.css @@ -0,0 +1,232 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #556; + font-size: 11px; + color: #000; + cursor: default; + background: #eef; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ +} + +.calendar .nav { + background: #778 url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #fff; + color: #000; + padding: 2px; +} + +.calendar thead .headrow { /* Row containing navigation buttons */ + background: #778; + color: #fff; +} + +.calendar thead .daynames { /* Row containing the day names */ + background: #bdf; +} + +.calendar thead .name { /* Cells containing the day names */ + border-bottom: 1px solid #556; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #a66; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #aaf; + color: #000; + border: 1px solid #04f; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #77c; + padding: 2px 0px 0px 2px; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells containing month days dates */ + width: 2em; + color: #456; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #bdf; +} + +.calendar tbody .rowhilite td { + background: #def; +} + +.calendar tbody .rowhilite td.wn { + background: #eef; +} + +.calendar tbody td.hilite { /* Hovered cells */ + background: #def; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells */ + background: #cde; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fff; + color: #000; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #a66; +} + +.calendar tbody td.today { /* Cell showing selected date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The in footer (only one right now) */ + text-align: center; + background: #556; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell */ + background: #fff; + color: #445; + border-top: 1px solid #556; + padding: 1px; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #aaf; + border: 1px solid #04f; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #77c; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #def; + color: #000; + font-size: 90%; + z-index: 100; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #acf; +} + +.calendar .combo .active { + border-top: 1px solid #46a; + border-bottom: 1px solid #46a; + background: #eef; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #f4f0e8; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #667; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/htdocs/js/jscalendar/calendar-setup.js b/htdocs/js/jscalendar/calendar-setup.js new file mode 100644 index 0000000..c269f7d --- /dev/null +++ b/htdocs/js/jscalendar/calendar-setup.js @@ -0,0 +1,200 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * --------------------------------------------------------------------------- + * + * The DHTML Calendar + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + * + * This file defines helper functions for setting up the calendar. They are + * intended to help non-programmers get a working calendar on their site + * quickly. This script should not be seen as part of the calendar. It just + * shows you what one can do with the calendar, while in the same time + * providing a quick and simple method for setting it up. If you need + * exhaustive customization of the calendar creation process feel free to + * modify this code to suit your needs (this is recommended and much better + * than modifying calendar.js itself). + */ + +// $Id$ + +/** + * This function "patches" an input field (or other element) to use a calendar + * widget for date selection. + * + * The "params" is a single object that can have the following properties: + * + * prop. name | description + * ------------------------------------------------------------------------------------------------- + * inputField | the ID of an input field to store the date + * displayArea | the ID of a DIV or other element to show the date + * button | ID of a button or other element that will trigger the calendar + * eventName | event that will trigger the calendar, without the "on" prefix (default: "click") + * ifFormat | date format that will be stored in the input field + * daFormat | the date format that will be used to display the date in displayArea + * singleClick | (true/false) wether the calendar is in single click mode or not (default: true) + * firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc. + * align | alignment (default: "Br"); if you don't know what's this see the calendar documentation + * range | array with 2 elements. Default: [1900, 2999] -- the range of years available + * weekNumbers | (true/false) if it's true (default) the calendar will display week numbers + * flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID + * flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar) + * disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar + * onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay) + * onClose | function that gets called when the calendar is closed. [default] + * onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar. + * date | the date that the calendar will be initially displayed to + * showsTime | default: false; if true the calendar will include a time selector + * timeFormat | the time format; can be "12" or "24", default is "12" + * electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close + * step | configures the step of the years in drop-down boxes; default: 2 + * position | configures the calendar absolute position; default: null + * cache | if "true" (but default: "false") it will reuse the same calendar object, where possible + * showOthers | if "true" (but default: "false") it will show days from other months too + * + * None of them is required, they all have default values. However, if you + * pass none of "inputField", "displayArea" or "button" you'll get a warning + * saying "nothing to setup". + */ +Calendar.setup = function (params) { + function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } }; + + param_default("inputField", null); + param_default("displayArea", null); + param_default("button", null); + param_default("eventName", "click"); + param_default("ifFormat", "%Y/%m/%d"); + param_default("daFormat", "%Y/%m/%d"); + param_default("singleClick", true); + param_default("disableFunc", null); + param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined + param_default("dateText", null); + param_default("firstDay", null); + param_default("align", "Br"); + param_default("range", [1900, 2999]); + param_default("weekNumbers", true); + param_default("flat", null); + param_default("flatCallback", null); + param_default("onSelect", null); + param_default("onClose", null); + param_default("onUpdate", null); + param_default("date", null); + param_default("showsTime", false); + param_default("timeFormat", "24"); + param_default("electric", true); + param_default("step", 2); + param_default("position", null); + param_default("cache", false); + param_default("showOthers", false); + param_default("multiple", null); + + var tmp = ["inputField", "displayArea", "button"]; + for (var i in tmp) { + if (typeof params[tmp[i]] == "string") { + params[tmp[i]] = document.getElementById(params[tmp[i]]); + } + } + if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) { + alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code"); + return false; + } + + function onSelect(cal) { + var p = cal.params; + var update = (cal.dateClicked || p.electric); + if (update && p.inputField) { + p.inputField.value = cal.date.print(p.ifFormat); + if (typeof p.inputField.onchange == "function") + p.inputField.onchange(); + } + if (update && p.displayArea) + p.displayArea.innerHTML = cal.date.print(p.daFormat); + if (update && typeof p.onUpdate == "function") + p.onUpdate(cal); + if (update && p.flat) { + if (typeof p.flatCallback == "function") + p.flatCallback(cal); + } + if (update && p.singleClick && cal.dateClicked) + cal.callCloseHandler(); + }; + + if (params.flat != null) { + if (typeof params.flat == "string") + params.flat = document.getElementById(params.flat); + if (!params.flat) { + alert("Calendar.setup:\n Flat specified but can't find parent."); + return false; + } + var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect); + cal.showsOtherMonths = params.showOthers; + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.params = params; + cal.weekNumbers = params.weekNumbers; + cal.setRange(params.range[0], params.range[1]); + cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; + if (params.ifFormat) { + cal.setDateFormat(params.ifFormat); + } + if (params.inputField && typeof params.inputField.value == "string") { + cal.parseDate(params.inputField.value); + } + cal.create(params.flat); + cal.show(); + return false; + } + + var triggerEl = params.button || params.displayArea || params.inputField; + triggerEl["on" + params.eventName] = function() { + var dateEl = params.inputField || params.displayArea; + var dateFmt = params.inputField ? params.ifFormat : params.daFormat; + var mustCreate = false; + var cal = window.calendar; + if (dateEl) + params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt); + if (!(cal && params.cache)) { + window.calendar = cal = new Calendar(params.firstDay, + params.date, + params.onSelect || onSelect, + params.onClose || function(cal) { cal.hide(); }); + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.weekNumbers = params.weekNumbers; + mustCreate = true; + } else { + if (params.date) + cal.setDate(params.date); + cal.hide(); + } + if (params.multiple) { + cal.multiple = {}; + for (var i = params.multiple.length; --i >= 0;) { + var d = params.multiple[i]; + var ds = d.print("%Y%m%d"); + cal.multiple[ds] = d; + } + } + cal.showsOtherMonths = params.showOthers; + cal.yearStep = params.step; + cal.setRange(params.range[0], params.range[1]); + cal.params = params; + cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; + cal.setDateFormat(dateFmt); + if (mustCreate) + cal.create(); + cal.refresh(); + if (!params.position) + cal.showAtElement(params.button || params.displayArea || params.inputField, params.align); + else + cal.showAt(params.position[0], params.position[1]); + return false; + }; + + return cal; +}; diff --git a/htdocs/js/jscalendar/calendar.js b/htdocs/js/jscalendar/calendar.js new file mode 100644 index 0000000..f6c1398 --- /dev/null +++ b/htdocs/js/jscalendar/calendar.js @@ -0,0 +1,1806 @@ +/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo + * ----------------------------------------------------------- + * + * The DHTML Calendar, version 1.0 "It is happening again" + * + * Details and latest version at: + * www.dynarch.com/projects/calendar + * + * This script is developed by Dynarch.com. Visit us at www.dynarch.com. + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + */ + +// $Id$ + +/** The Calendar object constructor. */ +Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { + // member variables + this.activeDiv = null; + this.currentDateEl = null; + this.getDateStatus = null; + this.getDateToolTip = null; + this.getDateText = null; + this.timeout = null; + this.onSelected = onSelected || null; + this.onClose = onClose || null; + this.dragging = false; + this.hidden = false; + this.minYear = 1970; + this.maxYear = 2050; + this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"]; + this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"]; + this.isPopup = true; + this.weekNumbers = true; + this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc. + this.showsOtherMonths = false; + this.dateStr = dateStr; + this.ar_days = null; + this.showsTime = false; + this.time24 = true; + this.yearStep = 2; + this.hiliteToday = true; + this.multiple = null; + // HTML elements + this.table = null; + this.element = null; + this.tbody = null; + this.firstdayname = null; + // Combo boxes + this.monthsCombo = null; + this.yearsCombo = null; + this.hilitedMonth = null; + this.activeMonth = null; + this.hilitedYear = null; + this.activeYear = null; + // Information + this.dateClicked = false; + + // one-time initializations + if (typeof Calendar._SDN == "undefined") { + // table of short day names + if (typeof Calendar._SDN_len == "undefined") + Calendar._SDN_len = 3; + var ar = new Array(); + for (var i = 8; i > 0;) { + ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len); + } + Calendar._SDN = ar; + // table of short month names + if (typeof Calendar._SMN_len == "undefined") + Calendar._SMN_len = 3; + ar = new Array(); + for (var i = 12; i > 0;) { + ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len); + } + Calendar._SMN = ar; + } +}; + +// ** constants + +/// "static", needed for event handlers. +Calendar._C = null; + +/// detect a special case of "web browser" +Calendar.is_ie = ( /msie/i.test(navigator.userAgent) && + !/opera/i.test(navigator.userAgent) ); + +Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); + +/// detect Opera browser +Calendar.is_opera = /opera/i.test(navigator.userAgent); + +/// detect KHTML-based browsers +Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); + +// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate +// library, at some point. + +Calendar.getAbsolutePos = function(el) { + var SL = 0, ST = 0; + var is_div = /^div$/i.test(el.tagName); + if (is_div && el.scrollLeft) + SL = el.scrollLeft; + if (is_div && el.scrollTop) + ST = el.scrollTop; + var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST }; + if (el.offsetParent) { + var tmp = this.getAbsolutePos(el.offsetParent); + r.x += tmp.x; + r.y += tmp.y; + } + return r; +}; + +Calendar.isRelated = function (el, evt) { + var related = evt.relatedTarget; + if (!related) { + var type = evt.type; + if (type == "mouseover") { + related = evt.fromElement; + } else if (type == "mouseout") { + related = evt.toElement; + } + } + while (related) { + if (related == el) { + return true; + } + related = related.parentNode; + } + return false; +}; + +Calendar.removeClass = function(el, className) { + if (!(el && el.className)) { + return; + } + var cls = el.className.split(" "); + var ar = new Array(); + for (var i = cls.length; i > 0;) { + if (cls[--i] != className) { + ar[ar.length] = cls[i]; + } + } + el.className = ar.join(" "); +}; + +Calendar.addClass = function(el, className) { + Calendar.removeClass(el, className); + el.className += " " + className; +}; + +// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately. +Calendar.getElement = function(ev) { + var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget; + while (f.nodeType != 1 || /^div$/i.test(f.tagName)) + f = f.parentNode; + return f; +}; + +Calendar.getTargetElement = function(ev) { + var f = Calendar.is_ie ? window.event.srcElement : ev.target; + while (f.nodeType != 1) + f = f.parentNode; + return f; +}; + +Calendar.stopEvent = function(ev) { + ev || (ev = window.event); + if (Calendar.is_ie) { + ev.cancelBubble = true; + ev.returnValue = false; + } else { + ev.preventDefault(); + ev.stopPropagation(); + } + return false; +}; + +Calendar.addEvent = function(el, evname, func) { + if (el.attachEvent) { // IE + el.attachEvent("on" + evname, func); + } else if (el.addEventListener) { // Gecko / W3C + el.addEventListener(evname, func, true); + } else { + el["on" + evname] = func; + } +}; + +Calendar.removeEvent = function(el, evname, func) { + if (el.detachEvent) { // IE + el.detachEvent("on" + evname, func); + } else if (el.removeEventListener) { // Gecko / W3C + el.removeEventListener(evname, func, true); + } else { + el["on" + evname] = null; + } +}; + +Calendar.createElement = function(type, parent) { + var el = null; + if (document.createElementNS) { + // use the XHTML namespace; IE won't normally get here unless + // _they_ "fix" the DOM2 implementation. + el = document.createElementNS("http://www.w3.org/1999/xhtml", type); + } else { + el = document.createElement(type); + } + if (typeof parent != "undefined") { + parent.appendChild(el); + } + return el; +}; + +// END: UTILITY FUNCTIONS + +// BEGIN: CALENDAR STATIC FUNCTIONS + +/** Internal -- adds a set of events to make some element behave like a button. */ +Calendar._add_evs = function(el) { + with (Calendar) { + addEvent(el, "mouseover", dayMouseOver); + addEvent(el, "mousedown", dayMouseDown); + addEvent(el, "mouseout", dayMouseOut); + if (is_ie) { + addEvent(el, "dblclick", dayMouseDblClick); + el.setAttribute("unselectable", true); + } + } +}; + +Calendar.findMonth = function(el) { + if (typeof el.month != "undefined") { + return el; + } else if (typeof el.parentNode.month != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.findYear = function(el) { + if (typeof el.year != "undefined") { + return el; + } else if (typeof el.parentNode.year != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.showMonthsCombo = function () { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var mc = cal.monthsCombo; + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + if (cal.activeMonth) { + Calendar.removeClass(cal.activeMonth, "active"); + } + var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()]; + Calendar.addClass(mon, "active"); + cal.activeMonth = mon; + var s = mc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var mcw = mc.offsetWidth; + if (typeof mcw == "undefined") + // Konqueror brain-dead techniques + mcw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; +}; + +Calendar.showYearsCombo = function (fwd) { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var yc = cal.yearsCombo; + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + if (cal.activeYear) { + Calendar.removeClass(cal.activeYear, "active"); + } + cal.activeYear = null; + var Y = cal.date.getFullYear() + (fwd ? 1 : -1); + var yr = yc.firstChild; + var show = false; + for (var i = 12; i > 0; --i) { + if (Y >= cal.minYear && Y <= cal.maxYear) { + yr.innerHTML = Y; + yr.year = Y; + yr.style.display = "block"; + show = true; + } else { + yr.style.display = "none"; + } + yr = yr.nextSibling; + Y += fwd ? cal.yearStep : -cal.yearStep; + } + if (show) { + var s = yc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var ycw = yc.offsetWidth; + if (typeof ycw == "undefined") + // Konqueror brain-dead techniques + ycw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; + } +}; + +// event handlers + +Calendar.tableMouseUp = function(ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + if (cal.timeout) { + clearTimeout(cal.timeout); + } + var el = cal.activeDiv; + if (!el) { + return false; + } + var target = Calendar.getTargetElement(ev); + ev || (ev = window.event); + Calendar.removeClass(el, "active"); + if (target == el || target.parentNode == el) { + Calendar.cellClick(el, ev); + } + var mon = Calendar.findMonth(target); + var date = null; + if (mon) { + date = new Date(cal.date); + if (mon.month != date.getMonth()) { + date.setMonth(mon.month); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } else { + var year = Calendar.findYear(target); + if (year) { + date = new Date(cal.date); + if (year.year != date.getFullYear()) { + date.setFullYear(year.year); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } + } + with (Calendar) { + removeEvent(document, "mouseup", tableMouseUp); + removeEvent(document, "mouseover", tableMouseOver); + removeEvent(document, "mousemove", tableMouseOver); + cal._hideCombos(); + _C = null; + return stopEvent(ev); + } +}; + +Calendar.tableMouseOver = function (ev) { + var cal = Calendar._C; + if (!cal) { + return; + } + var el = cal.activeDiv; + var target = Calendar.getTargetElement(ev); + if (target == el || target.parentNode == el) { + Calendar.addClass(el, "hilite active"); + Calendar.addClass(el.parentNode, "rowhilite"); + } else { + if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2))) + Calendar.removeClass(el, "active"); + Calendar.removeClass(el, "hilite"); + Calendar.removeClass(el.parentNode, "rowhilite"); + } + ev || (ev = window.event); + if (el.navtype == 50 && target != el) { + var pos = Calendar.getAbsolutePos(el); + var w = el.offsetWidth; + var x = ev.clientX; + var dx; + var decrease = true; + if (x > pos.x + w) { + dx = x - pos.x - w; + decrease = false; + } else + dx = pos.x - x; + + if (dx < 0) dx = 0; + var range = el._range; + var current = el._current; + var count = Math.floor(dx / 10) % range.length; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + while (count-- > 0) + if (decrease) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.innerHTML = newval; + + cal.onUpdateTime(); + } + var mon = Calendar.findMonth(target); + if (mon) { + if (mon.month != cal.date.getMonth()) { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + Calendar.addClass(mon, "hilite"); + cal.hilitedMonth = mon; + } else if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + } else { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + var year = Calendar.findYear(target); + if (year) { + if (year.year != cal.date.getFullYear()) { + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + Calendar.addClass(year, "hilite"); + cal.hilitedYear = year; + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.tableMouseDown = function (ev) { + if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) { + return Calendar.stopEvent(ev); + } +}; + +Calendar.calDragIt = function (ev) { + var cal = Calendar._C; + if (!(cal && cal.dragging)) { + return false; + } + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posX = ev.pageX; + posY = ev.pageY; + } + cal.hideShowCovered(); + var st = cal.element.style; + st.left = (posX - cal.xOffs) + "px"; + st.top = (posY - cal.yOffs) + "px"; + return Calendar.stopEvent(ev); +}; + +Calendar.calDragEnd = function (ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + cal.dragging = false; + with (Calendar) { + removeEvent(document, "mousemove", calDragIt); + removeEvent(document, "mouseup", calDragEnd); + tableMouseUp(ev); + } + cal.hideShowCovered(); +}; + +Calendar.dayMouseDown = function(ev) { + var el = Calendar.getElement(ev); + if (el.disabled) { + return false; + } + var cal = el.calendar; + cal.activeDiv = el; + Calendar._C = cal; + if (el.navtype != 300) with (Calendar) { + if (el.navtype == 50) { + el._current = el.innerHTML; + addEvent(document, "mousemove", tableMouseOver); + } else + addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver); + addClass(el, "hilite active"); + addEvent(document, "mouseup", tableMouseUp); + } else if (cal.isPopup) { + cal._dragStart(ev); + } + if (el.navtype == -1 || el.navtype == 1) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250); + } else if (el.navtype == -2 || el.navtype == 2) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250); + } else { + cal.timeout = null; + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseDblClick = function(ev) { + Calendar.cellClick(Calendar.getElement(ev), ev || window.event); + if (Calendar.is_ie) { + document.selection.empty(); + } +}; + +Calendar.dayMouseOver = function(ev) { + var el = Calendar.getElement(ev); + if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) { + return false; + } + if (el.ttip) { + if (el.ttip.substr(0, 1) == "_") { + el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); + } + el.calendar.tooltips.innerHTML = el.ttip; + } + if (el.navtype != 300) { + Calendar.addClass(el, "hilite"); + if (el.caldate) { + Calendar.addClass(el.parentNode, "rowhilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseOut = function(ev) { + with (Calendar) { + var el = getElement(ev); + if (isRelated(el, ev) || _C || el.disabled) + return false; + removeClass(el, "hilite"); + if (el.caldate) + removeClass(el.parentNode, "rowhilite"); + if (el.calendar) + el.calendar.tooltips.innerHTML = _TT["SEL_DATE"]; + return stopEvent(ev); + } +}; + +/** + * A generic "click" handler :) handles all types of buttons defined in this + * calendar. + */ +Calendar.cellClick = function(el, ev) { + var cal = el.calendar; + var closing = false; + var newdate = false; + var date = null; + if (typeof el.navtype == "undefined") { + if (cal.currentDateEl) { + Calendar.removeClass(cal.currentDateEl, "selected"); + Calendar.addClass(el, "selected"); + closing = (cal.currentDateEl == el); + if (!closing) { + cal.currentDateEl = el; + } + } + cal.date.setDateOnly(el.caldate); + date = cal.date; + var other_month = !(cal.dateClicked = !el.otherMonth); + if (!other_month && !cal.currentDateEl) + cal._toggleMultipleDate(new Date(date)); + else + newdate = !el.disabled; + // a date was clicked + if (other_month) + cal._init(cal.firstDayOfWeek, date); + } else { + if (el.navtype == 200) { + Calendar.removeClass(el, "hilite"); + cal.callCloseHandler(); + return; + } + date = new Date(cal.date); + if (el.navtype == 0) + date.setDateOnly(new Date()); // TODAY + // unless "today" was clicked, we assume no date was clicked so + // the selected handler will know not to close the calenar when + // in single-click mode. + // cal.dateClicked = (el.navtype == 0); + cal.dateClicked = false; + var year = date.getFullYear(); + var mon = date.getMonth(); + function setMonth(m) { + var day = date.getDate(); + var max = date.getMonthDays(m); + if (day > max) { + date.setDate(max); + } + date.setMonth(m); + }; + switch (el.navtype) { + case 400: + Calendar.removeClass(el, "hilite"); + var text = Calendar._TT["ABOUT"]; + if (typeof text != "undefined") { + text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : ""; + } else { + // FIXME: this should be removed as soon as lang files get updated! + text = "Help and about box text is not translated into this language.\n" + + "If you know this language and you feel generous please update\n" + + "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + + "and send it back to to get it into the distribution ;-)\n\n" + + "Thank you!\n" + + "http://dynarch.com/mishoo/calendar.epl\n"; + } + alert(text); + return; + case -2: + if (year > cal.minYear) { + date.setFullYear(year - 1); + } + break; + case -1: + if (mon > 0) { + setMonth(mon - 1); + } else if (year-- > cal.minYear) { + date.setFullYear(year); + setMonth(11); + } + break; + case 1: + if (mon < 11) { + setMonth(mon + 1); + } else if (year < cal.maxYear) { + date.setFullYear(year + 1); + setMonth(0); + } + break; + case 2: + if (year < cal.maxYear) { + date.setFullYear(year + 1); + } + break; + case 100: + cal.setFirstDayOfWeek(el.fdow); + return; + case 50: + var range = el._range; + var current = el.innerHTML; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + if (ev && ev.shiftKey) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.innerHTML = newval; + cal.onUpdateTime(); + return; + case 0: + // TODAY will bring us here + if ((typeof cal.getDateStatus == "function") && + cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { + return false; + } + break; + } + if (!date.equalsTo(cal.date)) { + cal.setDate(date); + newdate = true; + } else if (el.navtype == 0) + newdate = closing = true; + } + if (newdate) { + ev && cal.callHandler(); + } + if (closing) { + Calendar.removeClass(el, "hilite"); + ev && cal.callCloseHandler(); + } +}; + +// END: CALENDAR STATIC FUNCTIONS + +// BEGIN: CALENDAR OBJECT FUNCTIONS + +/** + * This function creates the calendar inside the given parent. If _par is + * null than it creates a popup calendar inside the BODY element. If _par is + * an element, be it BODY, then it creates a non-popup calendar (still + * hidden). Some properties need to be set before calling this function. + */ +Calendar.prototype.create = function (_par) { + var parent = null; + if (! _par) { + // default parent is the document body, in which case we create + // a popup calendar. + parent = document.getElementsByTagName("body")[0]; + this.isPopup = true; + } else { + parent = _par; + this.isPopup = false; + } + this.date = this.dateStr ? new Date(this.dateStr) : new Date(); + + var table = Calendar.createElement("table"); + this.table = table; + table.cellSpacing = 0; + table.cellPadding = 0; + table.calendar = this; + Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown); + + var div = Calendar.createElement("div"); + this.element = div; + div.className = "calendar"; + if (this.isPopup) { + div.style.position = "absolute"; + div.style.display = "none"; + } + div.appendChild(table); + + var thead = Calendar.createElement("thead", table); + var cell = null; + var row = null; + + var cal = this; + var hh = function (text, cs, navtype) { + cell = Calendar.createElement("td", row); + cell.colSpan = cs; + cell.className = "button"; + if (navtype != 0 && Math.abs(navtype) <= 2) + cell.className += " nav"; + Calendar._add_evs(cell); + cell.calendar = cal; + cell.navtype = navtype; + cell.innerHTML = "

" + text + "
"; + return cell; + }; + + row = Calendar.createElement("tr", thead); + var title_length = 6; + (this.isPopup) && --title_length; + (this.weekNumbers) && ++title_length; + + hh("?", 1, 400).ttip = Calendar._TT["INFO"]; + this.title = hh("", title_length, 300); + this.title.className = "title"; + if (this.isPopup) { + this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; + this.title.style.cursor = "move"; + hh("×", 1, 200).ttip = Calendar._TT["CLOSE"]; + } + + row = Calendar.createElement("tr", thead); + row.className = "headrow"; + + this._nav_py = hh("«", 1, -2); + this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; + + this._nav_pm = hh("‹", 1, -1); + this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; + + this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); + this._nav_now.ttip = Calendar._TT["GO_TODAY"]; + + this._nav_nm = hh("›", 1, 1); + this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; + + this._nav_ny = hh("»", 1, 2); + this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"]; + + // day names + row = Calendar.createElement("tr", thead); + row.className = "daynames"; + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + cell.className = "name wn"; + cell.innerHTML = Calendar._TT["WK"]; + } + for (var i = 7; i > 0; --i) { + cell = Calendar.createElement("td", row); + if (!i) { + cell.navtype = 100; + cell.calendar = this; + Calendar._add_evs(cell); + } + } + this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; + this._displayWeekdays(); + + var tbody = Calendar.createElement("tbody", table); + this.tbody = tbody; + + for (i = 6; i > 0; --i) { + row = Calendar.createElement("tr", tbody); + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + } + for (var j = 7; j > 0; --j) { + cell = Calendar.createElement("td", row); + cell.calendar = this; + Calendar._add_evs(cell); + } + } + + if (this.showsTime) { + row = Calendar.createElement("tr", tbody); + row.className = "time"; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + cell.innerHTML = Calendar._TT["TIME"] || " "; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = this.weekNumbers ? 4 : 3; + + (function(){ + function makeTimePart(className, init, range_start, range_end) { + var part = Calendar.createElement("span", cell); + part.className = className; + part.innerHTML = init; + part.calendar = cal; + part.ttip = Calendar._TT["TIME_PART"]; + part.navtype = 50; + part._range = []; + if (typeof range_start != "number") + part._range = range_start; + else { + for (var i = range_start; i <= range_end; ++i) { + var txt; + if (i < 10 && range_end >= 10) txt = '0' + i; + else txt = '' + i; + part._range[part._range.length] = txt; + } + } + Calendar._add_evs(part); + return part; + }; + var hrs = cal.date.getHours(); + var mins = cal.date.getMinutes(); + var t12 = !cal.time24; + var pm = (hrs > 12); + if (t12 && pm) hrs -= 12; + var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); + var span = Calendar.createElement("span", cell); + span.innerHTML = ":"; + span.className = "colon"; + var M = makeTimePart("minute", mins, 0, 59); + var AP = null; + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + if (t12) + AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]); + else + cell.innerHTML = " "; + + cal.onSetTime = function() { + var pm, hrs = this.date.getHours(), + mins = this.date.getMinutes(); + if (t12) { + pm = (hrs >= 12); + if (pm) hrs -= 12; + if (hrs == 0) hrs = 12; + AP.innerHTML = pm ? "pm" : "am"; + } + H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs; + M.innerHTML = (mins < 10) ? ("0" + mins) : mins; + }; + + cal.onUpdateTime = function() { + var date = this.date; + var h = parseInt(H.innerHTML, 10); + if (t12) { + if (/pm/i.test(AP.innerHTML) && h < 12) + h += 12; + else if (/am/i.test(AP.innerHTML) && h == 12) + h = 0; + } + var d = date.getDate(); + var m = date.getMonth(); + var y = date.getFullYear(); + date.setHours(h); + date.setMinutes(parseInt(M.innerHTML, 10)); + date.setFullYear(y); + date.setMonth(m); + date.setDate(d); + this.dateClicked = false; + this.callHandler(); + }; + })(); + } else { + this.onSetTime = this.onUpdateTime = function() {}; + } + + var tfoot = Calendar.createElement("tfoot", table); + + row = Calendar.createElement("tr", tfoot); + row.className = "footrow"; + + cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); + cell.className = "ttip"; + if (this.isPopup) { + cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; + cell.style.cursor = "move"; + } + this.tooltips = cell; + + div = Calendar.createElement("div", this.element); + this.monthsCombo = div; + div.className = "combo"; + for (i = 0; i < Calendar._MN.length; ++i) { + var mn = Calendar.createElement("div"); + mn.className = Calendar.is_ie ? "label-IEfix" : "label"; + mn.month = i; + mn.innerHTML = Calendar._SMN[i]; + div.appendChild(mn); + } + + div = Calendar.createElement("div", this.element); + this.yearsCombo = div; + div.className = "combo"; + for (i = 12; i > 0; --i) { + var yr = Calendar.createElement("div"); + yr.className = Calendar.is_ie ? "label-IEfix" : "label"; + div.appendChild(yr); + } + + this._init(this.firstDayOfWeek, this.date); + parent.appendChild(this.element); +}; + +/** keyboard navigation, only for popup calendars */ +Calendar._keyEvent = function(ev) { + var cal = window._dynarch_popupCalendar; + if (!cal || cal.multiple) + return false; + (Calendar.is_ie) && (ev = window.event); + var act = (Calendar.is_ie || ev.type == "keypress"), + K = ev.keyCode; + if (ev.ctrlKey) { + switch (K) { + case 37: // KEY left + act && Calendar.cellClick(cal._nav_pm); + break; + case 38: // KEY up + act && Calendar.cellClick(cal._nav_py); + break; + case 39: // KEY right + act && Calendar.cellClick(cal._nav_nm); + break; + case 40: // KEY down + act && Calendar.cellClick(cal._nav_ny); + break; + default: + return false; + } + } else switch (K) { + case 32: // KEY space (now) + Calendar.cellClick(cal._nav_now); + break; + case 27: // KEY esc + act && cal.callCloseHandler(); + break; + case 37: // KEY left + case 38: // KEY up + case 39: // KEY right + case 40: // KEY down + if (act) { + var prev, x, y, ne, el, step; + prev = K == 37 || K == 38; + step = (K == 37 || K == 39) ? 1 : 7; + function setVars() { + el = cal.currentDateEl; + var p = el.pos; + x = p & 15; + y = p >> 4; + ne = cal.ar_days[y][x]; + };setVars(); + function prevMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() - step); + cal.setDate(date); + }; + function nextMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() + step); + cal.setDate(date); + }; + while (1) { + switch (K) { + case 37: // KEY left + if (--x >= 0) + ne = cal.ar_days[y][x]; + else { + x = 6; + K = 38; + continue; + } + break; + case 38: // KEY up + if (--y >= 0) + ne = cal.ar_days[y][x]; + else { + prevMonth(); + setVars(); + } + break; + case 39: // KEY right + if (++x < 7) + ne = cal.ar_days[y][x]; + else { + x = 0; + K = 40; + continue; + } + break; + case 40: // KEY down + if (++y < cal.ar_days.length) + ne = cal.ar_days[y][x]; + else { + nextMonth(); + setVars(); + } + break; + } + break; + } + if (ne) { + if (!ne.disabled) + Calendar.cellClick(ne); + else if (prev) + prevMonth(); + else + nextMonth(); + } + } + break; + case 13: // KEY enter + if (act) + Calendar.cellClick(cal.currentDateEl, ev); + break; + default: + return false; + } + return Calendar.stopEvent(ev); +}; + +/** + * (RE)Initializes the calendar to the given date and firstDayOfWeek + */ +Calendar.prototype._init = function (firstDayOfWeek, date) { + var today = new Date(), + TY = today.getFullYear(), + TM = today.getMonth(), + TD = today.getDate(); + this.table.style.visibility = "hidden"; + var year = date.getFullYear(); + if (year < this.minYear) { + year = this.minYear; + date.setFullYear(year); + } else if (year > this.maxYear) { + year = this.maxYear; + date.setFullYear(year); + } + this.firstDayOfWeek = firstDayOfWeek; + this.date = new Date(date); + var month = date.getMonth(); + var mday = date.getDate(); + var no_days = date.getMonthDays(); + + // calendar voodoo for computing the first day that would actually be + // displayed in the calendar, even if it's from the previous month. + // WARNING: this is magic. ;-) + date.setDate(1); + var day1 = (date.getDay() - this.firstDayOfWeek) % 7; + if (day1 < 0) + day1 += 7; + date.setDate(-day1); + date.setDate(date.getDate() + 1); + + var row = this.tbody.firstChild; + var MN = Calendar._SMN[month]; + var ar_days = this.ar_days = new Array(); + var weekend = Calendar._TT["WEEKEND"]; + var dates = this.multiple ? (this.datesCells = {}) : null; + for (var i = 0; i < 6; ++i, row = row.nextSibling) { + var cell = row.firstChild; + if (this.weekNumbers) { + cell.className = "day wn"; + cell.innerHTML = date.getWeekNumber(); + cell = cell.nextSibling; + } + row.className = "daysrow"; + var hasdays = false, iday, dpos = ar_days[i] = []; + for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) { + iday = date.getDate(); + var wday = date.getDay(); + cell.className = "day"; + cell.pos = i << 4 | j; + dpos[j] = cell; + var current_month = (date.getMonth() == month); + if (!current_month) { + if (this.showsOtherMonths) { + cell.className += " othermonth"; + cell.otherMonth = true; + } else { + cell.className = "emptycell"; + cell.innerHTML = " "; + cell.disabled = true; + continue; + } + } else { + cell.otherMonth = false; + hasdays = true; + } + cell.disabled = false; + cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday; + if (dates) + dates[date.print("%Y%m%d")] = cell; + if (this.getDateStatus) { + var status = this.getDateStatus(date, year, month, iday); + if (this.getDateToolTip) { + var toolTip = this.getDateToolTip(date, year, month, iday); + if (toolTip) + cell.title = toolTip; + } + if (status === true) { + cell.className += " disabled"; + cell.disabled = true; + } else { + if (/disabled/i.test(status)) + cell.disabled = true; + cell.className += " " + status; + } + } + if (!cell.disabled) { + cell.caldate = new Date(date); + cell.ttip = "_"; + if (!this.multiple && current_month + && iday == mday && this.hiliteToday) { + cell.className += " selected"; + this.currentDateEl = cell; + } + if (date.getFullYear() == TY && + date.getMonth() == TM && + iday == TD) { + cell.className += " today"; + cell.ttip += Calendar._TT["PART_TODAY"]; + } + if (weekend.indexOf(wday.toString()) != -1) + cell.className += cell.otherMonth ? " oweekend" : " weekend"; + } + } + if (!(hasdays || this.showsOtherMonths)) + row.className = "emptyrow"; + } + this.title.innerHTML = Calendar._MN[month] + ", " + year; + this.onSetTime(); + this.table.style.visibility = "visible"; + this._initMultipleDates(); + // PROFILE + // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms"; +}; + +Calendar.prototype._initMultipleDates = function() { + if (this.multiple) { + for (var i in this.multiple) { + var cell = this.datesCells[i]; + var d = this.multiple[i]; + if (!d) + continue; + if (cell) + cell.className += " selected"; + } + } +}; + +Calendar.prototype._toggleMultipleDate = function(date) { + if (this.multiple) { + var ds = date.print("%Y%m%d"); + var cell = this.datesCells[ds]; + if (cell) { + var d = this.multiple[ds]; + if (!d) { + Calendar.addClass(cell, "selected"); + this.multiple[ds] = date; + } else { + Calendar.removeClass(cell, "selected"); + delete this.multiple[ds]; + } + } + } +}; + +Calendar.prototype.setDateToolTipHandler = function (unaryFunction) { + this.getDateToolTip = unaryFunction; +}; + +/** + * Calls _init function above for going to a certain date (but only if the + * date is different than the currently selected one). + */ +Calendar.prototype.setDate = function (date) { + if (!date.equalsTo(this.date)) { + this._init(this.firstDayOfWeek, date); + } +}; + +/** + * Refreshes the calendar. Useful if the "disabledHandler" function is + * dynamic, meaning that the list of disabled date can change at runtime. + * Just * call this function if you think that the list of disabled dates + * should * change. + */ +Calendar.prototype.refresh = function () { + this._init(this.firstDayOfWeek, this.date); +}; + +/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ +Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) { + this._init(firstDayOfWeek, this.date); + this._displayWeekdays(); +}; + +/** + * Allows customization of what dates are enabled. The "unaryFunction" + * parameter must be a function object that receives the date (as a JS Date + * object) and returns a boolean value. If the returned value is true then + * the passed date will be marked as disabled. + */ +Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) { + this.getDateStatus = unaryFunction; +}; + +/** Customization of allowed year range for the calendar. */ +Calendar.prototype.setRange = function (a, z) { + this.minYear = a; + this.maxYear = z; +}; + +/** Calls the first user handler (selectedHandler). */ +Calendar.prototype.callHandler = function () { + if (this.onSelected) { + this.onSelected(this, this.date.print(this.dateFormat)); + } +}; + +/** Calls the second user handler (closeHandler). */ +Calendar.prototype.callCloseHandler = function () { + if (this.onClose) { + this.onClose(this); + } + this.hideShowCovered(); +}; + +/** Removes the calendar object from the DOM tree and destroys it. */ +Calendar.prototype.destroy = function () { + var el = this.element.parentNode; + el.removeChild(this.element); + Calendar._C = null; + window._dynarch_popupCalendar = null; +}; + +/** + * Moves the calendar element to a different section in the DOM tree (changes + * its parent). + */ +Calendar.prototype.reparent = function (new_parent) { + var el = this.element; + el.parentNode.removeChild(el); + new_parent.appendChild(el); +}; + +// This gets called when the user presses a mouse button anywhere in the +// document, if the calendar is shown. If the click was outside the open +// calendar this function closes it. +Calendar._checkCalendar = function(ev) { + var calendar = window._dynarch_popupCalendar; + if (!calendar) { + return false; + } + var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); + for (; el != null && el != calendar.element; el = el.parentNode); + if (el == null) { + // calls closeHandler which should hide the calendar. + window._dynarch_popupCalendar.callCloseHandler(); + return Calendar.stopEvent(ev); + } +}; + +/** Shows the calendar. */ +Calendar.prototype.show = function () { + var rows = this.table.getElementsByTagName("tr"); + for (var i = rows.length; i > 0;) { + var row = rows[--i]; + Calendar.removeClass(row, "rowhilite"); + var cells = row.getElementsByTagName("td"); + for (var j = cells.length; j > 0;) { + var cell = cells[--j]; + Calendar.removeClass(cell, "hilite"); + Calendar.removeClass(cell, "active"); + } + } + this.element.style.display = "block"; + this.hidden = false; + if (this.isPopup) { + window._dynarch_popupCalendar = this; + Calendar.addEvent(document, "keydown", Calendar._keyEvent); + Calendar.addEvent(document, "keypress", Calendar._keyEvent); + Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); + } + this.hideShowCovered(); +}; + +/** + * Hides the calendar. Also removes any "hilite" from the class of any TD + * element. + */ +Calendar.prototype.hide = function () { + if (this.isPopup) { + Calendar.removeEvent(document, "keydown", Calendar._keyEvent); + Calendar.removeEvent(document, "keypress", Calendar._keyEvent); + Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); + } + this.element.style.display = "none"; + this.hidden = true; + this.hideShowCovered(); +}; + +/** + * Shows the calendar at a given absolute position (beware that, depending on + * the calendar element style -- position property -- this might be relative + * to the parent's containing rectangle). + */ +Calendar.prototype.showAt = function (x, y) { + var s = this.element.style; + s.left = x + "px"; + s.top = y + "px"; + this.show(); +}; + +/** Shows the calendar near a given element. */ +Calendar.prototype.showAtElement = function (el, opts) { + var self = this; + var p = Calendar.getAbsolutePos(el); + if (!opts || typeof opts != "string") { + this.showAt(p.x, p.y + el.offsetHeight); + return true; + } + function fixPosition(box) { + if (box.x < 0) + box.x = 0; + if (box.y < 0) + box.y = 0; + var cp = document.createElement("div"); + var s = cp.style; + s.position = "absolute"; + s.right = s.bottom = s.width = s.height = "0px"; + document.body.appendChild(cp); + var br = Calendar.getAbsolutePos(cp); + document.body.removeChild(cp); + if (Calendar.is_ie) { + br.y += document.body.scrollTop; + br.x += document.body.scrollLeft; + } else { + br.y += window.scrollY; + br.x += window.scrollX; + } + var tmp = box.x + box.width - br.x; + if (tmp > 0) box.x -= tmp; + tmp = box.y + box.height - br.y; + if (tmp > 0) box.y -= tmp; + }; + this.element.style.display = "block"; + Calendar.continuation_for_the_fucking_khtml_browser = function() { + var w = self.element.offsetWidth; + var h = self.element.offsetHeight; + self.element.style.display = "none"; + var valign = opts.substr(0, 1); + var halign = "l"; + if (opts.length > 1) { + halign = opts.substr(1, 1); + } + // vertical alignment + switch (valign) { + case "T": p.y -= h; break; + case "B": p.y += el.offsetHeight; break; + case "C": p.y += (el.offsetHeight - h) / 2; break; + case "t": p.y += el.offsetHeight - h; break; + case "b": break; // already there + } + // horizontal alignment + switch (halign) { + case "L": p.x -= w; break; + case "R": p.x += el.offsetWidth; break; + case "C": p.x += (el.offsetWidth - w) / 2; break; + case "l": p.x += el.offsetWidth - w; break; + case "r": break; // already there + } + p.width = w; + p.height = h + 40; + self.monthsCombo.style.display = "none"; + fixPosition(p); + self.showAt(p.x, p.y); + }; + if (Calendar.is_khtml) + setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); + else + Calendar.continuation_for_the_fucking_khtml_browser(); +}; + +/** Customizes the date format. */ +Calendar.prototype.setDateFormat = function (str) { + this.dateFormat = str; +}; + +/** Customizes the tooltip date format. */ +Calendar.prototype.setTtDateFormat = function (str) { + this.ttDateFormat = str; +}; + +/** + * Tries to identify the date represented in a string. If successful it also + * calls this.setDate which moves the calendar to the given date. + */ +Calendar.prototype.parseDate = function(str, fmt) { + if (!fmt) + fmt = this.dateFormat; + this.setDate(Date.parseDate(str, fmt)); +}; + +Calendar.prototype.hideShowCovered = function () { + if (!Calendar.is_ie && !Calendar.is_opera) + return; + function getVisib(obj){ + var value = obj.style.visibility; + if (!value) { + if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C + if (!Calendar.is_khtml) + value = document.defaultView. + getComputedStyle(obj, "").getPropertyValue("visibility"); + else + value = ''; + } else if (obj.currentStyle) { // IE + value = obj.currentStyle.visibility; + } else + value = ''; + } + return value; + }; + + var tags = new Array("applet", "iframe", "select"); + var el = this.element; + + var p = Calendar.getAbsolutePos(el); + var EX1 = p.x; + var EX2 = el.offsetWidth + EX1; + var EY1 = p.y; + var EY2 = el.offsetHeight + EY1; + + for (var k = tags.length; k > 0; ) { + var ar = document.getElementsByTagName(tags[--k]); + var cc = null; + + for (var i = ar.length; i > 0;) { + cc = ar[--i]; + + p = Calendar.getAbsolutePos(cc); + var CX1 = p.x; + var CX2 = cc.offsetWidth + CX1; + var CY1 = p.y; + var CY2 = cc.offsetHeight + CY1; + + if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = cc.__msh_save_visibility; + } else { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = "hidden"; + } + } + } +}; + +/** Internal function; it displays the bar with the names of the weekday. */ +Calendar.prototype._displayWeekdays = function () { + var fdow = this.firstDayOfWeek; + var cell = this.firstdayname; + var weekend = Calendar._TT["WEEKEND"]; + for (var i = 0; i < 7; ++i) { + cell.className = "day name"; + var realday = (i + fdow) % 7; + if (i) { + cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); + cell.navtype = 100; + cell.calendar = this; + cell.fdow = realday; + Calendar._add_evs(cell); + } + if (weekend.indexOf(realday.toString()) != -1) { + Calendar.addClass(cell, "weekend"); + } + cell.innerHTML = Calendar._SDN[(i + fdow) % 7]; + cell = cell.nextSibling; + } +}; + +/** Internal function. Hides all combo boxes that might be displayed. */ +Calendar.prototype._hideCombos = function () { + this.monthsCombo.style.display = "none"; + this.yearsCombo.style.display = "none"; +}; + +/** Internal function. Starts dragging the element. */ +Calendar.prototype._dragStart = function (ev) { + if (this.dragging) { + return; + } + this.dragging = true; + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posY = ev.clientY + window.scrollY; + posX = ev.clientX + window.scrollX; + } + var st = this.element.style; + this.xOffs = posX - parseInt(st.left); + this.yOffs = posY - parseInt(st.top); + with (Calendar) { + addEvent(document, "mousemove", calDragIt); + addEvent(document, "mouseup", calDragEnd); + } +}; + +// BEGIN: DATE OBJECT PATCHES + +/** Adds the number of days array to the Date object. */ +Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); + +/** Constants used for time computations */ +Date.SECOND = 1000 /* milliseconds */; +Date.MINUTE = 60 * Date.SECOND; +Date.HOUR = 60 * Date.MINUTE; +Date.DAY = 24 * Date.HOUR; +Date.WEEK = 7 * Date.DAY; + +Date.parseDate = function(str, fmt) { + var today = new Date(); + var y = 0; + var m = -1; + var d = 0; + var a = str.split(/\W+/); + var b = fmt.match(/%./g); + var i = 0, j = 0; + var hr = 0; + var min = 0; + for (i = 0; i < a.length; ++i) { + if (!a[i]) + continue; + switch (b[i]) { + case "%d": + case "%e": + d = parseInt(a[i], 10); + break; + + case "%m": + m = parseInt(a[i], 10) - 1; + break; + + case "%Y": + case "%y": + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + break; + + case "%b": + case "%B": + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } + } + break; + + case "%H": + case "%I": + case "%k": + case "%l": + hr = parseInt(a[i], 10); + break; + + case "%P": + case "%p": + if (/pm/i.test(a[i]) && hr < 12) + hr += 12; + else if (/am/i.test(a[i]) && hr >= 12) + hr -= 12; + break; + + case "%M": + min = parseInt(a[i], 10); + break; + } + } + if (isNaN(y)) y = today.getFullYear(); + if (isNaN(m)) m = today.getMonth(); + if (isNaN(d)) d = today.getDate(); + if (isNaN(hr)) hr = today.getHours(); + if (isNaN(min)) min = today.getMinutes(); + if (y != 0 && m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); + y = 0; m = -1; d = 0; + for (i = 0; i < a.length; ++i) { + if (a[i].search(/[a-zA-Z]+/) != -1) { + var t = -1; + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } + } + if (t != -1) { + if (m != -1) { + d = m+1; + } + m = t; + } + } else if (parseInt(a[i], 10) <= 12 && m == -1) { + m = a[i]-1; + } else if (parseInt(a[i], 10) > 31 && y == 0) { + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + } else if (d == 0) { + d = a[i]; + } + } + if (y == 0) + y = today.getFullYear(); + if (m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); + return today; +}; + +/** Returns the number of days in the current month */ +Date.prototype.getMonthDays = function(month) { + var year = this.getFullYear(); + if (typeof month == "undefined") { + month = this.getMonth(); + } + if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { + return 29; + } else { + return Date._MD[month]; + } +}; + +/** Returns the number of day in the year. */ +Date.prototype.getDayOfYear = function() { + var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); + var time = now - then; + return Math.floor(time / Date.DAY); +}; + +/** Returns the number of the week in year, as defined in ISO 8601. */ +Date.prototype.getWeekNumber = function() { + var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var DoW = d.getDay(); + d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu + var ms = d.valueOf(); // GMT + d.setMonth(0); + d.setDate(4); // Thu in Week 1 + return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; +}; + +/** Checks date and time equality */ +Date.prototype.equalsTo = function(date) { + return ((this.getFullYear() == date.getFullYear()) && + (this.getMonth() == date.getMonth()) && + (this.getDate() == date.getDate()) && + (this.getHours() == date.getHours()) && + (this.getMinutes() == date.getMinutes())); +}; + +/** Set only the year, month, date parts (keep existing time) */ +Date.prototype.setDateOnly = function(date) { + var tmp = new Date(date); + this.setDate(1); + this.setFullYear(tmp.getFullYear()); + this.setMonth(tmp.getMonth()); + this.setDate(tmp.getDate()); +}; + +/** Prints the date in a string according to the given format. */ +Date.prototype.print = function (str) { + var m = this.getMonth(); + var d = this.getDate(); + var y = this.getFullYear(); + var wn = this.getWeekNumber(); + var w = this.getDay(); + var s = {}; + var hr = this.getHours(); + var pm = (hr >= 12); + var ir = (pm) ? (hr - 12) : hr; + var dy = this.getDayOfYear(); + if (ir == 0) + ir = 12; + var min = this.getMinutes(); + var sec = this.getSeconds(); + s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N] + s["%A"] = Calendar._DN[w]; // full weekday name + s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N] + s["%B"] = Calendar._MN[m]; // full month name + // FIXME: %c : preferred date and time representation for the current locale + s["%C"] = 1 + Math.floor(y / 100); // the century number + s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) + s["%e"] = d; // the day of the month (range 1 to 31) + // FIXME: %D : american date style: %m/%d/%y + // FIXME: %E, %F, %G, %g, %h (man strftime) + s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) + s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) + s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) + s["%k"] = hr; // hour, range 0 to 23 (24h format) + s["%l"] = ir; // hour, range 1 to 12 (12h format) + s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 + s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 + s["%n"] = "\n"; // a newline character + s["%p"] = pm ? "PM" : "AM"; + s["%P"] = pm ? "pm" : "am"; + // FIXME: %r : the time in am/pm notation %I:%M:%S %p + // FIXME: %R : the time in 24-hour notation %H:%M + s["%s"] = Math.floor(this.getTime() / 1000); + s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 + s["%t"] = "\t"; // a tab character + // FIXME: %T : the time in 24-hour notation (%H:%M:%S) + s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; + s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) + s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) + // FIXME: %x : preferred date representation for the current locale without the time + // FIXME: %X : preferred time representation for the current locale without the date + s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) + s["%Y"] = y; // year with the century + s["%%"] = "%"; // a literal '%' character + + var re = /%./g; + if (!Calendar.is_ie5 && !Calendar.is_khtml) + return str.replace(re, function (par) { return s[par] || par; }); + + var a = str.match(re); + for (var i = 0; i < a.length; i++) { + var tmp = s[a[i]]; + if (tmp) { + re = new RegExp(a[i], 'g'); + str = str.replace(re, tmp); + } + } + + return str; +}; + +Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; +Date.prototype.setFullYear = function(y) { + var d = new Date(this); + d.__msh_oldSetFullYear(y); + if (d.getMonth() != this.getMonth()) + this.setDate(28); + this.__msh_oldSetFullYear(y); +}; + +// END: DATE OBJECT PATCHES + + +// global object that remembers the calendar +window._dynarch_popupCalendar = null; diff --git a/htdocs/js/jscalendar/lang/calendar-af.js b/htdocs/js/jscalendar/lang/calendar-af.js new file mode 100644 index 0000000..aeda581 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-af.js @@ -0,0 +1,39 @@ +// ** I18N Afrikaans +Calendar._DN = new Array +("Sondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrydag", + "Saterdag", + "Sondag"); +Calendar._MN = new Array +("Januarie", + "Februarie", + "Maart", + "April", + "Mei", + "Junie", + "Julie", + "Augustus", + "September", + "Oktober", + "November", + "Desember"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Verander eerste dag van die week"; +Calendar._TT["PREV_YEAR"] = "Vorige jaar (hou vir keuselys)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (hou vir keuselys)"; +Calendar._TT["GO_TODAY"] = "Gaan na vandag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (hou vir keuselys)"; +Calendar._TT["NEXT_YEAR"] = "Volgende jaar (hou vir keuselys)"; +Calendar._TT["SEL_DATE"] = "Kies datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te skuif"; +Calendar._TT["PART_TODAY"] = " (vandag)"; +Calendar._TT["MON_FIRST"] = "Vertoon Maandag eerste"; +Calendar._TT["SUN_FIRST"] = "Display Sunday first"; +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; diff --git a/htdocs/js/jscalendar/lang/calendar-al.js b/htdocs/js/jscalendar/lang/calendar-al.js new file mode 100644 index 0000000..4f701cf --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-al.js @@ -0,0 +1,101 @@ +// Calendar ALBANIAN language +//author Rigels Gordani rige@hotmail.com + +// ditet +Calendar._DN = new Array +("E Diele", +"E Hene", +"E Marte", +"E Merkure", +"E Enjte", +"E Premte", +"E Shtune", +"E Diele"); + +//ditet shkurt +Calendar._SDN = new Array +("Die", +"Hen", +"Mar", +"Mer", +"Enj", +"Pre", +"Sht", +"Die"); + +// muajt +Calendar._MN = new Array +("Janar", +"Shkurt", +"Mars", +"Prill", +"Maj", +"Qeshor", +"Korrik", +"Gusht", +"Shtator", +"Tetor", +"Nentor", +"Dhjetor"); + +// muajte shkurt +Calendar._SMN = new Array +("Jan", +"Shk", +"Mar", +"Pri", +"Maj", +"Qes", +"Kor", +"Gus", +"Sht", +"Tet", +"Nen", +"Dhj"); + +// ndihmesa +Calendar._TT = {}; +Calendar._TT["INFO"] = "Per kalendarin"; + +Calendar._TT["ABOUT"] = +"Zgjedhes i ores/dates ne DHTML \n" + +"\n\n" +"Zgjedhja e Dates:\n" + +"- Perdor butonat \xab, \xbb per te zgjedhur vitin\n" + +"- Perdor butonat" + String.fromCharCode(0x2039) + ", " + +String.fromCharCode(0x203a) + +" per te zgjedhur muajin\n" + +"- Mbani shtypur butonin e mousit per nje zgjedje me te shpejte."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Zgjedhja e kohes:\n" + +"- Kliko tek ndonje nga pjeset e ores per ta rritur ate\n" + +"- ose kliko me Shift per ta zvogeluar ate\n" + +"- ose cliko dhe terhiq per zgjedhje me te shpejte."; + +Calendar._TT["PREV_YEAR"] = "Viti i shkuar (prit per menune)"; +Calendar._TT["PREV_MONTH"] = "Muaji i shkuar (prit per menune)"; +Calendar._TT["GO_TODAY"] = "Sot"; +Calendar._TT["NEXT_MONTH"] = "Muaji i ardhshem (prit per menune)"; +Calendar._TT["NEXT_YEAR"] = "Viti i ardhshem (prit per menune)"; +Calendar._TT["SEL_DATE"] = "Zgjidh daten"; +Calendar._TT["DRAG_TO_MOVE"] = "Terhiqe per te levizur"; +Calendar._TT["PART_TODAY"] = " (sot)"; + +// "%s" eshte dita e pare e javes +// %s do te zevendesohet me emrin e dite +Calendar._TT["DAY_FIRST"] = "Trego te %s te paren"; + + +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Mbyll"; +Calendar._TT["TODAY"] = "Sot"; +Calendar._TT["TIME_PART"] = "Kliko me (Shift-)ose terhiqe per te ndryshuar +vleren"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Java"; +Calendar._TT["TIME"] = "Koha:"; + diff --git a/htdocs/js/jscalendar/lang/calendar-bg.js b/htdocs/js/jscalendar/lang/calendar-bg.js new file mode 100644 index 0000000..5eb73ec --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-bg.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar BG language +// Author: Mihai Bazon, +// Translator: Valentin Sheiretsky, +// Encoding: Windows-1251 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Íåäåëÿ", + "Ïîíåäåëíèê", + "Âòîðíèê", + "Ñðÿäà", + "×åòâúðòúê", + "Ïåòúê", + "Ñúáîòà", + "Íåäåëÿ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Íåä", + "Ïîí", + "Âòî", + "Ñðÿ", + "×åò", + "Ïåò", + "Ñúá", + "Íåä"); + +// full month names +Calendar._MN = new Array +("ßíóàðè", + "Ôåâðóàðè", + "Ìàðò", + "Àïðèë", + "Ìàé", + "Þíè", + "Þëè", + "Àâãóñò", + "Ñåïòåìâðè", + "Îêòîìâðè", + "Íîåìâðè", + "Äåêåìâðè"); + +// short month names +Calendar._SMN = new Array +("ßíó", + "Ôåâ", + "Ìàð", + "Àïð", + "Ìàé", + "Þíè", + "Þëè", + "Àâã", + "Ñåï", + "Îêò", + "Íîå", + "Äåê"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Èíôîðìàöèÿ çà êàëåíäàðà"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Date selection:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + +"- Hold mouse button on any of the above buttons for faster selection."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- Click on any of the time parts to increase it\n" + +"- or Shift-click to decrease it\n" + +"- or click and drag for faster selection."; + +Calendar._TT["PREV_YEAR"] = "Ïðåäíà ãîäèíà (çàäðúæòå çà ìåíþ)"; +Calendar._TT["PREV_MONTH"] = "Ïðåäåí ìåñåö (çàäðúæòå çà ìåíþ)"; +Calendar._TT["GO_TODAY"] = "Èçáåðåòå äíåñ"; +Calendar._TT["NEXT_MONTH"] = "Ñëåäâàù ìåñåö (çàäðúæòå çà ìåíþ)"; +Calendar._TT["NEXT_YEAR"] = "Ñëåäâàùà ãîäèíà (çàäðúæòå çà ìåíþ)"; +Calendar._TT["SEL_DATE"] = "Èçáåðåòå äàòà"; +Calendar._TT["DRAG_TO_MOVE"] = "Ïðåìåñòâàíå"; +Calendar._TT["PART_TODAY"] = " (äíåñ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s êàòî ïúðâè äåí"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Çàòâîðåòå"; +Calendar._TT["TODAY"] = "Äíåñ"; +Calendar._TT["TIME_PART"] = "(Shift-)Click èëè drag çà äà ïðîìåíèòå ñòîéíîñòòà"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A - %e %B %Y"; + +Calendar._TT["WK"] = "Ñåäì"; +Calendar._TT["TIME"] = "×àñ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-big5-utf8.js b/htdocs/js/jscalendar/lang/calendar-big5-utf8.js new file mode 100644 index 0000000..14e0d5d --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-big5-utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar big5-utf8 language +// Author: Gary Fu, +// Encoding: utf8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("星期日", + "星期一", + "星期二", + "星期三", + "星期四", + "星期五", + "星期六", + "星期日"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("æ—¥", + "一", + "二", + "三", + "å››", + "五", + "å…­", + "æ—¥"); + +// full month names +Calendar._MN = new Array +("一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "ä¹æœˆ", + "å月", + "å一月", + "å二月"); + +// short month names +Calendar._SMN = new Array +("一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "ä¹æœˆ", + "å月", + "å一月", + "å二月"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "關於"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"日期é¸æ“‡æ–¹æ³•:\n" + +"- 使用 \xab, \xbb 按鈕å¯é¸æ“‡å¹´ä»½\n" + +"- 使用 " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " 按鈕å¯é¸æ“‡æœˆä»½\n" + +"- 按ä½ä¸Šé¢çš„按鈕å¯ä»¥åŠ å¿«é¸å–"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"時間é¸æ“‡æ–¹æ³•:\n" + +"- 點擊任何的時間部份å¯å¢žåŠ å…¶å€¼\n" + +"- åŒæ™‚按Shiftéµå†é»žæ“Šå¯æ¸›å°‘其值\n" + +"- 點擊並拖曳å¯åŠ å¿«æ”¹è®Šçš„值"; + +Calendar._TT["PREV_YEAR"] = "上一年 (按ä½é¸å–®)"; +Calendar._TT["PREV_MONTH"] = "下一年 (按ä½é¸å–®)"; +Calendar._TT["GO_TODAY"] = "到今日"; +Calendar._TT["NEXT_MONTH"] = "上一月 (按ä½é¸å–®)"; +Calendar._TT["NEXT_YEAR"] = "下一月 (按ä½é¸å–®)"; +Calendar._TT["SEL_DATE"] = "é¸æ“‡æ—¥æœŸ"; +Calendar._TT["DRAG_TO_MOVE"] = "拖曳"; +Calendar._TT["PART_TODAY"] = " (今日)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "å°‡ %s 顯示在å‰"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "關閉"; +Calendar._TT["TODAY"] = "今日"; +Calendar._TT["TIME_PART"] = "點擊or拖曳å¯æ”¹è®Šæ™‚é–“(åŒæ™‚按Shift為減)"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "週"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-big5.js b/htdocs/js/jscalendar/lang/calendar-big5.js new file mode 100644 index 0000000..a589358 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-big5.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar big5 language +// Author: Gary Fu, +// Encoding: big5 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("¬P´Á¤é", + "¬P´Á¤@", + "¬P´Á¤G", + "¬P´Á¤T", + "¬P´Á¥|", + "¬P´Á¤­", + "¬P´Á¤»", + "¬P´Á¤é"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("¤é", + "¤@", + "¤G", + "¤T", + "¥|", + "¤­", + "¤»", + "¤é"); + +// full month names +Calendar._MN = new Array +("¤@¤ë", + "¤G¤ë", + "¤T¤ë", + "¥|¤ë", + "¤­¤ë", + "¤»¤ë", + "¤C¤ë", + "¤K¤ë", + "¤E¤ë", + "¤Q¤ë", + "¤Q¤@¤ë", + "¤Q¤G¤ë"); + +// short month names +Calendar._SMN = new Array +("¤@¤ë", + "¤G¤ë", + "¤T¤ë", + "¥|¤ë", + "¤­¤ë", + "¤»¤ë", + "¤C¤ë", + "¤K¤ë", + "¤E¤ë", + "¤Q¤ë", + "¤Q¤@¤ë", + "¤Q¤G¤ë"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Ãö©ó"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"¤é´Á¿ï¾Ü¤èªk:\n" + +"- ¨Ï¥Î \xab, \xbb «ö¶s¥i¿ï¾Ü¦~¥÷\n" + +"- ¨Ï¥Î " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " «ö¶s¥i¿ï¾Ü¤ë¥÷\n" + +"- «ö¦í¤W­±ªº«ö¶s¥i¥H¥[§Ö¿ï¨ú"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"®É¶¡¿ï¾Ü¤èªk:\n" + +"- ÂIÀ»¥ô¦óªº®É¶¡³¡¥÷¥i¼W¥[¨ä­È\n" + +"- ¦P®É«öShiftÁä¦AÂIÀ»¥i´î¤Ö¨ä­È\n" + +"- ÂIÀ»¨Ã©ì¦²¥i¥[§Ö§ïÅܪº­È"; + +Calendar._TT["PREV_YEAR"] = "¤W¤@¦~ («ö¦í¿ï³æ)"; +Calendar._TT["PREV_MONTH"] = "¤U¤@¦~ («ö¦í¿ï³æ)"; +Calendar._TT["GO_TODAY"] = "¨ì¤µ¤é"; +Calendar._TT["NEXT_MONTH"] = "¤W¤@¤ë («ö¦í¿ï³æ)"; +Calendar._TT["NEXT_YEAR"] = "¤U¤@¤ë («ö¦í¿ï³æ)"; +Calendar._TT["SEL_DATE"] = "¿ï¾Ü¤é´Á"; +Calendar._TT["DRAG_TO_MOVE"] = "©ì¦²"; +Calendar._TT["PART_TODAY"] = " (¤µ¤é)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "±N %s Åã¥Ü¦b«e"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Ãö³¬"; +Calendar._TT["TODAY"] = "¤µ¤é"; +Calendar._TT["TIME_PART"] = "ÂIÀ»or©ì¦²¥i§ïÅܮɶ¡(¦P®É«öShift¬°´î)"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "¶g"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-br.js b/htdocs/js/jscalendar/lang/calendar-br.js new file mode 100644 index 0000000..bfb0747 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-br.js @@ -0,0 +1,108 @@ +// ** I18N + +// Calendar pt-BR language +// Author: Fernando Dourado, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terça", + "Quarta", + "Quinta", + "Sexta", + "Sabádo", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +// [No changes using default values] + +// full month names +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// short month names +// [No changes using default values] + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre o calendário"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Translate to portuguese Brazil (pt-BR) by Fernando Dourado (fernando.dourado@ig.com.br)\n" + +"Tradução para o português Brasil (pt-BR) por Fernando Dourado (fernando.dourado@ig.com.br)" + +"\n\n" + +"Selecionar data:\n" + +"- Use as teclas \xab, \xbb para selecionar o ano\n" + +"- Use as teclas " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para selecionar o mês\n" + +"- Clique e segure com o mouse em qualquer botão para selecionar rapidamente."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selecionar hora:\n" + +"- Clique em qualquer uma das partes da hora para aumentar\n" + +"- ou Shift-clique para diminuir\n" + +"- ou clique e arraste para selecionar rapidamente."; + +Calendar._TT["PREV_YEAR"] = "Ano anterior (clique e segure para menu)"; +Calendar._TT["PREV_MONTH"] = "Mês anterior (clique e segure para menu)"; +Calendar._TT["GO_TODAY"] = "Ir para a data atual"; +Calendar._TT["NEXT_MONTH"] = "Próximo mês (clique e segure para menu)"; +Calendar._TT["NEXT_YEAR"] = "Próximo ano (clique e segure para menu)"; +Calendar._TT["SEL_DATE"] = "Selecione uma data"; +Calendar._TT["DRAG_TO_MOVE"] = "Clique e segure para mover"; +Calendar._TT["PART_TODAY"] = " (hoje)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Exibir %s primeiro"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; +Calendar._TT["TIME_PART"] = "(Shift-)Clique ou arraste para mudar o valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%d de %B de %Y"; + +Calendar._TT["WK"] = "sem"; +Calendar._TT["TIME"] = "Hora:"; + diff --git a/htdocs/js/jscalendar/lang/calendar-ca.js b/htdocs/js/jscalendar/lang/calendar-ca.js new file mode 100644 index 0000000..a2121bc --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ca.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar CA language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Diumenge", + "Dilluns", + "Dimarts", + "Dimecres", + "Dijous", + "Divendres", + "Dissabte", + "Diumenge"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Diu", + "Dil", + "Dmt", + "Dmc", + "Dij", + "Div", + "Dis", + "Diu"); + +// full month names +Calendar._MN = new Array +("Gener", + "Febrer", + "Març", + "Abril", + "Maig", + "Juny", + "Juliol", + "Agost", + "Setembre", + "Octubre", + "Novembre", + "Desembre"); + +// short month names +Calendar._SMN = new Array +("Gen", + "Feb", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Oct", + "Nov", + "Des"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre el calendari"; + +Calendar._TT["ABOUT"] = +"DHTML Selector de Data/Hora\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Sel.lecció de Dates:\n" + +"- Fes servir els botons \xab, \xbb per sel.leccionar l'any\n" + +"- Fes servir els botons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per se.lecciconar el mes\n" + +"- Manté el ratolí apretat en qualsevol dels anteriors per sel.lecció ràpida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- claca en qualsevol de les parts de la hora per augmentar-les\n" + +"- o Shift-click per decrementar-la\n" + +"- or click and arrastra per sel.lecció ràpida."; + +Calendar._TT["PREV_YEAR"] = "Any anterior (Mantenir per menu)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (Mantenir per menu)"; +Calendar._TT["GO_TODAY"] = "Anar a avui"; +Calendar._TT["NEXT_MONTH"] = "Mes següent (Mantenir per menu)"; +Calendar._TT["NEXT_YEAR"] = "Any següent (Mantenir per menu)"; +Calendar._TT["SEL_DATE"] = "Sel.leccionar data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar per moure"; +Calendar._TT["PART_TODAY"] = " (avui)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostra %s primer"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Tanca"; +Calendar._TT["TODAY"] = "Avui"; +Calendar._TT["TIME_PART"] = "(Shift-)Click a arrastra per canviar el valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "st"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-cs-utf8.js b/htdocs/js/jscalendar/lang/calendar-cs-utf8.js new file mode 100644 index 0000000..f6bbbeb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-cs-utf8.js @@ -0,0 +1,65 @@ +/* + calendar-cs-win.js + language: Czech + encoding: windows-1250 + author: Lubos Jerabek (xnet@seznam.cz) + Jan Uhlir (espinosa@centrum.cz) +*/ + +// ** I18N +Calendar._DN = new Array('NedÄ›le','PondÄ›lí','Úterý','StÅ™eda','ÄŒtvrtek','Pátek','Sobota','NedÄ›le'); +Calendar._SDN = new Array('Ne','Po','Út','St','ÄŒt','Pá','So','Ne'); +Calendar._MN = new Array('Leden','Únor','BÅ™ezen','Duben','KvÄ›ten','ÄŒerven','ÄŒervenec','Srpen','Září','Říjen','Listopad','Prosinec'); +Calendar._SMN = new Array('Led','Úno','BÅ™e','Dub','KvÄ›','ÄŒrv','ÄŒvc','Srp','Zář','Říj','Lis','Pro'); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O komponentÄ› kalendář"; +Calendar._TT["TOGGLE"] = "ZmÄ›na prvního dne v týdnu"; +Calendar._TT["PREV_YEAR"] = "PÅ™edchozí rok (pÅ™idrž pro menu)"; +Calendar._TT["PREV_MONTH"] = "PÅ™edchozí mÄ›síc (pÅ™idrž pro menu)"; +Calendar._TT["GO_TODAY"] = "DneÅ¡ní datum"; +Calendar._TT["NEXT_MONTH"] = "Další mÄ›síc (pÅ™idrž pro menu)"; +Calendar._TT["NEXT_YEAR"] = "Další rok (pÅ™idrž pro menu)"; +Calendar._TT["SEL_DATE"] = "Vyber datum"; +Calendar._TT["DRAG_TO_MOVE"] = "ChyÅ¥ a táhni, pro pÅ™esun"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "Ukaž jako první PondÄ›lí"; +//Calendar._TT["SUN_FIRST"] = "Ukaž jako první NedÄ›li"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"VýbÄ›r datumu:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Použijte tlaÄítka " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " k výbÄ›ru mÄ›síce\n" + +"- Podržte tlaÄítko myÅ¡i na jakémkoliv z tÄ›ch tlaÄítek pro rychlejší výbÄ›r."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"VýbÄ›r Äasu:\n" + +"- KliknÄ›te na jakoukoliv z Äástí výbÄ›ru Äasu pro zvýšení.\n" + +"- nebo Shift-click pro snížení\n" + +"- nebo kliknÄ›te a táhnÄ›te pro rychlejší výbÄ›r."; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Zobraz %s první"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Zavřít"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikni nebo táhni pro zmÄ›nu hodnoty"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "ÄŒas:"; diff --git a/htdocs/js/jscalendar/lang/calendar-cs-win.js b/htdocs/js/jscalendar/lang/calendar-cs-win.js new file mode 100644 index 0000000..140dff3 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-cs-win.js @@ -0,0 +1,65 @@ +/* + calendar-cs-win.js + language: Czech + encoding: windows-1250 + author: Lubos Jerabek (xnet@seznam.cz) + Jan Uhlir (espinosa@centrum.cz) +*/ + +// ** I18N +Calendar._DN = new Array('Nedìle','Pondìlí','Úterý','Støeda','Ètvrtek','Pátek','Sobota','Nedìle'); +Calendar._SDN = new Array('Ne','Po','Út','St','Èt','Pá','So','Ne'); +Calendar._MN = new Array('Leden','Únor','Bøezen','Duben','Kvìten','Èerven','Èervenec','Srpen','Záøí','Øíjen','Listopad','Prosinec'); +Calendar._SMN = new Array('Led','Úno','Bøe','Dub','Kvì','Èrv','Èvc','Srp','Záø','Øíj','Lis','Pro'); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O komponentì kalendáø"; +Calendar._TT["TOGGLE"] = "Zmìna prvního dne v týdnu"; +Calendar._TT["PREV_YEAR"] = "Pøedchozí rok (pøidrž pro menu)"; +Calendar._TT["PREV_MONTH"] = "Pøedchozí mìsíc (pøidrž pro menu)"; +Calendar._TT["GO_TODAY"] = "Dnešní datum"; +Calendar._TT["NEXT_MONTH"] = "Další mìsíc (pøidrž pro menu)"; +Calendar._TT["NEXT_YEAR"] = "Další rok (pøidrž pro menu)"; +Calendar._TT["SEL_DATE"] = "Vyber datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Chy a táhni, pro pøesun"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "Ukaž jako první Pondìlí"; +//Calendar._TT["SUN_FIRST"] = "Ukaž jako první Nedìli"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Výbìr datumu:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Použijte tlaèítka " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " k výbìru mìsíce\n" + +"- Podržte tlaèítko myši na jakémkoliv z tìch tlaèítek pro rychlejší výbìr."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Výbìr èasu:\n" + +"- Kliknìte na jakoukoliv z èástí výbìru èasu pro zvýšení.\n" + +"- nebo Shift-click pro snížení\n" + +"- nebo kliknìte a táhnìte pro rychlejší výbìr."; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Zobraz %s první"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Zavøít"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikni nebo táhni pro zmìnu hodnoty"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Èas:"; diff --git a/htdocs/js/jscalendar/lang/calendar-da.js b/htdocs/js/jscalendar/lang/calendar-da.js new file mode 100644 index 0000000..a99b598 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-da.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar DA language +// Author: Michael Thingmand Henriksen, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Søndag", +"Mandag", +"Tirsdag", +"Onsdag", +"Torsdag", +"Fredag", +"Lørdag", +"Søndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Søn", +"Man", +"Tir", +"Ons", +"Tor", +"Fre", +"Lør", +"Søn"); + +// full month names +Calendar._MN = new Array +("Januar", +"Februar", +"Marts", +"April", +"Maj", +"Juni", +"Juli", +"August", +"September", +"Oktober", +"November", +"December"); + +// short month names +Calendar._SMN = new Array +("Jan", +"Feb", +"Mar", +"Apr", +"Maj", +"Jun", +"Jul", +"Aug", +"Sep", +"Okt", +"Nov", +"Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om Kalenderen"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For den seneste version besøg: http://www.dynarch.com/projects/calendar/\n"; + +"Distribueret under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detajler." + +"\n\n" + +"Valg af dato:\n" + +"- Brug \xab, \xbb knapperne for at vælge Ã¥r\n" + +"- Brug " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knapperne for at vælge mÃ¥ned\n" + +"- Hold knappen pÃ¥ musen nede pÃ¥ knapperne ovenfor for hurtigere valg."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Valg af tid:\n" + +"- Klik pÃ¥ en vilkÃ¥rlig del for større værdi\n" + +"- eller Shift-klik for for mindre værdi\n" + +"- eller klik og træk for hurtigere valg."; + +Calendar._TT["PREV_YEAR"] = "Ét Ã¥r tilbage (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Én mÃ¥ned tilbage (hold for menu)"; +Calendar._TT["GO_TODAY"] = "GÃ¥ til i dag"; +Calendar._TT["NEXT_MONTH"] = "Én mÃ¥ned frem (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Ét Ã¥r frem (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Vælg dag"; +Calendar._TT["DRAG_TO_MOVE"] = "Træk vinduet"; +Calendar._TT["PART_TODAY"] = " (i dag)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Vis %s først"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Luk"; +Calendar._TT["TODAY"] = "I dag"; +Calendar._TT["TIME_PART"] = "(Shift-)klik eller træk for at ændre værdi"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Uge"; +Calendar._TT["TIME"] = "Tid:"; diff --git a/htdocs/js/jscalendar/lang/calendar-de.js b/htdocs/js/jscalendar/lang/calendar-de.js new file mode 100644 index 0000000..4bc1137 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-de.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar DE language +// Author: Jack (tR), +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sonntag", + "Montag", + "Dienstag", + "Mittwoch", + "Donnerstag", + "Freitag", + "Samstag", + "Sonntag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("So", + "Mo", + "Di", + "Mi", + "Do", + "Fr", + "Sa", + "So"); + +// full month names +Calendar._MN = new Array +("Januar", + "Februar", + "M\u00e4rz", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "M\u00e4r", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Dez"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "\u00DCber dieses Kalendarmodul"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Datum ausw\u00e4hlen:\n" + +"- Benutzen Sie die \xab, \xbb Buttons um das Jahr zu w\u00e4hlen\n" + +"- Benutzen Sie die " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " Buttons um den Monat zu w\u00e4hlen\n" + +"- F\u00fcr eine Schnellauswahl halten Sie die Maustaste \u00fcber diesen Buttons fest."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Zeit ausw\u00e4hlen:\n" + +"- Klicken Sie auf die Teile der Uhrzeit, um diese zu erh\u00F6hen\n" + +"- oder klicken Sie mit festgehaltener Shift-Taste um diese zu verringern\n" + +"- oder klicken und festhalten f\u00fcr Schnellauswahl."; + +Calendar._TT["TOGGLE"] = "Ersten Tag der Woche w\u00e4hlen"; +Calendar._TT["PREV_YEAR"] = "Voriges Jahr (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["PREV_MONTH"] = "Voriger Monat (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["GO_TODAY"] = "Heute ausw\u00e4hlen"; +Calendar._TT["NEXT_MONTH"] = "N\u00e4chst. Monat (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["NEXT_YEAR"] = "N\u00e4chst. Jahr (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["SEL_DATE"] = "Datum ausw\u00e4hlen"; +Calendar._TT["DRAG_TO_MOVE"] = "Zum Bewegen festhalten"; +Calendar._TT["PART_TODAY"] = " (Heute)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Woche beginnt mit %s "; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Schlie\u00dfen"; +Calendar._TT["TODAY"] = "Heute"; +Calendar._TT["TIME_PART"] = "(Shift-)Klick oder Festhalten und Ziehen um den Wert zu \u00e4ndern"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Zeit:"; diff --git a/htdocs/js/jscalendar/lang/calendar-du.js b/htdocs/js/jscalendar/lang/calendar-du.js new file mode 100644 index 0000000..2200448 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-du.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Toggle startdag van de week"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (indrukken voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige month (indrukken voor menu)"; +Calendar._TT["GO_TODAY"] = "Naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende Maand (indrukken voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (indrukken voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "Vandaag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "wk"; diff --git a/htdocs/js/jscalendar/lang/calendar-el.js b/htdocs/js/jscalendar/lang/calendar-el.js new file mode 100644 index 0000000..43a9b2c --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-el.js @@ -0,0 +1,89 @@ +// ** I18N +Calendar._DN = new Array +("ΚυÏιακή", + "ΔευτέÏα", + "ΤÏίτη", + "ΤετάÏτη", + "Πέμπτη", + "ΠαÏασκευή", + "Σάββατο", + "ΚυÏιακή"); + +Calendar._SDN = new Array +("Κυ", + "Δε", + "TÏ", + "Τε", + "Πε", + "Πα", + "Σα", + "Κυ"); + +Calendar._MN = new Array +("ΙανουάÏιος", + "ΦεβÏουάÏιος", + "ΜάÏτιος", + "ΑπÏίλιος", + "Μάϊος", + "ΙοÏνιος", + "ΙοÏλιος", + "ΑÏγουστος", + "ΣεπτέμβÏιος", + "ΟκτώβÏιος", + "ÎοέμβÏιος", + "ΔεκέμβÏιος"); + +Calendar._SMN = new Array +("Ιαν", + "Φεβ", + "ΜαÏ", + "ΑπÏ", + "Μαι", + "Ιουν", + "Ιουλ", + "Αυγ", + "Σεπ", + "Οκτ", + "Îοε", + "Δεκ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Για το ημεÏολόγιο"; + +Calendar._TT["ABOUT"] = +"Επιλογέας ημεÏομηνίας/ÏŽÏας σε DHTML\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Για τελευταία έκδοση: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Επιλογή ημεÏομηνίας:\n" + +"- ΧÏησιμοποιείστε τα κουμπιά \xab, \xbb για επιλογή έτους\n" + +"- ΧÏησιμοποιείστε τα κουμπιά " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " για επιλογή μήνα\n" + +"- ΚÏατήστε κουμπί Ï€Î¿Î½Ï„Î¹ÎºÎ¿Ï Ï€Î±Ï„Î·Î¼Î­Î½Î¿ στα παÏαπάνω κουμπιά για πιο γÏήγοÏη επιλογή."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Επιλογή ÏŽÏας:\n" + +"- Κάντε κλικ σε ένα από τα μέÏη της ÏŽÏας για αÏξηση\n" + +"- ή Shift-κλικ για μείωση\n" + +"- ή κλικ και μετακίνηση για πιο γÏήγοÏη επιλογή."; +Calendar._TT["TOGGLE"] = "ΜπάÏα Ï€Ïώτης ημέÏας της εβδομάδας"; +Calendar._TT["PREV_YEAR"] = "ΠÏοηγ. έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["PREV_MONTH"] = "ΠÏοηγ. μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["GO_TODAY"] = "ΣήμεÏα"; +Calendar._TT["NEXT_MONTH"] = "Επόμενος μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["NEXT_YEAR"] = "Επόμενο έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["SEL_DATE"] = "Επιλέξτε ημεÏομηνία"; +Calendar._TT["DRAG_TO_MOVE"] = "ΣÏÏτε για να μετακινήσετε"; +Calendar._TT["PART_TODAY"] = " (σήμεÏα)"; +Calendar._TT["MON_FIRST"] = "Εμφάνιση ΔευτέÏας Ï€Ïώτα"; +Calendar._TT["SUN_FIRST"] = "Εμφάνιση ΚυÏιακής Ï€Ïώτα"; +Calendar._TT["CLOSE"] = "Κλείσιμο"; +Calendar._TT["TODAY"] = "ΣήμεÏα"; +Calendar._TT["TIME_PART"] = "(Shift-)κλικ ή μετακίνηση για αλλαγή"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "D, d M"; + +Calendar._TT["WK"] = "εβδ"; + diff --git a/htdocs/js/jscalendar/lang/calendar-en.js b/htdocs/js/jscalendar/lang/calendar-en.js new file mode 100644 index 0000000..0dbde79 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-en.js @@ -0,0 +1,127 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun"); + +// First day of the week. "0" means display Sunday first, "1" means display +// Monday first, etc. +Calendar._FD = 0; + +// full month names +Calendar._MN = new Array +("January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "About the calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Date selection:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + +"- Hold mouse button on any of the above buttons for faster selection."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- Click on any of the time parts to increase it\n" + +"- or Shift-click to decrease it\n" + +"- or click and drag for faster selection."; + +Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; +Calendar._TT["GO_TODAY"] = "Go Today"; +Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Select date"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; +Calendar._TT["PART_TODAY"] = " (today)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Display %s first"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; +Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-es.js b/htdocs/js/jscalendar/lang/calendar-es.js new file mode 100644 index 0000000..19c1b30 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-es.js @@ -0,0 +1,129 @@ +// ** I18N + +// Calendar ES (spanish) language +// Author: Mihai Bazon, +// Updater: Servilio Afre Puentes +// Updated: 2004-06-03 +// Encoding: utf-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miércoles", + "Jueves", + "Viernes", + "Sábado", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mié", + "Jue", + "Vie", + "Sáb", + "Dom"); + +// First day of the week. "0" means display Sunday first, "1" means display +// Monday first, etc. +Calendar._FD = 1; + +// full month names +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// short month names +Calendar._SMN = new Array +("Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Acerca del calendario"; + +Calendar._TT["ABOUT"] = +"Selector DHTML de Fecha/Hora\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Para conseguir la última versión visite: http://www.dynarch.com/projects/calendar/\n" + +"Distribuido bajo licencia GNU LGPL. Visite http://gnu.org/licenses/lgpl.html para más detalles." + +"\n\n" + +"Selección de fecha:\n" + +"- Use los botones \xab, \xbb para seleccionar el año\n" + +"- Use los botones " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga pulsado el ratón en cualquiera de estos botones para una selección rápida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selección de hora:\n" + +"- Pulse en cualquiera de las partes de la hora para incrementarla\n" + +"- o pulse las mayúsculas mientras hace clic para decrementarla\n" + +"- o haga clic y arrastre el ratón para una selección más rápida."; + +Calendar._TT["PREV_YEAR"] = "Año anterior (mantener para menú)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (mantener para menú)"; +Calendar._TT["GO_TODAY"] = "Ir a hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes siguiente (mantener para menú)"; +Calendar._TT["NEXT_YEAR"] = "Año siguiente (mantener para menú)"; +Calendar._TT["SEL_DATE"] = "Seleccionar fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar para mover"; +Calendar._TT["PART_TODAY"] = " (hoy)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Hacer %s primer día de la semana"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; +Calendar._TT["TIME_PART"] = "(Mayúscula-)Clic o arrastre para cambiar valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "sem"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-fi.js b/htdocs/js/jscalendar/lang/calendar-fi.js new file mode 100644 index 0000000..328eabb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-fi.js @@ -0,0 +1,98 @@ +// ** I18N + +// Calendar FI language (Finnish, Suomi) +// Author: Jarno Käyhkö, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("Sunnuntai", + "Maanantai", + "Tiistai", + "Keskiviikko", + "Torstai", + "Perjantai", + "Lauantai", + "Sunnuntai"); + +// short day names +Calendar._SDN = new Array +("Su", + "Ma", + "Ti", + "Ke", + "To", + "Pe", + "La", + "Su"); + +// full month names +Calendar._MN = new Array +("Tammikuu", + "Helmikuu", + "Maaliskuu", + "Huhtikuu", + "Toukokuu", + "Kesäkuu", + "Heinäkuu", + "Elokuu", + "Syyskuu", + "Lokakuu", + "Marraskuu", + "Joulukuu"); + +// short month names +Calendar._SMN = new Array +("Tam", + "Hel", + "Maa", + "Huh", + "Tou", + "Kes", + "Hei", + "Elo", + "Syy", + "Lok", + "Mar", + "Jou"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Tietoja kalenterista"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Uusin versio osoitteessa: http://www.dynarch.com/projects/calendar/\n" + +"Julkaistu GNU LGPL lisenssin alaisuudessa. Lisätietoja osoitteessa http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Päivämäärä valinta:\n" + +"- Käytä \xab, \xbb painikkeita valitaksesi vuosi\n" + +"- Käytä " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " painikkeita valitaksesi kuukausi\n" + +"- Pitämällä hiiren painiketta minkä tahansa yllä olevan painikkeen kohdalla, saat näkyviin valikon nopeampaan siirtymiseen."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Ajan valinta:\n" + +"- Klikkaa kellonajan numeroita lisätäksesi aikaa\n" + +"- tai pitämällä Shift-näppäintä pohjassa saat aikaa taaksepäin\n" + +"- tai klikkaa ja pidä hiiren painike pohjassa sekä liikuta hiirtä muuttaaksesi aikaa nopeasti eteen- ja taaksepäin."; + +Calendar._TT["PREV_YEAR"] = "Edell. vuosi (paina hetki, näet valikon)"; +Calendar._TT["PREV_MONTH"] = "Edell. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["GO_TODAY"] = "Siirry tähän päivään"; +Calendar._TT["NEXT_MONTH"] = "Seur. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["NEXT_YEAR"] = "Seur. vuosi (paina hetki, näet valikon)"; +Calendar._TT["SEL_DATE"] = "Valitse päivämäärä"; +Calendar._TT["DRAG_TO_MOVE"] = "Siirrä kalenterin paikkaa"; +Calendar._TT["PART_TODAY"] = " (tänään)"; +Calendar._TT["MON_FIRST"] = "Näytä maanantai ensimmäisenä"; +Calendar._TT["SUN_FIRST"] = "Näytä sunnuntai ensimmäisenä"; +Calendar._TT["CLOSE"] = "Sulje"; +Calendar._TT["TODAY"] = "Tänään"; +Calendar._TT["TIME_PART"] = "(Shift-) Klikkaa tai liikuta muuttaaksesi aikaa"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%d.%m.%Y"; + +Calendar._TT["WK"] = "Vko"; diff --git a/htdocs/js/jscalendar/lang/calendar-fr.js b/htdocs/js/jscalendar/lang/calendar-fr.js new file mode 100644 index 0000000..2a9e0b2 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-fr.js @@ -0,0 +1,125 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// Translator: David Duret, from previous french version + +// full day names +Calendar._DN = new Array +("Dimanche", + "Lundi", + "Mardi", + "Mercredi", + "Jeudi", + "Vendredi", + "Samedi", + "Dimanche"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dim", + "Lun", + "Mar", + "Mar", + "Jeu", + "Ven", + "Sam", + "Dim"); + +// full month names +Calendar._MN = new Array +("Janvier", + "Février", + "Mars", + "Avril", + "Mai", + "Juin", + "Juillet", + "Août", + "Septembre", + "Octobre", + "Novembre", + "Décembre"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Fev", + "Mar", + "Avr", + "Mai", + "Juin", + "Juil", + "Aout", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "A propos du calendrier"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Heure Selecteur\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Pour la derniere version visitez : http://www.dynarch.com/projects/calendar/\n" + +"Distribué par GNU LGPL. Voir http://gnu.org/licenses/lgpl.html pour les details." + +"\n\n" + +"Selection de la date :\n" + +"- Utiliser les bouttons \xab, \xbb pour selectionner l\'annee\n" + +"- Utiliser les bouttons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pour selectionner les mois\n" + +"- Garder la souris sur n'importe quels boutons pour une selection plus rapide"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selection de l\'heure :\n" + +"- Cliquer sur heures ou minutes pour incrementer\n" + +"- ou Maj-clic pour decrementer\n" + +"- ou clic et glisser-deplacer pour une selection plus rapide"; + +Calendar._TT["PREV_YEAR"] = "Année préc. (maintenir pour menu)"; +Calendar._TT["PREV_MONTH"] = "Mois préc. (maintenir pour menu)"; +Calendar._TT["GO_TODAY"] = "Atteindre la date du jour"; +Calendar._TT["NEXT_MONTH"] = "Mois suiv. (maintenir pour menu)"; +Calendar._TT["NEXT_YEAR"] = "Année suiv. (maintenir pour menu)"; +Calendar._TT["SEL_DATE"] = "Sélectionner une date"; +Calendar._TT["DRAG_TO_MOVE"] = "Déplacer"; +Calendar._TT["PART_TODAY"] = " (Aujourd'hui)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Afficher %s en premier"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fermer"; +Calendar._TT["TODAY"] = "Aujourd'hui"; +Calendar._TT["TIME_PART"] = "(Maj-)Clic ou glisser pour modifier la valeur"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Sem."; +Calendar._TT["TIME"] = "Heure :"; diff --git a/htdocs/js/jscalendar/lang/calendar-he-utf8.js b/htdocs/js/jscalendar/lang/calendar-he-utf8.js new file mode 100644 index 0000000..7861217 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-he-utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar EN language +// Author: Idan Sofer, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("ר×שון", + "שני", + "שלישי", + "רביעי", + "חמישי", + "שישי", + "שבת", + "ר×שון"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("×", + "ב", + "×’", + "ד", + "×”", + "ו", + "ש", + "×"); + +// full month names +Calendar._MN = new Array +("ינו×ר", + "פברו×ר", + "מרץ", + "×פריל", + "מ××™", + "יוני", + "יולי", + "×וגוסט", + "ספטמבר", + "×וקטובר", + "נובמבר", + "דצמבר"); + +// short month names +Calendar._SMN = new Array +("×™× ×", + "פבר", + "מרץ", + "×פר", + "מ××™", + "יונ", + "יול", + "×וג", + "ספט", + "×וק", + "נוב", + "דצמ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "×ודות השנתון"; + +Calendar._TT["ABOUT"] = +"בחרן ת×ריך/שעה DHTML\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"×”×’×™×¨×¡× ×”×חרונה זמינה ב: http://www.dynarch.com/projects/calendar/\n" + +"מופץ תחת זיכיון ×” GNU LGPL. עיין ב http://gnu.org/licenses/lgpl.html ×œ×¤×¨×˜×™× × ×•×¡×¤×™×." + +"\n\n" + +בחירת ת×ריך:\n" + +"- השתמש ×‘×›×¤×ª×•×¨×™× \xab, \xbb לבחירת שנה\n" + +"- השתמש ×‘×›×¤×ª×•×¨×™× " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " לבחירת חודש\n" + +"- החזק העכבר לחוץ מעל ×”×›×¤×ª×•×¨×™× ×”×ž×•×–×›×¨×™× ×œ×¢×™×œ לבחירה מהירה יותר."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"בחירת זמן:\n" + +"- לחץ על כל ×חד מחלקי הזמן כדי להוסיף\n" + +"- ×ו shift בשילוב ×¢× ×œ×—×™×¦×” כדי להחסיר\n" + +"- ×ו לחץ וגרור לפעולה מהירה יותר."; + +Calendar._TT["PREV_YEAR"] = "שנה קודמת - החזק לקבלת תפריט"; +Calendar._TT["PREV_MONTH"] = "חודש ×§×•×“× - החזק לקבלת תפריט"; +Calendar._TT["GO_TODAY"] = "עבור להיו×"; +Calendar._TT["NEXT_MONTH"] = "חודש ×”×‘× - החזק לתפריט"; +Calendar._TT["NEXT_YEAR"] = "שנה הב××” - החזק לתפריט"; +Calendar._TT["SEL_DATE"] = "בחר ת×ריך"; +Calendar._TT["DRAG_TO_MOVE"] = "גרור להזזה"; +Calendar._TT["PART_TODAY"] = " )היו×("; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "הצג %s קוד×"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "6"; + +Calendar._TT["CLOSE"] = "סגור"; +Calendar._TT["TODAY"] = "היו×"; +Calendar._TT["TIME_PART"] = "(שיפט-)לחץ וגרור כדי לשנות ערך"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "שעה::"; diff --git a/htdocs/js/jscalendar/lang/calendar-hr-utf8.js b/htdocs/js/jscalendar/lang/calendar-hr-utf8.js new file mode 100644 index 0000000..d569cfd --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-hr-utf8.js @@ -0,0 +1,49 @@ +/* Croatian language file for the DHTML Calendar version 0.9.2 +* Author Krunoslav Zubrinic , June 2003. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ +Calendar._DN = new Array +("Nedjelja", + "Ponedjeljak", + "Utorak", + "Srijeda", + "ÄŒetvrtak", + "Petak", + "Subota", + "Nedjelja"); +Calendar._MN = new Array +("SijeÄanj", + "VeljaÄa", + "Ožujak", + "Travanj", + "Svibanj", + "Lipanj", + "Srpanj", + "Kolovoz", + "Rujan", + "Listopad", + "Studeni", + "Prosinac"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Promjeni dan s kojim poÄinje tjedan"; +Calendar._TT["PREV_YEAR"] = "Prethodna godina (dugi pritisak za meni)"; +Calendar._TT["PREV_MONTH"] = "Prethodni mjesec (dugi pritisak za meni)"; +Calendar._TT["GO_TODAY"] = "Idi na tekući dan"; +Calendar._TT["NEXT_MONTH"] = "Slijedeći mjesec (dugi pritisak za meni)"; +Calendar._TT["NEXT_YEAR"] = "Slijedeća godina (dugi pritisak za meni)"; +Calendar._TT["SEL_DATE"] = "Izaberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni i povuci za promjenu pozicije"; +Calendar._TT["PART_TODAY"] = " (today)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedjeljak kao prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedjelju kao prvi dan"; +Calendar._TT["CLOSE"] = "Zatvori"; +Calendar._TT["TODAY"] = "Danas"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, dd.mm.y"; + +Calendar._TT["WK"] = "Tje"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-hr.js b/htdocs/js/jscalendar/lang/calendar-hr.js new file mode 100644 index 0000000..6c27f60 Binary files /dev/null and b/htdocs/js/jscalendar/lang/calendar-hr.js differ diff --git a/htdocs/js/jscalendar/lang/calendar-hu.js b/htdocs/js/jscalendar/lang/calendar-hu.js new file mode 100644 index 0000000..f5bf057 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-hu.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar HU language +// Author: ??? +// Modifier: KARASZI Istvan, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Vasárnap", + "Hétfõ", + "Kedd", + "Szerda", + "Csütörtök", + "Péntek", + "Szombat", + "Vasárnap"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("v", + "h", + "k", + "sze", + "cs", + "p", + "szo", + "v"); + +// full month names +Calendar._MN = new Array +("január", + "február", + "március", + "április", + "május", + "június", + "július", + "augusztus", + "szeptember", + "október", + "november", + "december"); + +// short month names +Calendar._SMN = new Array +("jan", + "feb", + "már", + "ápr", + "máj", + "jún", + "júl", + "aug", + "sze", + "okt", + "nov", + "dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "A kalendáriumról"; + +Calendar._TT["ABOUT"] = +"DHTML dátum/idõ kiválasztó\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"a legfrissebb verzió megtalálható: http://www.dynarch.com/projects/calendar/\n" + +"GNU LGPL alatt terjesztve. Lásd a http://gnu.org/licenses/lgpl.html oldalt a részletekhez." + +"\n\n" + +"Dátum választás:\n" + +"- használja a \xab, \xbb gombokat az év kiválasztásához\n" + +"- használja a " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gombokat a hónap kiválasztásához\n" + +"- tartsa lenyomva az egérgombot a gyors választáshoz."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Idõ választás:\n" + +"- kattintva növelheti az idõt\n" + +"- shift-tel kattintva csökkentheti\n" + +"- lenyomva tartva és húzva gyorsabban kiválaszthatja."; + +Calendar._TT["PREV_YEAR"] = "Elõzõ év (tartsa nyomva a menühöz)"; +Calendar._TT["PREV_MONTH"] = "Elõzõ hónap (tartsa nyomva a menühöz)"; +Calendar._TT["GO_TODAY"] = "Mai napra ugrás"; +Calendar._TT["NEXT_MONTH"] = "Köv. hónap (tartsa nyomva a menühöz)"; +Calendar._TT["NEXT_YEAR"] = "Köv. év (tartsa nyomva a menühöz)"; +Calendar._TT["SEL_DATE"] = "Válasszon dátumot"; +Calendar._TT["DRAG_TO_MOVE"] = "Húzza a mozgatáshoz"; +Calendar._TT["PART_TODAY"] = " (ma)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s legyen a hét elsõ napja"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Bezár"; +Calendar._TT["TODAY"] = "Ma"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikk vagy húzás az érték változtatásához"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b %e, %a"; + +Calendar._TT["WK"] = "hét"; +Calendar._TT["TIME"] = "idõ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-it.js b/htdocs/js/jscalendar/lang/calendar-it.js new file mode 100644 index 0000000..7f84cde --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-it.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translator: Fabio Di Bernardini, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domenica", + "Lunedì", + "Martedì", + "Mercoledì", + "Giovedì", + "Venerdì", + "Sabato", + "Domenica"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mer", + "Gio", + "Ven", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Gennaio", + "Febbraio", + "Marzo", + "Aprile", + "Maggio", + "Giugno", + "Luglio", + "Augosto", + "Settembre", + "Ottobre", + "Novembre", + "Dicembre"); + +// short month names +Calendar._SMN = new Array +("Gen", + "Feb", + "Mar", + "Apr", + "Mag", + "Giu", + "Lug", + "Ago", + "Set", + "Ott", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Informazioni sul calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Per gli aggiornamenti: http://www.dynarch.com/projects/calendar/\n" + +"Distribuito sotto licenza GNU LGPL. Vedi http://gnu.org/licenses/lgpl.html per i dettagli." + +"\n\n" + +"Selezione data:\n" + +"- Usa \xab, \xbb per selezionare l'anno\n" + +"- Usa " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per i mesi\n" + +"- Tieni premuto a lungo il mouse per accedere alle funzioni di selezione veloce."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selezione orario:\n" + +"- Clicca sul numero per incrementarlo\n" + +"- o Shift+click per decrementarlo\n" + +"- o click e sinistra o destra per variarlo."; + +Calendar._TT["PREV_YEAR"] = "Anno prec.(clicca a lungo per il menù)"; +Calendar._TT["PREV_MONTH"] = "Mese prec. (clicca a lungo per il menù)"; +Calendar._TT["GO_TODAY"] = "Oggi"; +Calendar._TT["NEXT_MONTH"] = "Pross. mese (clicca a lungo per il menù)"; +Calendar._TT["NEXT_YEAR"] = "Pross. anno (clicca a lungo per il menù)"; +Calendar._TT["SEL_DATE"] = "Seleziona data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trascina per spostarlo"; +Calendar._TT["PART_TODAY"] = " (oggi)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostra prima %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Chiudi"; +Calendar._TT["TODAY"] = "Oggi"; +Calendar._TT["TIME_PART"] = "(Shift-)Click o trascina per cambiare il valore"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a:%b:%e"; + +Calendar._TT["WK"] = "set"; +Calendar._TT["TIME"] = "Ora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-jp.js b/htdocs/js/jscalendar/lang/calendar-jp.js new file mode 100644 index 0000000..3bca7eb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-jp.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("“ú", + "ŒŽ", + "‰Î", + "…", + "–Ø", + "‹à", + "“y", + "“ú"); +Calendar._MN = new Array +("1ŒŽ", + "2ŒŽ", + "3ŒŽ", + "4ŒŽ", + "5ŒŽ", + "6ŒŽ", + "7ŒŽ", + "8ŒŽ", + "9ŒŽ", + "10ŒŽ", + "11ŒŽ", + "12ŒŽ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "T‚Ìʼn‚Ì—j“ú‚ðØ‚è‘Ö‚¦"; +Calendar._TT["PREV_YEAR"] = "‘O”N"; +Calendar._TT["PREV_MONTH"] = "‘OŒŽ"; +Calendar._TT["GO_TODAY"] = "¡“ú"; +Calendar._TT["NEXT_MONTH"] = "—‚ŒŽ"; +Calendar._TT["NEXT_YEAR"] = "—‚”N"; +Calendar._TT["SEL_DATE"] = "“ú•t‘I‘ð"; +Calendar._TT["DRAG_TO_MOVE"] = "ƒEƒBƒ“ƒhƒE‚̈ړ®"; +Calendar._TT["PART_TODAY"] = " (¡“ú)"; +Calendar._TT["MON_FIRST"] = "ŒŽ—j“ú‚ð擪‚É"; +Calendar._TT["SUN_FIRST"] = "“ú—j“ú‚ð擪‚É"; +Calendar._TT["CLOSE"] = "•Â‚¶‚é"; +Calendar._TT["TODAY"] = "¡“ú"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "%mŒŽ %d“ú (%a)"; + +Calendar._TT["WK"] = "T"; diff --git a/htdocs/js/jscalendar/lang/calendar-ko-utf8.js b/htdocs/js/jscalendar/lang/calendar-ko-utf8.js new file mode 100644 index 0000000..035dd74 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ko-utf8.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translation: Yourim Yi +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ì¼ìš”ì¼", + "월요ì¼", + "화요ì¼", + "수요ì¼", + "목요ì¼", + "금요ì¼", + "토요ì¼", + "ì¼ìš”ì¼"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ì¼", + "ì›”", + "í™”", + "수", + "목", + "금", + "토", + "ì¼"); + +// full month names +Calendar._MN = new Array +("1ì›”", + "2ì›”", + "3ì›”", + "4ì›”", + "5ì›”", + "6ì›”", + "7ì›”", + "8ì›”", + "9ì›”", + "10ì›”", + "11ì›”", + "12ì›”"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ì— ëŒ€í•´ì„œ"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"\n"+ +"최신 ë²„ì „ì„ ë°›ìœ¼ì‹œë ¤ë©´ http://www.dynarch.com/projects/calendar/ ì— ë°©ë¬¸í•˜ì„¸ìš”\n" + +"\n"+ +"GNU LGPL ë¼ì´ì„¼ìŠ¤ë¡œ ë°°í¬ë©ë‹ˆë‹¤. \n"+ +"ë¼ì´ì„¼ìŠ¤ì— 대한 ìžì„¸í•œ ë‚´ìš©ì€ http://gnu.org/licenses/lgpl.html ì„ ì½ìœ¼ì„¸ìš”." + +"\n\n" + +"날짜 ì„ íƒ:\n" + +"- ì—°ë„를 ì„ íƒí•˜ë ¤ë©´ \xab, \xbb ë²„íŠ¼ì„ ì‚¬ìš©í•©ë‹ˆë‹¤\n" + +"- ë‹¬ì„ ì„ íƒí•˜ë ¤ë©´ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ë²„íŠ¼ì„ ëˆ„ë¥´ì„¸ìš”\n" + +"- ê³„ì† ëˆ„ë¥´ê³  있으면 위 ê°’ë“¤ì„ ë¹ ë¥´ê²Œ ì„ íƒí•˜ì‹¤ 수 있습니다."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"시간 ì„ íƒ:\n" + +"- 마우스로 누르면 ì‹œê°„ì´ ì¦ê°€í•©ë‹ˆë‹¤\n" + +"- Shift 키와 함께 누르면 ê°ì†Œí•©ë‹ˆë‹¤\n" + +"- 누른 ìƒíƒœì—ì„œ 마우스를 움ì§ì´ë©´ 좀 ë” ë¹ ë¥´ê²Œ ê°’ì´ ë³€í•©ë‹ˆë‹¤.\n"; + +Calendar._TT["PREV_YEAR"] = "지난 í•´ (길게 누르면 목ë¡)"; +Calendar._TT["PREV_MONTH"] = "지난 달 (길게 누르면 목ë¡)"; +Calendar._TT["GO_TODAY"] = "오늘 날짜로"; +Calendar._TT["NEXT_MONTH"] = "ë‹¤ìŒ ë‹¬ (길게 누르면 목ë¡)"; +Calendar._TT["NEXT_YEAR"] = "ë‹¤ìŒ í•´ (길게 누르면 목ë¡)"; +Calendar._TT["SEL_DATE"] = "날짜를 ì„ íƒí•˜ì„¸ìš”"; +Calendar._TT["DRAG_TO_MOVE"] = "마우스 드래그로 ì´ë™ 하세요"; +Calendar._TT["PART_TODAY"] = " (오늘)"; +Calendar._TT["MON_FIRST"] = "월요ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["SUN_FIRST"] = "ì¼ìš”ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["CLOSE"] = "닫기"; +Calendar._TT["TODAY"] = "오늘"; +Calendar._TT["TIME_PART"] = "(Shift-)í´ë¦­ ë˜ëŠ” 드래그 하세요"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "주"; diff --git a/htdocs/js/jscalendar/lang/calendar-ko.js b/htdocs/js/jscalendar/lang/calendar-ko.js new file mode 100644 index 0000000..8cddf58 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ko.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translation: Yourim Yi +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ÀÏ¿äÀÏ", + "¿ù¿äÀÏ", + "È­¿äÀÏ", + "¼ö¿äÀÏ", + "¸ñ¿äÀÏ", + "±Ý¿äÀÏ", + "Åä¿äÀÏ", + "ÀÏ¿äÀÏ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ÀÏ", + "¿ù", + "È­", + "¼ö", + "¸ñ", + "±Ý", + "Åä", + "ÀÏ"); + +// full month names +Calendar._MN = new Array +("1¿ù", + "2¿ù", + "3¿ù", + "4¿ù", + "5¿ù", + "6¿ù", + "7¿ù", + "8¿ù", + "9¿ù", + "10¿ù", + "11¿ù", + "12¿ù"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ¿¡ ´ëÇؼ­"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"\n"+ +"ÃֽŠ¹öÀüÀ» ¹ÞÀ¸½Ã·Á¸é http://www.dynarch.com/projects/calendar/ ¿¡ ¹æ¹®Çϼ¼¿ä\n" + +"\n"+ +"GNU LGPL ¶óÀ̼¾½º·Î ¹èÆ÷µË´Ï´Ù. \n"+ +"¶óÀ̼¾½º¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº http://gnu.org/licenses/lgpl.html À» ÀÐÀ¸¼¼¿ä." + +"\n\n" + +"³¯Â¥ ¼±ÅÃ:\n" + +"- ¿¬µµ¸¦ ¼±ÅÃÇÏ·Á¸é \xab, \xbb ¹öÆ°À» »ç¿ëÇÕ´Ï´Ù\n" + +"- ´ÞÀ» ¼±ÅÃÇÏ·Á¸é " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ¹öÆ°À» ´©¸£¼¼¿ä\n" + +"- °è¼Ó ´©¸£°í ÀÖÀ¸¸é À§ °ªµéÀ» ºü¸£°Ô ¼±ÅÃÇÏ½Ç ¼ö ÀÖ½À´Ï´Ù."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"½Ã°£ ¼±ÅÃ:\n" + +"- ¸¶¿ì½º·Î ´©¸£¸é ½Ã°£ÀÌ Áõ°¡ÇÕ´Ï´Ù\n" + +"- Shift Å°¿Í ÇÔ²² ´©¸£¸é °¨¼ÒÇÕ´Ï´Ù\n" + +"- ´©¸¥ »óÅ¿¡¼­ ¸¶¿ì½º¸¦ ¿òÁ÷À̸é Á» ´õ ºü¸£°Ô °ªÀÌ º¯ÇÕ´Ï´Ù.\n"; + +Calendar._TT["PREV_YEAR"] = "Áö³­ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["PREV_MONTH"] = "Áö³­ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["GO_TODAY"] = "¿À´Ã ³¯Â¥·Î"; +Calendar._TT["NEXT_MONTH"] = "´ÙÀ½ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["NEXT_YEAR"] = "´ÙÀ½ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["SEL_DATE"] = "³¯Â¥¸¦ ¼±ÅÃÇϼ¼¿ä"; +Calendar._TT["DRAG_TO_MOVE"] = "¸¶¿ì½º µå·¡±×·Î À̵¿ Çϼ¼¿ä"; +Calendar._TT["PART_TODAY"] = " (¿À´Ã)"; +Calendar._TT["MON_FIRST"] = "¿ù¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["SUN_FIRST"] = "ÀÏ¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["CLOSE"] = "´Ý±â"; +Calendar._TT["TODAY"] = "¿À´Ã"; +Calendar._TT["TIME_PART"] = "(Shift-)Ŭ¸¯ ¶Ç´Â µå·¡±× Çϼ¼¿ä"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "ÁÖ"; diff --git a/htdocs/js/jscalendar/lang/calendar-lt-utf8.js b/htdocs/js/jscalendar/lang/calendar-lt-utf8.js new file mode 100644 index 0000000..d39653b --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lt-utf8.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "TreÄiadienis", + "Ketvirtadienis", + "Pentadienis", + "Å eÅ¡tadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Å eÅ¡", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Gegužė", + "Birželis", + "Liepa", + "RugpjÅ«tis", + "RugsÄ—jis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendorių"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"NaujausiÄ… versijÄ… rasite: http://www.dynarch.com/projects/calendar/\n" + +"Platinamas pagal GNU LGPL licencijÄ…. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metų pasirinkimas: \xab, \xbb\n" + +"- MÄ—nesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelÄ—s klaviÅ¡Ä… greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandų arba minuÄių - skaiÄius padidÄ—s vienetu.\n" + +"- Jei spausite kartu su Shift, skaiÄius sumažės.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelÄ™."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti Å¡iandienÄ…"; +Calendar._TT["NEXT_MONTH"] = "Kitas mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datÄ…"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (Å¡iandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitÄ—s diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitÄ—s diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uždaryti"; +Calendar._TT["TODAY"] = "Å iandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/htdocs/js/jscalendar/lang/calendar-lt.js b/htdocs/js/jscalendar/lang/calendar-lt.js new file mode 100644 index 0000000..43b93d6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lt.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, +// Encoding: Windows-1257 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "Treèiadienis", + "Ketvirtadienis", + "Pentadienis", + "Ðeðtadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Ðeð", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Geguþë", + "Birþelis", + "Liepa", + "Rugpjûtis", + "Rugsëjis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendoriø"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Naujausià versijà rasite: http://www.dynarch.com/projects/calendar/\n" + +"Platinamas pagal GNU LGPL licencijà. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metø pasirinkimas: \xab, \xbb\n" + +"- Mënesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelës klaviðà greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandø arba minuèiø - skaièus padidës vienetu.\n" + +"- Jei spausite kartu su Shift, skaièius sumaþës.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelæ."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mënuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti ðiandienà"; +Calendar._TT["NEXT_MONTH"] = "Kitas mënuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datà"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (ðiandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitës diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitës diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uþdaryti"; +Calendar._TT["TODAY"] = "Ðiandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/htdocs/js/jscalendar/lang/calendar-lv.js b/htdocs/js/jscalendar/lang/calendar-lv.js new file mode 100644 index 0000000..407699d --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lv.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar LV language +// Author: Juris Valdovskis, +// Encoding: cp1257 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Svçtdiena", + "Pirmdiena", + "Otrdiena", + "Treðdiena", + "Ceturdiena", + "Piektdiena", + "Sestdiena", + "Svçtdiena"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sv", + "Pr", + "Ot", + "Tr", + "Ce", + "Pk", + "Se", + "Sv"); + +// full month names +Calendar._MN = new Array +("Janvâris", + "Februâris", + "Marts", + "Aprîlis", + "Maijs", + "Jûnijs", + "Jûlijs", + "Augusts", + "Septembris", + "Oktobris", + "Novembris", + "Decembris"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Mai", + "Jûn", + "Jûl", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Par kalendâru"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Datuma izvçle:\n" + +"- Izmanto \xab, \xbb pogas, lai izvçlçtos gadu\n" + +"- Izmanto " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "pogas, lai izvçlçtos mçnesi\n" + +"- Turi nospiestu peles pogu uz jebkuru no augstâk minçtajâm pogâm, lai paâtrinâtu izvçli."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laika izvçle:\n" + +"- Uzklikðíini uz jebkuru no laika daïâm, lai palielinâtu to\n" + +"- vai Shift-klikðíis, lai samazinâtu to\n" + +"- vai noklikðíini un velc uz attiecîgo virzienu lai mainîtu âtrâk."; + +Calendar._TT["PREV_YEAR"] = "Iepr. gads (turi izvçlnei)"; +Calendar._TT["PREV_MONTH"] = "Iepr. mçnesis (turi izvçlnei)"; +Calendar._TT["GO_TODAY"] = "Ðodien"; +Calendar._TT["NEXT_MONTH"] = "Nâkoðais mçnesis (turi izvçlnei)"; +Calendar._TT["NEXT_YEAR"] = "Nâkoðais gads (turi izvçlnei)"; +Calendar._TT["SEL_DATE"] = "Izvçlies datumu"; +Calendar._TT["DRAG_TO_MOVE"] = "Velc, lai pârvietotu"; +Calendar._TT["PART_TODAY"] = " (ðodien)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Attçlot %s kâ pirmo"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "1,7"; + +Calendar._TT["CLOSE"] = "Aizvçrt"; +Calendar._TT["TODAY"] = "Ðodien"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikðíis vai pârvieto, lai mainîtu"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Laiks:"; diff --git a/htdocs/js/jscalendar/lang/calendar-nl.js b/htdocs/js/jscalendar/lang/calendar-nl.js new file mode 100644 index 0000000..a1dea94 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-nl.js @@ -0,0 +1,73 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); + +Calendar._SDN_len = 2; + +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Info"; + +Calendar._TT["ABOUT"] = +"DHTML Datum/Tijd Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + +"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\n" + +"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details." + +"\n\n" + +"Datum selectie:\n" + +"- Gebruik de \xab \xbb knoppen om een jaar te selecteren\n" + +"- Gebruik de " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knoppen om een maand te selecteren\n" + +"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Tijd selectie:\n" + +"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\n" + +"- of Shift-klik om het te verlagen\n" + +"- of klik en sleep voor een snellere selectie."; + +//Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)"; +Calendar._TT["GO_TODAY"] = "Ga naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +//Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +//Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; + +Calendar._TT["DAY_FIRST"] = "Toon %s eerst"; + +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "(vandaag)"; +Calendar._TT["TIME_PART"] = "(Shift-)Klik of sleep om de waarde te veranderen"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b %Y"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Tijd:"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-no.js b/htdocs/js/jscalendar/lang/calendar-no.js new file mode 100644 index 0000000..d9297d1 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-no.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar NO language +// Author: Daniel Holmen, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Søndag", + "Mandag", + "Tirsdag", + "Onsdag", + "Torsdag", + "Fredag", + "Lørdag", + "Søndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Søn", + "Man", + "Tir", + "Ons", + "Tor", + "Fre", + "Lør", + "Søn"); + +// full month names +Calendar._MN = new Array +("Januar", + "Februar", + "Mars", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Desember"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Mai", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Des"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om kalenderen"; + +Calendar._TT["ABOUT"] = +"DHTML Dato-/Tidsvelger\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For nyeste versjon, gÃ¥ til: http://www.dynarch.com/projects/calendar/\n" + +"Distribuert under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detaljer." + +"\n\n" + +"Datovalg:\n" + +"- Bruk knappene \xab og \xbb for Ã¥ velge Ã¥r\n" + +"- Bruk knappene " + String.fromCharCode(0x2039) + " og " + String.fromCharCode(0x203a) + " for Ã¥ velge mÃ¥ned\n" + +"- Hold inne musknappen eller knappene over for raskere valg."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Tidsvalg:\n" + +"- Klikk pÃ¥ en av tidsdelene for Ã¥ øke den\n" + +"- eller Shift-klikk for Ã¥ senke verdien\n" + +"- eller klikk-og-dra for raskere valg.."; + +Calendar._TT["PREV_YEAR"] = "Forrige. Ã¥r (hold for meny)"; +Calendar._TT["PREV_MONTH"] = "Forrige. mÃ¥ned (hold for meny)"; +Calendar._TT["GO_TODAY"] = "GÃ¥ til idag"; +Calendar._TT["NEXT_MONTH"] = "Neste mÃ¥ned (hold for meny)"; +Calendar._TT["NEXT_YEAR"] = "Neste Ã¥r (hold for meny)"; +Calendar._TT["SEL_DATE"] = "Velg dato"; +Calendar._TT["DRAG_TO_MOVE"] = "Dra for Ã¥ flytte"; +Calendar._TT["PART_TODAY"] = " (idag)"; +Calendar._TT["MON_FIRST"] = "Vis mandag først"; +Calendar._TT["SUN_FIRST"] = "Vis søndag først"; +Calendar._TT["CLOSE"] = "Lukk"; +Calendar._TT["TODAY"] = "Idag"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikk eller dra for Ã¥ endre verdi"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "uke"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-pl-utf8.js b/htdocs/js/jscalendar/lang/calendar-pl-utf8.js new file mode 100644 index 0000000..6b8ca67 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pl-utf8.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar PL language +// Author: Dariusz Pietrzak, +// Author: Janusz Piwowarski, +// Encoding: utf-8 +// Distributed under the same terms as the calendar itself. + +Calendar._DN = new Array +("Niedziela", + "PoniedziaÅ‚ek", + "Wtorek", + "Åšroda", + "Czwartek", + "PiÄ…tek", + "Sobota", + "Niedziela"); +Calendar._SDN = new Array +("Nie", + "Pn", + "Wt", + "Åšr", + "Cz", + "Pt", + "So", + "Nie"); +Calendar._MN = new Array +("StyczeÅ„", + "Luty", + "Marzec", + "KwiecieÅ„", + "Maj", + "Czerwiec", + "Lipiec", + "SierpieÅ„", + "WrzesieÅ„", + "Październik", + "Listopad", + "GrudzieÅ„"); +Calendar._SMN = new Array +("Sty", + "Lut", + "Mar", + "Kwi", + "Maj", + "Cze", + "Lip", + "Sie", + "Wrz", + "Paź", + "Lis", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Aby pobrać najnowszÄ… wersjÄ™, odwiedź: http://www.dynarch.com/projects/calendar/\n" + +"DostÄ™pny na licencji GNU LGPL. Zobacz szczegóły na http://gnu.org/licenses/lgpl.html." + +"\n\n" + +"Wybór daty:\n" + +"- Użyj przycisków \xab, \xbb by wybrać rok\n" + +"- Użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " by wybrać miesiÄ…c\n" + +"- Przytrzymaj klawisz myszy nad jednym z powyższych przycisków dla szybszego wyboru."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- Kliknij na jednym z pól czasu by zwiÄ™kszyć jego wartość\n" + +"- lub kliknij trzymajÄ…c Shift by zmiejszyć jego wartość\n" + +"- lub kliknij i przeciÄ…gnij dla szybszego wyboru."; + +//Calendar._TT["TOGGLE"] = "ZmieÅ„ pierwszy dzieÅ„ tygodnia"; +Calendar._TT["PREV_YEAR"] = "Poprzedni rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprzedni miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Idź do dzisiaj"; +Calendar._TT["NEXT_MONTH"] = "NastÄ™pny miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "NastÄ™pny rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzeciÄ…gnij by przesunąć"; +Calendar._TT["PART_TODAY"] = " (dzisiaj)"; +Calendar._TT["MON_FIRST"] = "WyÅ›wietl poniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "WyÅ›wietl niedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "Dzisiaj"; +Calendar._TT["TIME_PART"] = "(Shift-)Kliknij lub przeciÄ…gnij by zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %B, %A"; + +Calendar._TT["WK"] = "ty"; diff --git a/htdocs/js/jscalendar/lang/calendar-pl.js b/htdocs/js/jscalendar/lang/calendar-pl.js new file mode 100644 index 0000000..76e0551 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pl.js @@ -0,0 +1,56 @@ +// ** I18N +// Calendar PL language +// Author: Artur Filipiak, +// January, 2004 +// Encoding: UTF-8 +Calendar._DN = new Array +("Niedziela", "PoniedziaÅ‚ek", "Wtorek", "Åšroda", "Czwartek", "PiÄ…tek", "Sobota", "Niedziela"); + +Calendar._SDN = new Array +("N", "Pn", "Wt", "Åšr", "Cz", "Pt", "So", "N"); + +Calendar._MN = new Array +("StyczeÅ„", "Luty", "Marzec", "KwiecieÅ„", "Maj", "Czerwiec", "Lipiec", "SierpieÅ„", "WrzesieÅ„", "Październik", "Listopad", "GrudzieÅ„"); + +Calendar._SMN = new Array +("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Wybór daty:\n" + +"- aby wybrać rok użyj przycisków \xab, \xbb\n" + +"- aby wybrać miesiÄ…c użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- aby przyspieszyć wybór przytrzymaj wciÅ›niÄ™ty przycisk myszy nad ww. przyciskami."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- aby zwiÄ™kszyć wartość kliknij na dowolnym elemencie selekcji czasu\n" + +"- aby zmniejszyć wartość użyj dodatkowo klawisza Shift\n" + +"- możesz również poruszać myszkÄ™ w lewo i prawo wraz z wciÅ›niÄ™tym lewym klawiszem."; + +Calendar._TT["PREV_YEAR"] = "Poprz. rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprz. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Pokaż dziÅ›"; +Calendar._TT["NEXT_MONTH"] = "Nast. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "Nast. rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzesuÅ„ okienko"; +Calendar._TT["PART_TODAY"] = " (dziÅ›)"; +Calendar._TT["MON_FIRST"] = "Pokaż PoniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "Pokaż NiedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "DziÅ›"; +Calendar._TT["TIME_PART"] = "(Shift-)klik | drag, aby zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y.%m.%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-pt.js b/htdocs/js/jscalendar/lang/calendar-pt.js new file mode 100644 index 0000000..deee8a1 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pt.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar pt_BR language +// Author: Adalberto Machado, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terca", + "Quarta", + "Quinta", + "Sexta", + "Sabado", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Seg", + "Ter", + "Qua", + "Qui", + "Sex", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Marco", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Fev", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Out", + "Nov", + "Dez"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre o calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Ultima versao visite: http://www.dynarch.com/projects/calendar/\n" + +"Distribuido sobre GNU LGPL. Veja http://gnu.org/licenses/lgpl.html para detalhes." + +"\n\n" + +"Selecao de data:\n" + +"- Use os botoes \xab, \xbb para selecionar o ano\n" + +"- Use os botoes " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para selecionar o mes\n" + +"- Segure o botao do mouse em qualquer um desses botoes para selecao rapida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selecao de hora:\n" + +"- Clique em qualquer parte da hora para incrementar\n" + +"- ou Shift-click para decrementar\n" + +"- ou clique e segure para selecao rapida."; + +Calendar._TT["PREV_YEAR"] = "Ant. ano (segure para menu)"; +Calendar._TT["PREV_MONTH"] = "Ant. mes (segure para menu)"; +Calendar._TT["GO_TODAY"] = "Hoje"; +Calendar._TT["NEXT_MONTH"] = "Prox. mes (segure para menu)"; +Calendar._TT["NEXT_YEAR"] = "Prox. ano (segure para menu)"; +Calendar._TT["SEL_DATE"] = "Selecione a data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arraste para mover"; +Calendar._TT["PART_TODAY"] = " (hoje)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostre %s primeiro"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; +Calendar._TT["TIME_PART"] = "(Shift-)Click ou arraste para mudar valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b"; + +Calendar._TT["WK"] = "sm"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ro.js b/htdocs/js/jscalendar/lang/calendar-ro.js new file mode 100644 index 0000000..116e358 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ro.js @@ -0,0 +1,66 @@ +// ** I18N +Calendar._DN = new Array +("Duminică", + "Luni", + "MarÅ£i", + "Miercuri", + "Joi", + "Vineri", + "Sâmbătă", + "Duminică"); +Calendar._SDN_len = 2; +Calendar._MN = new Array +("Ianuarie", + "Februarie", + "Martie", + "Aprilie", + "Mai", + "Iunie", + "Iulie", + "August", + "Septembrie", + "Octombrie", + "Noiembrie", + "Decembrie"); + +// tooltips +Calendar._TT = {}; + +Calendar._TT["INFO"] = "Despre calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Pentru ultima versiune vizitaÅ£i: http://www.dynarch.com/projects/calendar/\n" + +"Distribuit sub GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"SelecÅ£ia datei:\n" + +"- FolosiÅ£i butoanele \xab, \xbb pentru a selecta anul\n" + +"- FolosiÅ£i butoanele " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pentru a selecta luna\n" + +"- TineÅ£i butonul mouse-ului apăsat pentru selecÅ£ie mai rapidă."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"SelecÅ£ia orei:\n" + +"- Click pe ora sau minut pentru a mări valoarea cu 1\n" + +"- Sau Shift-Click pentru a micÅŸora valoarea cu 1\n" + +"- Sau Click ÅŸi drag pentru a selecta mai repede."; + +Calendar._TT["PREV_YEAR"] = "Anul precedent (lung pt menu)"; +Calendar._TT["PREV_MONTH"] = "Luna precedentă (lung pt menu)"; +Calendar._TT["GO_TODAY"] = "Data de azi"; +Calendar._TT["NEXT_MONTH"] = "Luna următoare (lung pt menu)"; +Calendar._TT["NEXT_YEAR"] = "Anul următor (lung pt menu)"; +Calendar._TT["SEL_DATE"] = "Selectează data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trage pentru a miÅŸca"; +Calendar._TT["PART_TODAY"] = " (astăzi)"; +Calendar._TT["DAY_FIRST"] = "AfiÅŸează %s prima zi"; +Calendar._TT["WEEKEND"] = "0,6"; +Calendar._TT["CLOSE"] = "ÃŽnchide"; +Calendar._TT["TODAY"] = "Astăzi"; +Calendar._TT["TIME_PART"] = "(Shift-)Click sau drag pentru a selecta"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %d %B"; + +Calendar._TT["WK"] = "spt"; +Calendar._TT["TIME"] = "Ora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ru.js b/htdocs/js/jscalendar/lang/calendar-ru.js new file mode 100644 index 0000000..9f75a6a --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ru.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar RU language +// Translation: Sly Golovanov, http://golovanov.net, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("воÑкреÑенье", + "понедельник", + "вторник", + "Ñреда", + "четверг", + "пÑтница", + "Ñуббота", + "воÑкреÑенье"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("вÑк", + "пон", + "втр", + "Ñрд", + "чет", + "пÑÑ‚", + "Ñуб", + "вÑк"); + +// full month names +Calendar._MN = new Array +("Ñнварь", + "февраль", + "март", + "апрель", + "май", + "июнь", + "июль", + "авгуÑÑ‚", + "ÑентÑбрь", + "октÑбрь", + "ноÑбрь", + "декабрь"); + +// short month names +Calendar._SMN = new Array +("Ñнв", + "фев", + "мар", + "апр", + "май", + "июн", + "июл", + "авг", + "Ñен", + "окт", + "ноÑ", + "дек"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "О календаре..."; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Как выбрать дату:\n" + +"- При помощи кнопок \xab, \xbb можно выбрать год\n" + +"- При помощи кнопок " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " можно выбрать меÑÑц\n" + +"- Подержите Ñти кнопки нажатыми, чтобы поÑвилоÑÑŒ меню быÑтрого выбора."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Как выбрать времÑ:\n" + +"- При клике на чаÑах или минутах они увеличиваютÑÑ\n" + +"- при клике Ñ Ð½Ð°Ð¶Ð°Ñ‚Ð¾Ð¹ клавишей Shift они уменьшаютÑÑ\n" + +"- еÑли нажать и двигать мышкой влево/вправо, они будут менÑÑ‚ÑŒÑÑ Ð±Ñ‹Ñтрее."; + +Calendar._TT["PREV_YEAR"] = "Ðа год назад (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["PREV_MONTH"] = "Ðа меÑÑц назад (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["GO_TODAY"] = "СегоднÑ"; +Calendar._TT["NEXT_MONTH"] = "Ðа меÑÑц вперед (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["NEXT_YEAR"] = "Ðа год вперед (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["SEL_DATE"] = "Выберите дату"; +Calendar._TT["DRAG_TO_MOVE"] = "ПеретаÑкивайте мышкой"; +Calendar._TT["PART_TODAY"] = " (ÑегоднÑ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Первый день недели будет %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Закрыть"; +Calendar._TT["TODAY"] = "СегоднÑ"; +Calendar._TT["TIME_PART"] = "(Shift-)клик или нажать и двигать"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %b, %a"; + +Calendar._TT["WK"] = "нед"; +Calendar._TT["TIME"] = "ВремÑ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ru_win_.js b/htdocs/js/jscalendar/lang/calendar-ru_win_.js new file mode 100644 index 0000000..de455af --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ru_win_.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar RU language +// Translation: Sly Golovanov, http://golovanov.net, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("âîñêðåñåíüå", + "ïîíåäåëüíèê", + "âòîðíèê", + "ñðåäà", + "÷åòâåðã", + "ïÿòíèöà", + "ñóááîòà", + "âîñêðåñåíüå"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("âñê", + "ïîí", + "âòð", + "ñðä", + "÷åò", + "ïÿò", + "ñóá", + "âñê"); + +// full month names +Calendar._MN = new Array +("ÿíâàðü", + "ôåâðàëü", + "ìàðò", + "àïðåëü", + "ìàé", + "èþíü", + "èþëü", + "àâãóñò", + "ñåíòÿáðü", + "îêòÿáðü", + "íîÿáðü", + "äåêàáðü"); + +// short month names +Calendar._SMN = new Array +("ÿíâ", + "ôåâ", + "ìàð", + "àïð", + "ìàé", + "èþí", + "èþë", + "àâã", + "ñåí", + "îêò", + "íîÿ", + "äåê"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Î êàëåíäàðå..."; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Êàê âûáðàòü äàòó:\n" + +"- Ïðè ïîìîùè êíîïîê \xab, \xbb ìîæíî âûáðàòü ãîä\n" + +"- Ïðè ïîìîùè êíîïîê " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ìîæíî âûáðàòü ìåñÿö\n" + +"- Ïîäåðæèòå ýòè êíîïêè íàæàòûìè, ÷òîáû ïîÿâèëîñü ìåíþ áûñòðîãî âûáîðà."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Êàê âûáðàòü âðåìÿ:\n" + +"- Ïðè êëèêå íà ÷àñàõ èëè ìèíóòàõ îíè óâåëè÷èâàþòñÿ\n" + +"- ïðè êëèêå ñ íàæàòîé êëàâèøåé Shift îíè óìåíüøàþòñÿ\n" + +"- åñëè íàæàòü è äâèãàòü ìûøêîé âëåâî/âïðàâî, îíè áóäóò ìåíÿòüñÿ áûñòðåå."; + +Calendar._TT["PREV_YEAR"] = "Íà ãîä íàçàä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["PREV_MONTH"] = "Íà ìåñÿö íàçàä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["GO_TODAY"] = "Ñåãîäíÿ"; +Calendar._TT["NEXT_MONTH"] = "Íà ìåñÿö âïåðåä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["NEXT_YEAR"] = "Íà ãîä âïåðåä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["SEL_DATE"] = "Âûáåðèòå äàòó"; +Calendar._TT["DRAG_TO_MOVE"] = "Ïåðåòàñêèâàéòå ìûøêîé"; +Calendar._TT["PART_TODAY"] = " (ñåãîäíÿ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Ïåðâûé äåíü íåäåëè áóäåò %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Çàêðûòü"; +Calendar._TT["TODAY"] = "Ñåãîäíÿ"; +Calendar._TT["TIME_PART"] = "(Shift-)êëèê èëè íàæàòü è äâèãàòü"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %b, %a"; + +Calendar._TT["WK"] = "íåä"; +Calendar._TT["TIME"] = "Âðåìÿ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-si.js b/htdocs/js/jscalendar/lang/calendar-si.js new file mode 100644 index 0000000..cb3dfb9 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-si.js @@ -0,0 +1,94 @@ +/* Slovenian language file for the DHTML Calendar version 0.9.2 +* Author David Milost , January 2004. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ + // full day names +Calendar._DN = new Array +("Nedelja", + "Ponedeljek", + "Torek", + "Sreda", + "ÄŒetrtek", + "Petek", + "Sobota", + "Nedelja"); + // short day names + Calendar._SDN = new Array +("Ned", + "Pon", + "Tor", + "Sre", + "ÄŒet", + "Pet", + "Sob", + "Ned"); +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Maj", + "Jun", + "Jul", + "Avg", + "Sep", + "Okt", + "Nov", + "Dec"); + // full month names +Calendar._MN = new Array +("Januar", + "Februar", + "Marec", + "April", + "Maj", + "Junij", + "Julij", + "Avgust", + "September", + "Oktober", + "November", + "December"); + +// tooltips +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O koledarju"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Za zadnjo verzijo pojdine na naslov: http://www.dynarch.com/projects/calendar/\n" + +"Distribuirano pod GNU LGPL. Poglejte http://gnu.org/licenses/lgpl.html za podrobnosti." + +"\n\n" + +"Izbor datuma:\n" + +"- Uporabite \xab, \xbb gumbe za izbor leta\n" + +"- Uporabite " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gumbe za izbor meseca\n" + +"- Zadržite klik na kateremkoli od zgornjih gumbov za hiter izbor."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Izbor ćasa:\n" + +"- Kliknite na katerikoli del ćasa za poveć. le-tega\n" + +"- ali Shift-click za zmanj. le-tega\n" + +"- ali kliknite in povlecite za hiter izbor."; + +Calendar._TT["TOGGLE"] = "Spremeni dan s katerim se prićne teden"; +Calendar._TT["PREV_YEAR"] = "Predhodnje leto (dolg klik za meni)"; +Calendar._TT["PREV_MONTH"] = "Predhodnji mesec (dolg klik za meni)"; +Calendar._TT["GO_TODAY"] = "Pojdi na tekoći dan"; +Calendar._TT["NEXT_MONTH"] = "Naslednji mesec (dolg klik za meni)"; +Calendar._TT["NEXT_YEAR"] = "Naslednje leto (dolg klik za meni)"; +Calendar._TT["SEL_DATE"] = "Izberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni in povleci za spremembo pozicije"; +Calendar._TT["PART_TODAY"] = " (danes)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedeljek kot prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedeljo kot prvi dan"; +Calendar._TT["CLOSE"] = "Zapri"; +Calendar._TT["TODAY"] = "Danes"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Ted"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-sk.js b/htdocs/js/jscalendar/lang/calendar-sk.js new file mode 100644 index 0000000..4fe6a3c --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sk.js @@ -0,0 +1,99 @@ +// ** I18N + +// Calendar SK language +// Author: Peter Valach (pvalach@gmx.net) +// Encoding: utf-8 +// Last update: 2003/10/29 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("NedeÄľa", + "Pondelok", + "Utorok", + "Streda", + "Ĺ tvrtok", + "Piatok", + "Sobota", + "NedeÄľa"); + +// short day names +Calendar._SDN = new Array +("Ned", + "Pon", + "Uto", + "Str", + "Ĺ tv", + "Pia", + "Sob", + "Ned"); + +// full month names +Calendar._MN = new Array +("Január", + "Február", + "Marec", + "AprĂ­l", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "August", + "September", + "OktÄ‚Å‚ber", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendári"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + +"PoslednÄ‚ÅŸ verziu nájdete na: http://www.dynarch.com/projects/calendar/\n" + +"DistribuovanĂ© pod GNU LGPL. ViÄŹ http://gnu.org/licenses/lgpl.html pre detaily." + +"\n\n" + +"VÄ‚Ëber dátumu:\n" + +"- PouĹľite tlaÄŤidlá \xab, \xbb pre vÄ‚Ëber roku\n" + +"- PouĹľite tlaÄŤidlá " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pre vÄ‚Ëber mesiaca\n" + +"- Ak ktorĂ©koÄľvek z tÄ‚Ëchto tlaÄŤidiel podržíte dlhšie, zobrazĂ­ sa rÄ‚Ëchly vÄ‚Ëber."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"VÄ‚Ëber ÄŤasu:\n" + +"- Kliknutie na niektorÄ‚ÅŸ poloĹľku ÄŤasu ju zvÄ‚Ëši\n" + +"- Shift-klik ju znĂ­Ĺľi\n" + +"- Ak podržíte tlaÄŤĂ­tko stlaÄŤenĂ©, posÄ‚ÅŸvanĂ­m menĂ­te hodnotu."; + +Calendar._TT["PREV_YEAR"] = "PredošlÄ‚Ë rok (podrĹľte pre menu)"; +Calendar._TT["PREV_MONTH"] = "PredošlÄ‚Ë mesiac (podrĹľte pre menu)"; +Calendar._TT["GO_TODAY"] = "PrejsĹĄ na dnešok"; +Calendar._TT["NEXT_MONTH"] = "Nasl. mesiac (podrĹľte pre menu)"; +Calendar._TT["NEXT_YEAR"] = "Nasl. rok (podrĹľte pre menu)"; +Calendar._TT["SEL_DATE"] = "ZvoÄľte dátum"; +Calendar._TT["DRAG_TO_MOVE"] = "PodrĹľanĂ­m tlaÄŤĂ­tka zmenĂ­te polohu"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "ZobraziĹĄ pondelok ako prvÄ‚Ë"; +Calendar._TT["SUN_FIRST"] = "ZobraziĹĄ nedeÄľu ako prvÄ‚ÅŸ"; +Calendar._TT["CLOSE"] = "ZavrieĹĄ"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)klik/ĹĄahanie zmenĂ­ hodnotu"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "$d. %m. %Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e. %b"; + +Calendar._TT["WK"] = "tÄ‚ËĹľ"; diff --git a/htdocs/js/jscalendar/lang/calendar-sp.js b/htdocs/js/jscalendar/lang/calendar-sp.js new file mode 100644 index 0000000..239d1b3 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sp.js @@ -0,0 +1,110 @@ +// ** I18N + +// Calendar SP language +// Author: Rafael Velasco +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miercoles", + "Jueves", + "Viernes", + "Sabado", + "Domingo"); + +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mie", + "Jue", + "Vie", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// short month names +Calendar._SMN = new Array +("Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Información del Calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Nuevas versiones en: http://www.dynarch.com/projects/calendar/\n" + +"Distribuida bajo licencia GNU LGPL. Para detalles vea http://gnu.org/licenses/lgpl.html ." + +"\n\n" + +"Selección de Fechas:\n" + +"- Use \xab, \xbb para seleccionar el año\n" + +"- Use " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga presionado el botón del ratón en cualquiera de las opciones superiores para un acceso rapido ."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selección del Reloj:\n" + +"- Seleccione la hora para cambiar el reloj\n" + +"- o presione Shift-click para disminuirlo\n" + +"- o presione click y arrastre del ratón para una selección rapida."; + +Calendar._TT["PREV_YEAR"] = "Año anterior (Presione para menu)"; +Calendar._TT["PREV_MONTH"] = "Mes Anterior (Presione para menu)"; +Calendar._TT["GO_TODAY"] = "Ir a Hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes Siguiente (Presione para menu)"; +Calendar._TT["NEXT_YEAR"] = "Año Siguiente (Presione para menu)"; +Calendar._TT["SEL_DATE"] = "Seleccione fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastre y mueva"; +Calendar._TT["PART_TODAY"] = " (Hoy)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostrar %s primero"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; +Calendar._TT["TIME_PART"] = "(Shift-)Click o arrastra para cambar el valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%dd-%mm-%yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "Sm"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-sv.js b/htdocs/js/jscalendar/lang/calendar-sv.js new file mode 100644 index 0000000..db1f4b8 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sv.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar SV language (Swedish, svenska) +// Author: Mihai Bazon, +// Translation team: +// Translator: Leonard Norrgård +// Last translator: Leonard Norrgård +// Encoding: iso-latin-1 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("söndag", + "måndag", + "tisdag", + "onsdag", + "torsdag", + "fredag", + "lördag", + "söndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. +Calendar._SDN_len = 2; +Calendar._SMN_len = 3; + +// full month names +Calendar._MN = new Array +("januari", + "februari", + "mars", + "april", + "maj", + "juni", + "juli", + "augusti", + "september", + "oktober", + "november", + "december"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om kalendern"; + +Calendar._TT["ABOUT"] = +"DHTML Datum/tid-väljare\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"För senaste version gå till: http://www.dynarch.com/projects/calendar/\n" + +"Distribueras under GNU LGPL. Se http://gnu.org/licenses/lgpl.html för detaljer." + +"\n\n" + +"Val av datum:\n" + +"- Använd knapparna \xab, \xbb för att välja år\n" + +"- Använd knapparna " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " för att välja månad\n" + +"- Håll musknappen nedtryckt på någon av ovanstående knappar för snabbare val."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Val av tid:\n" + +"- Klicka på en del av tiden för att öka den delen\n" + +"- eller skift-klicka för att minska den\n" + +"- eller klicka och drag för snabbare val."; + +Calendar._TT["PREV_YEAR"] = "Föregående år (håll för menu)"; +Calendar._TT["PREV_MONTH"] = "Föregående månad (håll för menu)"; +Calendar._TT["GO_TODAY"] = "Gå till dagens datum"; +Calendar._TT["NEXT_MONTH"] = "Följande månad (håll för menu)"; +Calendar._TT["NEXT_YEAR"] = "Följande år (håll för menu)"; +Calendar._TT["SEL_DATE"] = "Välj datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag för att flytta"; +Calendar._TT["PART_TODAY"] = " (idag)"; +Calendar._TT["MON_FIRST"] = "Visa måndag först"; +Calendar._TT["SUN_FIRST"] = "Visa söndag först"; +Calendar._TT["CLOSE"] = "Stäng"; +Calendar._TT["TODAY"] = "Idag"; +Calendar._TT["TIME_PART"] = "(Skift-)klicka eller drag för att ändra tid"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A %d %b %Y"; + +Calendar._TT["WK"] = "vecka"; diff --git a/htdocs/js/jscalendar/lang/calendar-tr.js b/htdocs/js/jscalendar/lang/calendar-tr.js new file mode 100644 index 0000000..2164687 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-tr.js @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// Turkish Translation by Nuri AKMAN +// Location: Ankara/TURKEY +// e-mail : nuriakman@hotmail.com +// Date : April, 9 2003 +// +// Note: if Turkish Characters does not shown on you screen +// please include falowing line your html code: +// +// +// +////////////////////////////////////////////////////////////////////////////////////////////// + +// ** I18N +Calendar._DN = new Array +("Pazar", + "Pazartesi", + "Salý", + "Çarþamba", + "Perþembe", + "Cuma", + "Cumartesi", + "Pazar"); +Calendar._MN = new Array +("Ocak", + "Þubat", + "Mart", + "Nisan", + "Mayýs", + "Haziran", + "Temmuz", + "Aðustos", + "Eylül", + "Ekim", + "Kasým", + "Aralýk"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Haftanýn ilk gününü kaydýr"; +Calendar._TT["PREV_YEAR"] = "Önceki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["PREV_MONTH"] = "Önceki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["GO_TODAY"] = "Bugün'e git"; +Calendar._TT["NEXT_MONTH"] = "Sonraki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["NEXT_YEAR"] = "Sonraki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["SEL_DATE"] = "Tarih seçiniz"; +Calendar._TT["DRAG_TO_MOVE"] = "Taþýmak için sürükleyiniz"; +Calendar._TT["PART_TODAY"] = " (bugün)"; +Calendar._TT["MON_FIRST"] = "Takvim Pazartesi gününden baþlasýn"; +Calendar._TT["SUN_FIRST"] = "Takvim Pazar gününden baþlasýn"; +Calendar._TT["CLOSE"] = "Kapat"; +Calendar._TT["TODAY"] = "Bugün"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "d MM y, DD"; + +Calendar._TT["WK"] = "Hafta"; diff --git a/htdocs/js/jscalendar/lang/calendar-zh.js b/htdocs/js/jscalendar/lang/calendar-zh.js new file mode 100644 index 0000000..4a0feb6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-zh.js @@ -0,0 +1,119 @@ +// ** I18N + +// Calendar ZH language +// Author: muziq, +// Encoding: GB2312 or GBK +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("ÐÇÆÚÈÕ", + "ÐÇÆÚÒ»", + "ÐÇÆÚ¶þ", + "ÐÇÆÚÈý", + "ÐÇÆÚËÄ", + "ÐÇÆÚÎå", + "ÐÇÆÚÁù", + "ÐÇÆÚÈÕ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ÈÕ", + "Ò»", + "¶þ", + "Èý", + "ËÄ", + "Îå", + "Áù", + "ÈÕ"); + +// full month names +Calendar._MN = new Array +("Ò»ÔÂ", + "¶þÔÂ", + "ÈýÔÂ", + "ËÄÔÂ", + "ÎåÔÂ", + "ÁùÔÂ", + "ÆßÔÂ", + "°ËÔÂ", + "¾ÅÔÂ", + "Ê®ÔÂ", + "ʮһÔÂ", + "Ê®¶þÔÂ"); + +// short month names +Calendar._SMN = new Array +("Ò»ÔÂ", + "¶þÔÂ", + "ÈýÔÂ", + "ËÄÔÂ", + "ÎåÔÂ", + "ÁùÔÂ", + "ÆßÔÂ", + "°ËÔÂ", + "¾ÅÔÂ", + "Ê®ÔÂ", + "ʮһÔÂ", + "Ê®¶þÔÂ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "°ïÖú"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Ñ¡ÔñÈÕÆÚ:\n" + +"- µã»÷ \xab, \xbb °´Å¥Ñ¡ÔñÄê·Ý\n" + +"- µã»÷ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " °´Å¥Ñ¡ÔñÔ·Ý\n" + +"- ³¤°´ÒÔÉÏ°´Å¥¿É´Ó²Ëµ¥ÖпìËÙÑ¡ÔñÄê·Ý»òÔ·Ý"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Ñ¡Ôñʱ¼ä:\n" + +"- µã»÷Сʱ»ò·ÖÖÓ¿Éʹ¸ÄÊýÖµ¼ÓÒ»\n" + +"- °´×¡Shift¼üµã»÷Сʱ»ò·ÖÖÓ¿Éʹ¸ÄÊýÖµ¼õÒ»\n" + +"- µã»÷Í϶¯Êó±ê¿É½øÐпìËÙÑ¡Ôñ"; + +Calendar._TT["PREV_YEAR"] = "ÉÏÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["PREV_MONTH"] = "ÉÏÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["GO_TODAY"] = "תµ½½ñÈÕ"; +Calendar._TT["NEXT_MONTH"] = "ÏÂÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["NEXT_YEAR"] = "ÏÂÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["SEL_DATE"] = "Ñ¡ÔñÈÕÆÚ"; +Calendar._TT["DRAG_TO_MOVE"] = "Í϶¯"; +Calendar._TT["PART_TODAY"] = " (½ñÈÕ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "×î×ó±ßÏÔʾ%s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "¹Ø±Õ"; +Calendar._TT["TODAY"] = "½ñÈÕ"; +Calendar._TT["TIME_PART"] = "(Shift-)µã»÷Êó±ê»òÍ϶¯¸Ä±äÖµ"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %b %eÈÕ"; + +Calendar._TT["WK"] = "ÖÜ"; +Calendar._TT["TIME"] = "ʱ¼ä:"; diff --git a/htdocs/js/jscalendar/lang/cn_utf8.js b/htdocs/js/jscalendar/lang/cn_utf8.js new file mode 100644 index 0000000..a0ef7c6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/cn_utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Translator : Niko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("\u5468\u65e5",//\u5468\u65e5 + "\u5468\u4e00",//\u5468\u4e00 + "\u5468\u4e8c",//\u5468\u4e8c + "\u5468\u4e09",//\u5468\u4e09 + "\u5468\u56db",//\u5468\u56db + "\u5468\u4e94",//\u5468\u4e94 + "\u5468\u516d",//\u5468\u516d + "\u5468\u65e5");//\u5468\u65e5 + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("\u5468\u65e5", + "\u5468\u4e00", + "\u5468\u4e8c", + "\u5468\u4e09", + "\u5468\u56db", + "\u5468\u4e94", + "\u5468\u516d", + "\u5468\u65e5"); + +// full month names +Calendar._MN = new Array +("\u4e00\u6708", + "\u4e8c\u6708", + "\u4e09\u6708", + "\u56db\u6708", + "\u4e94\u6708", + "\u516d\u6708", + "\u4e03\u6708", + "\u516b\u6708", + "\u4e5d\u6708", + "\u5341\u6708", + "\u5341\u4e00\u6708", + "\u5341\u4e8c\u6708"); + +// short month names +Calendar._SMN = new Array +("\u4e00\u6708", + "\u4e8c\u6708", + "\u4e09\u6708", + "\u56db\u6708", + "\u4e94\u6708", + "\u516d\u6708", + "\u4e03\u6708", + "\u516b\u6708", + "\u4e5d\u6708", + "\u5341\u6708", + "\u5341\u4e00\u6708", + "\u5341\u4e8c\u6708"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "\u5173\u4e8e"; + +Calendar._TT["ABOUT"] = +" DHTML \u65e5\u8d77/\u65f6\u95f4\u9009\u62e9\u63a7\u4ef6\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: \u6700\u65b0\u7248\u672c\u8bf7\u767b\u9646http://www.dynarch.com/projects/calendar/\u5bdf\u770b\n" + +"\u9075\u5faaGNU LGPL. \u7ec6\u8282\u53c2\u9605 http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"\u65e5\u671f\u9009\u62e9:\n" + +"- \u70b9\u51fb\xab(\xbb)\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e00\u5e74\u5ea6.\n" + +"- \u70b9\u51fb" + String.fromCharCode(0x2039) + "(" + String.fromCharCode(0x203a) + ")\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e2a\u6708\u4efd.\n" + +"- \u957f\u65f6\u95f4\u6309\u7740\u6309\u94ae\u5c06\u51fa\u73b0\u66f4\u591a\u9009\u62e9\u9879."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"\u65f6\u95f4\u9009\u62e9:\n" + +"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u589e\u52a0\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\n" + +"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u6309\u4f4fShift\u952e\u540e\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u51cf\u5c11\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)."; + +Calendar._TT["PREV_YEAR"] = "\u4e0a\u4e00\u5e74"; +Calendar._TT["PREV_MONTH"] = "\u4e0a\u4e2a\u6708"; +Calendar._TT["GO_TODAY"] = "\u5230\u4eca\u5929"; +Calendar._TT["NEXT_MONTH"] = "\u4e0b\u4e2a\u6708"; +Calendar._TT["NEXT_YEAR"] = "\u4e0b\u4e00\u5e74"; +Calendar._TT["SEL_DATE"] = "\u9009\u62e9\u65e5\u671f"; +Calendar._TT["DRAG_TO_MOVE"] = "\u62d6\u52a8"; +Calendar._TT["PART_TODAY"] = " (\u4eca\u5929)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s\u4e3a\u8fd9\u5468\u7684\u7b2c\u4e00\u5929"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "\u5173\u95ed"; +Calendar._TT["TODAY"] = "\u4eca\u5929"; +Calendar._TT["TIME_PART"] = "(\u6309\u7740Shift\u952e)\u5355\u51fb\u6216\u62d6\u52a8\u6539\u53d8\u503c"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e\u65e5"; + +Calendar._TT["WK"] = "\u5468"; +Calendar._TT["TIME"] = "\u65f6\u95f4:"; diff --git a/htdocs/js/jscalendar/menuarrow.gif b/htdocs/js/jscalendar/menuarrow.gif new file mode 100644 index 0000000..ed2dee0 Binary files /dev/null and b/htdocs/js/jscalendar/menuarrow.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/active-bg.gif b/htdocs/js/jscalendar/skins/aqua/active-bg.gif new file mode 100644 index 0000000..d608c54 Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/active-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/dark-bg.gif b/htdocs/js/jscalendar/skins/aqua/dark-bg.gif new file mode 100644 index 0000000..1dea48a Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/dark-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/hover-bg.gif b/htdocs/js/jscalendar/skins/aqua/hover-bg.gif new file mode 100644 index 0000000..fbf94fc Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/hover-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/menuarrow.gif b/htdocs/js/jscalendar/skins/aqua/menuarrow.gif new file mode 100644 index 0000000..40c0aad Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/menuarrow.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/normal-bg.gif b/htdocs/js/jscalendar/skins/aqua/normal-bg.gif new file mode 100644 index 0000000..bdb5068 Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/normal-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/rowhover-bg.gif b/htdocs/js/jscalendar/skins/aqua/rowhover-bg.gif new file mode 100644 index 0000000..7715342 Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/rowhover-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/status-bg.gif b/htdocs/js/jscalendar/skins/aqua/status-bg.gif new file mode 100644 index 0000000..857108c Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/status-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/theme.css b/htdocs/js/jscalendar/skins/aqua/theme.css new file mode 100644 index 0000000..18dd6cf --- /dev/null +++ b/htdocs/js/jscalendar/skins/aqua/theme.css @@ -0,0 +1,236 @@ +/* Distributed as part of The Coolest DHTML Calendar + Author: Mihai Bazon, www.bazon.net/mishoo + Copyright Dynarch.com 2005, www.dynarch.com +*/ + +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #bdb2bf; + font-size: 11px; + color: #000; + cursor: default; + background: url("normal-bg.gif"); + font-family: "trebuchet ms",verdana,tahoma,sans-serif; +} + +.calendar { + border-color: #797979; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ + background: url("title-bg.gif") repeat-x 0 100%; color: #000; + font-weight: bold; +} + +.calendar .nav { + font-family: verdana,tahoma,sans-serif; +} + +.calendar .nav div { + background: transparent url("menuarrow.gif") no-repeat 100% 100%; +} + +.calendar thead tr { background: url("title-bg.gif") repeat-x 0 100%; color: #000; } + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + padding: 2px; + background: url("title-bg.gif") repeat-x 0 100%; color: #000; +} + +.calendar thead .headrow { /* Row containing navigation buttons */ +} + +.calendar thead .name { /* Cells containing the day names */ + border-bottom: 1px solid #797979; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #c44; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background: url("hover-bg.gif"); + border-bottom: 1px solid #797979; + padding: 2px 2px 1px 2px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background: url("active-bg.gif"); color: #fff; + padding: 3px 1px 0px 3px; + border-bottom: 1px solid #797979; +} + +.calendar thead .daynames { /* Row containing the day names */ + background: url("dark-bg.gif"); +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells containing month days dates */ + font-family: verdana,tahoma,sans-serif; + width: 2em; + color: #000; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #999; +} +.calendar tbody .day.othermonth.oweekend { + color: #f99; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #797979; + background: url("dark-bg.gif"); +} + +.calendar tbody .rowhilite td, +.calendar tbody .rowhilite td.wn { + background: url("rowhover-bg.gif"); +} + +.calendar tbody td.today { font-weight: bold; /* background: url("today-bg.gif") no-repeat 70% 50%; */ } + +.calendar tbody td.hilite { /* Hovered cells */ + background: url("hover-bg.gif"); + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells */ + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #c44; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border: 1px solid #797979; + padding: 1px 3px 1px 1px; + background: url("active-bg.gif"); color: #fff; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The in footer (only one right now) */ + text-align: center; + background: #565; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell */ + padding: 2px; + background: url("status-bg.gif") repeat-x 0 0; color: #000; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #afa; + border: 1px solid #084; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #7c7; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #797979; + background: url("normal-bg.gif"); color: #000; + z-index: 100; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: url("hover-bg.gif"); color: #000; +} + +.calendar .combo .active { + background: url("active-bg.gif"); color: #fff; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #797979; + padding: 1px 0px; + text-align: center; + background: url("dark-bg.gif"); +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 5px 0px 6px; + font-weight: bold; + background: url("normal-bg.gif"); color: #000; +} + +.calendar td.time .hour, +.calendar td.time .minute { + font-family: monospace; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + background: url("hover-bg.gif"); color: #000; +} + +.calendar td.time span.active { + background: url("active-bg.gif"); color: #fff; +} diff --git a/htdocs/js/jscalendar/skins/aqua/title-bg.gif b/htdocs/js/jscalendar/skins/aqua/title-bg.gif new file mode 100644 index 0000000..6a541b3 Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/title-bg.gif differ diff --git a/htdocs/js/jscalendar/skins/aqua/today-bg.gif b/htdocs/js/jscalendar/skins/aqua/today-bg.gif new file mode 100644 index 0000000..7161538 Binary files /dev/null and b/htdocs/js/jscalendar/skins/aqua/today-bg.gif differ diff --git a/htdocs/js/layersmenu-browser_detection.js b/htdocs/js/layersmenu-browser_detection.js new file mode 100644 index 0000000..55a5f79 --- /dev/null +++ b/htdocs/js/layersmenu-browser_detection.js @@ -0,0 +1,46 @@ +// PHP Layers Menu 3.2.0-rc (C) 2001-2004 Marco Pratesi - http://www.marcopratesi.it/ +// PHPLM v. 4.0.0 (C) 2007 Andreas Kasenides andreas@kasenides.org +// PHPLM v. 4.0.4 (C) 2008 Andreas Kasenides andreas@kasenides.org, Brett Zamir +/** + * @version 4.0.4 + * @author PHPLM v. 4.0.4 (C) 2008 Andreas Kasenides andreas@kasenides.org + * @author PHP Layers Menu 3.2.0-rc (C) 2001-2004 Marco Pratesi - http://www.marcopratesi.it/ +* @author Brett Zamir + */ + +var DOM = (document.getElementById) ? 1 : 0; +var NS4 = (document.layers) ? 1 : 0; + +// We need to explicitly detect Konqueror +// because Konqueror 3 sets IE = 1 ... AAAAAAAAAARGHHH!!! +var Konqueror = (navigator.userAgent.indexOf('Konqueror') > -1) ? 1 : 0; +// We need to detect Konqueror 2.2 as it does not handle the window.onresize event +var Konqueror22 = (navigator.userAgent.indexOf('Konqueror 2.2') > -1 || navigator.userAgent.indexOf('Konqueror/2.2') > -1) ? 1 : 0; +var Konqueror30 = + ( + navigator.userAgent.indexOf('Konqueror 3.0') > -1 + || navigator.userAgent.indexOf('Konqueror/3.0') > -1 + || navigator.userAgent.indexOf('Konqueror 3;') > -1 + || navigator.userAgent.indexOf('Konqueror/3;') > -1 + || navigator.userAgent.indexOf('Konqueror 3)') > -1 + || navigator.userAgent.indexOf('Konqueror/3)') > -1 + ) + ? 1 : 0; +var Konqueror31 = (navigator.userAgent.indexOf('Konqueror 3.1') > -1 || navigator.userAgent.indexOf('Konqueror/3.1') > -1) ? 1 : 0; +// We need to detect Konqueror 3.2 and 3.3 as they are affected by the see-through effect only for 2 form elements +var Konqueror32 = (navigator.userAgent.indexOf('Konqueror 3.2') > -1 || navigator.userAgent.indexOf('Konqueror/3.2') > -1) ? 1 : 0; +var Konqueror33 = (navigator.userAgent.indexOf('Konqueror 3.3') > -1 || navigator.userAgent.indexOf('Konqueror/3.3') > -1) ? 1 : 0; + +var Opera = (navigator.userAgent.indexOf('Opera') > -1) ? 1 : 0; +var Opera5 = (navigator.userAgent.indexOf('Opera 5') > -1 || navigator.userAgent.indexOf('Opera/5') > -1) ? 1 : 0; +var Opera6 = (navigator.userAgent.indexOf('Opera 6') > -1 || navigator.userAgent.indexOf('Opera/6') > -1) ? 1 : 0; +var Opera56 = Opera5 || Opera6; +var Opera7 = (navigator.userAgent.indexOf('Opera 7') > -1 || navigator.userAgent.indexOf('Opera/7') > -1) ? 1 : 0; +var Opera8 = (navigator.userAgent.indexOf('Opera 8') > -1 || navigator.userAgent.indexOf('Opera/8') > -1) ? 1 : 0; +var Opera9 = (navigator.userAgent.indexOf('Opera 9') > -1 || navigator.userAgent.indexOf('Opera/9') > -1) ? 1 : 0; + +var IE = (navigator.userAgent.indexOf('MSIE') > -1) ? 1 : 0; +IE = IE && !Opera; +var IE5 = IE && DOM; +var IE4 = (document.all) ? 1 : 0; +IE4 = IE4 && IE && !DOM; diff --git a/htdocs/js/modify_member.js b/htdocs/js/modify_member.js new file mode 100644 index 0000000..a601ccb --- /dev/null +++ b/htdocs/js/modify_member.js @@ -0,0 +1,89 @@ +var m1 = document.getElementById('member').notmembers; +var m2 = document.getElementById('member').members; + +/* This function generates hidden input array from new group members + * when submit button is pressed. + * see modify_member_form.php +*/ +function update_new_values(memberattr) { + el = document.getElementById("dnu"); + + for (i=0;i"; + } +} + + +/* This function moves members from left select box to right one + * see modify_member_form.php + */ +function one2two() { + m1len = m1.length ; + + for (i=0;i=0;i--){ + if (m1.options[i].selected == true) { + m1.options[i] = null; + } + } +} + +/* This function moves members from right select box to left one + * see modify_member_form.php + */ +function two2one() { + m2len = m2.length ; + + for (i=0;i=0;i--) { + if (m2.options[i].selected == true) { + m2.options[i] = null; + } + } +} + +/* This function moves all members from left select box to right one + * see modify_member_form.php + */ +function all2two() { + m1len = m1.length ; + + for (i=0;i=0;i--) { + m1.options[i] = null; + } +} + +/* This function moves all members from right select box to left one + * see modify_member_form.php + */ +function all2one() { + m2len = m2.length ; + + for (i=0;i=0;i--) { + m2.options[i] = null; + } +} diff --git a/htdocs/js/toAscii.js b/htdocs/js/toAscii.js new file mode 100644 index 0000000..287ff65 --- /dev/null +++ b/htdocs/js/toAscii.js @@ -0,0 +1,80 @@ +// +// Purpose of this file is to remap characters as ASCII characters +// +// + +var to_ascii_array = new Array(); +to_ascii_array['à'] = 'a'; +to_ascii_array['á'] = 'a'; +to_ascii_array['â'] = 'a'; +to_ascii_array['À'] = 'a'; +to_ascii_array['ã'] = 'a'; +to_ascii_array['Ã¥'] = 'a'; +to_ascii_array['À'] = 'A'; +to_ascii_array['ÃÂ'] = 'A'; +to_ascii_array['Ä'] = 'A'; +to_ascii_array['Â'] = 'A'; +to_ascii_array['Ã'] = 'A'; +to_ascii_array['Å'] = 'A'; +to_ascii_array['é'] = 'e'; +to_ascii_array['Ú'] = 'e'; +to_ascii_array['ë'] = 'e'; +to_ascii_array['ê'] = 'e'; +to_ascii_array['€'] = 'E'; +to_ascii_array['ï'] = 'i'; +to_ascii_array['î'] = 'i'; +to_ascii_array['ì'] = 'i'; +to_ascii_array['í'] = 'i'; +to_ascii_array['ÃÂ'] = 'I'; +to_ascii_array['Î'] = 'I'; +to_ascii_array['Ì'] = 'I'; +to_ascii_array['ÃÂ'] = 'I'; +to_ascii_array['ò'] = 'o'; +to_ascii_array['ó'] = 'o'; +to_ascii_array['ÃŽ'] = 'o'; +to_ascii_array['õ'] = 'o'; +to_ascii_array['ö'] = 'o'; +to_ascii_array['Þ'] = 'o'; +to_ascii_array['Ò'] = 'O'; +to_ascii_array['Ó'] = 'O'; +to_ascii_array['Ô'] = 'O'; +to_ascii_array['Õ'] = 'O'; +to_ascii_array['Ö'] = 'O'; +to_ascii_array['Ø'] = 'O'; +to_ascii_array['ù'] = 'u'; +to_ascii_array['ú'] = 'u'; +to_ascii_array['ÃŒ'] = 'u'; +to_ascii_array['û'] = 'u'; +to_ascii_array['Ù'] = 'U'; +to_ascii_array['Ú'] = 'U'; +to_ascii_array['Ü'] = 'U'; +to_ascii_array['Û'] = 'U'; +to_ascii_array['Ê'] = 'ae'; +to_ascii_array['Æ'] = 'AE'; +to_ascii_array['Ãœ'] = 'y'; +to_ascii_array['ÿ'] = 'y'; +to_ascii_array['ß'] = 'SS'; +to_ascii_array['Ç'] = 'C'; +to_ascii_array['ç'] = 'c'; +to_ascii_array['Ñ'] = 'N'; +to_ascii_array['ñ'] = 'n'; +to_ascii_array['¢'] = 'c'; +to_ascii_array['©'] = '(C)'; +to_ascii_array['®'] = '(R)'; +to_ascii_array['«'] = '<<'; +to_ascii_array['»'] = '>>'; + +function toAscii(text) { + //var text = field.value; + var position = 0; + var output = ""; + for (position = 0 ; position < text.length ; position++) { + var tmp = text.substring(position,position+1); + if (to_ascii_array[tmp] != undefined) { + tmp = to_ascii_array[tmp]; + } + output = output + tmp; + } + return output; +} + diff --git a/htdocs/login.php b/htdocs/login.php new file mode 100644 index 0000000..48f9e2e --- /dev/null +++ b/htdocs/login.php @@ -0,0 +1,37 @@ +_('Authenticate to server'), + 'body'=>_('You left the password blank.'), + 'type'=>'warn'), + sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST'))); + +if ($app['server']->login($user['login'],$user['password'],'user')) + system_message(array( + 'title'=>_('Authenticate to server'), + 'body'=>_('Successfully logged into server.'), + 'type'=>'info'), + sprintf('cmd.php?server_id=%s',get_request('server_id','REQUEST'))); +else + system_message(array( + 'title'=>_('Failed to Authenticate to server'), + 'body'=>_('Invalid Username or Password.'), + 'type'=>'error'), + sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST'))); +?> diff --git a/htdocs/login_form.php b/htdocs/login_form.php new file mode 100644 index 0000000..f16bdbf --- /dev/null +++ b/htdocs/login_form.php @@ -0,0 +1,98 @@ +%s %s',_('Authenticate to server'),$app['server']->getName()); +echo '
'; + +# Check for a secure connection +if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') { + echo '
'; + printf('%s: %s.', + _('You are not using \'https\'. Web browser will transmit login information in clear text.'), + _('Warning'),_('This web connection is unencrypted')); + echo '
'; + + echo '
'; +} + +# HTTP Basic Auth Form. +if ($app['server']->getAuthType() == 'http') { + ob_end_clean(); + + # When we pop up the basic athentication, we come back to this script, so try the login again. + if ($app['server']->isLoggedIn('user')) { + system_message(array( + 'title'=>_('Authenticate to server'), + 'body'=>_('Successfully logged into server.'), + 'type'=>'info'), + sprintf('cmd.php?server_id=%s&refresh=SID_%s',$app['server']->getIndex(),$app['server']->getIndex())); + + die(); + } + + header(sprintf('WWW-Authenticate: Basic realm="%s"',$_SESSION[APPCONFIG]->getValue('session','http_realm'))); + + if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') + header('HTTP/1.0 401 Unauthorized'); // http 1.0 method + else + header('Status: 401 Unauthorized'); // http 1.1 method + + return; + +# HTML Login Form +} else { + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + if (get_request('redirect','GET',false,false)) + printf('',rawurlencode(get_request('redirect','GET'))); + + echo '
'; + + echo ''; + + printf('', + $app['server']->getValue('login','auth_text') ? $app['server']->getValue('login','auth_text') : + ($app['server']->getValue('login','attr') == 'dn' ? _('Login DN') : $_SESSION[APPCONFIG]->getFriendlyName($app['server']->getValue('login','attr')))); + + printf('', + $app['server']->getValue('login','attr',false) == 'dn' ? $app['server']->getValue('login','bind_id') : ''); + + echo ''; + printf('',_('Password')); + echo ''; + echo ''; + + # If Anon bind allowed, then disable the form if the user choose to bind anonymously. + if ($app['server']->isAnonBindAllowed()) + printf('', + _('Anonymous')); + + printf('', + _('Authenticate')); + + echo '
%s:
 
%s:
 
%s
'; + echo '
'; + + echo '
'; + + echo ''; + + if ($app['server']->isAnonBindAllowed()) + printf('',JSDIR); +} +?> diff --git a/htdocs/logout.php b/htdocs/logout.php new file mode 100644 index 0000000..3c0e5eb --- /dev/null +++ b/htdocs/logout.php @@ -0,0 +1,29 @@ +logout()) { + unset($_SESSION['ACTIVITY'][$app['server']->getIndex()]); + + system_message(array( + 'title'=>_('Logout from Server'), + 'body'=>_('Successfully logged out of server.'), + 'type'=>'info'), + sprintf('index.php?server_id=%s',$app['server']->getIndex())); + +} else + system_message(array( + 'title'=>_('Failed to Logout of server'), + 'body'=>_('Please report this error to the admins.'), + 'type'=>'error'), + sprintf('index.php?server_id=%s',$app['server']->getIndex())); +?> diff --git a/htdocs/mass_delete.php b/htdocs/mass_delete.php new file mode 100644 index 0000000..4f91ae4 --- /dev/null +++ b/htdocs/mass_delete.php @@ -0,0 +1,147 @@ +_('No entry selected'), + 'body'=>_('No entry was selected to delete'), + 'type'=>'warn'),'index.php'); + +if (! is_array($request['dn'])) + $request['dn'] = array($request['dn']); + +$request['children'] = array(); +$request['parent'] = array(); +foreach ($request['dn'] as $dn) { + # Check if the entry exists. + if (! $dn || ! $app['server']->dnExists($dn)) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + # We search all children, not only the visible children in the tree + if (! in_array_ignore_case($dn,$request['children'])) { + $request['children'] = array_merge($request['children'],$app['server']->getContainerContents($dn,null,0,'(objectClass=*)',LDAP_DEREF_NEVER)); + array_push($request['parent'],$dn); + } +} + +printf('

%s

',_('Mass Delete')); +printf('

%s: %s

',_('Server'),$app['server']->getName()); +echo "\n"; + +echo '
'; +echo ''; + +if (count($request['parent']) == 1) + printf('',_('Are you sure you want to permanently delete this object?')); +else + printf('',_('Are you sure you want to permanently delete these objects?')); + +echo ''; +printf('',_('Server'),$app['server']->getName()); + +foreach ($request['parent'] as $dn) + printf('', + _('Distinguished Name'),_('DN'),$dn); + +echo ''; + +$request['delete'] = $request['parent']; + +if (count($request['children'])) { + printf('',_('Permanently delete all children also?')); + echo ''; + + # We need to see if the children have children + $query = array(); + $query['scope'] = 'sub'; + $query['attrs'] = array('dn'); + $query['size_limit'] = 0; + $query['deref'] = LDAP_DEREF_NEVER; + + $request['search'] = array(); + foreach ($request['children'] as $dn) { + $query['base'] = $dn; + $request['search'] = array_merge($request['search'],$app['server']->query($query,null)); + } + + foreach ($request['search'] as $value) + array_push($request['delete'],$value['dn']); + + echo ''; + echo ''; + + printf('', + sprintf(_('phpLDAPadmin can also recursively delete all %s of the child entries. See below for a list of all the entries that this action will delete. Do you want to do this?'),count($request['children']))); + + echo ''; + + printf('', + _('Note: this is potentially very dangerous and you do this at your own risk. This operation cannot be undone. Take into consideration aliases, referrals, and other things that may cause problems.')); + echo "\n"; + + echo ''; + + echo "\n"; + + printf('',_('List of entries to be deleted:')); + echo ''; + + $i = 0; + echo ''; + echo "\n"; + + echo ''; +} + +echo ''; +echo ''; + +echo ''; +echo ''; +echo "\n"; + +echo '
%s
%s
 
%s:%s
%s%s
 
%s
 
'; + printf(_('This request also includes %s children entries.'),count($request['children'])); + echo '
%s
 
%s
 
%s
 
'; + printf(''; + echo '
 
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +foreach ($request['parent'] as $dn) + printf('',htmlspecialchars($dn)); +printf('',sprintf(_('Delete all %s objects'),count($request['delete']))); +echo '
'; +echo '
'; + +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',_('Cancel')); +echo '
'; + +echo '
'; +echo '
'; + +echo '
'; +?> diff --git a/htdocs/mass_edit.php b/htdocs/mass_edit.php new file mode 100644 index 0000000..1ea7001 --- /dev/null +++ b/htdocs/mass_edit.php @@ -0,0 +1,133 @@ +dnExists($dn)) { + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + continue; + } + + $request['page'][$counter] = new MassRender($app['server']->getIndex(),'none'); + $request['page'][$counter]->setDN($dn); + $request['page'][$counter]->accept(true); + + $template = $request['page'][$counter]->getTemplate(); + + # Mark our attributes to edit as shown. + foreach ($template->getAttributes(true) as $attribute) { + if ($attribute->isInternal()) + continue; + + if (in_array_ignore_case($attribute->getName(),$request['attrs']) || in_array('*',$request['attrs'])) { + $attribute->show(); + + # Get a list of our columns (we are not interested in these attribute values) + if (! isset($attrcols[$attribute->getName()])) + $attrcols[$attribute->getName()] = $attribute; + } + } + + $counter++; +} + +usort($attrcols,'sortAttrs'); + +if (! count($request['page'])) + header('Location: index.php'); + +# We'll render this forms Title with the first DN's object. +$request['page'][0]->drawTitle(_('Bulk edit the following DNs')); +$request['page'][0]->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); + +foreach ($request['page'] as $j => $page) + printf('',$j,$page->getTemplate()->getDN()); + +echo '
'; + +echo ''; +echo ''; +echo ''; + +foreach ($attrcols as $attribute) { + echo ''; +} + +echo ''; + +$counter = 0; +foreach ($request['page'] as $j => $page) { + $template = $page->getTemplate(); + + printf('',$counter++%2==0?'even':'odd'); + printf('', + $template->getDN(),substr($template->getDN(),0,20)); + + foreach ($attrcols as $attrcol) { + $attribute = $template->getAttribute($attrcol->getName()); + + echo ''; + } + + echo ''; +} + +echo '
DN'; + $request['page'][0]->draw('Name',$attribute); + echo '
%s...'; + if ($attribute) { + foreach ($attribute->getValues() as $i => $val) + $page->draw('MassFormReadWriteValue',$attribute,$i,$j); + + # The attribute doesnt exist. If it is available by the shema, we can draw an empty input box. + } else { + $match = false; + + foreach ($template->getAvailAttrs() as $attribute) { + if ($attrcol->getName() == $attribute->getName()) { + $page->draw('MassFormReadWriteValue',$attribute,0,$j); + $match = true; + + break; + } + } + + if (! $match) + printf('
%s
', _('Attribute not available')); + } + + echo '
'; +echo '
'; +echo '
'; +printf('',_('Update Values')); +echo '
'; +echo '
'; +?> diff --git a/htdocs/mass_update.php b/htdocs/mass_update.php new file mode 100644 index 0000000..8a9dd01 --- /dev/null +++ b/htdocs/mass_update.php @@ -0,0 +1,175 @@ + $dn) { + # Check if the entry exists. + if (! $dn || ! $app['server']->dnExists($dn)) { + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + continue; + } + + # Simulate the requirements for *Render->accept() + if (! isset($request['mass_values'][$index])) + continue; + + $_REQUEST['new_values'] = $request['mass_values'][$index]; + + $render = new MassRender($app['server']->getIndex(),'none'); + $render->setDN($dn); + $render->accept(true); + + if ($render->getTemplate()->getLDAPmodify(false,$index)) + $request['update'][$index] = $render; +} + +# We can use the $render to give us a title +$render->drawTitle(_('Bulk update the following DNs')); +$render->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +if (count($request['update'])) { + if (get_request('confirm','REQUEST')) { + foreach ($request['update'] as $index => $page) { + $template = $page->getTemplate(); + + # Perform the modification + $result = $app['server']->modify($template->getDN(),$template->getLDAPmodify(false,$index)); + + if ($result) + printf('%s: %s
',$template->getDN(),_('Modification successful!')); + else + printf('%s: %s
',$template->getDN(),_('Modification NOT successful!')); + } + + } else { + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + foreach ($request['update'] as $j => $page) + printf('',$j,$page->getTemplate()->getDN()); + + echo ''; + echo ''; + echo '
'; + + echo '
'; + + echo ''; + echo ''; + echo '
'; + printf(_('There will be %s updates done with this mass update'),sprintf('%s',count($request['update']))); + echo '
'; + + echo '
'; + + foreach ($request['update'] as $index => $page) { + $template = $page->getTemplate(); + + echo ''; + echo ''; + printf('',IMGDIR,get_icon($app['server']->getIndex(),$template->getDN())); + + printf('', + $app['server']->getIndex(),rawurlencode(dn_unescape($template->getDN())),htmlspecialchars(get_rdn($template->getDN()))); + echo ''; + + printf('', + htmlspecialchars(dn_unescape($template->getDN())),_('Old Value')); + + foreach ($template->getLDAPmodify(true,$index) as $attribute) { + echo ''; + echo ''; + + echo ''; + + # Show NEW Values + echo ''; + + # Show OLD Values + echo ''; + + echo ''; + } + + echo '
icon%s
 dn%s%s
 '; + $page->draw('Name',$attribute); + echo ''; + + if (! $attribute->getValueCount() || $attribute->isForceDelete()) { + printf('[%s]',_('attribute deleted')); + printf('',$index,$attribute->getName(),0,''); + } + + foreach ($attribute->getValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ((count($attribute->getValues()) > 5) && in_array($value,$attribute->getAddedValues())) + echo ''; + + $page->draw('CurrentValue',$attribute,$key); + + # For multiple values, close the highlighting + if ((count($attribute->getValues()) > 5) && in_array($value,$attribute->getAddedValues())) + echo ''; + + echo '
'; + printf('',$index,$attribute->getName(),$key,$value); + } + + echo '
'; + + if (! $attribute->getOldValues()) + printf('[%s]',_('attribute doesnt exist')); + + foreach ($attribute->getOldValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ((count($attribute->getOldValues()) > 5) && in_array($value,$attribute->getRemovedValues()) && count($attribute->getValues())) + echo ''; + + $page->draw('OldValue',$attribute,$key); + + # For multiple values, close the highlighting + if ((count($attribute->getOldValues()) > 5) && in_array($value,$attribute->getRemovedValues()) && count($attribute->getValues())) + echo ''; + + echo '
'; + } + + echo '
'; + + echo '
'; + } + + echo '
'; + printf('',_('Update Values')); + echo '
'; + } + +} else { + echo '
'; + echo _('You made no changes'); + echo '
'; +} +?> diff --git a/htdocs/modify_member_form.php b/htdocs/modify_member_form.php new file mode 100644 index 0000000..208b9ef --- /dev/null +++ b/htdocs/modify_member_form.php @@ -0,0 +1,178 @@ +getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +if (! is_null($request['dn'])) + $rdn = get_rdn($request['dn']); +else + $rdn = null; + +# Get all current group members +$current_members = $app['server']->getDNAttrValue($request['dn'],$request['attr']); +usort($current_members,'pla_compare_dns'); + +# Loop through all base dn's and search possible member entries +$query = array(); + +# Get all entries that can be added to the group +if (preg_match("/^".$request['attr']."$/i",$_SESSION[APPCONFIG]->getValue('modify_member','posixgroupattr'))) { + $query['filter'] = $_SESSION[APPCONFIG]->getValue('modify_member','posixfilter'); + $attr = $_SESSION[APPCONFIG]->getValue('modify_member','posixattr'); + +} else { + $query['filter'] = $_SESSION[APPCONFIG]->getValue('modify_member','filter'); + $attr = $_SESSION[APPCONFIG]->getValue('modify_member','attr'); +} + +$query['attrs'] = array($attr); + +$possible_values = array(); +foreach ($app['server']->getBaseDN() as $base) { + $query['base'] = $base; + + $possible_values = array_merge($possible_values,$app['server']->query($query,null)); +} + +usort($possible_values,'pla_compare_dns'); + +$request['page']->drawTitle(sprintf('%s %s',_('Modify group'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('%s %s %s %s:', + _('There are'),count($current_members),_('members in group'),htmlspecialchars(get_rdn($request['dn']))); + +$possible_members = array(); +for ($i=0;$igetValue('modify_member','posixgroupattr'))) + $possible_members[$i] = $possible_values[$i][$_SESSION[APPCONFIG]->getValue('modify_member','posixattr')][0]; + else + $possible_members[$i] = $possible_values[$i][$_SESSION[APPCONFIG]->getValue('modify_member','attr')]; +} + +# Show only user that are not already in group. +$possible_members = array_diff($possible_members,$current_members); +usort($possible_members,'pla_compare_dns'); + +/* Draw form with select boxes, left for all possible members and + * right one for those that belong to group */ + +# Modifications will be sent to update_confirm which takes care of rest of the processing +echo '
'; +echo '
'; + +echo '
'; +echo '
'; +if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; +else + echo ''; +echo '
'; + +echo ''; + +echo ''; +printf('',IMGDIR,_('Available members')); +printf('',IMGDIR,_('Group members')); +echo ''; + +# Generate select box from all possible members +echo ''; +echo ''; + +# Generate select box from all current members +echo ''; + +echo ''; + +# Show buttons which move users from left to right and vice versa +echo ''; +echo ''; +echo ''; +echo ''; + +echo ''; + +echo '
Users %sMembers %s
'; +echo ''; +echo ''; +echo ''; +echo '
'; +printf(' ', + _('Add selected'),_('Add all')); +echo ''; +printf(' ', + _('Remove selected'),('Remove all')); +echo '
'; + +# Hidden attributes for update_confirm.php +printf('',$app['server']->getIndex()); +printf('',rawurlencode($request['dn'])); +printf('',$request['attr']); + +/* Generate array of input text boxes from current members. + * update_confirm.php will see this as old_values[member-attribute][item] */ +for ($i=0; $i', + htmlspecialchars($request['attr']),$i,htmlspecialchars($current_members[$i])); + +/* Javascript generates array of input text boxes from new members. + * update_confirm.php will see this as new_values[member-attribute][item] + * Input text boxes will be generated to div=dnu */ +echo '
'; +printf('',htmlspecialchars($request['attr'])); +echo '
'; + +# Submit values to update_confirm.php and when clicked, run addSelected +printf('',_('Save changes'),$request['attr']); +echo '
'; +echo '
'; +printf('',JSDIR); +?> diff --git a/htdocs/monitor.php b/htdocs/monitor.php new file mode 100644 index 0000000..51ac392 --- /dev/null +++ b/htdocs/monitor.php @@ -0,0 +1,259 @@ +getRootDSE(); + +$query = array(); +$query['base'] = $attrs['monitorcontext'][0]; +$query['scope'] = 'sub'; +$query['attrs'] = array('+','*'); +$results = $app['server']->query($query,null); + +if (! isset($attrs['monitorcontext']) || ! count($results)) + system_message(array( + 'title'=>_('Monitoring context does not exist'), + 'body'=>sprintf('%s: %s',_('Could not obtain the monitor context for this server'),$app['server']->getName()), + 'type'=>'warn'),'index.php'); + +printf('

%s%s

',_('Monitor info for: '),$app['server']->getName()); +printf('

%s

',_('Server reports the following information about itself')); + +echo ''; + +# cn=Monitor +printf('',_('LDAP Server')); +printf(''; + +foreach (array( + 'cn=Backends,cn=Monitor' => 'cn=Backend %s,%s', + 'cn=Overlays,cn=Monitor' => 'cn=Overlay %s,%s' + ) as $dn => $child) { + + if (isset($results[$dn]['description'])) { + $description = implode(' ',$results[$dn]['description']); + + $description = preg_replace('/"/','\'',$description); + } else { + $description = ''; + } + + printf('',$description,$dn); + echo ''; +} + +# cn=Connections,cn=Monitor +printf('',$results['cn=Connections,cn=Monitor']['description'],_('LDAP Connections')); +printf(''; + +foreach (array( + 'cn=Listeners,cn=Monitor', + 'cn=Log,cn=Monitor', + 'cn=Operations,cn=Monitor', + 'cn=SASL,cn=Monitor', + 'cn=TLS,cn=Monitor', + 'cn=Statistics,cn=Monitor', + 'cn=Threads,cn=Monitor', + 'cn=Time,cn=Monitor', + 'cn=Waiters,cn=Monitor' + ) as $dn ) { + + $description = implode(' ',$results[$dn]['description']); + $description = preg_replace('/"/','\'',$description); + + printf('',$description,$dn); + echo ''; +} + +echo '
%s
'); + +echo ''; +printf('',$results[$attrs['monitorcontext'][0]]['monitoredinfo'][0]); +echo '
%s
'; + +echo '
%s
'; + echo ''; + echo '
'; + echo ''; + + $attrs = array( + 'monitorruntimeconfig', + 'supportedcontrol' + ); + + echo ''; + printf('',_('Type'),'namingContext'); + + foreach ($attrs as $attr) + printf('',$attr); + + echo ''; + + $counter = 0; + foreach ($results[$dn]['monitoredinfo'] as $index => $backend) { + printf('',$counter++%2==0?'even':'odd'); + printf('',$backend); + + $key = sprintf($child,$index,$dn); + + echo ''; + + foreach ($attrs as $attr) { + echo ''; + } + echo ''; + } + + echo '
%s%s%s
%s'; + if (isset($results[$key]['seealso'])) { + $seealso = is_array($results[$key]['seealso']) ? $results[$key]['seealso'] : array($results[$key]['seealso']); + + foreach ($seealso as $db) + if (isset($results[$db]['namingcontexts'])) + printf('%s
', + isset($results[$db]['labeleduri']) ? implode(' ',$results[$db]['labeleduri']) : _('Internal'), + implode(' ',$results[$db]['namingcontexts'])); + else + printf('%s ',implode(' ',$results[$db]['monitoredinfo'])); + + } else { + echo ' '; + } + echo '
'; + if (isset($results[$key][$attr])) { + if (! is_array($results[$key][$attr])) + $sc = array($results[$key][$attr]); + else + $sc = $results[$key][$attr]; + + if (strcasecmp('supportedcontrol',$attr) == 0) + foreach ($sc as $control) { + $oidtotext = support_oid_to_text($control); + + printf('%s
', + $control,$oidtotext['title']); + } + + else + printf('%s ',implode('
',$sc)); + + } else { + echo ' '; + } + + echo '
'; + echo '
%s
'); +echo ''; +echo '
'; +echo ''; + +printf('', + _('Total Connections'),$results['cn=Total,cn=Connections,cn=Monitor']['monitorcounter']); +printf('', + _('Current Connections'),$results['cn=Current,cn=Connections,cn=Monitor']['monitorcounter']); + +# Look for some connections +foreach ($results as $key => $value) { + if (preg_match('/^cn=Connection.*,cn=Connections,cn=Monitor$/',$key)) { + echo ''; + printf('',$results[$key]['cn'][0]); + + echo ''; + echo ''; + } +} + +echo '
%s%s
%s%s
%s'; + echo ''; + + $counter = 0; + foreach (array( + 'monitorconnectionactivitytime', + 'monitorconnectionauthzdn', + 'monitorconnectionget', + 'monitorconnectionlistener', + 'monitorconnectionlocaladdress', + 'monitorconnectionmask', + 'monitorconnectionnumber', + 'monitorconnectionopscompleted', + 'monitorconnectionopsexecuting', + 'monitorconnectionopspending', + 'monitorconnectionopsreceived', + 'monitorconnectionpeeraddress', + 'monitorconnectionpeerdomain', + 'monitorconnectionprotocol', + 'monitorconnectionread', + 'monitorconnectionstarttime', + 'monitorconnectionwrite' + ) as $metric) { + + printf('',$counter++%2==0?'even':'odd'); + + printf('', + $metric,isset($results[$key][$metric]) ? $results[$key][$metric][0] : ' '); + echo ''; + } + + echo '
%s%s
'; + echo '
'; +echo '
%s
'; + echo ''; + echo '
'; + echo ''; + + if (isset($results[$dn]['monitoropinitiated'])) + printf('', + 'monitorOpInitiated',$results[$dn]['monitoropinitiated'][0]); + if (isset($results[$dn]['monitoropcompleted'])) + printf('', + 'monitorOpCompleted',$results[$dn]['monitoropcompleted'][0]); + if (isset($results[$dn]['monitoredinfo'])) + printf('', + 'monitoredInfo',$results[$dn]['monitoredinfo'][0]); + + # Look for some connecitons + foreach ($results as $key => $value) { + if (preg_match('/^.*,'.$dn.'$/',$key)) { + echo ''; + printf('',$results[$key]['cn'][0]); + + echo ''; + echo ''; + } + } + echo '
%s%s
%s%s
%s%s
%s'; + echo ''; + + foreach (array( + 'labeleduri', + 'monitorconnectionlocaladdress', + 'monitoredinfo', + 'monitorcounter', + 'monitoropinitiated', + 'monitoropcompleted', + 'monitortimestamp' + ) as $metric) { + + if (isset($results[$key][$metric])) { + printf('',$counter++%2==0?'even':'odd'); + + printf('', + $metric,$results[$key][$metric][0]); + + echo ''; + } + } + + echo '
%s%s
'; + echo '
'; + echo '
'; +?> diff --git a/htdocs/password_checker.php b/htdocs/password_checker.php new file mode 100644 index 0000000..c616e2e --- /dev/null +++ b/htdocs/password_checker.php @@ -0,0 +1,88 @@ +%s',_('Password Checker Tool')); + +echo '
'; +echo ''; +printf('',$request['attribute']); + +echo ''; + +echo ''; +printf('',_('Compare')); +printf('', + (obfuscate_password_display($request['enc_type']) ? 'password' : 'text'),htmlspecialchars($request['hash'])); +echo ''; + +echo ''; +printf('',_('To')); +printf('', + htmlspecialchars($request['password'])); +echo ''; + +echo ''; +echo ''; + +echo ''; +echo ''; +echo '
%s
%s
 '; + +if ($request['action'] == 'compare') { + echo '    '; + + if (password_check($request['hash'],$request['password'],$request['attribute'])) + printf('%s',_('Passwords match!')); + else + printf('%s',_('Passwords do not match!')); + + echo ''; +} + +echo '
'; +echo '
'; + +# Pull our password from the form that opened this window. +if ($request['componentid']) { + echo ''; +} + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +# Render the popup. +$www['page']->display(array('CONTROL'=>false,'FOOT'=>false,'HEAD'=>false,'TREE'=>false)); +?> diff --git a/htdocs/purge_cache.php b/htdocs/purge_cache.php new file mode 100644 index 0000000..339fe73 --- /dev/null +++ b/htdocs/purge_cache.php @@ -0,0 +1,33 @@ +_('Purge cache'), + 'body'=>$body, + 'type'=>'info'), + get_request('meth','REQUEST') == 'ajax' ? null : 'index.php'); +?> diff --git a/htdocs/query_engine.php b/htdocs/query_engine.php new file mode 100644 index 0000000..a94fedd --- /dev/null +++ b/htdocs/query_engine.php @@ -0,0 +1,19 @@ +getIndex(),get_request('query','REQUEST',false,null)); +$request['page']->accept(); +?> diff --git a/htdocs/rdelete.php b/htdocs/rdelete.php new file mode 100644 index 0000000..bb864a9 --- /dev/null +++ b/htdocs/rdelete.php @@ -0,0 +1,89 @@ +dnExists($dn)) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s)',_('Unable to delete entry, it does not exist'),$dn), + 'type'=>'error')); + else + array_push($request['parent'],$dn); + +printf('

%s

',_('Delete LDAP entries')); +printf('

%s

',_('Recursive delete progress')); + +# Prevent script from bailing early on a long delete +@set_time_limit(0); + +foreach ($request['parent'] as $dn) { + echo '

'; + echo ''; + $result = pla_rdelete($app['server'],$dn); + echo '
'; + + if ($result) { + printf(_('Entry %s and sub-tree deleted successfully.'),''.$dn.''); + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($request['dn'])), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); + } +} + +function pla_rdelete($server,$dn) { + # We delete all children, not only the visible children in the tree + $children = $server->getContainerContents($dn,null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + + if (! is_array($children) || count($children) == 0) { + printf('%s %s...',_('Deleting'),$dn); + + if ($server->delete($dn)) { + printf(' %s
',_('Success')); + return true; + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($dn)), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + } + + } else { + foreach ($children as $child_dn) + pla_rdelete($server,$child_dn); + + printf('%s %s...',_('Deleting'),$dn); + + if ($server->delete($dn)) { + printf(' %s
',_('Success')); + return true; + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($dn)), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + } + } +} +?> diff --git a/htdocs/refresh.php b/htdocs/refresh.php new file mode 100644 index 0000000..385c4c6 --- /dev/null +++ b/htdocs/refresh.php @@ -0,0 +1,46 @@ +getIndex(),'tree'); + del_cached_item($app['server']->getIndex(),'tree'); + + if ($tree) + $openDNs = $tree->listOpenItems(); + else + $openDNs = array(); + + $tree = Tree::getInstance($app['server']->getIndex()); + + foreach ($openDNs as $value) { + $entry = $tree->getEntry($value); + if (! $entry) { + $tree->addEntry($value); + $entry = $tree->getEntry($value); + } + + $tree->readChildren($value,true); + $entry->open(); + } + + set_cached_item($app['server']->getIndex(),'tree','null',$tree); +} + +if (get_request('meth','REQUEST') == 'ajax') + header(sprintf('Location: cmd.php?cmd=draw_tree_node&noheader=%s&server_id=%s&meth=ajax&frame=TREE',get_request('noheader','REQUEST',false,0),$app['server']->getIndex())); +else + header(sprintf('Location: cmd.php?server_id=%s',$app['server']->getIndex())); + +die(); +?> diff --git a/htdocs/rename.php b/htdocs/rename.php new file mode 100644 index 0000000..96c2e33 --- /dev/null +++ b/htdocs/rename.php @@ -0,0 +1,64 @@ +getContainer($request['dnSRC']); + +# Error checking +if (! $app['server']->isBranchRenameEnabled()) { + # We search all children, not only the visible children in the tree + $children = $app['server']->getContainerContents($request['dnSRC'],null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + + if (count($children) > 0) + error(_('You cannot rename an entry which has children entries (eg, the rename operation is not allowed on non-leaf entries)'),'error','index.php'); +} + +$request['dnDST'] = sprintf('%s,%s',$request['rdnDST'],$request['container']); + +if ($request['dnDST'] == $request['dnSRC']) + error(_('You did not change the RDN'),'error','index.php'); + +$rdnattr = array(); +$rdnattr['SRC'] = explode('=',$request['dnSRC']); +$rdnattr['SRC'] = $rdnattr['SRC'][0]; + +$new_dn_value = explode('=',$request['rdnDST'],2); +$rdnattr['DST'] = $new_dn_value[0]; + +if (count($new_dn_value) != 2 || ! isset($new_dn_value[1])) + error(_('Invalid RDN value'),'error','index.php'); + +$deleteoldrdn = $rdnattr['SRC'] == $rdnattr['DST']; +$success = $app['server']->rename($request['dnSRC'],$request['rdnDST'],$request['container'],$deleteoldrdn); + +if ($success) { + $rename_message = sprintf('%s',_('Rename successful!')); + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&template=%s', + $app['server']->getIndex(),rawurlencode($request['dnDST']),get_request('template','REQUEST')); + + system_message(array( + 'title'=>_('Rename Entry'), + 'body'=>$rename_message, + 'type'=>'info'), + $redirect_url); + +} else { + system_message(array( + 'title'=>_('Could not rename the entry.'), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); +} +?> diff --git a/htdocs/rename_form.php b/htdocs/rename_form.php new file mode 100644 index 0000000..aebc5fb --- /dev/null +++ b/htdocs/rename_form.php @@ -0,0 +1,40 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Rename'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +echo '
'; +printf('%s %s %s:

',_('Rename'),get_rdn($request['dn']),_('to a new object')); + +echo '
'; +printf('',$app['server']->getIndex()); +printf('',rawurlencode($request['dn'])); +printf('',$request['template']); +printf('',get_rdn($request['dn'])); +printf('',_('Rename')); +echo '
'; + +echo '
'; +echo "\n"; +?> diff --git a/htdocs/schema.php b/htdocs/schema.php new file mode 100644 index 0000000..aa4a749 --- /dev/null +++ b/htdocs/schema.php @@ -0,0 +1,640 @@ +%s.

%s
  • %s
  • %s
  • %s
  • %s
', + _('Could not retrieve schema from'),$app['server']->getName(), + _('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.'),_('phpLDAPadmin doesn\'t know how to fetch the schema for your server.'), + _('Or lastly, your LDAP server doesnt provide this information.')); + +printf('

%s %s

',_('Schema for server'),$app['server']->getName()); + +$entry['schema_types'] = array( + 'objectclasses'=>_('ObjectClasses'), + 'attributes'=>_('Attribute Types'), + 'syntaxes'=>_('Syntaxes'), + 'matching_rules'=>_('Matching Rules')); + +echo '
'; +echo '
'; + +$counter = 0; +foreach ($entry['schema_types'] as $item => $value) { + if ($counter++) + echo ' | '; + + $entry['href'][$item] = sprintf('cmd=schema&server_id=%s&view=%s',$app['server']->getIndex(),$item); + + if ($entry['view'] == $item) { + echo _($value); + + } else { + if (isAjaxEnabled()) + printf('%s', + htmlspecialchars($entry['href'][$item]),htmlspecialchars($entry['href'][$item]),$value,$value,$value); + else + printf('%s',htmlspecialchars($entry['href'][$item]),_($value)); + } +} + +echo '
'; +echo '
'; + +switch($entry['view']) { + case 'syntaxes': + $highlight_oid = get_request('highlight_oid','GET',false,false); + + echo ''; + printf('',_('Syntax OID'),_('Description')); + + $counter = 1; + + $schema_syntaxes = $app['server']->SchemaSyntaxes(); + if (! $schema_syntaxes) + error($schema_error_str,'error','index.php'); + + foreach ($schema_syntaxes as $syntax) { + $counter++; + $oid = $syntax->getOID(); + $desc = $syntax->getDescription(); + + if ($highlight_oid && $highlight_oid == $oid) + echo ''; + + else + printf('',$counter%2==0?'even':'odd'); + + printf('',$oid,$desc); + } + + echo '
%s%s
%s%s
'; + break; + + case 'attributes': + $entry['attr_types'] = array( + 'desc' => _('Description'), + 'obsolete' => _('Obsolete'), + 'inherits' => _('Inherits from'), + 'equality' => _('Equality'), + 'ordering' => _('Ordering'), + 'substring_rule' => _('Substring Rule'), + 'syntax' => _('Syntax'), + 'single_valued' => _('Single Valued'), + 'collective' => _('Collective'), + 'user_modification' => _('User Modification'), + 'usage' => _('Usage'), + 'maximum_length' => _('Maximum Length'), + 'aliases' => _('Aliases'), + 'used_by_objectclasses' => _('Used by objectClasses'), + 'force_as_may' => _('Force as MAY by config') + ); + + $sattrs = $app['server']->SchemaAttributes(); + + if (! $sattrs || ! $app['server']->SchemaObjectClasses()) + error($schema_error_str,'error','index.php'); + + printf('%s:',_('Jump to an attribute type')); + echo '
'; + echo '
'; + echo ''; + printf('',$entry['view']); + printf('',$app['server']->getIndex()); + + if (isAjaxEnabled()) { + drawJSItems($sattrs); + echo ''; + + echo ''; + foreach ($sattrs as $name => $attr) + printf('', + $name,$name == $entry['value'] ? 'selected="selected" ': '',$attr->getName(false)); + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + foreach ($sattrs as $attr) { + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$attr->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$attr->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (isAjaxEnabled() && $entry['value']) + printf('
',$attr->getName(),strcasecmp($entry['value'],$attr->getName()) ? 'none' : 'block'); + else + printf('
',$attr->getName()); + + echo ''; + printf('', + $attr->getName(),$attr->getName(false)); + + $counter = 0; + + foreach ($entry['attr_types'] as $item => $value) { + + printf('',++$counter%2 ? 'odd' : 'even'); + printf('',$value); + + switch ($item) { + case 'desc': + printf('', + is_null($attr->getDescription()) ? + '('._('no description').')' : $attr->getDescription()); + + echo ''; + printf('',++$counter%2 ? 'odd' : 'even'); + echo ''; + printf('',$attr->getOID()); + + break; + + case 'obsolete': + printf('',$attr->getIsObsolete() ? ''._('Yes').'' : _('No')); + break; + + case 'inherits': + echo ''; + break; + + case 'equality': + echo ''; + break; + + case 'ordering': + printf('', + is_null($attr->getOrdering()) ? '('._('not specified').')' : $attr->getOrdering()); + break; + + case 'substring_rule': + printf('', + is_null($attr->getSubstr()) ? '('._('not specified').')' : $attr->getSubstr()); + break; + + case 'syntax': + echo ''; + break; + + case 'single_valued': + printf('',$attr->getIsSingleValue() ? _('Yes') : _('No')); + break; + + case 'collective': + printf('',$attr->getIsCollective() ? _('Yes') : _('No')); + break; + + case 'user_modification': + printf('',$attr->getIsNoUserModification() ? _('No') : _('Yes')); + break; + + case 'usage': + printf('',$attr->getUsage() ? $attr->getUsage() : '('._('not specified').')'); + break; + + case 'maximum_length': + echo ''; + break; + + case 'aliases': + echo ''; + break; + + case 'used_by_objectclasses': + echo ''; + break; + + case 'force_as_may': + printf('',$attr->isForceMay() ? _('Yes') : _('No')); + break; + + } + echo ''; + } + echo '
%s
%s%s
OID%s%s'; + + if (is_null($attr->getSupAttribute())) + printf('(%s)',_('none')); + + else { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],strtolower($attr->getSupAttribute()))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($attr->getSupAttribute()),$attr->getSupAttribute()); + else + printf('%s',$href,$attr->getSupAttribute()); + } + + echo ''; + + if (is_null($attr->getEquality())) + printf('(%s)',_('not specified')); + + else { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['matching_rules'],$attr->getEquality())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Matching Rules'),$attr->getEquality(),$attr->getEquality()); + else + printf('%s',$href,$attr->getEquality()); + } + + echo '%s%s'; + + if (is_null($attr->getType())) { + echo $attr->getSyntaxOID(); + + } else { + $href = htmlspecialchars(sprintf('%s&highlight_oid=%s',$entry['href']['syntaxes'],$attr->getSyntaxOID())); + if (isAjaxEnabled()) + printf('%s (%s)', + $href,$href,_('Syntaxes'),'',$attr->getType(),$attr->getSyntaxOID()); + else + printf('%s (%s)',$href,$attr->getType(),$attr->getSyntaxOID()); + } + + echo '%s%s%s%s'; + + if ( is_null($attr->getMaxLength())) + echo '('._('not applicable').')'; + + else + printf('%s %s',number_format($attr->getMaxLength()), + $attr->getMaxLength()>1 ? _('characters') : _('character')); + + echo ''; + + if (count($attr->getAliases()) == 0) + printf('(%s)',_('none')); + + else + foreach ($attr->getAliases() as $alias) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],strtolower($alias))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($alias),$alias); + else + printf('%s',$href,$alias); + } + + echo ''; + + if (count($attr->getUsedInObjectClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($attr->getUsedInObjectClasses() as $objectclass) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($objectclass))); + if (isAjaxEnabled()) + printf('%s ', + $href,$href,_('ObjectClasses'),strtolower($objectclass),$objectclass); + else + printf('%s ',$href,$objectclass); + } + + echo '%s
'; + echo '
'; + echo '
'; + } + } + + break; + + case 'matching_rules': + $schema_matching_rules = $app['server']->MatchingRules(); + if (! $schema_matching_rules) + error($schema_error_str,'error','index.php'); + + printf('%s
',_('Jump to a matching rule')); + + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + if (isAjaxEnabled()) { + drawJSItems($schema_matching_rules); + echo ''; + + echo ''; + foreach ($schema_matching_rules as $rule) + printf('', + $rule->getName(), + ($rule->getName() == $entry['value'] ? 'selected="selected"': ''), + $rule->getName(false)); + + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + echo ''; + printf('', + _('Matching Rule OID'),_('Name'),_('Used by Attributes')); + + $counter = 1; + + foreach ($schema_matching_rules as $rule) { + $counter++; + $oid = $rule->getOID(); + $desc = $rule->getName(false); + + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$rule->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$rule->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (null != $rule->getDescription()) + $desc .= sprintf(' (%s)',$rule->getDescription()); + + if ( $rule->getIsObsolete()) + $desc .= sprintf(' %s',_('Obsolete')); + + if (isAjaxEnabled() && $entry['value']) + printf('',$counter%2 ? 'odd' : 'even',$rule->getName(), + strcasecmp($entry['value'],$rule->getName()) ? 'none' : ''); + else + printf('',$counter%2 ? 'odd' : 'even',$rule->getName()); + printf('',$oid); + printf('',$desc); + + echo ''; + echo ''; + } + } + + echo '
%s%s%s
%s%s'; + + if (count($rule->getUsedByAttrs()) == 0) { + printf('
(%s)


',_('none')); + + } else { + echo '
'; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + printf('
'; + + if (isAjaxEnabled()) + printf('', + _('Go'),$app['server']->getIndex(),_('Attributes'),$rule->getName()); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + } + echo '
'; + break; + + case 'objectclasses': + $socs = $app['server']->SchemaObjectClasses(); + if (! $socs) + error($schema_error_str,'error','index.php'); + + printf('%s:',_('Jump to an objectClass')); + + echo '
'; + echo '
'; + echo ''; + printf('',$entry['view']); + printf('',$app['server']->getIndex()); + + if (isAjaxEnabled()) { + drawJSItems($socs); + echo ''; + + echo ''; + foreach ($socs as $name => $oclass) + printf('', + $name,$name == $entry['value'] ? 'selected="selected" ': '',$oclass->getName(false)); + + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + foreach ($socs as $name => $oclass) { + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$oclass->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$oclass->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (isAjaxEnabled() && $entry['value']) + printf('
',$oclass->getName(),strcasecmp($entry['value'],$oclass->getName()) ? 'none' : ''); + else + printf('
',$oclass->getName()); + + echo ''; + printf('',$name,$oclass->getName(false)); + printf('',_('OID'),$oclass->getOID()); + + if ($oclass->getDescription()) + printf('',_('Description'),$oclass->getDescription()); + + printf('',_('Type'),$oclass->getType()); + + if ($oclass->getIsObsolete()) + printf('',_('This objectClass is obsolete.')); + + printf(''; + + printf(''; + + printf('', + _('Required Attributes'),_('Optional Attributes')); + + echo ''; + echo ''; + echo ''; + echo ''; + echo '
%s
%s: %s
%s: %s
%s: %s
%s
%s: ',_('Inherits from')); + if (count($oclass->getSupClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($oclass->getSupClasses() as $i => $object_class) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($object_class))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($object_class),$object_class); + else + printf('%s', + $href,$object_class,_('Jump to this objectClass definition'),$object_class); + + if ($i < count($oclass->getSupClasses()) - 1) + echo ', '; + } + echo '
%s: ',_('Parent to')); + if (strcasecmp($oclass->getName(),'top') == 0) { + $href = htmlspecialchars($entry['href']['objectclasses']); + if (isAjaxEnabled()) + printf('all', + $href); + else + printf('(all)',$href); + + } elseif (count($oclass->getChildObjectClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($oclass->getChildObjectClasses() as $i => $object_class) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($object_class))); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($object_class),$object_class); + else + printf('%s',$href,_('Jump to this objectClass definition'),$object_class); + + if ( $i < count($oclass->getChildObjectClasses()) - 1) + echo ', '; + } + echo '
 %s%s 
'; + + if ($attrs = $oclass->getMustAttrs(true)) { + echo '
    '; + + foreach ($attrs as $attr) { + echo '
  • '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],$attr->getName())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Attributes'),$attr->getName(),$attr->getName(false)); + else + printf('%s',$href,$attr->getName(false)); + + if ($attr->getSource() != $oclass->getName(false)) { + echo '
    '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($attr->getSource()))); + printf('(%s ',_('Inherited from')); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($attr->getSource()),$attr->getSource()); + else + printf('%s',$href,$attr->getSource()); + echo ')'; + } + echo '
  • '; + } + echo '
'; + + } else + printf('(%s)',_('none')); + + echo '
'; + + if ($attrs = $oclass->getMayAttrs(true)) { + echo '
    '; + + foreach ($attrs as $attr) { + echo '
  • '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],$attr->getName())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Attributes'),$attr->getName(),$attr->getName(false)); + else + printf('%s',$href,$attr->getName(false)); + + if ($attr->getSource() != $oclass->getName(false)) { + echo '
    '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($attr->getSource()))); + printf('(%s ',_('Inherited from')); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($attr->getSource()),$attr->getSource()); + else + printf('%s',$href,$attr->getSource()); + echo ')'; + } + + if ($oclass->isForceMay($attr->getName())) { + echo '
    '; + printf('%s',_('This attribute has been forced as a MAY attribute by the configuration')); + } + echo '
  • '; + } + echo '
'; + + } else + printf('(%s)',_('none')); + + echo '
'; + echo '
'; + echo '
'; + } + } + break; +} + +if (! is_null($entry['value']) && ! $entry['viewed']) + error(sprintf(_('No such schema item: "%s"'),$entry['value']),'error','index.php'); + +function drawJSItems($object) { + echo ''; +} +?> diff --git a/htdocs/server_info.php b/htdocs/server_info.php new file mode 100644 index 0000000..222b912 --- /dev/null +++ b/htdocs/server_info.php @@ -0,0 +1,89 @@ +getRootDSE(); + +printf('

%s%s

',_('Server info for: '),$app['server']->getName()); +printf('

%s

',_('Server reports the following information about itself')); + +if (! count($attrs)) { + echo '

'; + printf('
%s
',_('This server has nothing to report.')); + return; +} + +echo ''; +foreach ($attrs as $key => $values) { + if ($key == 'dn') + continue; + + echo ''; + + echo ''; +} +echo '
'; + + $sattr = $app['server']->getSchemaAttribute($key); + + if ($sattr && $_SESSION[APPCONFIG]->isCommandAvailable('script','schema') && $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link')) { + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s',$app['server']->getIndex(),$sattr->getName()); + printf('%s', + $href,_('Click to view the schema definition for attribute type'),$sattr->getName(false),$sattr->getName(false)); + + } else + echo $key; + + echo '
 '; + echo ''; + + if (is_array($values)) + foreach ($values as $value) { + $oidtext = ''; + print ''; + + if (preg_match('/^[0-9]+\.[0-9]+/',$value)) { + printf('', + IMGDIR,$value,htmlspecialchars($value)); + + if ($oidtext = support_oid_to_text($value)) + if (isset($oidtext['ref'])) + printf('',$oidtext['ref'],$oidtext['title']); + else + printf('',$oidtext['title']); + + else + if (strlen($value) > 0) + printf('',$value); + + } else { + printf('',$value); + } + + print ''; + + if (isset($oidtext['desc']) && trim($oidtext['desc'])) + printf('',$oidtext['desc']); + else + echo ''; + + if ($oidtext) + echo ''; + } + + else + printf('',$values); + + + echo '
%s%s%s%s%s
%s
 
 
%s 
'; + echo '
'; +?> diff --git a/htdocs/show_cache.php b/htdocs/show_cache.php new file mode 100644 index 0000000..5ce6cd3 --- /dev/null +++ b/htdocs/show_cache.php @@ -0,0 +1,101 @@ +getValue('appearance','hide_debug_info')) { + echo '
    '; + + foreach (array_keys($request['dumpvar']) as $key) { + if ((in_array($key,array('cache'))) && is_array($request['dumpvar'][$key])) + foreach (array_keys($request['dumpvar'][$key]) as $server) { + foreach (array_keys($request['dumpvar'][$key][$server]) as $x) { + $index = sprintf('%s:%s',$server,$x); + + printf('
  • %s
  • ', + $key.$index,$key,$index,$key.'.'.$index,$key.$index,$key.$index); + } + } + else + printf('
  • %s
  • ', + $key,$key,$key,$key); + } + echo '
'; +} +?> + + diff --git a/htdocs/template_engine.php b/htdocs/template_engine.php new file mode 100644 index 0000000..1cfaba9 --- /dev/null +++ b/htdocs/template_engine.php @@ -0,0 +1,57 @@ +getIndex(),get_request('template','REQUEST',false,null)); + +# If we have a DN, then this is to edit the entry. +if ($request['dn']) { + $app['server']->dnExists($request['dn']) + or error(sprintf('%s (%s)',_('No such entry'),pretty_print_dn($request['dn'])),'error','index.php'); + + $request['page']->setDN($request['dn']); + $request['page']->accept(); + +} else { + if ($app['server']->isReadOnly()) + error(_('You cannot perform updates while server is in read-only mode'),'error','index.php'); + + $request['page']->setContainer(get_request('container','REQUEST')); + $request['page']->accept(); +} +?> diff --git a/htdocs/update.php b/htdocs/update.php new file mode 100644 index 0000000..45762cf --- /dev/null +++ b/htdocs/update.php @@ -0,0 +1,78 @@ +getIndex(),rawurlencode($request['dn']))); + + die(); +} + +if (! $request['dn'] || ! $app['server']->dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +# Perform the modification +$result = $app['server']->modify($request['dn'],$request['template']->getLDAPmodify()); + +if ($result) { + # Fire the post modification event to the user's custom callback function. + $mustRelogin = false; + + foreach ($request['template']->getLDAPmodify() as $attr_name => $val) { + /* Was this a user's password modification who is currently + * logged in? If so, they need to logout and log back in + * with the new password. */ + if (($attr_name == 'userpassword') && + in_array($app['server']->getValue('login','auth_type'),array('cookie','session')) && + pla_compare_dns($app['server']->getLogin(),$request['dn']) === 0) + + $mustRelogin = true; + } + + # If the user password was changed, not tell the to relogin. + if ($mustRelogin) { + $app['server']->logout('user'); + unset($_SESSION['ACTIVITY'][$app['server']->getIndex()]); + + system_message(array( + 'title'=>_('Modification successful!'), + 'body'=>_('Since you changed your password, you must now login again with your new password.'), + 'type'=>'info'), + sprintf('cmd.php?cmd=login_form&server_id=%s',$app['server']->getIndex())); + + exit; + } + + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + foreach ($request['template']->getLDAPmodify() as $attr => $junk) + $redirect_url .= sprintf('&modified_attrs[]=%s',$attr); + + if (get_request('meth','REQUEST') == 'ajax') + $redirect_url .= '&meth=ajax'; + + header("Location: $redirect_url"); + die(); +} +?> diff --git a/htdocs/update_confirm.php b/htdocs/update_confirm.php new file mode 100644 index 0000000..037b91d --- /dev/null +++ b/htdocs/update_confirm.php @@ -0,0 +1,253 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +$request['page']->drawTitle(get_rdn($request['template']->getDN())); +$request['page']->drawSubTitle(); + +# Confirm the updates +if (count($request['template']->getLDAPmodify(true))) { + echo '
'; + echo _('Do you want to make these changes?'); + echo '

'; + echo '
'; + + echo "\n\n"; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + echo "\n"; + + $request['page']->drawHiddenAttributes(); + echo '
'; + + echo ''; + echo "\n"; + + printf('', + _('Attribute'),_('Old Value'),_('New Value'),_('Skip')); + echo "\n\n"; + + # If we skip objectclass changes, but there are new must/may attrs provided by the new objectclass, they need to be skip. + $mustattrs = getMustAttrs($request['template']->getAttribute('objectclass')->getValues()); + + $counter = 0; + foreach ($request['template']->getLDAPmodify(true) as $attribute) { + $counter++; + + printf('',$counter%2 ? 'even' : 'odd'); + printf('',$attribute->getFriendlyName()); + + # Show OLD Values + echo ''; + + # Show NEW Values + echo ''; + + # Show SKIP Option + $input_disabled = ''; + $input_onclick = ''; + + if ($attribute->isForceDelete() || (in_array($attribute->getName(),$mustattrs)) && $request['template']->getAttribute('objectclass')->justModified()) + $input_disabled = 'disabled="disabled"'; + + if ($attribute->getName() == 'objectclass') { + $input_onclick = ''; + + # If there are attributes being force deleted... + if (count($request['template']->getForceDeleteAttrs()) > 0) { + $input_onclick = 'onclick="if (this.checked) {'; + + # And this OC is being skipped, then these attributes can be optionally deleted. + foreach ($request['template']->getForceDeleteAttrs() as $ad_name) { + # Only if it is not a must attr by this objectclass now staying + if (! in_array($ad_name->getName(),getMustAttrs($attribute->getOldValues()))) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = false;",$ad_name->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = true;",$ad_name->getName()); + $input_onclick .= "\n"; + } + + $input_onclick .= '} else {'; + + # Otherwise the attributes must be deleted. + foreach ($request['template']->getForceDeleteAttrs() as $ad_name) { + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = false;",$ad_name->getName()); + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = true;",$ad_name->getName()); + $input_onclick .= "\n"; + } + + $input_onclick .= '};'; + } + + # If the attributes arent force deleted... + if ($input_onclick) + $input_onclick .= 'if (this.checked) {'; + else + $input_onclick = 'onclick="if (this.checked) {'; + + # IE: There are new objectclasses that result in new values. + foreach ($request['template']->getLDAPmodify(true) as $skipattr) { + if (! $skipattr->getOldValues()) { + if (! in_array($skipattr->getName(),$mustattrs)) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = true;",$skipattr->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = true;",$skipattr->getName()); + $input_onclick .= "\n"; + } + } + + $input_onclick .= '} else {'; + + foreach ($request['template']->getLDAPmodify(true) as $skipattr) { + if (! $skipattr->getOldValues()) { + if (! in_array($skipattr->getName(),$mustattrs)) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = false;",$skipattr->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = false;",$skipattr->getName()); + $input_onclick .= "\n"; + } + } + + $input_onclick .= '};"'; + } + + printf('', + htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick); + echo ''; + echo "\n\n"; + } + + echo '
%s%s%s%s
%s'; + + if (! $attribute->getOldValues()) + printf('[%s]',_('attribute doesnt exist')); + + $dv = $attribute->getRemovedValues(); + foreach ($attribute->getOldValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ($x = ((count($attribute->getOldValues()) > 5) && count($attribute->getValues()) && in_array($value,$dv))) + echo ''; + + $request['page']->draw('OldValue',$attribute,$key); + + # For multiple values, close the highlighting + if ($x) + echo ''; + + echo '
'; + } + + echo '
'; + + if (! $attribute->getValueCount() || $attribute->isForceDelete()) + printf('[%s]',_('attribute deleted')); + + $dv = $attribute->getAddedValues(); + foreach ($attribute->getValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ($x = ((count($attribute->getValues()) > 5) && count($attribute->getOldValues()) && in_array($value,$dv))) + echo ''; + + $request['page']->draw('CurrentValue',$attribute,$key); + + # For multiple values, close the highlighting + if ($x) + echo ''; + + echo '
'; + } + + echo '
'; + + echo '
'; + echo '
'; + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Update Object')); + + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&dn=%s\',\'%s\');"',htmlspecialchars($request['dn']),_('Retrieving DN')) : '')); + + echo '
'; + echo '
'; + echo '
'; + + if (count($request['template']->getForceDeleteAttrs()) > 0) { + echo ''; + printf('',_('The deletion of objectClass(es)')); + printf('',implode(', ',$request['template']->getAttribute('objectclass')->getRemovedValues())); + echo ''; + printf('',_('will delete the attribute(s)')); + echo '
%s:%s
%s:'; + + $i = 0; + foreach ($request['template']->getForceDeleteAttrs() as $attribute) { + if ($i++ != 0) + echo ', '; + + echo $_SESSION[APPCONFIG]->getFriendlyHTML($attribute); + } + echo '
'; + } + +} else { + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + echo '
'; + echo _('You made no changes'); + + if (isAjaxEnabled()) + printf(' %s.', + htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back')); + else + printf(' %s.',htmlspecialchars($href),_('Go back')); + + echo '
'; +} + +function getMustAttrs($oclasses) { + global $app; + + $mustattrs = array(); + + foreach ($oclasses as $value) { + $soc = $app['server']->getSchemaObjectClass($value); + + if ($soc) + foreach ($soc->getMustAttrs() as $sma) + array_push($mustattrs,$sma->getName()); + } + + return $mustattrs; +} +?> diff --git a/htdocs/view_jpeg_photo.php b/htdocs/view_jpeg_photo.php new file mode 100644 index 0000000..d52501c --- /dev/null +++ b/htdocs/view_jpeg_photo.php @@ -0,0 +1,77 @@ +getDNAttrValues($request['dn'],null,LDAP_DEREF_NEVER,array($request['attr'])); + + break; +} + +if (! isset($jpeg_data[$request['attr']][$request['index']])) { + if (function_exists('imagecreate')) { + $im = imagecreate(160,30); + if (is_resource($im)) { + header('Content-type: image/png'); + + # Set the background + imagecolorallocatealpha($im,0xFC,0xFC,0xFE,127); + $text_color = imagecolorallocate($im,0,0,0); + imagestring($im,4,3,5,_('Image not available'),$text_color); + imagepng($im); + imagedestroy($im); + + die(); + } + } + + # We cant display an error, but we can set a system message, which will be display on the next page render. + system_message(array( + 'title'=>_('No image available'), + 'body'=>sprintf(_('Could not fetch jpeg data from LDAP server for attribute [%s].'),$request['attr']), + 'type'=>'warn')); + + die(); +} + +if (! is_array($jpeg_data[$request['attr']])) + $jpeg_data[$request['attr']] = array($jpeg_data[$request['attr']]); + +$obStatus = ob_get_status(); +if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + +header(sprintf('Content-type: %s',$request['type'])); +header(sprintf('Content-disposition: inline; filename="%s"',$request['filename'])); +echo $jpeg_data[$request['attr']][$request['index']]; +die(); +?> diff --git a/htdocs/welcome.php b/htdocs/welcome.php new file mode 100644 index 0000000..e427281 --- /dev/null +++ b/htdocs/welcome.php @@ -0,0 +1,29 @@ +'; +echo '

'; +printf('%s',IMGDIR,_('phpLDAPadmin logo'),_('phpLDAPadmin logo')); +echo '

'; +echo _('Use the menu to the left to navigate'); +echo '

'; + +if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks')) { + printf('%s',get_href('credits'),_('Credits')); + printf(' | %s',get_href('documentation'),_('Documentation')); + printf(' | %s',get_href('donate'),_('Donate')); + echo '

'; +} + +echo '
'; +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..716e607 --- /dev/null +++ b/index.php @@ -0,0 +1,11 @@ + diff --git a/lib/AJAXTree.php b/lib/AJAXTree.php new file mode 100644 index 0000000..300a976 --- /dev/null +++ b/lib/AJAXTree.php @@ -0,0 +1,307 @@ +" + * @param boolean $first_child is the first child entry, which is normally the "Create New Entry" option + * @param boolean $last_child is the last child entry, which is normally the "Create New Entry" option + */ + protected function draw_item($item,$level,$first_child=true,$last_child=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # Level pre-treatment + $code = ''; + if (is_string($level)) { + for ($i=0; $i 0) + $code = '0' * $level; + + $level = strlen($code); + + # Get entry to display as node + $entry = $this->getEntry($item); + + # If the entry doesnt exist, we'll add it. + if (! $entry) { + $this->addEntry($item); + $entry = $this->getEntry($item); + } + + # If the entry doesnt exist in the server, then return here with an empty string. + if (! $entry) + return ''; + + # Get our children. + $child_count = $this->readChildrenNumber($entry->getDN()); + + $nb = 0; + if ($first_child) + $nb += 1; + if ($last_child) + $nb += 2; + + $imgs['expand'] = array('tree_expand.png','tree_expand.png','tree_expand_corner.png', + ($level > 0) ? 'tree_expand_corner.png' : 'tree_expand_corner_first.png'); + + $imgs['collapse'] = array('tree_collapse.png','tree_collapse.png','tree_collapse_corner.png', + ($level > 0) ? 'tree_collapse_corner.png' : 'tree_collapse_corner_first.png'); + + $imgs['tree'] = array('tree_split.png','tree_split.png','tree_corner.png','tree_corner.png'); + + /** Information on array[$nb] + * nb == 1 => the node is the first child + * nb == 2 => the node is the last child + * nb == 3 => the node is the unique child + * nb == 0 => the node is a child */ + $new_code = array('1','1','0','0'); + + # Links + $parms['openclose'] = htmlspecialchars(sprintf('server_id=%s&dn=%s&code=%s%s',$this->getServerID(),$entry->getDNEncode(),$code,$new_code[$nb])); + $parms['edit'] = htmlspecialchars(sprintf('cmd=template_engine&server_id=%s&dn=%s',$this->getServerID(),$entry->getDNEncode())); + $href = sprintf('cmd.php?%s',$parms['edit']); + + # Each node has a unique id based on dn + $node_id = sprintf('node%s',base64_encode(sprintf('%s-%s',$server->getIndex(),$entry->getDN()))); + $node_id = str_replace('=','_',$node_id); + + if ($level == 0) + printf('',$this->getDepth()+3-1); + + printf(''; + + printf('
',$node_id,($entry->isOpened() ? 'block' : 'none')); + if ($entry->isOpened()) + $this->draw_children($entry,$code.$new_code[$nb]); + + echo '
'; + + if ($level == 0) + echo ''; + } + + /** + * Expand and draw a child entry, when it is clicked on. This is using AJAX just to render this section of the tree. + */ + public function draw_children($parent_entry,$code) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $children = array(); + + foreach ($parent_entry->getChildren() as $child) { + if (! $this->getEntry($child)) + $this->addEntry($child); + + array_push($children,$this->getEntry($child)); + } + + $first_child = $this->create_before_child($parent_entry,$code); + $last_child = $this->create_after_child($parent_entry,$code); + + # If compression is on, we need to compress this output - but only if called by draw_tree_node + if (function_exists('isCompress') && isCompress() && get_request('cmd','REQUEST') == 'draw_tree_node') + ob_start(); + + echo $first_child; + + for ($i=0; $idraw_item($children[$i]->getDN(),$code,$first,$last); + else + echo '
problem getting DN entry from ldap'; + + echo "\n"; + } + + echo $last_child; + + # If compression is on, we need to compress this output + if (function_exists('isCompress') && isCompress() && get_request('cmd','REQUEST') == 'draw_tree_node') { + $output = ob_get_clean(); + echo gzencode($output); + } + } + + /** + * Return the indentation before a node + * + * @param $code a string of 0 and 1 ; $code == "000101" will return " | |" + */ + protected function get_indentation($code) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $indent = ''; + + for ($i=0; $i',IMGDIR); + break; + + case '1': + $indent .= sprintf('| ',IMGDIR); + break; + } + } + + return $indent; + } + + /** + * Draw the javascript to support the tree. + */ + protected function draw_javascript() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + parent::draw_javascript(); + printf('',JSDIR); + printf('',JSDIR); + } + + /** + * Draw the "Create New Entry" item before the children. + */ + private function create_before_child($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (strlen($level) == 0) + return ''; + + $server = $this->getServer(); + $output = ''; + + if (! $server->isReadOnly() && ! $entry->isLeaf() && (count($entry->getChildren()) > 10) && $this->getServer()->isShowCreateEnabled() + && $_SESSION[APPCONFIG]->getValue('appearance','show_top_create')) + $output = $this->draw_create_new_entry($entry,$level,IMGDIR.'/tree_split.png'); + + return $output; + } + + /** + * Draw the "Create New Entry" item after the children. + */ + private function create_after_child($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (strlen($level) == 0) + return ''; + + $server = $this->getServer(); + $output = ''; + + if (! $server->isReadOnly() && ! $entry->isLeaf() && $this->getServer()->isShowCreateEnabled()) + $output = $this->draw_create_new_entry($entry,$level,IMGDIR.'/tree_corner.png'); + + return $output; + } + + /** + * Draw the "Create New Entry" item. + */ + private function draw_create_new_entry($entry,$level,$img) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $output = ''; + + $href = sprintf('cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$entry->getDNEncode()); + + $output .= $this->get_indentation($level); + $output .= sprintf('--',$img); + $output .= sprintf('',htmlspecialchars($href),$entry->getDN()); + $output .= sprintf('->',IMGDIR); + $output .= ''; + $output .= ' '; + + if (isAjaxEnabled()) + $output .= sprintf('', + htmlspecialchars($href),_('Create new entry here'), + htmlspecialchars($href),_('Loading')); + else + $output .= sprintf('',htmlspecialchars($href),_('Create new entry here')); + + $output .= _('Create new entry here'); + $output .= ''; + + return $output; + } + + /** + * List the items in the tree that are open + * + * @return array List of open nodes + */ + public function listOpenItems() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->entries as $dn => $value) + if ($value->isOpened()) + array_push($result,$value->getDN()); + + return $result; + } +} +?> diff --git a/lib/Attribute.php b/lib/Attribute.php new file mode 100644 index 0000000..9c4ef98 --- /dev/null +++ b/lib/Attribute.php @@ -0,0 +1,917 @@ +getServer($server_id); + + $sattr = $server->getSchemaAttribute($name); + if ($sattr) { + $this->name = $sattr->getName(false); + $this->setLDAPdetails($sattr); + + } else + $this->name = $name; + + $this->source = $source; + + # XML attributes are shown by default + switch ($source) { + case 'XML': $this->show(); + $this->setXML($values); + + break; + + default: + if (! isset($values['values'])) + debug_dump_backtrace('no index "values"',1); + + $this->initValue($values['values']); + } + + # Should this attribute be hidden + if ($server->isAttrHidden($this->name)) + $this->forcehide = true; + + # Should this attribute value be read only + if ($server->isAttrReadOnly($this->name)) + $this->readonly = true; + + # Should this attribute value be unique + if ($server->isAttrUnique($this->name)) + $this->unique = true; + } + + /** + * Return the name of the attribute. + * + * @param boolean $lower - Return the attribute in normal or lower case (default lower) + * @param boolean $real - Return the real attribute name (with ;binary, or just the name) + * @return string Attribute name + */ + public function getName($lower=true,$real=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + if ($real) + return $lower ? strtolower($this->name) : $this->name; + else + return $lower ? strtolower($this->real_attr_name()) : $this->real_attr_name(); + } + + public function getValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); + + return $this->values; + } + + public function getOldValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oldvalues); + + return $this->oldvalues; + } + + public function getValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); + + return count($this->values); + } + + public function getSource() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source); + + return $this->source; + } + + /** + * Autovalue is called after the attribute is initialised, and thus the values from the ldap server will be set. + */ + public function autoValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values) + return; + + $this->values = $new_val; + } + + public function initValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values || $this->oldvalues) { + debug_dump(array('new_val'=>$new_val,'this'=>$this)); + debug_dump_backtrace('new and/or old values are set',1); + } + + $this->values = $new_val; + } + + public function clearValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->values = array(); + } + + public function setOldValue($val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->oldvalues = $val; + } + + public function setValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values) { + if ($this->values == $new_val) + return; + + if ($this->oldvalues) { + debug_dump($this); + debug_dump_backtrace('old values are set',1); + } else + $this->oldvalues = $this->values; + } + + if ($new_val == $this->values) + return; + + $this->values = $new_val; + $this->justModified(); + } + + public function addValue($new_val,$i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($i < 0) + $i = $this->getValueCount(); + + $old_val = $this->getValue($i); + if (is_null($old_val) || ($old_val != $new_val)) + $this->justModified(); + + $this->values[$i] = $new_val; + } + + public function delValue($i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($i < 0) + $this->setValue(array()); + + if (! $this->hasBeenModified()) + $this->oldvalues = $this->values; + + if (isset($this->values[$i])) { + unset($this->values[$i]); + $this->values = array_values($this->values); + $this->justModified(); + } + } + + public function getValue($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->values[$i])) + return $this->values[$i]; + else + return null; + } + + public function getOldValue($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->oldvalues[$i])) + return $this->oldvalues[$i]; + else + return null; + } + + public function getMinValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->min_value_count); + + return $this->min_value_count; + } + + public function setMinValueCount($min) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->min_value_count = $min; + } + + public function getMaxValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->max_value_count); + + return $this->max_value_count; + } + + public function setMaxValueCount($max) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->max_value_count = $max; + } + + public function haveMoreValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMaxValueCount() < 0 || ($this->getValueCount() < $this->getMaxValueCount())) + return true; + else + return false; + } + + public function justModified() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->modified = true; + } + + public function hasBeenModified() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->modified); + + return $this->modified; + } + + public function isForceDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forcedelete); + + return $this->forcedelete; + } + + public function setForceDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->forcedelete = true; + $this->oldvalues = $this->values; + $this->values = array(); + $this->justModified(); + } + + public function isInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->internal); + + return $this->internal; + } + + public function setInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->internal = true; + } + + public function isRequired() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMinValueCount() > 0) + return true; + elseif ($this->ldaptype == 'must') + return true; + elseif ($this->isRDN()) + return true; + else + return false; + } + + public function isMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (($this->ldaptype == 'may') && ! $this->isRequired()) + return true; + else + return false; + } + + public function setType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->type = strtolower($type); + } + + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + public function setLDAPtype($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->ldaptype = strtolower($type); + } + + public function getLDAPtype() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ldaptype); + + return $this->ldaptype; + } + + public function setProperties($properties) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($properties as $index => $value) { + if ($index == 'maxvalnb') { + $this->setMaxValueCount($value); + continue; + + } elseif ($index == 'minvalnb') { + $this->setMinValueCount($value); + continue; + + } elseif ($index == 'maxlength') { + $this->setMinValueCount($value); + continue; + + } elseif ($index == 'hidden') { + $this->visible = $value; + continue; + + } elseif (in_array($index,array('cols','rows'))) { + # @todo To be implemented + continue; + } + + if (isset($this->$index)) + $this->$index = $value; + else { + debug_dump($this); + debug_dump_backtrace(sprintf('Unknown property (%s) with value (%s) for (%s)',$index,$value,$this->getName()),1); + } + } + } + + public function setRequired() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMinValueCount() <= 0) + $this->setMinValueCount(1); + } + + public function setOptional() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->setMinValueCount(0); + } + + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readonly); + + return $this->readonly; + } + + public function setReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->readonly = true; + } + + public function isMultiple() { + return false; + } + + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->visible && (! $this->forcehide); + } + + public function hide() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->visible = false; + } + + public function show() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->visible = true; + } + + public function haveFriendlyName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->haveFriendlyName($this); + } + + public function getFriendlyName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->display); + + if ($this->display) + return $this->display; + else + return $_SESSION[APPCONFIG]->getFriendlyName($this); + } + + public function setDescription($description) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->description = $description; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + public function setIcon($icon) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->icon = $icon; + } + + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + return $this->icon ? sprintf('%s/%s',IMGDIR,$this->icon) : ''; + } + + public function getHint() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->hint); + + return $this->hint; + } + + public function setHint($hint) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->hint = $hint; + } + + public function getMaxLength() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->maxlength); + + return $this->maxlength; + } + + public function setMaxLength($maxlength) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->maxlength = $maxlength; + } + + public function getSize() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->size); + + return $this->size; + } + + public function setSize($size) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size = $size; + } + + public function getSpacer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->spacer); + + return $this->spacer; + } + + public function getPage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->page); + + return $this->page; + } + public function setPage($page) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->page = $page; + } + + public function getOnChange() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->onchange); + + return $this->onchange; + } + + public function getHelper() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helper); + + return $this->helper; + } + + public function getHelperValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helpervalue); + + return $this->helpervalue; + } + + public function getVerify() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->verify); + + return $this->verify; + } + + public function setRDN($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->rdn = $rdn; + } + + /** + * Return if this attribute is an RDN attribute + * + * @return boolean + */ + public function isRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->rdn); + + return $this->rdn; + } + + /** + * Capture all the LDAP details we are interested in + * + * @param sattr Schema Attribute + */ + private function setLDAPdetails($sattr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # By default, set this as a MAY attribute, later processing should make it a MUST attribute if it is. + if (! $this->ldaptype) + $this->ldaptype = 'may'; + + # Store our Aliases + foreach ($sattr->getAliases() as $alias) + array_push($this->aliases,strtolower($alias)); + + if ($sattr->getIsSingleValue()) + $this->setMaxValueCount(1); + } + + /** + * Return a list of aliases for this Attribute (as defined by the schema) + * This list will be lowercase. + */ + public function getAliases() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases); + + return $this->aliases; + } + + public function getAutoValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->autovalue); + + return $this->autovalue; + } + + public function getPostValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->postvalue); + + return $this->postvalue; + } + + public function setPostValue($postvalue) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->postvalue = $postvalue; + } + + public function setXML($values) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Mostly all the time, this should be an array + if (is_array($values)) + foreach ($values as $index => $value) + switch ($index) { + # Helpers should be accompanied with a attribute. + case 'helper': + if (! isset($values['post']) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Missing [post] setting in XML file'),$index), + 'body'=>_('[helper] needs an accompanying [post] action.'), + 'type'=>'warn')); + + if (isset($value['value']) && ! is_array($value['value']) && preg_match('/^=php\.(\w+)\((.*)\)$/',$value['value'],$matches)) { + $this->helpervalue['function'] = $matches[1]; + $this->helpervalue['args'] = $matches[2]; + + unset ($value['value']); + } + + foreach ($value as $i => $detail) { + if (! in_array($i,array('default','display','id','value'))) { + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$i), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting for helper will be ignored.'),$detail), + 'type'=>'warn')); + + unset($value[$i]); + } + } + + $this->$index = $value; + + break; + + case 'hidden': $value ? $this->visible = false : $this->visible = true; + break; + + case 'spacer': $value ? $this->$index = true : $this->$index = false; + break; + + # Essentially, we ignore type, it is used to select an Attribute type in the Factory. But we'll generated a warning if there is an unknown type. + case 'type': + if (! in_array($value,array('password','multiselect','select','textarea')) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), + 'type'=>'warn')); + + break; + + case 'post': + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { + $this->postvalue['function'] = $matches[1]; + $this->postvalue['args'] = $matches[2]; + + } else + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), + 'type'=>'warn')); + + case 'value': + if (is_array($value)) + foreach ($value as $x => $y) { + if (! $this->haveMoreValues()) { + system_message(array( + 'title'=>_('Automatically removed attribute values from template'), + 'body'=>sprintf('%s [%s]',_('Template defines more values than can be accepted by attribute.'),$this->getName(true)), + 'type'=>'warn')); + + $this->clearValue(); + + break; + + } else + $this->addValue($x,$y); + } + + else + # Check to see if the value is auto generated. + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { + $this->autovalue['function'] = $matches[1]; + $this->autovalue['args'] = $matches[2]; + + # We'll add a hint too + if (! $this->hint) + $this->hint = _('Automatically determined'); + + } else + $this->addValue($value); + + break; + + # Queries + case 'ordersort': + + # Creation/Editing Templates + case 'cols': + case 'default': + case 'display': + case 'hint': + case 'icon': + case 'maxlength': + case 'onchange': + case 'order': + case 'page': + case 'readonly': + case 'rows': + case 'size': + case 'values': + case 'verify': $this->$index = $value; + break; + + case 'max': + if ($this->getMaxValueCount() == -1) + $this->setMaxValueCount($value); + + default: + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown attribute setting will be ignored.'),serialize($value)), + 'type'=>'warn')); + } + + elseif (is_string($values) && (strlen($values) > 0)) + $this->values = array($values); + } + + /** + * Display the values removed in an attribute. + */ + public function getRemovedValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_diff($this->getOldValues(),$this->getValues()); + } + + /** + * Display the values removed in an attribute. + */ + public function getAddedValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_diff($this->getValues(),$this->getOldValues()); + } + + /** + * Prunes off anything after the ";" in an attr name. This is useful for + * attributes that may have ";binary" appended to their names. With + * real_attr_name(), you can more easily fetch these attributes' schema + * with their "real" attribute name. + * + * @param string $attr_name The name of the attribute to examine. + * @return string + */ + private function real_attr_name() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return preg_replace('/;.*$/U','',$this->name); + } + + /** + * Does this attribute need supporting JS + */ + public function needJS($type=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_null($type)) { + foreach (array('focus','blur','validate') as $type) + if ($this->needJS($type)) + return true; + + return false; + + } elseif ($type == 'focus') { + # We dont have any focus javascript routines. + return false; + + } elseif ($type == 'blur') { + if ($this->onchange || $this->isRequired()) + return true; + else + return false; + + } elseif ($type == 'validate') { + if ($this->isRequired()) + return true; + else + return false; + + } else + debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1); + } +} +?> diff --git a/lib/AttributeFactory.php b/lib/AttributeFactory.php new file mode 100644 index 0000000..82cf562 --- /dev/null +++ b/lib/AttributeFactory.php @@ -0,0 +1,188 @@ +getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template [post] function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template function is not known and will be ignored.'),$values['post']), + 'type'=>'warn')); + + unset($values['post']); + } + } + } + + # Check our helper functions exists + if (isset($values['helper']['value']) && ! is_array($values['helper']['value'])) + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$values['helper']['value'],$matches)) + if (! in_array($matches[1],array('GetNextNumber','PasswordEncryptionTypes'))) { + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template helper function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template helper function is not known and will be ignored.'),$values['helper']['value']), + 'type'=>'warn')); + + unset($values['helper']['value']); + } + + # Check to see if the value is auto generated, our attribute type is dependant on the function called. + if (isset($values['value']) && ! is_array($values['value'])) { + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$values['value'],$matches)) { + switch ($matches[1]) { + case 'MultiList': + if (! isset($values['type'])) + $values['type'] = 'multiselect'; + + case 'PickList': + return $this->newSelectionAttribute($name,$values,$server_id,$source); + + case 'RandomPassword': + return $this->newRandomPasswordAttribute($name,$values,$server_id,$source); + + # Fall through and determine the attribute using other methods. + case 'GetNextNumber': + case 'Function' : + break; + + default: + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template function is not known and will be ignored.'),$values['value']), + 'type'=>'warn')); + + unset($values['value']); + } + } + } + + if (isset($values['type'])) + switch ($values['type']) { + case 'password': + if (! strcasecmp($name,'sambaLMPassword') || ! strcasecmp($name,'sambaNTPassword')) + return $this->newSambaPasswordAttribute($name,$values,$server_id,$source); + else + return $this->newPasswordAttribute($name,$values,$server_id,$source); + + case 'multiselect': + case 'select': + return $this->newSelectionAttribute($name,$values,$server_id,$source); + + case 'textarea': + return $this->newMultiLineAttribute($name,$values,$server_id,$source); + } + + if (! strcasecmp($name,'objectClass')) { + return $this->newObjectClassAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isJpegPhoto($name) || in_array($name,$app['server']->getValue('server','jpeg_attributes'))) { + return $this->newJpegAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isAttrBinary($name)) { + return $this->newBinaryAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'userPassword')) { + return $this->newPasswordAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'sambaLMPassword') || ! strcasecmp($name,'sambaNTPassword')) { + return $this->newSambaPasswordAttribute($name,$values,$server_id,$source); + + } elseif (in_array(strtolower($name),array_keys(array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs'))))) { + return $this->newDateAttribute($name,$values,$server_id,$source); + + } elseif (in_array(strtolower($name),array('shadowlastchange','shadowmin','shadowmax','shadowexpire','shadowwarning','shadowinactive'))) { + return $this->newShadowAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isAttrBoolean($name)) { + $attribute = $this->newSelectionAttribute($name,$values,$server_id,$source); + $attribute->addOption('TRUE',_('true')); + $attribute->addOption('FALSE',_('false')); + return $attribute; + + } elseif ($app['server']->isDNAttr($name)) { + return $this->newDnAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isMultiLineAttr($name)) { + return $this->newMultiLineAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'gidNumber')) { + return $this->newGidAttribute($name,$values,$server_id,$source); + + } else { + return new Attribute($name,$values,$server_id,$source); + } + } + + private function newJpegAttribute($name,$values,$server_id,$source) { + return new JpegAttribute($name,$values,$server_id,$source); + } + + private function newBinaryAttribute($name,$values,$server_id,$source) { + return new BinaryAttribute($name,$values,$server_id,$source); + } + + private function newPasswordAttribute($name,$values,$server_id,$source) { + return new PasswordAttribute($name,$values,$server_id,$source); + } + + private function newSambaPasswordAttribute($name,$values,$server_id,$source) { + return new SambaPasswordAttribute($name,$values,$server_id,$source); + } + + private function newRandomPasswordAttribute($name,$values,$server_id,$source) { + return new RandomPasswordAttribute($name,$values,$server_id,$source); + } + + private function newShadowAttribute($name,$values,$server_id,$source) { + return new ShadowAttribute($name,$values,$server_id,$source); + } + + private function newSelectionAttribute($name,$values,$server_id,$source) { + return new SelectionAttribute($name,$values,$server_id,$source); + } + + private function newMultiLineAttribute($name,$values,$server_id,$source) { + return new MultiLineAttribute($name,$values,$server_id,$source); + } + + private function newDateAttribute($name,$values,$server_id,$source) { + return new DateAttribute($name,$values,$server_id,$source); + } + + private function newObjectClassAttribute($name,$values,$server_id,$source) { + return new ObjectClassAttribute($name,$values,$server_id,$source); + } + + private function newDnAttribute($name,$values,$server_id,$source) { + return new DnAttribute($name,$values,$server_id,$source); + } + + private function newGidAttribute($name,$values,$server_id,$source) { + return new GidAttribute($name,$values,$server_id,$source); + } +} +?> diff --git a/lib/BinaryAttribute.php b/lib/BinaryAttribute.php new file mode 100644 index 0000000..6b5053b --- /dev/null +++ b/lib/BinaryAttribute.php @@ -0,0 +1,60 @@ +filepaths = array(); + $this->filenames = array(); + } + + public function getFileNames() { + return $this->filenames; + } + + public function getFileName($i) { + if (isset($this->filenames[$i])) return $this->filenames[$i]; + else return null; + } + + public function addFileName($name, $i = -1) { + if ($i < 0) { + $this->filenames[] = $name; + } else { + $this->filenames[$i] = $name; + } + } + + public function getFilePaths() { + return $this->filepaths; + } + + public function getFilePath($i) { + if (isset($this->filepaths[$i])) return $this->filepaths[$i]; + else return null; + } + + public function addFilePath($path, $i = -1) { + if ($i < 0) { + $this->filepaths[] = $path; + } else { + $this->filepaths[$i] = $path; + } + } +} +?> diff --git a/lib/DateAttribute.php b/lib/DateAttribute.php new file mode 100644 index 0000000..e1a687f --- /dev/null +++ b/lib/DateAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/DnAttribute.php b/lib/DnAttribute.php new file mode 100644 index 0000000..1f5c02f --- /dev/null +++ b/lib/DnAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/GidAttribute.php b/lib/GidAttribute.php new file mode 100644 index 0000000..7442a07 --- /dev/null +++ b/lib/GidAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/HTMLTree.php b/lib/HTMLTree.php new file mode 100644 index 0000000..90861cb --- /dev/null +++ b/lib/HTMLTree.php @@ -0,0 +1,587 @@ +getServer(); + + echo ''; + if (! $onlytree) + $this->draw_server_name(); + + $this->javascript = ''; + $javascript_id = 0; + + /* Do we have what it takes to authenticate here, or do we need to + * present the user with a login link (for 'cookie' and 'session' auth_types)? + */ + if ($server->isLoggedIn(null)) { + if (! $onlytree) { + $this->draw_menu(); + + if ($server->getAuthType() != 'config') + $this->draw_logged_in_user(); + else + printf('',$this->getDepth()+3); + + if ($server->isReadOnly()) + printf('',$this->getDepth()+3-1,_('read only')); + else + printf('',$this->getDepth()+3); + + printf(''; + + echo '
 
(%s)
 
 
', + $_SESSION[APPCONFIG]->getValue('appearance','tree_width') ? sprintf('width: %spx; ',$_SESSION[APPCONFIG]->getValue('appearance','tree_width')) : '', + $_SESSION[APPCONFIG]->getValue('appearance','tree_height') ? sprintf('height: %spx; ',$_SESSION[APPCONFIG]->getValue('appearance','tree_height')) : '', + $server->getIndex()); + } + + echo ''; + + if (! count($this->getBaseEntries())) { + # We didnt get any baseDN entries in our tree? + printf('', + $this->getDepth()+3-2, + _('Could not determine the root of your LDAP tree.'), + _('It appears that the LDAP server has been configured to not reveal its root.'), + _('Please specify it in config.php')); + + echo '
%s
%s
%s
'; + + if (! $onlytree) + echo '
'; + return; + } + + /** + * Check if the LDAP server is not yet initialized + * (ie, the base DN configured in config.php does not exist) + */ + foreach ($this->getBaseEntries() as $base) { + if (! $base->isInLDAP()) { + $js_drawn = false; + $javascript_id++; + + $rdn = explode('=',get_rdn($base->getDN())); + printf('%s', + IMGDIR,$this->getDepth()+3-3,pretty_print_dn($base->getDN())); + + $this->javascript .= sprintf('
',$server->getIndex(),$javascript_id); + $this->javascript .= '
'; + $this->javascript .= ''; + $this->javascript .= sprintf('',$server->getIndex()); + $this->javascript .= sprintf('',htmlspecialchars($server->getContainer($base->getDN()))); + $this->javascript .= sprintf('',get_rdn($base->getDN())); + $this->javascript .= sprintf('',$rdn[0]); + $this->javascript .= sprintf('',$rdn[0],$rdn[1]); + $this->javascript .= ''; + $this->javascript .= ''; + $this->javascript .= '
'; + $this->javascript .= sprintf('
'); + + if (preg_match('/,/',$base->getDN())) + printf('%s', + $this->getDepth()+3-3,_('This base cannot be created with PLA.')); + else + printf('%s %s', + $this->getDepth()+3-3,_('This base entry does not exist.'),$server->getIndex(),$javascript_id,_('Create it?')); + + } else { + $this->draw_item($base->getDN(),-1); + } + } + + echo ''; + + if (! $onlytree) + echo '
'; + + # We are not logged in, draw a login... link. + } else { + switch ($server->getAuthType()) { + case 'cookie': + case 'http': + case 'session': + $this->draw_login_link(); + break; + + case 'config': + case 'proxy': + case 'sasl': + break; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$server->getAuthType())); + } + } + + # Tree Footer. + echo ''; + echo "\n\n"; + + if (! $js_drawn) { + $this->draw_javascript(); + $js_drawn = true; + } + } + + /** + * Draw the server name + */ + protected function draw_server_name() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + echo ''; + printf('%s',IMGDIR,_('Server')); + printf('',$this->getDepth()+3-1); + printf('%s',$server->getName()); + + if (! is_null($server->inactivityTime())) { + $m = sprintf(_('Inactivity will log you off at %s'), + strftime('%H:%M',$server->inactivityTime())); + printf(' %s',IMGDIR,$m,'Timeout'); + } + echo ''; + } + + /** + * Draw the tree menu options + */ + protected function draw_menu() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $links = ''; + + if (is_array($_SESSION[APPCONFIG]->getValue('menu','session'))) + foreach ($_SESSION[APPCONFIG]->getValue('menu','session') as $link => $title) { + if ($this->get_menu_item($link)) + $links .= sprintf('%s',$this->get_menu_item($link)); + } + + # Finally add our logout link. + $links .= sprintf('%s',$this->get_logout_menu_item()); + + # Draw the quick-links below the server name: + if ($links) { + printf('',$this->getDepth()+3-1); + printf('%s
',$links); + echo ''; + } + } + + /** + * Get the HTML for each tree menu option + */ + protected function get_menu_item($item) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $menu = array(); + + switch($item) { + case 'schema': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return ''; + + $menu['cmd'] = 'schema'; + $menu['ajax'] = _('Loading Schema'); + $menu['div'] = 'BODY'; + $menu['title'] = _('View schema for'); + $menu['img'] = 'schema-big.png'; + $menu['name'] = _('schema'); + + break; + + case 'search': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','query_engine')) + return ''; + + $menu['cmd'] = 'query_engine'; + $menu['ajax'] = _('Loading Search'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Search'); + $menu['img'] = 'search-big.png'; + $menu['name'] = _('search'); + + break; + + case 'refresh': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','refresh')) + return ''; + + $menu['cmd'] = 'refresh'; + $menu['href'] = '&noheader=1&purge=1'; + $menu['ajax'] = _('Refreshing Tree'); + $menu['div'] = sprintf('SID_%s_nodes',$server->getIndex()); + $menu['title'] = _('Refresh'); + $menu['img'] = 'refresh-big.png'; + $menu['name'] = _('refresh'); + + break; + + case 'server_info': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','server_info')) + return ''; + + $menu['cmd'] = 'server_info'; + $menu['ajax'] = _('Loading Info'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Info'); + $menu['img'] = 'info-big.png'; + $menu['name'] = _('info'); + + break; + + case 'monitor': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','monitor')) + return ''; + + $attrs = $server->getRootDSE(); + if (! $attrs || ! isset($attrs['monitorcontext'])) + return ''; + + $menu['cmd'] = 'monitor'; + $menu['ajax'] = _('Loading Monitor Info'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Monitor'); + $menu['img'] = 'monitorserver-big.png'; + $menu['name'] = _('monitor'); + + break; + + case 'import': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','import_form') || ! $_SESSION[APPCONFIG]->isCommandAvailable('script','import') || $server->isReadOnly()) + return ''; + + $menu['cmd'] = 'import_form'; + $menu['ajax'] = _('Loading Import'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Import'); + $menu['img'] = 'import-big.png'; + $menu['name'] = _('import'); + + break; + + case 'export': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') || ! $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return ''; + + $menu['cmd'] = 'export_form'; + $menu['ajax'] = _('Loading Export'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Export'); + $menu['img'] = 'export-big.png'; + $menu['name'] = _('export'); + + break; + + default: + return false; + } + + $href_parms = htmlspecialchars(sprintf('cmd=%s&server_id=%s%s',$menu['cmd'],$server->getIndex(),isset($menu['href']) ? $menu['href'] : '')); + + if (isAjaxEnabled()) + return sprintf('%s
%s
', + $href_parms,$menu['div'],$href_parms,$menu['ajax'],$menu['title'],$server->getName(),IMGDIR,$menu['img'],$menu['name'],$menu['name']); + else + return sprintf('%s
%s
', + $href_parms,$menu['title'],$server->getName(),IMGDIR,$menu['img'],$menu['name'],$menu['name']); + } + + protected function get_logout_menu_item() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex()); + + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy','sasl'))) + return ''; + else + return sprintf('%s
%s
', + htmlspecialchars($href),_('Logout of this server'),IMGDIR,'logout-big.png',_('logout'),_('logout')); + } + + /** + * Draw the Logged in User + */ + protected function draw_logged_in_user() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + $logged_in_dn = $server->getLogin(null); + echo ''; + echo ''; + printf('%s: ',$this->getDepth()+3-1,_('Logged in as')); + + if ($server->getContainerTop($logged_in_dn) == $logged_in_dn) { + $logged_in_branch = ''; + $logged_in_dn_array = array(); + + } else { + $logged_in_branch = preg_replace('/,'.$server->getContainerTop($logged_in_dn).'$/','',$logged_in_dn); + $logged_in_dn_array = pla_explode_dn($logged_in_branch); + } + + $bases = $server->getContainerTop($logged_in_dn); + if (is_array($bases) && count($bases)) + array_push($logged_in_dn_array,$bases); + + $rdn = $logged_in_dn; + + # Some sanity checking here, in case our DN doesnt look like a DN + if (! is_array($logged_in_dn_array)) + $logged_in_dn_array = array($logged_in_dn); + + if (trim($logged_in_dn)) { + if ($server->dnExists($logged_in_dn)) + foreach ($logged_in_dn_array as $rdn_piece) { + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),rawurlencode($rdn)); + printf('%s',htmlspecialchars($href),pretty_print_dn($rdn_piece)); + + if ($rdn_piece != end($logged_in_dn_array)) + echo ','; + + $rdn = substr($rdn,(1 + strpos($rdn,','))); + } + + else + echo $logged_in_dn; + + } else { + echo 'Anonymous'; + } + + echo ''; + echo ''; + } + + /** + * Recursively descend on the given dn and draw the tree in html + * + * @param dn $dn Current dn. + * @param int $level Level to start drawing (start to -1) + */ + protected function draw_item($item,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # Get entry to display as node + $entry = $this->getEntry($item); + + # If the entry doesnt exist, we'll add it. + if (! $entry) { + $this->addEntry($item); + $entry = $this->getEntry($item); + } + + # If the entry doesnt exist in the server, then return here with an empty string. + if (! $entry) + return; + + # Get our children. + $child_count = $this->readChildrenNumber($item); + + $rdn = get_rdn($item); + $dnENCODE = rawurlencode($item); + $href['expand'] = htmlspecialchars(sprintf('cmd.php?cmd=expand&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + $href['collapse'] = htmlspecialchars(sprintf('cmd.php?cmd=collapse&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + $href['edit'] = htmlspecialchars(sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + + echo ''; + printf('',$level+2); + + # Is this node expanded? (deciding whether to draw "+" or "-") + if ($entry->isOpened()) + if (! $child_count && ! $this->getServer()->isShowCreateEnabled()) + printf('-',IMGDIR); + else + printf('-',$href['collapse'],IMGDIR); + else + if (($child_count !== false) && (! $child_count) && (! $this->getServer()->isShowCreateEnabled())) + printf('-',IMGDIR); + else + printf('+',$href['expand'],IMGDIR); + + printf('img', + $href['edit'],$server->getIndex(),preg_replace('/=/','_',base64_encode($item)),IMGDIR,$entry->getIcon()); + + printf('',$this->getDepth()+3-$level); + printf('%s',$href['edit'],$this->get_formatted_dn($entry,$level)); + + if ($child_count) + printf(' (%s)',$child_count); + + echo ''; + + if ($entry->isOpened()) { + /* Draw the "create new" link at the top of the tree list if there are more than 10 + * entries in the listing for this node. + */ + if (!$server->isReadOnly() && (count($entry->getChildren()) > 10) + && $this->getServer()->isShowCreateEnabled()) { + + $this->draw_create_link($rdn,$level,$dnENCODE); + } + + foreach ($entry->getChildren() as $dnChildEntry) + $this->draw_item($dnChildEntry,$level+1); + + # Always draw the "create new" link at the bottom of the listing + if (! $server->isReadOnly() && ! $entry->isLeaf() && $this->getServer()->isShowCreateEnabled()) { + $this->draw_create_link($rdn,$level,$dnENCODE); + } + } + + if (DEBUG_ENABLED) + debug_log('Leaving (%s,%s)',33,0,__FILE__,__LINE__,__METHOD__,$item,$level); + } + + protected function get_formatted_dn($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($level < 0) + return pretty_print_dn($entry->getDN()); + else + return draw_formatted_dn($this->getServer(),$entry); + } + + /** + * Print the HTML to show the "create new entry here". + * + * @param dn $rdn + * @param int $level + * @param dn $encoded_dn + */ + protected function draw_create_link($rdn,$level,$encoded_dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # print the "Create New object" link. + $href = htmlspecialchars(sprintf('cmd.php?cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$encoded_dn)); + + echo ''; + printf('',$level+3); + printf('%s',$href,IMGDIR,_('new')); + printf('%s', + $this->getDepth()+3-$level,$href,_('Create a new entry in'),$rdn,_('Create new entry here')); + echo ''; + } + + /** + * Draw login link + */ + protected function draw_login_link() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $href_parm = htmlspecialchars(sprintf('cmd=%s&server_id=%s',get_custom_file($server->getIndex(),'login_form',''),$server->getIndex())); + + echo ''; + + if (isAjaxEnabled()) { + printf('%s', + $href_parm,$href_parm,_('Loading Login'),_('Login to'),$server->getName(),IMGDIR,'login.png',_('login')); + printf('%s', + $this->getDepth()+3-2,$href_parm,$href_parm,_('Loading Login'),_('Login to'),$server->getName(),_('login')); + + } else { + printf('%s',$href_parm,IMGDIR,'login.png',_('login')); + printf('%s...',$this->getDepth()+3-2,$href_parm,_('Login')); + } + + echo ''; + + printf(' ',$this->getDepth()+3); + printf(' ',$this->getDepth()+3); + } + + /** + * If there is javascript, draw it + */ + protected function draw_javascript() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->javascript) { + echo "\n"; + echo $this->javascript; + echo "\n"; + $this->javascript = ''; + } + } + + /** + * Work out how deep the "opened" tree is. + */ + public function getDepth() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # If we are not logged in + if (! $server->isLoggedIn(null)) + return 0; + + static $depths = array(); + + if (! isset($depths[$server->getIndex()])) { + $max = 0; # BaseDN are open, so we start at 1. + + foreach ($this->entries as $dn) { + $basedepth = count(pla_explode_dn($server->getContainerPath($dn->getDN(),'/'))); + $depth = 0; + + $depth = count(pla_explode_dn($dn->getDN()))+1-$basedepth; + + if ($depth > $max) + $max = $depth; + } + + $depths[$server->getIndex()] = $max; + } + + return $depths[$server->getIndex()]; + } +} +?> diff --git a/lib/JpegAttribute.php b/lib/JpegAttribute.php new file mode 100644 index 0000000..d440048 --- /dev/null +++ b/lib/JpegAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/MassRender.php b/lib/MassRender.php new file mode 100644 index 0000000..f0bf67e --- /dev/null +++ b/lib/MassRender.php @@ -0,0 +1,48 @@ +%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper()) + echo '
'; + + printf('', + $j,htmlspecialchars($attribute->getName()),$i, + $j,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + if ($attribute->getHelper()) { + echo ''; + $this->draw('AttributeHelper',$attribute,$i); + echo '
'; + } + } + + protected function drawMassFormReadWriteValueBinaryAttribute($attribute,$i,$j) { + $this->drawFormReadWriteValueBinaryAttribute($attribute,$i); + } + + protected function drawMassFormReadWriteValueJpegAttribute($attribute,$i,$j) { + $this->drawFormReadOnlyValueJpegAttribute($attribute,$i); + } +} +?> diff --git a/lib/MultiLineAttribute.php b/lib/MultiLineAttribute.php new file mode 100644 index 0000000..b6d0eb5 --- /dev/null +++ b/lib/MultiLineAttribute.php @@ -0,0 +1,35 @@ +rows; + } + + public function setRows($rows) { + $this->rows = $rows; + } + + public function getCols() { + return $this->cols; + } + + public function setCols($cols) { + $this->cols = $cols; + } +} +?> diff --git a/lib/ObjectClassAttribute.php b/lib/ObjectClassAttribute.php new file mode 100644 index 0000000..939094d --- /dev/null +++ b/lib/ObjectClassAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/PageRender.php b/lib/PageRender.php new file mode 100644 index 0000000..7d86a54 --- /dev/null +++ b/lib/PageRender.php @@ -0,0 +1,1244 @@ +server_id = $server_id; + $this->template_id = $template_id; + } + + /** + * Dummy method... + */ + protected function visitAttribute() {} + + /** + * Get our templates applicable for this object + */ + protected function getTemplates() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return new Templates($this->server_id); + } + + public function getTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template; + } + + public function getTemplateID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template->getID(); + } + + /** + * Initialise the PageRender + */ + public function accept() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s:%s
',time(),__METHOD__); + + if ($this->template_id) { + $templates = $this->getTemplates(); + $this->template = $templates->getTemplate($this->template_id); + + if ($this->dn) + $this->template->setDN($this->dn); + elseif ($this->container) + $this->template->setContainer($this->container); + + $this->template->accept(); + + # Process our actions + if (get_request('post_value','REQUEST')) + foreach (get_request('post_value','REQUEST') as $attr => $values) { + $attribute = $this->template->getAttribute($attr); + + if (! $attribute) + debug_dump_backtrace(sprintf('There was a post_value for an attribute [%s], but it doesnt exist?',$attr),1); + + foreach ($values as $index) + if ($attribute->getPostValue()) + $this->get('Post',$attribute,$index); + else + $this->get('AutoPost',$attribute,$index); + } + + foreach ($this->template->getAttributes(true) as $attribute) { + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Accept:%s]
',__METHOD__,get_class($attribute)); + + $this->visit('',$attribute); + } + + // Sort our attribute values for display, if we are the custom template. + if ($this->template->getID() == 'none') + $this->template->sort(); + } + } + + public function drawTitle($title='Title') { + printf('

%s

',$title); + } + + public function drawSubTitle($subtitle=null) { + if (is_null($subtitle)) + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(),_('Distinguished Name'),$this->dn); + + printf('

%s

',$subtitle); + } + + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->container) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'CONTAINER set while setting DN', + 'type'=>'info')); + + $this->dn = $dn; + } + + public function setContainer($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->dn) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'DN set while setting CONTAINER', + 'type'=>'info')); + + $this->container = $dn; + } + + /** + * May be overloaded in other classes + */ + protected function getMode() {} + protected function getModeContainer() {} + + /** + * Process our arguments from the templates + */ + protected function getPostAttribute($attribute,$i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $autovalue = $attribute->getPostValue(); + $args = explode(';',$autovalue['args']); + $server = $this->getServer(); + $vals = $attribute->getValues(); + + switch ($autovalue['function']) { + /** + * Join will concatenate values with a string, similiar to explode() + * eg: =php.Join(-;%sambaSID%,%sidsuffix%) + * + * * arg 0 + * - character to use when joining the attributes + * + * * arg 1 + * - values to concatenate together. we'll explode %attr% values. + */ + case 'Join': + preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',$args[1],$matchall); + $matchattrs = $matchall[1]; + $char = $args[0]; + + $values = array(); + $blank = 0; + foreach ($matchattrs as $joinattr) { + $attribute2 = $this->template->getAttribute($joinattr); + + if (! $attribute2) { + if (($pv = get_request(strtolower($joinattr),'REQUEST')) && isset($pv[$attribute->getName()][$i])) { + array_push($values,$pv[$attribute->getName()][$i]); + + if (! $pv[$attribute->getName()][$i]) + $blank++; + + } else { + array_push($values,''); + $blank++; + } + + } elseif (count($attribute2->getValues()) == 0) { + return; + + } elseif (count($attribute2->getValues()) != 1) { + array_push($values,''); + $blank++; + + system_message(array( + 'title'=>_('Invalid value count for [post] processing'), + 'body'=>sprintf('%s (%s [%s])',_('Function() variable expansion can only handle 1 value'), + $attribute->getName(false),count($attribute->getValues())), + 'type'=>'warn')); + + } else + array_push($values,$attribute2->getValue(0)); + } + + # If all our value expansion results in blanks, we'll return no value + if (count($matchattrs) == $blank) + if (count($vals) > 1) + $vals[$i] = null; + else + $vals = null; + + else + $vals[$i] = implode($char,$values); + + break; + + /** + * PasswordEncrypt will encrypt a password + * eg: =php.PasswordEncrypt(%enc%;%userPassword%) + * + * This function will encrypt the users password "userPassword" using the "enc" method. + */ + case 'PasswordEncrypt': + if (count($args) != 2) { + system_message(array( + 'title'=>_('Invalid argument count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('PasswordEncrypt() only accepts two arguments'),$autovalue['args']), + 'type'=>'warn')); + + return; + } + + if (! $attribute->hasBeenModified()) + return; + + # Get the attribute. + if (preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[1]),$matchall)) { + if (count($matchall[1]) != 1) + system_message(array( + 'title'=>_('Invalid value count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])), + 'type'=>'warn')); + + $passwordattr = $matchall[1][0]; + $passwordvalue = $_REQUEST['new_values'][$passwordattr][$i]; + + } else + $passwordvalue = $args[1]; + + if (! trim($passwordvalue) || in_array($passwordvalue,$attribute->getOldValues())) + return; + + # Get the encoding + if ($passwordattr && preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[0]),$matchall)) { + if (count($matchall[1]) != 1) + system_message(array( + 'title'=>_('Invalid value count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])), + 'type'=>'warn')); + + $enc = $_REQUEST[$matchall[1][0]][$passwordattr][$i]; + + } else + $enc = $args[0]; + + $enc = strtolower($enc); + + switch ($enc) { + case 'lm': + $sambapassword = new smbHash; + $vals[$i] = $sambapassword->lmhash($passwordvalue); + + break; + + case 'nt': + $sambapassword = new smbHash; + $vals[$i] = $sambapassword->nthash($passwordvalue); + + break; + + default: + $vals[$i] = password_hash($passwordvalue,$enc); + } + + $vals = array_unique($vals); + + break; + + default: + $vals = $this->get('AutoPost',$attribute,$i); + } + + if (! $vals || $vals == $attribute->getValues()) + return; + + $attribute->clearValue(); + + if (! is_array($vals)) + $attribute->setValue(array($vals)); + else + $attribute->setValue($vals); + } + + /** + * This function is invoked if we dont know which template we should be using. + * + * @return string Template ID to be used or null if the user was presented with a list. + */ + protected function getTemplateChoice() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # First work out our template + $templates = $this->getTemplates(); + $template = $templates->getTemplate($this->template_id); + + # If the template we asked for is available + if ($this->template_id === $template->getID()) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'Choosing the SELECTED template'); + + return $this->template_id; + + # If there are no defined templates + } elseif (count($templates->getTemplates($this->getMode(),$this->getModeContainer(),false)) <= 0) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'Choosing the DEFAULT template, no other template applicable'); + + # Since getTemplate() returns a default template if the one we want doesnt exist, we can return $templates->getID(), it should be the default. + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template') AND $this->getMode() == 'creation') { + + system_message(array( + 'title'=>_('No available templates'), + 'body'=>_('There are no available active templates for this container.'), + 'type'=>'warn')); + + return 'invalid'; + + } else + return $template->getID(); + + # If there is only 1 defined template, and no default available, then that is our template. + } elseif ((count($templates->getTemplates($this->getMode(),$this->getModeContainer(),true)) == 1) && ! $this->haveDefaultTemplate()) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'AUTOMATIC choosing a template, only 1 template applicable'); + + $template = $templates->getTemplates($this->getMode(),$this->getModeContainer(),true); + $template = array_shift($template); + + # Dont render the only available template if it is invalid. + if (! $template->isInvalid()) + return $template->getID(); + else + $this->drawTemplateChoice(); + + } else { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'SELECT a template to use.'); + + # Propose the template choice + $this->drawTemplateChoice(); + } + + # If we got here, then there wasnt a template. + return null; + } + + /** DRAW ATTRIBUTE NAME **/ + + final protected function drawNameAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s', + $this->getServerID(),$attribute->getName()); + + if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + printf('%s',_($attribute->getFriendlyName())); + + elseif ($attribute->getLDAPtype()) + printf('%s', + htmlspecialchars($href), + _('Click to view the schema definition for attribute type'),$attribute->getName(false),_($attribute->getFriendlyName())); + else + printf('%s',_('This attribute is not defined in the LDAP schema'),_($attribute->getFriendlyName())); + + if (DEBUGTMPSUB) printf(' [%s]',get_class($attribute)); + } + + /** ATTRIBUTE NOTES */ + + protected function drawNotesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $attr_note = ''; + + foreach (array('NoteAlias','NoteRequired','NoteRDN','NoteHint','NoteRO') as $note) { + $alias_note = $this->get($note,$attribute); + + if ($alias_note) { + if (trim($attr_note)) + $attr_note .= ', '; + + $attr_note .= $alias_note; + } + } + + if ($attr_note) + printf('%s',$attr_note); + } + + protected function getNoteAliasAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is there a user-friendly translation available for this attribute? + $friendly_name = $attribute->getFriendlyName(); + + if (strtolower($friendly_name) != $attribute->getName()) + return sprintf('%s', + _('Note'),$friendly_name,_('is an alias for'),$attribute->getName(false),_('alias')); + else + return ''; + } + + #@todo this function shouldnt re-calculate requiredness, it should be known in the template already - need to set the ldaptype when initiating the attribute. + protected function getNoteRequiredAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $required_by = ''; + $sattr_required = ''; + + # Is this attribute required by an objectClass ? + $sattr = $this->getServer()->getSchemaAttribute($attribute->getName()); + if ($sattr) + $sattr_required = $sattr->getRequiredByObjectClasses(); + + if ($sattr_required) { + $oc = $this->template->getAttribute('objectclass'); + + if ($oc) + foreach ($oc->getValues() as $objectclass) { + # If this objectclass is in our required list + if (in_array_ignore_case($objectclass,$sattr_required)) { + $required_by .= sprintf('%s ',$objectclass); + continue; + } + + # If not, see if it is in our parent. + $sattr = $this->getServer()->getSchemaObjectClass($objectclass); + + if (array_intersect($sattr->getParents(),$sattr_required)) + $required_by .= sprintf('%s ',$objectclass); + } + + else + debug_dump_backtrace('How can there be no objectclasses?',1); + } + + if ($required_by) + return sprintf('%s',_('Required attribute for objectClass(es)'),$required_by,_('required')); + else + return ''; + } + + protected function getNoteRDNAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is this attribute required because its the RDN + if ($attribute->isRDN()) + return sprintf('rdn',_('This attribute is required for the RDN.')); + else + return ''; + } + + protected function getNoteHintAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is there a hint for this attribute + if ($attribute->getHint()) + return sprintf('%s',_($attribute->getHint()),_('hint')); + else + return ''; + } + + protected function getNoteROAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is this attribute is readonly + if ($attribute->isReadOnly()) + return sprintf('ro',_('This attribute has been marked as Read Only.')); + else + return ''; + } + /** DRAW HIDDEN VALUES **/ + + /** + * Draw all hidden attributes + */ + final public function drawHiddenAttributes() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->template->getAttributes(true) as $attribute) + if ($attribute->hasbeenModified()) { + if ($attribute->getValues()) + foreach ($attribute->getValues() as $index => $details) + $this->draw('HiddenValue',$attribute,$index); + + # We are deleting this attribute, so we need to display an empty value + else + $this->draw('HiddenValue',$attribute,0); + } + } + + /** + * Draw specific hidden attribute + */ + final protected function drawHiddenValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val)); + } + + /** DRAW DISPLAYED OLD VALUES **/ + protected function drawOldValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($attribute->getValues() as $index => $details) + $this->draw('OldValue',$attribute,$index); + } + + final protected function drawOldValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo $attribute->getOldValue($i); + } + + /** DRAW DISPLAYED CURRENT VALUES **/ + + protected function drawCurrentValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + for ($i=0;$i<$attribute->getValueCount();$i++) { + if ($i > 0) + echo '
'; + + $this->draw('CurrentValue',$attribute,$i); + } + } + + /** + * Draw the current specific value of an attribute + */ + final protected function drawCurrentValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + echo htmlspecialchars($attribute->getValue($i)); + } + + /** + * Draw a input value for an attribute - used in a form. + */ + protected function drawFormValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + if ($this->getServer()->isReadOnly() || $attribute->isReadOnly() + || ($attribute->isRDN() && $this->template->getType() != 'creation' && $i < count($attribute->getValues()))) + + $this->draw('FormReadOnlyValue',$attribute,$i); + else + $this->draw('FormReadWriteValue',$attribute,$i); + + # Show the ADDVALUE DIV if the attribute can have more values, and we have rendered the last value + if ($attribute->haveMoreValues() && $attribute->getValueCount() == $i+1) + printf('
',$attribute->getName()); + + if ($attribute->getPostValue()) + printf('',$attribute->getName(),$i); + } + + protected function drawFormReadOnlyValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val)); + } + + protected function drawFormReadWriteValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper() || $attribute->getVerify()) + echo ''; + + } elseif ($attribute->getVerify()) + echo ''; + + if ($attribute->getVerify()) { + printf(''; + } + + if ($attribute->getHelper() || $attribute->getVerify()) + echo '
'; + + printf('', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + if ($attribute->getHelper()) { + echo ''; + $this->draw('AttributeHelper',$attribute,$i); + echo '
', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + printf('(%s)',_('confirm')); + echo '
'; + } + + /** + * Draw specific hidden binary attribute + */ + final protected function drawHiddenValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,base64_encode($val)); + } + + final protected function drawOldValueBinaryAttribute($attribute,$i) { + # If we dont have a value, we'll just return; + if (! $attribute->getOldValue($i)) + return; + + printf('[%s]',_('Binary Value')); + } + + final protected function drawCurrentValueBinaryAttribute($attribute,$i) { + printf('[%s]',_('Binary Value')); + + if (in_array($attribute->getName(),array('objectsid'))) + printf(' (%s)', binSIDtoText($attribute->getValue(0))); + } + + protected function drawFormReadOnlyValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('CurrentValue',$attribute,$i); + echo '

'; + + $href = sprintf('download_binary_attr.php?server_id=%s&dn=%s&attr=%s&index=%s', + $this->getServerID(),rawurlencode($this->template->getDN()),$attribute->getName(),$i); + + printf('Save %s', + htmlspecialchars($href),IMGDIR,_('download value')); + + echo '
'; + } + + protected function drawFormReadWriteValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->getValue($i)) { + $this->draw('FormReadOnlyValue',$attribute,$i); + + if (! $attribute->isReadOnly() && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete_attr')) + printf('Trash %s', + $attribute->getName(),$attribute->getFriendlyName(),$i,IMGDIR,_('delete attribute')); + + } else { + printf('
', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '', + ($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : ''); + } + } + + protected function drawFormReadWriteValueDateAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + echo ''; + printf(' ', + $attribute->getName(),$i, + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + $this->draw('SelectorPopup',$attribute,$i); + echo ''."\n"; + } + + protected function drawFormReadWriteValueDnAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper()) + echo '
'; + + $input_name = sprintf('new_values[%s][%s]',htmlspecialchars($attribute->getName()),$i); + $id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i); + + printf(' ', + $input_name,$id,htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '', + ($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : ''); + + # Draw a link for popping up the entry browser if this is the type of attribute that houses DNs. + draw_chooser_link('entry_form',$id,false); + echo ''; + + if ($attribute->getHelper()) { + echo ''; + $this->draw('Helper',$attribute,$i); + echo '
'; + } + + echo "\n"; + } + + protected function drawFormReadWriteValueGidAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadWriteValueAttribute($attribute,$i); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + # If this is a gidNumber on a non-PosixGroup entry, lookup its name and description for convenience + if ($this->template->getDN() && ! in_array_ignore_case('posixGroup',$this->getServer()->getDNAttrValue($this->template->getDN(),'objectclass'))) { + $query['filter'] = sprintf('(&(objectClass=posixGroup)(gidNumber=%s))',$val); + $query['attrs'] = array('dn','description'); + + # Reorganise our base, so that our base is first + $bases = array_unique(array_merge(array($server->getContainerTop($this->template->getDN())),$server->getBaseDN())); + + # Search our bases, until we find a match. + foreach ($bases as $base) { + $query['base'] = $base; + $group = $this->getServer()->query($query,null); + + if (count($group) > 0) { + echo '
'; + + $group = array_pop($group); + $group_dn = $group['dn']; + $group_name = explode('=',get_rdn($group_dn)); + $group_name = $group_name[1]; + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $this->getServerID(),rawurlencode($group_dn)); + + echo ''; + printf('%s',htmlspecialchars($href),$group_name); + + $description = isset($group['description']) ? $group['description'] : null; + + if (is_array($description)) + foreach ($description as $item) + printf(' (%s)',$item); + else + printf(' (%s)',$description); + + echo ''; + + break; + } + } + } + } + + /** + * Draw a Jpeg Attribute + */ + final protected function drawOldValueJpegAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + # If we dont have a value, we'll just return; + if (! $attribute->getOldValue($i)) + return; + + draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + /** + * Draw a Jpeg Attribute + */ + final protected function drawCurrentValueJpegAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + # If we dont have a value, we'll just return; + if (! $attribute->getValue($i)) + return; + + # If the attribute is modified, the new value needs to be stored in a session variable for the draw_jpeg_photo callback. + if ($attribute->hasBeenModified()) { + $_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i); + draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false); + } else + draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + protected function drawFormReadOnlyValueJpegAttribute($attribute,$i) { + $this->draw('HiddenValue',$attribute,$i); + $_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i); + + draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + protected function drawFormReadOnlyValueMultiLineAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + ($attribute->getRows() > 0) ? $attribute->getRows() : 5, + ($attribute->getCols() > 0) ? $attribute->getCols() : 100, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $val); + } + + protected function drawFormReadWriteValueMultiLineAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + ($attribute->getRows() > 0) ? $attribute->getRows() : 5, + ($attribute->getCols() > 0) ? $attribute->getCols() : 100, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + $val); + } + + protected function drawFormValueObjectClassAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + /* It seems that openLDAP allows us to remove additional structural objectclasses + however other LDAP servers, dont remove them (even if we ask them to). */ + # Do we have our internal attributes. + $internal = $this->template->getAttribute('structuralobjectclass'); + + if ($internal) { + $structural = in_array_ignore_case($val,$internal->getValues()); + + # We'll work it out the traditional way. + } else { + # If this schema structural? + $schema_object = ($val) ? $this->getServer()->getSchemaObjectClass($val) : false; + $structural = (is_object($schema_object) && $schema_object->getType() == 'structural'); + } + + if ($structural) { + $this->draw('FormReadOnlyValue',$attribute,$i); + + printf(' (%s)', + _('This is a structural ObjectClass and cannot be removed.'), + _('structural')); + + } else + $this->draw('FormReadWriteValue',$attribute,$i); + } + + protected function getAutoPostPasswordAttribute($attribute,$i) { + # If the password is already encoded, then we'll return + if (preg_match('/^\{.+\}.+/',$attribute->getValue($i))) + return; + + $attribute->setPostValue(array('function'=>'PasswordEncrypt','args'=>sprintf('%%enc%%;%%%s%%',$attribute->getName()))); + $this->get('Post',$attribute,$i); + } + + protected function drawOldValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + $val = $attribute->getOldValue($i); + + if (obfuscate_password_display(get_enc_type($val))) + echo str_repeat('*',16); + else + echo nl2br(htmlspecialchars($attribute->getOldValue($i))); + } + + final protected function drawCurrentValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + $val = $attribute->getValue($i); + + if (obfuscate_password_display(get_enc_type($val))) + echo str_repeat('*',16); + else + echo nl2br(htmlspecialchars($attribute->getValue($i))); + } + + protected function drawFormReadOnlyValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + if (trim($val)) + $enc_type = get_enc_type($val); + else + $enc_type = $server->getValue('appearance','password_hash'); + + $obfuscate_password = obfuscate_password_display($enc_type); + + printf('
', + ($obfuscate_password ? 'password' : 'text'), + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()), + $i,htmlspecialchars($val),($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : ''); + + if (trim($val)) + $this->draw('CheckLink',$attribute,'new_values_'.htmlspecialchars($attribute->getName()).'_'.$i); + } + + protected function drawFormReadWriteValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + $enc_type = get_enc_type($val); + + # Set the default hashing type if the password is blank (must be newly created) + if (trim($val)) + $enc_type = get_enc_type($val); + else + $enc_type = $server->getValue('appearance','password_hash'); + + echo '
'; + + $obfuscate_password = obfuscate_password_display($enc_type); + $id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i); + + printf('', + ($obfuscate_password ? 'password' : 'text'), + htmlspecialchars($attribute->getName()),$i,$id, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + + if ($attribute->getHelper()) + $this->draw('Helper',$attribute,$i); + else + $this->draw('DefaultHelper',$attribute,$i); + + echo '
'; + + if ($attribute->getVerify() && $obfuscate_password) { + printf('', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + printf('(%s)',_('confirm')); + echo '
'; + } + + $this->draw('CheckLink',$attribute,$id); + echo '
'; + } + + protected function drawFormReadWriteValueSelectionAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isMultiple()) { + # For multiple selection, we draw the component only one time + if ($i > 0) + return; + + $selected = array(); + $vals = $attribute->getValues(); + $j = 0; + + if (! $vals && ! is_null($attribute->getDefault()) && ! is_array($vals = $attribute->getDefault())) + $vals = array($attribute->getDefault()); + + if (($attribute->getSize() > 0) && ($attribute->getSize() < $attribute->getOptionCount())) { + + printf(''; + + } else { + echo ''; + + // For checkbox items, we need to render a blank entry, so that we detect an all-unselect situation + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),''); + + foreach ($attribute->getSelection() as $value => $description) { + if (in_array($value,$vals)) + $selected[$value] = true; + + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),$value, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + isset($selected[$value]) ? 'checked="checked"' : '', + $description); + } + + foreach ($vals as $val) + if (! isset($selected[$val])) + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),$val, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + $val); + + echo '
 %s
 %s
'; + } + + # This is a single value attribute + } else { + $val = $attribute->getValue($i) ? $attribute->getValue($i) : $attribute->getDefault(); + + if ($attribute->getHelper()) + echo '
'; + + $found = false; + $empty_value = false; + + # If we are a required attribute, and the selection is blank, then the user cannot submit this form. + if ($attribute->isRequired() && ! count($attribute->getSelection())) + system_message(array( + 'title'=>_('Template Value Error'), + 'body'=>sprintf('This template uses a selection list for attribute [%s], however the selection list is empty.
You may need to create some dependancy entries in your LDAP server so that this attribute renders with values. Alternatively, you may be able to define the appropriate selection values in the template file.',$attribute->getName(false)), + 'type'=>'warn')); + + printf(''; + + if ($attribute->getHelper()) { + echo '
'; + $this->draw('Helper',$attribute,$i); + echo '
'; + } + } + } + + /** + * Takes a shadow* attribute and returns the date as an integer. + * + * @param array Attribute objects + * @param string A shadow attribute name + */ + private function shadow_date($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $shadowattr = array(); + $shadowattr['lastchange'] = $this->template->getAttribute('shadowlastchange'); + $shadowattr['max'] = $this->template->getAttribute('shadowmax'); + + $shadow = array(); + $shadow['lastchange'] = $shadowattr['lastchange'] ? $shadowattr['lastchange']->getValue(0) : null; + $shadow['max'] = $shadowattr['max'] ? $shadowattr['max']->getValue(0) : null; + + if (($attribute->getName() == 'shadowlastchange') && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']; + + elseif (($attribute->getName() == 'shadowmax') && ($shadow['max'] > 0) && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']+$shadow['max']; + + elseif (($attribute->getName() == 'shadowwarning') && ($attribute->getValue(0) > 0) + && $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0) + $shadow_date = $shadow['lastchange']+$shadow['max']-$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowinactive') && ($attribute->getValue(0) > 0) + && $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0) + $shadow_date = $shadow['lastchange']+$shadow['max']+$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowmin') && ($attribute->getValue(0) > 0) && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']+$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowexpire') && ($attribute->getValue(0) > 0)) + $shadow_date = $shadowattr->getValue(0); + + # Couldn't interpret the shadow date (could be 0 or -1 or something) + else + return false; + + return $shadow_date*24*3600; + } + + protected function drawShadowDateShadowAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $shadow_before_today_attrs = arrayLower($attribute->shadow_before_today_attrs); + $shadow_after_today_attrs = arrayLower($attribute->shadow_after_today_attrs); + $shadow_date = $this->shadow_date($attribute); + + if (! $shadow_date) + return; + + $today = date('U'); + + echo '
'; + if (($today < $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_before_today_attrs)) + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + elseif (($today > $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_after_today_attrs)) + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + else + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + echo '
'; + } + + protected function drawFormReadOnlyValueShadowAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadOnlyValueAttribute($attribute,$i); + $this->draw('ShadowDate',$attribute); + } + + protected function drawFormReadWriteValueShadowAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadWriteValueAttribute($attribute,$i); + $this->draw('ShadowDate',$attribute); + } +} +?> diff --git a/lib/PasswordAttribute.php b/lib/PasswordAttribute.php new file mode 100644 index 0000000..2667197 --- /dev/null +++ b/lib/PasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/Query.php b/lib/Query.php new file mode 100644 index 0000000..62a3d2b --- /dev/null +++ b/lib/Query.php @@ -0,0 +1,283 @@ +getServer(); + + foreach ($xmldata['query'] as $xml_key => $xml_value) { + if (DEBUG_ENABLED) + debug_log('Foreach loop Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key,is_array($xml_value)); + + switch ($xml_key) { + + # Build our attribute list from the DN and Template. + case ('attributes'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (is_array($xmldata['query'][$xml_key])) { + foreach ($xmldata['query'][$xml_key] as $tattrs) { + foreach ($tattrs as $index => $details) { + + if (DEBUG_ENABLED) + debug_log('Foreach tattrs Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__, + $index,$details); + + # If there is no schema definition for the attribute, it will be ignored. + if ($sattr = $server->getSchemaAttribute($index)) { + if (is_null($attribute = $this->getAttribute($sattr->getName()))) + $attribute = $this->addAttribute($sattr->getName(false),array('values'=>array())); + + $attribute->show(); + $attribute->setXML($details); + } + } + } + } + + break; + + # Build our bases list from the DN and Template. + case ('bases'): + if (isset($xmldata['query'][$xml_key]['base'])) + if (is_array($xmldata['query'][$xml_key]['base'])) + $this->base = $xmldata['query'][$xml_key]['base']; + else + $this->base = array($xmldata['query'][$xml_key]['base']); + else + error(sprintf(_('In the XML file (%s), [%s] contains an unknown key.'), + $this->filename,$xml_key),'error','index.php'); + + $this->base = array_unique($this->base); + break; + + default: + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + # Some key definitions need to be an array, some must not be: + $allowed_arrays = array(''); + $storelower = array(''); + $storearray = array(''); + + # Items that must be stored lowercase + if (in_array($xml_key,$storelower)) + if (is_array($xml_value)) + foreach ($xml_value as $index => $value) + $xml_value[$index] = strtolower($value); + else + $xml_value = strtolower($xml_value); + + # Items that must be stored as arrays + if (in_array($xml_key,$storearray) && ! is_array($xml_value)) + $xml_value = array($xml_value); + + # Items that should not be an array + if (! in_array($xml_key,$allowed_arrays) && is_array($xml_value)) { + debug_dump(array(__METHOD__,'key'=>$xml_key,'value'=>$xml_value)); + error(sprintf(_('In the XML file (%s), [%s] is an array, it must be a string.'), + $this->filename,$xml_key),'error'); + } + + $this->$xml_key = $xml_value; + } + } + + # Check we have some manditory items. + foreach (array() as $key) { + if (! isset($this->$key) + || (! is_array($this->$key) && ! trim($this->$key))) { + + $this->setInvalid(sprintf(_('Missing %s in the XML file.'),$key)); + break; + } + } + } + + /** + * Accept will run the query and store the results in results() + */ + public function accept() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + $query = array(); + $query['size_limit'] = get_request('size_limit','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','size_limit')); + $query['format'] = get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display')); + $query['orderby'] = get_request('orderby','REQUEST',false,'dn'); + + # If this is a custom search, we need to populate are paramters + if ($this->getID() == 'none') { + $bases = get_request('base','REQUEST',false,null); + $query['filter'] = get_request('filter','REQUEST',false,'objectClass=*'); + $query['scope'] = get_request('scope','REQUEST',false,'sub'); + $attrs = get_request('display_attrs','REQUEST'); + + $attrs = preg_replace('/\s+/','',$attrs); + if ($attrs) + $query['attrs'] = explode(',',$attrs); + else + $query['attrs'] = array('*'); + + } else { + $bases = $this->base; + $query['filter'] = $this->filter; + $query['scope'] = $this->scope; + $query['attrs'] = $this->getAttributeNames(); + } + + if (! $bases) + $bases = $server->getBaseDN(); + elseif (! is_array($bases)) + $bases = explode('|',$bases); + + foreach ($bases as $base) { + $query['base'] = $base; + + $time_start = utime(); + $this->results[$base] = $server->query($query,null); + $time_end = utime(); + + $this->resultsdata[$base]['time'] = round($time_end-$time_start,2); + $this->resultsdata[$base]['scope'] = $query['scope']; + $this->resultsdata[$base]['filter'] = $query['filter']; + $this->resultsdata[$base]['attrs'] = $query['attrs']; + + if ($this->getAttrSortOrder() == 'dn') + usort($this->results[$base],'pla_compare_dns'); + elseif ($this->getAttrSortOrder()) + masort($this->results[$base],$this->getAttrSortOrder()); + } + } + + /** + * This is temporary to get around objects that use a DN for rendering, for example jpegPhoto + */ + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->dn = $dn; + } + + /** + * This is temporary to get around objects that use a DN for rendering, for example jpegPhoto + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + return $this->dn; + } + + public function getDNEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn)); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn); + } + + public function getAttrSortOrder() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (count($this->attributes)) { + masort($this->attributes,'ordersort'); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + } else { + $display = preg_replace('/,\s+/',',',get_request('orderby','REQUEST',false,'dn')); + + if (trim($display)) + $result = explode(',',$display); + } + + return implode(',',$result); + } + + public function getAttrDisplayOrder() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (count($this->attributes)) { + masort($this->attributes,'order'); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + } else { + $display = preg_replace('/,\s+/',',',get_request('display_attrs','REQUEST',false,'')); + + if (trim($display)) + $result = explode(',',$display); + } + + # If our display order is empty, then dynamically build it + if (! count($result)) { + foreach ($this->results as $details) + foreach ($details as $attrs) + $result = array_merge($result,array_keys(array_change_key_case($attrs))); + + $result = array_unique($result); + sort($result); + } + + # Put the DN first + array_unshift($result,'dn'); + $result = array_unique($result); + + return implode(',',$result); + } + + /** + * Test if the template is visible + * + * @return boolean + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->visible); + + return $this->visible; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } +} +?> diff --git a/lib/QueryRender.php b/lib/QueryRender.php new file mode 100644 index 0000000..16660bc --- /dev/null +++ b/lib/QueryRender.php @@ -0,0 +1,557 @@ +%s
',__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [GETquery:%s]
',__METHOD__,get_request('query','REQUEST')); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Page:%s]
',__METHOD__,get_request('page','REQUEST')); + + $this->template_id = $this->getTemplateChoice(); + $this->page = get_request('page','REQUEST',false,1); + + # If we are the default template, make sure we pressed search + if ($this->template_id == 'none' && ! get_request('search','REQUEST')) + $this->drawTemplateChoice(); + + elseif ($this->template_id) { + $templates = $this->getTemplates(); + $this->template = $templates->getTemplate($this->template_id); + $this->template->accept(); + + $this->visitStart(); + $this->visitEnd(); + } + } + + /** + * Get our templates applicable for this object + */ + protected function getTemplates() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return new Queries($this->server_id); + } + + /** + * Are default queries enabled? + */ + protected function haveDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + if ($server->getValue('query','disable_default')) + return false; + else + return true; + } + + protected function drawTemplateChoice() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + + $this->drawTitle(_('Search')); + $this->drawSubTitle(); + + echo "\n"; + + $baseDNs = $server->getBaseDN(); + + printf('',JSDIR); + echo '
'; + echo '
'; + echo ''; + printf('',$server->getIndex()); + echo '
'; + + echo ''; + echo ''; + + $templates = $this->getTemplates(); + + if (count($templates->getTemplates())) { + echo ''; + printf('',_('Run a predefined query'),_('Predefined Query')); + echo ''; + echo ''; + } + + echo ''; + printf('',_('The format to show the query results'),_('Display Format')); + echo ''; + echo ''; + + echo ''; + printf('',_('Entries to show per page'),_('Show Results')); + echo ''; + echo ''; + + echo ''; + + echo ''; + echo ''; + + printf('',_('Search')); + + echo '
 
%s'; + echo ''; + echo '
%s'; + echo ''; + echo '
%s'; + echo ''; + echo '
'; + printf('
','block'); + echo '
'; + echo '
'; + printf('%s',_('Custom Query')); + echo ''; + + printf('',_('Base DN')); + printf(''; + echo ''; + + echo ''; + printf('',_('The scope in which to search'),_('Search Scope')); + + echo ''; + echo ''; + + echo ''; + printf('', + htmlspecialchars(_('Standard LDAP search filter. Example: (&(sn=Smith)(givenName=David))')),_('Search Filter')); + + printf('', + 'objectClass=*'); + + echo ''; + + echo ''; + printf('', + _('A list of attributes to display in the results (comma-separated)'),_('Show Attributes')); + + printf('', + implode(', ',$_SESSION[APPCONFIG]->getValue('search','result_attributes'))); + echo ''; + + echo ''; + printf('',_('Order by'),_('Order by')); + printf('',''); + echo ''; + + echo ''; + printf('',_('Set the search results to 0 to retrieve all available records'),_('Search Results')); + printf('',$_SESSION[APPCONFIG]->getValue('search','size_limit')); + echo ''; + + echo '
%s',count($baseDNs) == 1 ? $baseDNs[0] : ''); + + draw_chooser_link('advanced_search_form','base'); + + echo '
%s'; + echo ''; + echo '
%s
%s
%s
%s
'; + echo '
'; + echo '
'; + echo '

'; + echo '
'; + } + + private function visitStart() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->drawTitle(_('Search Results')); + $this->drawSubTitle(); + echo '
'; + } + + private function visitEnd() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $afattrs = $this->getAFAttrs(); + + # If Mass Actions Enabled + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) { + $mass_actions = array( + _('delete') => 'mass_delete', + _('edit') => 'mass_edit' + ); + } + + $this->drawBaseTabs(); + $ado = $this->template->getAttrDisplayOrder(); + $counter = 0; + $j = 0; + + foreach ($this->template->results as $base => $results) { + $counter++; + + if (! $show = get_request('show','REQUEST')) + $show = ($counter === 1 ? $this->getAjaxRef($base) : null); + + printf('
', + $this->getAjaxRef($base), ($show == $this->getAjaxRef($base) ? 'block' : 'none')); + + echo ''; + echo ''; + echo '
'; + echo '
'; + echo '
'; + + $this->drawResultsTable($base,count($results)); + + echo '
'; + echo '
'; + + switch(get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display'))) { + case 'list': + foreach ($results as $dndetails) { + $dndetails = array_change_key_case($dndetails); + + # Temporarily set our DN, for rendering that leverages our DN (eg: JpegPhoto) + $this->template->setDN($dndetails['dn']); + + echo ''; + + echo ''; + printf('',IMGDIR,get_icon($server->getIndex(),$dndetails['dn'])); + + printf('', + $server->getIndex(),$this->template->getDNEncode(),htmlspecialchars(get_rdn($dndetails['dn']))); + echo ''; + + printf('', + htmlspecialchars(dn_unescape($dndetails['dn']))); + + # Iterate over each attribute for this entry + foreach (explode(',',$ado) as $attr) { + $attr = strtolower($attr); + + # Ignore DN, we've already displayed it. + if ($attr == 'dn') + continue 2; + + if (! isset($dndetails[$attr])) + continue 2; + + # Set our object with our values + $afattrs[$attr]->clearValue(); + + if (is_array($dndetails[$attr])) + $afattrs[$attr]->initValue($dndetails[$attr]); + else + $afattrs[$attr]->initValue(array($dndetails[$attr])); + + echo ''; + echo ''; + + echo ''; + + echo ''; + echo ''; + } + + echo '
icon%s
 dn%s
 '; + $this->draw('Name',$afattrs[$attr]); + echo ''; + $this->draw('CurrentValues',$afattrs[$attr]); + echo '
'; + echo '
'; + } + + break; + + # Display the results. + case 'table': + if (! $results) { + echo _('Search returned no results'); + + continue 2; + } + + printf('
',$counter); + echo '
'; + printf('',$server->getIndex()); + + foreach ($this->template->resultsdata[$base]['attrs'] as $attr) + printf('',$attr); + + echo '
'; + + echo ''; + + echo ''; + echo ''; + echo ''; + echo ''; + + foreach (explode(',',$ado) as $attr) { + echo ''; + } + + echo ''; + echo ''; + + echo ''; + foreach ($results as $dndetails) { + $j++; + $dndetails = array_change_key_case($dndetails); + + # Temporarily set our DN, for rendering that leverages our DN (eg: JpegPhoto) + $this->template->setDN($dndetails['dn']); + + printf('', + $j%2 ? 'even' : 'odd',$j,$j); + + # Is mass action enabled. + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) + printf('',$j,$dndetails['dn']); + + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),$this->template->getDNEncode()); + printf('', + htmlspecialchars($href), + IMGDIR,get_icon($server->getIndex(),$dndetails['dn'])); + + # We'll clone our attribute factory attributes, since we need to add the values to them for rendering. + foreach (explode(',',$ado) as $attr) { + # If the entry is blank, we'll draw an empty box and continue. + if (! isset($dndetails[$attr])) { + echo ''; + continue; + } + + # Special case for DNs + if ($attr == 'dn') { + $dn_display = strlen($dndetails['dn']) > 40 + ? sprintf('%s...',htmlspecialchars($dndetails['dn']),htmlspecialchars(substr($dndetails['dn'],0,40))) + : htmlspecialchars($dndetails['dn']); + + printf('',htmlspecialchars($href),$dn_display); + continue; + } + + # Set our object with our values + $afattrs[$attr]->clearValue(); + if (is_array($dndetails[$attr])) + $afattrs[$attr]->initValue($dndetails[$attr]); + else + $afattrs[$attr]->initValue(array($dndetails[$attr])); + + echo ''; + } + + echo ''; + } + + # Is mass action enabled. + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) { + printf('',++$j%2 ? 'odd' : 'even'); + printf('',$counter); + printf(''; + echo ''; + } + + echo ''; + echo '
  '; + $this->draw('Name',$afattrs[$attr]); + echo '
icon %s'; + $this->draw('CurrentValues',$afattrs[$attr]); + echo '
',2+count(explode(',',$ado))); + + foreach ($mass_actions as $display => $action) + printf('  ',$action,$display); + + echo '
'; + echo '
'; + echo "\n\n"; + + break; + + default: + printf('Have ID [%s], run this query for page [%s]',$this->template_id,$this->page); + } + + echo '
'; + echo '
'; + echo "\n\n"; + } + + if (get_request('format','REQUEST',false,'table') == 'table') + printf('',JSDIR); + } + + public function drawSubTitle($subtitle=null) { + if (is_null($subtitle)) { + $server = $this->getServer(); + + $subtitle = sprintf('%s: %s',_('Server'),$server->getName()); + + if ($this->template) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',('Query'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + } + + parent::drawSubTitle($subtitle); + } + + private function getAFattrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute_factory = new AttributeFactory(); + $results = array(); + + foreach (explode(',',$this->template->getAttrDisplayOrder()) as $attr) + $results[strtolower($attr)] = $attribute_factory->newAttribute($attr,array('values'=>array()),$this->getServerID()); + + return $results; + } + + private function getAjaxRef($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return preg_replace('/=/','.',base64_encode($dn)); + } + + private function drawBaseTabs() { + # Setup the Javascript to show/hide our DIVs. + echo ''; + echo "\n\n"; + + echo ''; + echo ''; + $counter = 0; + foreach ($this->template->results as $base => $results) { + if (! $show = get_request('show','REQUEST')) + $show = ($counter++ === 0 ? $this->getAjaxRef($base) : null); + + printf('', + $this->getAjaxRef($base), + $this->getAjaxRef($base), + ($show == $this->getAjaxRef($base) ? '#F0F0F0' : '#E0E0E0'), + htmlspecialchars($base)); + } + echo ''; + echo '
%s
'; + echo "\n\n"; + } + + private function drawResultsTable($base,$results) { + $server = $this->getServer(); + + echo ''; + + echo ''; + printf('',_('Entries found'), + number_format($results),$this->template->resultsdata[$base]['time'],_('seconds')); + + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','export') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form')) { + $href = htmlspecialchars(sprintf('cmd.php?cmd=export_form&server_id=%s&scope=%s&dn=%s&filter=%s&attributes=%s', + $server->getIndex(),$this->template->resultsdata[$base]['scope'], + $base,rawurlencode($this->template->resultsdata[$base]['filter']), + rawurlencode(implode(', ',$this->template->resultsdata[$base]['attrs'])))); + + printf(''; + echo ''; + echo '
%s: %s

(%s %s)
[ Save %s ]', + $href,IMGDIR,_('export results')); + } + + printf('[ rename %s:',IMGDIR,_('Format')); + + foreach (array('list','table') as $f) { + echo ' '; + + if (get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display')) == $f) { + printf('%s',_($f)); + + } else { + $query_string = htmlspecialchars(sprintf('%s&format=%s&show=%s&focusbase=%s',array_to_query_string($_GET,array('format','meth')),$f,$this->getAjaxRef($base),$base)); + + if (isAjaxEnabled()) + printf('%s', + $query_string,$query_string,_('Loading Search'),_($f)); + else + printf('%s',$query_string,_($f)); + } + } + + echo ' ]'; + + echo '
'; + printf('%s: %s',_('Base DN'),htmlspecialchars($base)); + + echo '
'; + printf('%s: %s',_('Filter performed'),htmlspecialchars($this->template->resultsdata[$base]['filter'])); + + echo '
'; + } +} +?> diff --git a/lib/RandomPasswordAttribute.php b/lib/RandomPasswordAttribute.php new file mode 100644 index 0000000..ca11f8d --- /dev/null +++ b/lib/RandomPasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/SambaPasswordAttribute.php b/lib/SambaPasswordAttribute.php new file mode 100644 index 0000000..35c1a08 --- /dev/null +++ b/lib/SambaPasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/SelectionAttribute.php b/lib/SelectionAttribute.php new file mode 100644 index 0000000..5f1c8bb --- /dev/null +++ b/lib/SelectionAttribute.php @@ -0,0 +1,71 @@ +source == 'XML' && $this->values) { + $this->selection = $this->values; + $this->values = array(); + } + + if (isset($values['type']) && $values['type'] == 'multiselect') + $this->multiple = true; + else + $this->multiple = false; + } + + public function addOption($value,$description) { + $this->selection[$value] = $description; + } + + public function addValue($new_val,$i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->addOption($new_val,$i); + } + + public function getOptionCount() { + return count($this->selection); + } + + public function getSelection() { + return $this->selection; + } + + public function autoValue($value) { + $this->selection = $value; + } + + public function getDefault() { + return $this->default; + } + + public function isMultiple() { + return $this->multiple; + } + + public function setMultiple() { + $this->multiple = true; + } +} +?> diff --git a/lib/ShadowAttribute.php b/lib/ShadowAttribute.php new file mode 100644 index 0000000..eeb7cd1 --- /dev/null +++ b/lib/ShadowAttribute.php @@ -0,0 +1,19 @@ + diff --git a/lib/Template.php b/lib/Template.php new file mode 100644 index 0000000..a9f7a17 --- /dev/null +++ b/lib/Template.php @@ -0,0 +1,1571 @@ +noleaf = $_SESSION[APPCONFIG]->getValue('appearance','disable_default_leaf'); + } + + public function __clone() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # We need to clone our attributes, when passing back a template with getTemplate + foreach ($this->attributes as $key => $value) + $this->attributes[$key] = clone $value; + } + + /** + * Main processing to store the template. + * + * @param xmldata Parsed xmldata from xml2array object + */ + protected function storeTemplate($xmldata) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $objectclasses = array(); + + foreach ($xmldata['template'] as $xml_key => $xml_value) { + if (DEBUG_ENABLED) + debug_log('Foreach loop Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key,is_array($xml_value)); + + switch ($xml_key) { + # Build our object Classes from the DN and Template. + case ('objectclasses'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (isset($xmldata['template'][$xml_key]['objectclass'])) + if (is_array($xmldata['template'][$xml_key]['objectclass'])) { + foreach ($xmldata['template'][$xml_key]['objectclass'] as $index => $details) { + + # XML files with only 1 objectClass dont have a numeric index. + $soc = $server->getSchemaObjectClass(strtolower($details)); + + # If we havent recorded this objectclass already, do so now. + if (is_object($soc) && ! in_array($soc->getName(),$objectclasses)) + array_push($objectclasses,$soc->getName(false)); + + elseif (! is_object($soc) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>_('Automatically removed objectClass from template'), + 'body'=>sprintf('%s: %s %s',$this->getTitle(),$details,_('removed from template as it is not defined in the schema')), + 'type'=>'warn')); + } + + } else { + # XML files with only 1 objectClass dont have a numeric index. + $soc = $server->getSchemaObjectClass(strtolower($xmldata['template'][$xml_key]['objectclass'])); + + # If we havent recorded this objectclass already, do so now. + if (is_object($soc) && ! in_array($soc->getName(),$objectclasses)) + array_push($objectclasses,$soc->getName(false)); + } + + break; + + # Build our attribute list from the DN and Template. + case ('attributes'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (is_array($xmldata['template'][$xml_key])) { + foreach ($xmldata['template'][$xml_key] as $tattrs) + foreach ($tattrs as $index => $details) { + if (DEBUG_ENABLED) + debug_log('Foreach tattrs Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__, + $index,$details); + + # If there is no schema definition for the attribute, it will be ignored. + if ($sattr = $server->getSchemaAttribute($index)) + if (is_null($this->getAttribute($sattr->getName()))) + $this->addAttribute($sattr->getName(),$details,'XML'); + } + + masort($this->attributes,'order'); + } + + break; + + default: + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + # Some key definitions need to be an array, some must not be: + $allowed_arrays = array('rdn'); + $storelower = array('rdn'); + $storearray = array('rdn'); + + # Items that must be stored lowercase + if (in_array($xml_key,$storelower)) + if (is_array($xml_value)) + foreach ($xml_value as $index => $value) + $xml_value[$index] = strtolower($value); + else + $xml_value = strtolower($xml_value); + + # Items that must be stored as arrays + if (in_array($xml_key,$storearray) && ! is_array($xml_value)) + $xml_value = array($xml_value); + + # Items that should not be an array + if (! in_array($xml_key,$allowed_arrays) && is_array($xml_value)) { + debug_dump(array(__METHOD__,'key'=>$xml_key,'value'=>$xml_value)); + error(sprintf(_('In the XML file (%s), [%s] is an array, it must be a string.'), + $this->filename,$xml_key),'error'); + } + + $this->$xml_key = $xml_value; + + if ($xml_key == 'invalid' && $xml_value) + $this->setInvalid(_('Disabled by XML configuration'),true); + } + } + + if (! count($objectclasses)) { + $this->setInvalid(_('ObjectClasses in XML dont exist in LDAP server.')); + return; + + } else { + $attribute = $this->addAttribute('objectClass',array('values'=>$objectclasses),'XML'); + $attribute->justModified(); + $attribute->setRequired(); + $attribute->hide(); + } + + $this->rebuildTemplateAttrs(); + + # Check we have some manditory items. + foreach (array('rdn','structural_oclass','visible') as $key) { + if (! isset($this->$key) + || (! is_array($this->$key) && ! trim($this->$key))) { + + $this->setInvalid(sprintf(_('Missing %s in the XML file.'),$key)); + break; + } + } + + # Mark our RDN attributes as RDN + $counter = 1; + foreach ($this->rdn as $key) { + if ((is_null($attribute = $this->getAttribute($key))) && (in_array_ignore_case('extensibleobject',$this->getObjectClasses()))) { + $attribute = $this->addAttribute($key,array('values'=>array())); + $attribute->show(); + } + + if (! is_null($attribute)) + $attribute->setRDN($counter++); + elseif ($this->isType('creation')) + $this->setInvalid(sprintf(_('Missing RDN attribute %s in the XML file.'),$key)); + } + } + + /** + * Is default templates enabled? + * This will disable the default template from the engine. + * + * @return boolean + */ + protected function hasDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template')) + return false; + else + return true; + } + + /** + * Return the templates of type (creation/modification) + * + * @param $string type - creation/modification + * @return array - Array of templates of that type + */ + protected function readTemplates($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $template_xml = new Templates($this->server_id); + return $template_xml->getTemplates($type); + } + + /** + * This function will perform the following intialisation steps: + * + If a DN is set, query the ldap and load the object + * + Read our $_REQUEST variable and set the values + * After this action, the template should self describe as to whether it is an update, create + * or delete. + * (OLD values are IGNORED, we will have got them when we build this object from the LDAP server DN.) + */ + public function accept($makeVisible=false,$nocache=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # If a DN is set, then query the LDAP server for the details. + if ($this->dn) { + if (! $server->dnExists($this->dn)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>sprintf('DN (%s) didnt exist in LDAP?',$this->dn), + 'type'=>'info')); + + $rdnarray = rdn_explode(strtolower(get_rdn(dn_escape($this->dn)))); + + $counter = 1; + foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('*'),$server->getValue('server','custom_attrs')),$nocache) as $attr => $values) { + # We ignore DNs. + if ($attr == 'dn') + continue; + + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$values)); + else + if ($attribute->getValues()) { + # Override values to those that are defined in the XML file. + if ($attribute->getSource() != 'XML') + $attribute->setValue(array_values($values)); + else + $attribute->setOldValue(array_values($values)); + + } else + $attribute->initValue(array_values($values)); + + # Work out the RDN attributes + foreach ($attribute->getValues() as $index => $value) + if (in_array(sprintf('%s=%s', + $attribute->getName(),strtolower($attribute->getValue($index))),$rdnarray)) + $attribute->setRDN($counter++); + + if ($makeVisible) + $attribute->show(); + } + + # Get the Internal Attributes + foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('+'),$server->getValue('server','custom_sys_attrs'))) as $attr => $values) { + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$values)); + else + if ($attribute->getValues()) + $attribute->setValue(array_values($values)); + else + $attribute->initValue(array_values($values)); + + if (! in_array_ignore_case($attribute->getName(),$server->getValue('server','custom_attrs'))) + $attribute->setInternal(); + } + + # If this is the default template, and our $_REQUEST has defined our objectclass, then query the schema to get the attributes + } elseif ($this->container) { + if ($this->isType('default') && ! count($this->getAttributes(true)) && isset($_REQUEST['new_values']['objectclass'])) { + $attribute = $this->addAttribute('objectclass',array('values'=>$_REQUEST['new_values']['objectclass'])); + $attribute->justModified(); + $this->rebuildTemplateAttrs(); + unset($_REQUEST['new_values']['objectclass']); + } + + } elseif (get_request('create_base')) { + if (get_request('rdn')) { + $rdn = explode('=',get_request('rdn')); + $attribute = $this->addAttribute($rdn[0],array('values'=>array($rdn[1]))); + $attribute->setRDN(1); + } + + } else { + debug_dump_backtrace('No DN or CONTAINER?',1); + } + + # Read in our new values. + foreach (array('new_values') as $key) { + if (isset($_REQUEST[$key])) + foreach ($_REQUEST[$key] as $attr => $values) { + # If it isnt an array, silently ignore it. + if (! is_array($values)) + continue; + + # If _REQUEST['skip_array'] with this attr set, we'll ignore this new_value + if (isset($_REQUEST['skip_array'][$attr]) && $_REQUEST['skip_array'][$attr] == 'on') + continue; + + # Prune out entries with a blank value. + foreach ($values as $index => $value) + if (! strlen(trim($value))) + unset($values[$index]); + + $attribute = $this->getAttribute($attr); + # If the attribute is null, then no attribute exists, silently ignore it (unless this is the default template) + if (is_null($attribute) && (! $this->isType('default') && ! $this->isType(null))) + continue; + + # If it is a binary attribute, the post should have base64 encoded the value, we'll need to reverse that + if ($server->isAttrBinary($attr)) + foreach ($values as $index => $value) + $values[$index] = base64_decode($value); + + if (is_null($attribute)) { + $attribute = $this->addAttribute($attr,array('values'=>$values)); + + if (count($values)) + $attribute->justModified(); + + } else + $attribute->setValue(array_values($values)); + } + + # Read in our new binary values + if (isset($_FILES[$key]['name'])) + foreach ($_FILES[$key]['name'] as $attr => $values) { + $new_values = array(); + + foreach ($values as $index => $details) { + # Ignore empty files + if (! $_FILES[$key]['size'][$attr][$index]) + continue; + + if (! is_uploaded_file($_FILES[$key]['tmp_name'][$attr][$index])) { + if (isset($_FILES[$key]['error'][$attr][$index])) + switch($_FILES[$key]['error'][$attr][$index]) { + + # No error; possible file attack! + case 0: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + + # Uploaded file exceeds the upload_max_filesize directive in php.ini + case 1: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file exceeds the MAX_FILE_SIZE directive specified in the html form + case 2: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file was only partially uploaded + case 3: + $msg = _('The file you selected was only partially uploaded, likley due to a network error.'); + break; + + # No file was uploaded + case 4: + $msg = _('You left the attribute value blank. Please go back and try again.'); + break; + + # A default error, just in case! :) + default: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + } + + else + $msg = _('Security error: The file being uploaded may be malicious.'); + + system_message(array( + 'title'=>_('Upload Binary Attribute Error'),'body'=>$msg,'type'=>'warn')); + + } else { + $binaryfile = array(); + $binaryfile['name'] = $_FILES[$key]['tmp_name'][$attr][$index]; + $binaryfile['handle'] = fopen($binaryfile['name'],'r'); + $binaryfile['data'] = fread($binaryfile['handle'],filesize($binaryfile['name'])); + fclose($binaryfile['handle']); + + $new_values[$index] = $binaryfile['data']; + } + } + + if (count($new_values)) { + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$new_values)); + else + foreach ($new_values as $value) + $attribute->addValue($value); + + $attribute->justModified(); + } + } + } + + # If there are any single item additions (from the add_attr form for example) + if (isset($_REQUEST['single_item_attr'])) { + if (isset($_REQUEST['single_item_value'])) { + if (! is_array($_REQUEST['single_item_value'])) + $values = array($_REQUEST['single_item_value']); + else + $values = $_REQUEST['single_item_value']; + + } elseif (isset($_REQUEST['binary'])) { + /* Special case for binary attributes (like jpegPhoto and userCertificate): + * we must go read the data from the file and override $_REQUEST['single_item_value'] with the + * binary data. Secondly, we must check if the ";binary" option has to be appended to the name + * of the attribute. */ + + if ($_FILES['single_item_value']['size'] === 0) + system_message(array( + 'title'=>_('Upload Binary Attribute Error'), + 'body'=>sprintf('%s %s',_('The file you chose is either empty or does not exist.'),_('Please go back and try again.')), + 'type'=>'warn')); + + else { + if (! is_uploaded_file($_FILES['single_item_value']['tmp_name'])) { + if (isset($_FILES['single_item_value']['error'])) + switch($_FILES['single_item_value']['error']) { + + # No error; possible file attack! + case 0: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + + # Uploaded file exceeds the upload_max_filesize directive in php.ini + case 1: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file exceeds the MAX_FILE_SIZE directive specified in the html form + case 2: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file was only partially uploaded + case 3: + $msg = _('The file you selected was only partially uploaded, likley due to a network error.'); + break; + + # No file was uploaded + case 4: + $msg = _('You left the attribute value blank. Please go back and try again.'); + break; + + # A default error, just in case! :) + default: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + } + + else + $msg = _('Security error: The file being uploaded may be malicious.'); + + system_message(array( + 'title'=>_('Upload Binary Attribute Error'),'body'=>$msg,'type'=>'warn'),'index.php'); + } + + $binaryfile = array(); + $binaryfile['name'] = $_FILES['single_item_value']['tmp_name']; + $binaryfile['handle'] = fopen($binaryfile['name'],'r'); + $binaryfile['data'] = fread($binaryfile['handle'],filesize($binaryfile['name'])); + fclose($binaryfile['handle']); + + $values = array($binaryfile['data']); + } + } + + if (count($values)) { + $attribute = $this->getAttribute($_REQUEST['single_item_attr']); + + if (is_null($attribute)) + $attribute = $this->addAttribute($_REQUEST['single_item_attr'],array('values'=>$values)); + else + $attribute->setValue(array_values($values)); + + $attribute->justModified(); + } + } + + # If this is the default creation template, we need to set some additional values + if ($this->isType('default') && $this->getContext() == 'create') { + # Load our schema, based on the objectclasses that may have already been defined. + if (! get_request('create_base')) + $this->rebuildTemplateAttrs(); + + # Set the RDN attribute + $counter = 1; + foreach (get_request('rdn_attribute','REQUEST',false,array()) as $key => $value) { + $attribute = $this->getAttribute($value); + + if (! is_null($attribute)) + $attribute->setRDN($counter++); + + else { + system_message(array( + 'title'=>_('No RDN attribute'), + 'body'=>_('No RDN attribute was selected'), + 'type'=>'warn'),'index.php'); + + die(); + } + } + } + } + + /** + * Set the DN for this template, if we are editing entries + * + * @param dn The DN of the entry + */ + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->container)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'CONTAINER set while setting DN', + 'type'=>'info')); + + $this->dn = $dn; + } + + /** + * Set the RDN attributes + * Given an RDN, mark the attributes as RDN attributes. If there is no defined attribute, + * then the remaining RDNs will be returned. + * + * @param RDN + * @return RDN attributes not processed + */ + public function setRDNAttributes($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Setup to work out our RDN. + $rdnarray = rdn_explode($rdn); + + $counter = 1; + foreach ($this->getAttributes(true) as $attribute) + foreach ($rdnarray as $index => $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + + if (strtolower($attr) == $attribute->getName()) { + $attribute->setRDN($counter++); + unset($rdnarray[$index]); + } + } + + return $rdnarray; + } + + /** + * Display the DN for this template entry. If the DN is not set (creating a new entry), then + * a generated DN will be produced, taken from the RDN and the CONTAINER details. + * + * @return dn + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + if ($this->dn) + return $this->dn; + + # If DN is not set, our DN will be made from our RDN and Container. + elseif ($this->getRDN() && $this->getContainer()) + return sprintf('%s,%s',$this->getRDN(),$this->GetContainer()); + + # If container is not set, we're probably creating the base + elseif ($this->getRDN() && get_request('create_base')) + return $this->getRDN(); + } + + public function getDNEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN())); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN()); + } + + /** + * Set the container for this template, if we are creating entries + * + * @param dn The DN of the container + * @todo Trigger a query to the LDAP server and generate an error if the container doesnt exist + */ + public function setContainer($container) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->dn)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'DN set while setting CONTAINER', + 'type'=>'info')); + + $this->container = $container; + } + + /** + * Get the DN of the container for this entry + * + * @return dn DN of the container + */ + public function getContainer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->container); + + return $this->container; + } + + public function getContainerEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->container)); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->container); + } + + /** + * Copy a DN + */ + public function copy($template,$rdn,$asnew=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $rdnarray = rdn_explode($rdn); + + $counter = 1; + foreach ($template->getAttributes(true) as $sattribute) { + $attribute = $this->addAttribute($sattribute->getName(false),array('values'=>$sattribute->getValues())); + + # Set our new RDN, and its values + if (is_null($attribute)) { + debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?'); + + } else { + + # Mark our internal attributes. + if ($sattribute->isInternal()) + $attribute->setInternal(); + + $modified = false; + foreach ($rdnarray as $index => $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + if (strtolower($attr) == $attribute->getName()) { + + # If this is already marked as an RDN, then this multivalue RDN was updated on a previous loop + if (! $modified) { + $attribute->setValue(array($value)); + $attribute->setRDN($counter++); + $modified = true; + + } else { + $attribute->addValue($value); + } + + # This attribute has been taken care of, we'll drop it from our list. + unset($rdnarray[$index]); + } + } + } + + // @todo If this is a Jpeg Attribute, we need to mark it read only, since it cant be deleted like text attributes can + if (strcasecmp(get_class($attribute),'jpegAttribute') == 0) + $attribute->setReadOnly(); + } + + # If we have any RDN values left over, there werent in the original entry and need to be added. + foreach ($rdnarray as $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + + $attribute = $this->addAttribute($attr,array('values'=>array($value))); + + if (is_null($attribute)) + debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?'); + else + $attribute->setRDN($counter++); + } + + # If we are copying into a new entry, we need to discard all the "old values" + if ($asnew) + foreach ($this->getAttributes(true) as $sattribute) + $sattribute->setOldValue(array()); + } + + /** + * Get Attributes by LDAP type + * This function will return a list of attributes by LDAP type (MUST,MAY). + * + * @return array Array of attributes. + */ + function getAttrbyLdapType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $index => $attribute) { + if ($attribute->getLDAPtype() == strtolower($type)) + array_push($result,$attribute->getName()); + } + + return $result; + } + + /** + * Return true if this is a MUST,MAY attribute + */ + function isAttrType($attr,$type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array(strtolower($attr),$this->getAttrbyLdapType($type))) + return true; + else + return false; + } + + /** + * Return the attributes that comprise the RDN. + * + * @return array Array of RDN objects + */ + private function getRDNObjects() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isRDN()) + array_push($return,$attribute); + + masort($return,'rdn'); + return $return; + } + + /** + * Get all the RDNs for this template, in RDN order. + * + * @return array RDNs in order. + */ + public function getRDNAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->getRDNObjects() as $attribute) { + # We'll test if two RDN's have the same number (we cant test anywhere else) + if (isset($return[$attribute->isRDN()]) && $this->getType() == 'creation') + system_message(array( + 'title'=>_('RDN attribute sequence already defined'), + 'body'=>sprintf('%s %s', + sprintf(_('There is a problem in template [%s].'),$this->getName()), + sprintf(_('RDN attribute sequence [%s] is already used by attribute [%s] and cant be used by attribute [%s] also.'), + $attribute->isRDN(),$return[$attribute->isRDN()],$attribute->getName())), + 'type'=>'error'),'index.php'); + + $return[$attribute->isRDN()] = $attribute->getName(); + } + + return $return; + } + + /** + * Return the RDN for this template. If the DN is already defined, then the RDN will be calculated from it. + * If the DN is not set, then the RDN will be calcuated from the template attribute definitions + * + * @return rdn RDN for this template + */ + public function getRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If the DN is set, then the RDN will be calculated from it. + if ($this->dn) + return get_rdn($this->dn); + + $rdn = ''; + + foreach ($this->getRDNObjects() as $attribute) { + $vals = $attribute->getValues(); + + # If an RDN attribute has no values, return with an empty string. The calling script should handle this. + if (! count($vals)) + return ''; + + foreach ($vals as $val) + $rdn .= sprintf('%s=%s+',$attribute->getName(false),$val); + } + + # Chop the last plus sign off when returning + return preg_replace('/\+$/','',$rdn); + } + + /** + * Return the attribute name part of the RDN + */ + public function getRDNAttributeName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr = array(); + + if ($this->getDN()) { + $i = strpos($this->getDN(),','); + if ($i !== false) { + $attrs = explode('\+',substr($this->getDN(),0,$i)); + foreach ($attrs as $id => $attr) { + list ($name,$value) = explode('=',$attr); + $attrs[$id] = $name; + } + + $attr = array_unique($attrs); + } + } + + return $attr; + } + + /** + * Determine the type of template this is + */ + public function getContext() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getContainer() && get_request('cmd','REQUEST') == 'copy') + return 'copyasnew'; + elseif ($this->getContainer() || get_request('create_base')) + return 'create'; + elseif ($this->getDN()) + return 'edit'; + else + return 'unknown'; + } + + /** + * Test if the template is visible + * + * @return boolean + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->visible); + + return $this->visible; + } + + public function setVisible() { + $this->visible = true; + } + + public function setInvisible() { + $this->visible = false; + } + + public function getRegExp() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->regexp); + + return $this->regexp; + } + + /** + * Test if this template has been marked as a read-only template + */ + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ((($this->getContext() == 'edit') && $this->readonly) || $this->getServer()->isReadOnly()) + return true; + else + return false; + } + + /** + * Get the attribute entries + * + * @param boolean Include the optional attributes + * @return array Array of attributes + */ + public function getAttributes($optional=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($optional) + return $this->attributes; + + $result = array(); + foreach ($this->attributes as $attribute) { + if (! $attribute->isRequired()) + continue; + + array_push($result,$attribute); + } + + return $result; + } + + /** + * Return a list of attributes that should be shown + */ + public function getAttributesShown() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isVisible()) + array_push($result,$attribute); + + return $result; + } + + /** + * Return a list of the internal attributes + */ + public function getAttributesInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isInternal()) + array_push($result,$attribute); + + return $result; + } + + /** + * Return the objectclasses defined in this template + * + * @return array Array of Objects + */ + public function getObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute('objectclass'); + if ($attribute) + return $attribute->getValues(); + else + return array(); + } + + /** + * Get template icon + */ + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + return isset($this->icon) ? sprintf('%s/%s',IMGDIR,$this->icon) : ''; + } + + /** + * Return the template description + * + * @return string Description + */ + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + /** + * Set a template as invalid + * + * @param string Message indicating the reason the template has been invalidated + */ + public function setInvalid($msg,$admin=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->invalid = true; + $this->invalid_reason = $msg; + $this->invalid_admin = $admin; + } + + /** + * Get the template validity or the reason it is invalid + * + * @return string Invalid reason, or false if not invalid + */ + public function isInValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->invalid) + return $this->invalid_reason; + else + return false; + } + + public function isAdminDisabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->invalid_admin); + + return $this->invalid_admin; + } + + /** + * Set the minimum number of values for an attribute + * + * @param object Attribute + * @param int + */ + private function setMinValueCount($attr,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($attr); + + if (! is_null($attribute)) + $attribute->setMinValueCount($value); + } + + /** + * Set the LDAP type property for an attribute + * + * @param object Attribute + * @param string (MUST,MAY,OPTIONAL) + */ + private function setAttrLDAPtype($attr,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>array())); + + $attribute->setLDAPtype($value); + } + + /** + * OnChangeAdd javascript processing + */ + public function OnChangeAdd($origin,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($origin); + + if (preg_match('/^=(\w+)\((.*)\)$/',$value,$matches)) { + $command = $matches[1]; + $arg = $matches[2]; + } else + return; + + switch ($command) { + /* + autoFill:string + string is a literal string, and may contain many fields like %attr|start-end/flags% + to substitute values read from other fields. + |start-end is optional, but must be present if the k flag is used. + /flags is optional. + + flags may be: + T: Read display text from selection item (drop-down list), otherwise, read the value of the field + For fields that aren't selection items, /T shouldn't be used, and the field value will always be read. + k: Tokenize: + If the "k" flag is not given: + A |start-end instruction will perform a sub-string operation upon + the value of the attr, passing character positions start-end through. + start can be 0 for first character, or any other integer. + end can be 0 for last character, or any other integer for a specific position. + If the "k" flag is given: + The string read will be split into fields, using : as a delimiter + "start" indicates which field number to pass through. + K: The string read will be split into fields, using ' ' as a delimiter "start" indicates which field number to pass through. + l: Make the result lower case. + U: Make the result upper case. + */ + case 'autoFill': + if (! preg_match('/;/',$arg)) { + system_message(array( + 'title'=>_('Problem with autoFill() in template'), + 'body'=>sprintf('%s (%s)',_('There is only 1 argument, when there should be two'),$attribute->getName(false)), + 'type'=>'warn')); + + return; + } + + list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U',$string,$matchall); + //print"
";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod
+
+				if (! isset($attribute->js['autoFill']))
+					$attribute->js['autoFill'] = '';
+
+				$formula = $string;
+				$formula = preg_replace('/^([^%])/','\'$1',$formula);
+				$formula = preg_replace('/([^%])$/','$1\'',$formula);
+
+				# Check that our attributes match our schema attributes.
+				foreach ($matchall[1] as $index => $checkattr) {
+					$sattr = $this->getServer()->getSchemaAttribute($checkattr);
+
+					# If the attribute is the same as in the XML file, then dont need to do anything.
+					if (! $sattr || ! strcasecmp($sattr->getName(),$checkattr))
+						continue;
+
+					$formula = preg_replace("/$checkattr/",$sattr->getName(),$formula);
+					$matchall[1][$index] = $sattr->getName();
+				}
+
+				$elem_id = 0;
+
+				foreach ($matchall[0] as $index => $null) {
+					$match_attr = strtolower($matchall[1][$index]);
+					$match_subst = $matchall[2][$index];
+					$match_mod = $matchall[3][$index];
+
+					$substrarray = array();
+
+					if (! isset($varcount[$match_attr]))
+						$varcount[$match_attr] = 0;
+					else
+						$varcount[$match_attr]++;
+
+					$js_match_attr = $match_attr;
+					$match_attr = $js_match_attr.'xx'.$varcount[$match_attr];
+
+					$formula = preg_replace('/%'.$js_match_attr.'([|\/%])/i','%'.$match_attr.'$1',$formula,1);
+
+					$attribute->js['autoFill'] .= sprintf("  var %s;\n",$match_attr);
+					$attribute->js['autoFill'] .= sprintf(
+							"  var elem$elem_id = document.getElementById(pre+'%s'+suf);\n".
+							"  if (!elem$elem_id) return;\n", $js_match_attr);
+
+					if (strstr($match_mod,'T')) {
+						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.options[elem$elem_id.selectedIndex].text;\n",
+							$match_attr);
+					} else {
+						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.value;\n",$match_attr);
+					}
+
+					$elem_id++;
+
+					if (strstr($match_mod,'k')) {
+						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
+						if (isset($substrarray[1][0])) {
+							$tok_idx = $substrarray[1][0];
+						} else {
+							$tok_idx = '0';
+						}
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.split(':')[%s];\n",$match_attr,$match_attr,$tok_idx);
+
+					} elseif (strstr($match_mod,'K')) {
+						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray); 
+						if (isset($substrarray[1][0])) { 
+							$tok_idx = $substrarray[1][0]; 
+						} else { 
+							$tok_idx = '0'; 
+						} 
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.split(' ')[%s];\n",$match_attr,$match_attr,$tok_idx); 
+
+					} else {
+						preg_match_all('/([0-9]*)-([0-9]*)/',trim($match_subst),$substrarray);
+						if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
+							$attribute->js['autoFill'] .= sprintf("   %s = %s.substr(%s,%s);\n",
+								$match_attr,$match_attr,
+								$substrarray[1][0] ? $substrarray[1][0] : '0',
+								$substrarray[2][0] ? $substrarray[2][0] : sprintf('%s.length',$match_attr));
+						}
+					}
+
+					if (strstr($match_mod,'l')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.toLowerCase();\n",$match_attr,$match_attr);
+					}
+					if (strstr($match_mod,'U')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.toUpperCase();\n",$match_attr,$match_attr);
+					}
+					if (strstr($match_mod,'A')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = toAscii(%s);\n",$match_attr,$match_attr);
+					}
+
+					# Matchfor only entry without modifiers.
+					$formula = preg_replace('/^%('.$match_attr.')%$/U','$1 + \'\'',$formula);
+					# Matchfor only entry with modifiers.
+					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','$1 + \'\'',$formula);
+					# Matchfor begining entry.
+					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U','$1 + \'',$formula);
+					# Matchfor ending entry.
+					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','\' + $1 ',$formula);
+					# Match for entries not at begin/end.
+					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[:lTUA]+)?%/U','\' + $1 + \'',$formula);
+					$attribute->js['autoFill'] .= "\n";
+				}
+
+				$attribute->js['autoFill'] .= sprintf(" fillRec(pre+'%s'+suf, %s); // %s\n",strtolower($attr),$formula,$string);
+				$attribute->js['autoFill'] .= "\n";
+				break;
+
+			default: $return = '';
+		}
+	}
+
+	/**
+	 * This functions main purpose is to discover our MUST attributes based on objectclass
+	 * definitions in the template file and to discover which of the objectclasses are
+	 * STRUCTURAL - without one, creating an entry will just product an LDAP error.
+	 */
+	private function rebuildTemplateAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$server = $this->getServer();
+
+		# Collect our structural, MUST & MAY attributes.
+		$oclass_processed = array();
+		$superclasslist = array();
+		$allattrs = array('objectclass');
+
+		foreach ($this->getObjectClasses() as $oclass) {
+			# If we get some superclasses - then we'll need to go through them too.
+			$supclass = true;
+			$inherited = false;
+
+			while ($supclass) {
+				$soc = $server->getSchemaObjectClass($oclass);
+
+				if ($soc->getType() == 'structural' && (! $inherited))
+					array_push($this->structural_oclass,$oclass);
+
+				# Make sure our MUST attributes are marked as such for this template.
+				if ($soc->getMustAttrs())
+					foreach ($soc->getMustAttrs() as $index => $details) {
+						$objectclassattr = $details->getName();
+
+						# We add the 'objectClass' attribute, only if it's explicitly in the template attribute list
+						if ((strcasecmp('objectClass',$objectclassattr) != 0) ||
+								((strcasecmp('objectClass',$objectclassattr) == 0) && (! is_null($this->getAttribute($objectclassattr))))) {
+
+							# Go through the aliases, and ignore any that are already defined.
+							$ignore = false;
+							$sattr = $server->getSchemaAttribute($objectclassattr);
+							foreach ($sattr->getAliases() as $alias) {
+								if ($this->isAttrType($alias,'must')) {
+									$ignore = true;
+									break;
+								}
+							}
+
+							if ($ignore)
+								continue;
+
+							$this->setAttrLDAPtype($sattr->getName(),'must');
+							$this->setMinValueCount($sattr->getName(),1);
+
+							# We need to mark the attributes as show, except for the objectclass attribute.
+							if (strcasecmp('objectClass',$objectclassattr) != 0) {
+								$attribute = $this->getAttribute($sattr->getName());
+								$attribute->show();
+							}
+						}
+
+						if (! in_array($objectclassattr,$allattrs))
+							array_push($allattrs,$objectclassattr);
+					}
+
+				if ($soc->getMayAttrs())
+					foreach ($soc->getMayAttrs() as $index => $details) {
+						$objectclassattr = $details->getName();
+						$sattr = $server->getSchemaAttribute($objectclassattr);
+
+						# If it is a MUST attribute, skip to the next one.
+						if ($this->isAttrType($objectclassattr,'must'))
+							continue;
+
+						if (! $this->isAttrType($objectclassattr,'may'))
+							$this->setAttrLDAPtype($sattr->getName(false),'may');
+
+						if (! in_array($objectclassattr,$allattrs))
+							array_push($allattrs,$objectclassattr);
+					}
+
+				# Keep a list to objectclasses we have processed, so we dont get into a loop.
+				array_push($oclass_processed,$oclass);
+				$supoclasses = $soc->getSupClasses();
+
+				if (count($supoclasses) || count($superclasslist)) {
+					foreach ($supoclasses as $supoclass) {
+						if (! in_array($supoclass,$oclass_processed))
+							$superclasslist[] = $supoclass;
+					}
+
+					$oclass = array_shift($superclasslist);
+					if ($oclass)
+						$inherited = true;
+					else
+						$supclass = false;
+
+				} else {
+					$supclass = false;
+				}
+			}
+		}
+
+		# Check that attributes are defined by an ObjectClass
+		foreach ($this->getAttributes(true) as $index => $attribute)
+			if (! in_array($attribute->getName(),$allattrs) && (! array_intersect($attribute->getAliases(),$allattrs))
+				&& (! in_array_ignore_case('extensibleobject',$this->getObjectClasses()))
+				&& (! in_array_ignore_case($attribute->getName(),$server->getValue('server','custom_attrs')))) {
+				unset($this->attributes[$index]);
+
+				if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
+					system_message(array(
+						'title'=>_('Automatically removed attribute from template'),
+						'body'=>sprintf('%s: %s %s',$this->getTitle(),$attribute->getName(false),_('removed from template as it is not defined by an ObjectClass')),
+						'type'=>'warn'));
+			}
+	}
+
+	/**
+	 * Return an array, that can be passed to ldap_add().
+	 * Attributes with empty values will be excluded.
+	 */
+	public function getLDAPadd($attrsOnly=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = array();
+		$returnattrs = array();
+
+		if ($attrsOnly && count($returnattrs))
+			return $returnattrs;
+
+		foreach ($this->getAttributes(true) as $attribute)
+			if (! $attribute->isInternal() && count($attribute->getValues())) {
+				$return[$attribute->getName()] = $attribute->getValues();
+				$returnattrs[$attribute->getName()] = $attribute;
+			}
+
+		# Ensure that our objectclasses has "top".
+		if (isset($return['objectclass']) && ! in_array('top',$return['objectclass']))
+			array_push($return['objectclass'],'top');
+
+		if ($attrsOnly)
+			return $returnattrs;
+
+		return $return;
+	}
+
+	/**
+	 * Return an array, that can be passed to ldap_mod_replace().
+	 * Only attributes that have changed their value will be returned.
+	 *
+	 * This function will cache its results, so that it can be called with count() to see
+	 * if there are changes, and if they are, the 2nd call will just return the results
+	 *
+	 * @param boolean Return the attribute objects (useful for a confirmation process), or the modification array for ldap_modify()
+	 */
+	public function getLDAPmodify($attrsOnly=false,$index=0) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $return = array();
+		static $returnattrs = array();
+
+		if ($attrsOnly && isset($returnattrs[$index]) && count($returnattrs[$index]))
+			return $returnattrs[$index];
+
+		$returnattrs[$index] = array();
+		$return[$index] = array();
+
+		# If an objectclass is being modified, we need to remove all the orphan attributes that would result.
+		if ($this->getAttribute('objectclass')->hasBeenModified()) {
+			$attr_to_keep = array();
+			$server = $this->getServer();
+
+			# Make sure that there will be a structural object class remaining.
+			$haveStructural = false;
+			foreach ($this->getAttribute('objectclass')->getValues() as $value) {
+				$soc = $server->getSchemaObjectClass($value);
+
+				if ($soc) {
+					if ($soc->isStructural())
+						$haveStructural = true;
+
+					# While we are looping, workout which attributes these objectclasses define.
+					foreach ($soc->getMustAttrs(true) as $value)
+						if (! in_array($value->getName(),$attr_to_keep))
+							array_push($attr_to_keep,$value->getName());
+
+					foreach ($soc->getMayAttrs(true) as $value)
+						if (! in_array($value->getName(),$attr_to_keep))
+							array_push($attr_to_keep,$value->getName());
+				}
+			}
+
+			if (! $haveStructural)
+				error(_('An entry should have one structural objectClass.'),'error','index.php');
+
+			# Work out the attributes to delete.
+			foreach ($this->getAttribute('objectclass')->getRemovedValues() as $value) {
+				$soc = $server->getSchemaObjectClass($value);
+
+				foreach ($soc->getMustAttrs() as $value) {
+					$attribute = $this->getAttribute($value->getName());
+
+					if ($attribute && (! in_array($value->getName(),$attr_to_keep)) && ($value->getName() != 'objectclass'))
+						#array_push($attr_to_delete,$value->getName(false));
+						$attribute->setForceDelete();
+				}
+
+				foreach ($soc->getMayAttrs() as $value) {
+					$attribute = $this->getAttribute($value->getName());
+
+					if ($attribute && (! in_array($value->getName(),$attr_to_keep)) && ($value->getName() != 'objectclass'))
+						$attribute->setForceDelete();
+				}
+			}
+		}
+
+		foreach ($this->getAttributes(true) as $attribute)
+			if ($attribute->hasBeenModified()
+				&& (count(array_diff($attribute->getValues(),$attribute->getOldValues())) || ! count($attribute->getValues())
+					|| $attribute->isForceDelete() || (count($attribute->getValues()) != count($attribute->getOldValues()))))
+				$returnattrs[$index][$attribute->getName()] = $attribute;
+
+		if ($attrsOnly)
+			return $returnattrs[$index];
+
+		foreach ($returnattrs[$index] as $attribute)
+			$return[$index][$attribute->getName()] = $attribute->getValues();
+
+		return $return[$index];
+	}
+
+	/**
+	 * Get the attributes that are marked as force delete
+	 * We'll cache this result in the event of multiple calls.
+	 */
+	public function getForceDeleteAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $result = array();
+
+		if (count($result))
+			return $result;
+
+		foreach ($this->attributes as $attribute)
+			if ($attribute->isForceDelete())
+				array_push($result,$attribute);
+
+		return $result;
+	}
+
+	/**
+	 * Get available attributes
+	 */
+	public function getAvailAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$attributes = array();
+		$server = $this->getServer();
+
+		# Initialise the Attribute Factory.
+		$attribute_factory = new AttributeFactory();
+
+		if (in_array_ignore_case('extensibleobject',$this->getObjectClasses())) {
+			foreach ($server->SchemaAttributes() as $sattr) {
+				$attribute = $attribute_factory->newAttribute($sattr->getName(),array('values'=>array()),$server->getIndex(),null);
+				array_push($attributes,$attribute);
+			}
+
+		} else {
+			$attrs = array();
+
+			foreach ($this->getObjectClasses() as $oc) {
+				$soc = $server->getSchemaObjectClass($oc);
+				$attrs = array_merge($attrs,$soc->getMustAttrNames(true),$soc->getMayAttrNames(true));
+				$attrs = array_unique($attrs);
+			}
+
+			foreach ($attrs as $attr)
+				if (is_null($this->getAttribute($attr))) {
+					$attribute = $attribute_factory->newAttribute($attr,array('values'=>array()),$server->getIndex(),null);
+					array_push($attributes,$attribute);
+				}
+		}
+
+		masort($attributes,'name');
+		return $attributes;
+	}
+
+	public function isNoLeaf() {
+		return $this->noleaf;
+	}
+
+	public function sort() {
+		usort($this->attributes,'sortAttrs');
+	}
+}
+?>
diff --git a/lib/TemplateRender.php b/lib/TemplateRender.php
new file mode 100644
index 0000000..f761b86
--- /dev/null
+++ b/lib/TemplateRender.php
@@ -0,0 +1,2533 @@
+%s:%s
',time(),__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Visit-Start:%s]
',__METHOD__,get_class($this)); + + $tree = get_cached_item($this->server_id,'tree'); + if (! $tree) + $tree = Tree::getInstance($this->server_id); + + $treeitem = $tree->getEntry($this->dn); + + # If we have a DN, and no template_id, see if the tree has one from last time + if ($this->dn && is_null($this->template_id) && $treeitem && $treeitem->getTemplate()) + $this->template_id = $treeitem->getTemplate(); + + # Check that we have a valid template, or present a selection + # @todo change this so that the modification templates rendered are the ones for the objectclass of the dn. + if (! $this->template_id) + $this->template_id = $this->getTemplateChoice(); + + if ($treeitem) + $treeitem->setTemplate($this->template_id); + + $this->page = get_request('page','REQUEST',false,1); + + if ($this->template_id AND $this->template_id != 'invalid') { + if (! $this->template) + parent::accept(); + + $this->url_base = sprintf('server_id=%s&dn=%s', + $this->getServerID(),$this->template->getDNEncode()); + $this->layout['hint'] = sprintf('%s%%s', + IMGDIR,_('Hint')); + $this->layout['action'] = '%s%s'; + $this->layout['actionajax'] = '%s%s'; + + # If we dont want to render this template automatically, we'll return here. + if ($norender) + return; + + $this->visitStart(); + + foreach ($this->template->getAttributes(true) as $attribute) { + # Evaluate our defaults + if ($attribute->getAutoValue()) + $this->get('Default',$attribute, + $this->template->getContainer() ? $this->template->getContainer() : $this->getServer()->getContainerPath($this->template->getDN()), + 'autovalue'); + + # If this is the default template, we should mark all our attributes to show(). + if (($this->template->getID() == 'none') && (! $attribute->isInternal()) + && (($this->template->getContext() == 'edit' && $this->template->getID() == 'none') + || ($this->template->getContext() == 'create' && $attribute->getName() != 'objectclass'))) + $attribute->show(); + } + + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Visit-End:%s]
',__METHOD__,get_class($this)); + + $this->visitEnd(); + } + } + + protected function getDefaultAttribute($attribute,$container,$type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($type) { + case 'autovalue': + $autovalue = $attribute->getAutoValue(); + + break; + + case 'helpervalue': + $autovalue = $attribute->getHelperValue(); + + break; + + default: + system_message(array( + 'title'=>_('Unknown Default Attribute context'), + 'body'=>sprintf('%s (%s)',_('A call was made to getDefaultAttribute() with an unkown context'),$type), + 'type'=>'warn')); + + return; + } + + $args = explode(';',$autovalue['args']); + $server = $this->getServer(); + $vals = ''; + + switch ($autovalue['function']) { + /** + * Function enables normal PHP functions to be called to evaluate a value. + * eg: =php.Function(date;dmY) + * + * All arguments will be passed to the function, and its value returned. + * If this used used in a POST context, the attribute values can be used as arguments. + * + * Mandatory Arguments: + * * arg 0 + * - php Function to call + * + * Additional arguments will be passed to the function. + */ + case 'Function': + $function = array_shift($args); + + if (count($args) && count($args) > 1) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Function() only takes two arguments and more than two were specified'),count($args)), + 'type'=>'warn')); + + return; + } + + $function_args = explode(',',$args[0]); + + if (function_exists($function)) + $vals = call_user_func_array($function,$function_args); + + else + system_message(array( + 'title'=>_('Function doesnt exist'), + 'body'=>sprintf('%s (%s)',_('An attempt was made to call a function that doesnt exist'),$function), + 'type'=>'warn')); + + break; + + /** + * GetNextNumber will query the LDAP server and calculate the next number based on the query + * eg: + * + * Mandatory Arguments: + * * arg 0 + * - "$" => 'auto_number','search_base' in config file + * - "/",".",".." => get container parent as usual + * + * * arg 1 + * - attribute to query for + * + * Optional Arguments: + * * arg 2 (pool mechanism only) + * - "true" increments attribute by 1 + * - "false" do nothing + * + * * arg 3 (pool mechanism only) + * - ldap filter (must match one entry only in container) + * + * * arg 4 + * - calculus on number, eg: + * - *2,+1000 => number = (2*number) + 1000 + * + * * arg 5 + * - Min number + */ + case 'GetNextNumber': + # If the attribute already has values, we'll return + if ($type == 'autovalue' && $attribute->getValues()) + return; + + if ($args[0] == '$') + $args[0] = $server->getValue($this->server_id,'auto_number','search_base'); + + $container = $server->getContainerPath($container,$args[0]); + + $vals = get_next_number($container,$args[1], + (! empty($args[2]) && ($args[2] == 'false')) ? false : true, + (! empty($args[3])) ? $args[3] : false, + (! empty($args[5])) ? $args[5] : null); + + # Operate calculus on next number. + if (! empty($args[4])) { + $mod = explode(',',$args[4]); + $next_number = $vals; + + foreach ($mod as $calc) { + $operand = $calc{0}; + $operator = substr ($calc,1); + + switch ($operand) { + case '*': + $next_number = $next_number * $operator; + break; + + case '+': + $next_number = $next_number + $operator; + break; + + case '-': + $next_number = $next_number - $operator; + break; + + case '/': + $next_number = $next_number / $operator; + break; + } + } + + $vals = $next_number; + } + + break; + + /** + * PickList will query the LDAP server and provide a select list of values + * MultiList will query the LDAP server and provide a multi select list of values + * eg: + * + * eg: cn=root,nobody => cn=nobody;gidNumber;10)]]> + * + * Mandatory Arguments: + * * arg 0 + * - container, to query from current position + * - "/",".",".." => get container parent as usual + * + * * arg 1 + * - LDAP filter. May include '%attr%', it will be expanded. + * + * * arg2 + * - list attribute key + * + * Optional Arguments: + * * arg3 + * - select display (plus modifier /C: Capitalize) + * - replaced by %arg 2% if not given + * + * * arg 4 + * - the value furnished in output - must be attribute id. replaced by arg 2 if not given + * + * * arg 5 + * - container override + * + * * arg 6 + * - csv list (, separator) of added values. syntax: key => display_attribute=value, key... + * + * * arg 7 + * - csv list (, separator) of sort attributes (less to more important) + * + * * arg 8 (for MultiList) + * - size of displayed list (default: 10 lines) + */ + case 'MultiList': + case 'PickList': + # arg5 overrides our container + if (empty($args[5])) + $container = $server->getContainerPath($container,$args[0]); + else + $container = $args[5]; + + # Process filter (arg 1), eventually replace %attr% by it's value set in a previous page. + preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[1],$filtermatchall); + //print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod + + if (isset($_REQUEST['form'])) { + $formvalues = array_change_key_case($_REQUEST['form']); + + foreach ($filtermatchall[1] as $arg) { + $value = $formvalues[strtolower($arg)]; + $args[1] = preg_replace("/%($arg)(\|.+)?(\/[lU])?%/U",$value,$args[1]); + } + } + + if (empty($args[3])) + $args[3] = "%{$args[2]}%"; + + preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[3],$matchall); + //print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod + + $attrs = array_unique(array_merge($matchall[1],array($args[2]))); + + # arg7 is sort attributes + if (isset($args[7])) { + $sort_attrs = explode(',',$args[7]); + $attrs = array_unique(array_merge($attrs,$sort_attrs)); + } + + $picklistvalues = return_ldap_hash($container,$args[1],$args[2],$attrs,(isset($args[7]) && ($args[7])) ? $sort_attrs : false); + + # arg6 is a set of fixed values to add to search result + if (isset($args[6])) { + $fixedvalues = explode(',',$args[6]); + + foreach ($fixedvalues as $fixedvalue) { + if (empty($fixedvalue)) + continue; + + $fixedvalue = preg_split('/=\>/',$fixedvalue); + $displayvalue = explode('=',$fixedvalue[1]); + + $newvalue[trim($fixedvalue[0])] = array($args[2]=>trim($fixedvalue[0]),trim($displayvalue[0])=>trim($displayvalue[1])); + + $picklistvalues = array_merge($picklistvalues,$newvalue); + } + } + + $vals = array(); + + foreach ($picklistvalues as $key => $values) { + $display = $args[3]; + + foreach ($matchall[1] as $key => $arg) { + if (isset($values[$arg])) + $disp_val = $values[$arg]; + else + $disp_val = ''; + + if (is_array($disp_val)) + $disp_val = $disp_val[0]; + + if ($matchall[3][$key]) + switch ($matchall[3][$key]) { + case '/l': + # lowercase + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_LOWER,'utf-8'); + else + $disp_val = strtolower($disp_val); + + break; + + case '/U': + # uppercase + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_UPPER,'utf-8'); + else + $disp_val = strtoupper($disp_val); + + break; + + case '/C': + # capitalize + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_TITLE,'utf-8'); + else + $disp_val = ucfirst($disp_val); + + break; + + default: + break; + } + + # make value a substring of + preg_match_all('/^\|([0-9]*)-([0-9]*)$/',trim($matchall[2][$key]),$substrarray); + + if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) { + $begin = $substrarray[1][0] ? $substrarray[1][0] : '0'; + $end = $substrarray[2][0] ? $substrarray[2][0] : strlen($disp_val); + + if (function_exists('mb_substr')) + $disp_val = mb_substr($disp_val,$begin,$end,'utf-8'); + else + $disp_val = substr($disp_val,$begin,$end); + } + + $display = preg_replace("/%($arg)(\|.+)?(\/[lUC])?%/U",$disp_val,$display); + } + + if (! isset($picklist[$values[$args[2]]])) { + $vals[$values[$args[2]]] = $display; + $picklist[$values[$args[2]]] = true; + } + } + + break; + + /** + * PasswordEncryptionTypes will return a list of our support password encryption types + * eg: =php.PasswordEncryptionTypes() + * + * This function doesnt use any arguments + */ + case 'PasswordEncryptionTypes': + $vals = password_types(); + + break; + + /** + * RandomPassword will create a random password for the value. + * eg: =php.RandomPassword() + * + * When calling the attribute Javascript it will generate a random password. + * + * This function doesnt use any arguments + */ + case 'RandomPassword': + break; + } + + switch ($type) { + case 'autovalue': + if (! is_array($vals)) + $attribute->autoValue(array($vals)); + else + $attribute->autoValue($vals); + + break; + + case 'helpervalue': + return $vals; + } + } + + /** + * Set the mode of the TemplateRender + * Applicable modes are "create" or "edit" + */ + protected function getMode() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->dn) + return 'modification'; + elseif ($this->container) + return 'creation'; + elseif (get_request('create_base')) + return 'creation'; + else + debug_dump_backtrace(sprintf('Unknown mode for %s',__METHOD__),1); + } + + /** + * Return the container for this mode + */ + protected function getModeContainer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($this->getMode()) { + case 'creation': + return $this->container; + break; + + case 'modification': + return $this->dn; + break; + + default: + return null; + } + } + + /** + * Is the default template enabled? + */ + protected function haveDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template')) + return false; + else + return true; + } + + /** + * Present a list of available templates for creating and editing LDAP entries + */ + protected function drawTemplateChoice() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawTitle(); + $this->drawSubTitle(); + echo "\n"; + + switch ($this->getMode()) { + case 'creation': + $msg = _('Select a template for the creation process'); + break; + + case 'modification': + $msg = _('Select a template to edit the entry'); + break; + } + + $avail_templates = $this->getTemplates(); + $templates = $avail_templates->getTemplates($this->getMode(),$this->getModeContainer()); + printf('

%s

',$msg); + + $href_parms = array_to_query_string($_GET,array('meth')); + printf('
',htmlspecialchars($href_parms)); + echo "\n\n"; + + if (count($_POST)) { + echo '
'; + foreach ($_POST as $p => $v) + printf('',$p,$v); + echo '
'; + echo "\n\n"; + } + + echo ''; + echo ''; + printf('',_('Templates')); + echo ''; + + echo '
%s:'; + echo ''; + + $i = -1; + $nb_templates = count($templates); + + if ($this->haveDefaultTemplate()) + $nb_templates++; + + foreach ($templates as $name => $details) { + $i++; + + $isInValid = $details->isInValid(); + + # Balance the columns properly + if (($nb_templates % 2 == 0 && $i == intval($nb_templates / 2)) || + ($nb_templates % 2 == 1 && $i == intval($nb_templates / 2) + 1)) { + echo '
'; + } + + echo "\n"; + echo ''; + + if ($isInValid) + printf('',IMGDIR); + + else { + if (isAjaxEnabled()) + printf('', + htmlspecialchars($details->getID()),htmlspecialchars($details->getID()),htmlspecialchars($href_parms),$details->getID(),str_replace('\'','\\\'',_('Retrieving DN'))); + else + printf('', + htmlspecialchars($details->getID()),htmlspecialchars($details->getID())); + } + + printf('', + htmlspecialchars($details->getID()),$details->getIcon()); + printf(''; + echo ''; + } + echo "\n"; + + # Default template + if ($this->haveDefaultTemplate()) { + $i++; + + # Balance the columns properly + if (($nb_templates % 2 == 0 && $i == intval($nb_templates / 2)) || + ($nb_templates % 2 == 1 && $i == intval($nb_templates / 2) + 1)) { + echo '
Disabled
'; + } + + echo ''; + if (isAjaxEnabled()) + printf('', + htmlspecialchars($href_parms),'none',str_replace('\'','\\\'',_('Retrieving DN'))); + else + echo ''; + + printf('',IMGDIR); + printf('',_('Default')); + echo ''; + } + + echo '
'; + echo '
'; + echo '
'; + } + + /** VISIT METHODS **/ + + /** + * This function will setup our template object (read LDAP for current values, read $_REQUEST for new values, etc) + * so that it can be rendered. + */ + private function visitStart() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # If we have a DN, then we are an editing template + if ($this->dn) + $this->template->setDN($this->dn); + + # Else if we have a container, we are a creating template + elseif ($this->container || get_request('create_base')) + $this->template->setContainer($this->container); + + else + debug_dump_backtrace('Dont know what type of template we are - no DN or CONTAINER?',1); + + # Header + $this->drawHeader(); + } + + private function visitEnd() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($this->template->getAttributesShown() as $attribute) + if ($attribute->getPage() > $this->pagelast) + $this->pagelast = $attribute->getPage(); + echo "\n\n"; + + if ($this->template->getContext() == 'create') { + $this->drawStepTitle($this->page); + $this->drawStepFormStart($this->page); + $this->drawStepForm($this->page); + $this->drawStepFormEnd(); + + } elseif ($this->template->getContext() == 'copyasnew') { + $this->drawStepFormStart($this->page); + printf('',$this->template->getContainer(false)); + echo '
'; + $this->drawRDNChooser(); + echo '
'; + $this->drawForm(true); + $this->drawStepFormSubmitButton($this->page); + + } else { + # Draw internal attributes + if (get_request('show_internal_attrs','REQUEST')) { + echo ''; + $this->drawInternalAttributes(); + echo '

'; + echo "\n"; + } + + $this->drawFormStart(); + + # To support our AJAX add Attribute + printf('
','none'); + + $this->drawForm(); + $this->drawStepFormEnd(); + } + } + + /** PAGE DRAWING METHODS **/ + + private function drawHeader() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Title + $this->drawTitle(); + if (get_request('create_base')) + $this->drawSubTitle(sprintf('%s: %s',_('Creating Base DN'),$this->template->getDN())); + else + $this->drawSubTitle(); + echo "\n"; + + # Menu + $this->drawMenu(); + } + + public function drawTitle($title=null) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (is_null($title)) + switch ($this->getMode()) { + case 'creation': + $title = _('Create Object'); + break; + + case 'modification': + $title = htmlspecialchars(get_rdn($this->dn)); + break; + + default: + $title = 'Title'; + } + + parent::drawTitle($title); + } + + public function drawSubTitle($subtitle=null) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($subtitle) + return parent::drawSubTitle($subtitle); + + switch ($this->getMode()) { + case 'creation': + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(), + _('Container'),htmlspecialchars($this->container)); + + if ($this->template_id) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',_('Template'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + + break; + + case 'modification': + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(), + _('Distinguished Name'),htmlspecialchars($this->dn)); + + if ($this->template_id) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',_('Template'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + + break; + } + + parent::drawSubTitle($subtitle); + } + + /** PAGE ENTRY MENU **/ + + private function drawMenu() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # We only have a menu for editing entries. + if ($this->template->getContext() == 'edit') { + + echo ''; + echo ''; + $menuitem_number = 0; + + foreach (array('entryrefresh','showinternal','switchtemplate','entryexport','entrycopy','entrydelete','entryrename','entrycompare','childcreate','addattr','msgdel','childview','childexport','msgschema','msgro','msgmodattr') as $item) { + $item = $this->getMenuItem($item); + + if ($item) { + $endofrow = false; + $start = true; + $it = ''; // menu item + $ms = ''; // item message + + if (is_array($item) && count($item) > 0) { + $it = $item[0]; + + if (count($item) > 1) + $ms = $item[1]; + + } else { + $it = $item; + } + + if ($it) { + $menuitem_number++; + echo $it; + + if ($ms) { + if (($menuitem_number % 2) == 1) { + $menuitem_number++; + echo ''; + $endofrow = false; + $start = false; + } + + if ($endofrow) + print $ms; + else + echo "$ms"; + + echo ''; + $endofrow = true; + $start = false; + + } else { + if ($menuitem_number > 1 && ($menuitem_number % 2) == 0) { + echo ''; + $endofrow = true; + $start = false; + } + } + + } elseif ($ms) { + if (($menuitem_number % 2) == 1) { + $menuitem_number++; + echo ''; + $endofrow = false; + $start = false; + } + + if ($endofrow || $start) + print $ms; + else + echo "$ms"; + + echo ''; + $endofrow = true; + $start = false; + } + + echo "\n"; + } + } + + if (($menuitem_number % 2) == 1) + echo ''; + else + echo ''; + + echo ''; + echo ''; + } + } + + /** PAGE ENTRY MENU ITEMS **/ + + private function getMenuItem($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s (%s)
',__METHOD__,$i); + + switch ($i) { + case 'entryrefresh': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','entry_refresh')) + return $this->getMenuItemRefresh(); + else + return ''; + + case 'switchtemplate': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','switch_template')) + return $this->getMenuItemSwitchTemplate(); + else + return ''; + + case 'entryexport': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return $this->getMenuItemExportBase(); + else + return ''; + + case 'entrycopy': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','copy_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','copy') && ! $this->template->isReadOnly()) + return $this->getMenuItemMove(); + else + return ''; + + case 'showinternal': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','entry_internal_attributes_show')) + return $this->getMenuItemInternalAttributes(); + else + return ''; + + case 'entrydelete': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','delete_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete') && ! $this->template->isReadOnly()) + return $this->getMenuItemDelete(); + else + return ''; + + case 'entryrename': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','rename_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename') && ! $this->template->isReadOnly()) { + + # Check if any of the RDN's are read only. + $rdnro = false; + foreach ($this->template->getRDNAttributeName() as $attr) { + $attribute = $this->template->getAttribute($attr); + + if ($attribute && $attribute->isVisible() && ! $attribute->isReadOnly()) { + $rdnro = true; + break; + } + } + + if (! $rdnro) + return $this->getMenuItemRename(); + } + + return ''; + + case 'msgdel': + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints') + && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete') && ! $this->template->isReadOnly()) + return array('',$this->getDeleteAttributeMessage()); + else + return ''; + + case 'entrycompare': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','compare_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','compare') && ! $this->template->isReadOnly()) + return $this->getMenuItemCompare(); + else + return ''; + + case 'childcreate': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','create') && ! $this->template->isReadOnly() && ! $this->template->isNoLeaf()) + return $this->getMenuItemCreate(); + else + return ''; + + case 'addattr': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','add_attr_form') && ! $this->template->isReadOnly()) + return $this->getMenuItemAddAttribute(); + else + return ''; + + case 'childview': + case 'childexport': + static $children_count = false; + static $more_children = false; + + $tree = get_cached_item($this->getServerID(),'tree'); + $tree_item = $tree->getEntry($this->template->getDN()); + + if (! $tree_item) { + $tree->addEntry($this->template->getDN()); + $tree_item = $tree->getEntry($this->template->getDN()); + } + + if ($children_count === false) { + # Visible children in the tree + $children_count = count($tree_item->getChildren()); + # Is there filtered children ? + $more_children = $tree_item->isSizeLimited(); + + if (! $children_count || ! $more_children) { + # All children in ldap + $all_children = $this->getServer()->getContainerContents( + $this->template->getDN(),null,$children_count+1,'(objectClass=*)',$_SESSION[APPCONFIG]->getValue('deref','view'),null); + + $more_children = (count($all_children) > $children_count); + } + } + + if ($children_count > 0 || $more_children) { + if ($children_count <= 0) + $children_count = ''; + if ($more_children) + $children_count .= '+'; + + if ($i == 'childview') + return $this->getMenuItemShowChildren($children_count); + elseif ($i == 'childexport' && $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return $this->getMenuItemExportSub(); + else + return ''; + + } else + return ''; + + case 'msgschema': + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints') && $_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return array('',$this->getViewSchemaMessage()); + else + return array(); + + case 'msgro': + if ($this->template->isReadOnly()) + return array('',$this->getReadOnlyMessage()); + else + return array(); + + case 'msgmodattr': + $modified_attrs = array(); + $modified = get_request('modified_attrs','REQUEST',false,array()); + + foreach ($this->template->getAttributes(true) as $attribute) + if (in_array($attribute->getName(),$modified)) + array_push($modified_attrs,$attribute->getFriendlyName()); + + if (count($modified_attrs)) + return array('',$this->getModifiedAttributesMessage($modified_attrs)); + else + return array(); + + default: + return false; + } + } + + protected function getDeleteAttributeMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','delete_attr') && ! $this->template->isReadOnly()) + return sprintf($this->layout['hint'],_('Hint: To delete an attribute, empty the text field and click save.')); + else + return ''; + } + + protected function getModifiedAttributesMessage(&$modified_attributes) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'], + (count($modified_attributes) == 1) ? + sprintf(_('An attribute (%s) was modified and is highlighted below.'),implode('',$modified_attributes)) : + sprintf(_('Some attributes (%s) were modified and are highlighted below.'),implode(', ',$modified_attributes))); + } + + protected function getReadOnlyMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'],_('Viewing entry in read-only mode.')); + } + + protected function getViewSchemaMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'],_('Hint: To view the schema for an attribute, click the attribute name.')); + } + + /** PAGE ENTRY MENU ITEMS DETAILS **/ + + private function getMenuItemRefresh() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=template_engine&%s&junk=%s',$this->url_base,random_junk()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'refresh.png',_('Refresh'), + htmlspecialchars($href),_('Refresh this entry'),htmlspecialchars($href),str_replace('\'','\\\'',_('Reloading')),_('Refresh')); + else + return sprintf($this->layout['action'],IMGDIR,'refresh.png',_('Refresh'), + htmlspecialchars($href),_('Refresh this entry'),_('Refresh')); + } + + protected function getMenuItemSwitchTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $href = sprintf('cmd=template_engine&%s&template=',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'switch.png',_('Switch Template'), + htmlspecialchars($href),_('Change to another template'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Switch Template')); + else + return sprintf($this->layout['action'],IMGDIR,'switch.png',_('Switch Template'), + htmlspecialchars($href),_('Change to another template'),_('Switch Template')); + } + + protected function getMenuItemExportBase() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=export_form&%s&scope=base',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'export.png',_('Export'), + htmlspecialchars($href),_('Save a dump of this object'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Export')); + else + return sprintf($this->layout['action'],IMGDIR,'export.png',_('Export'), + htmlspecialchars($href),_('Save a dump of this object'),_('Export')); + } + + private function getMenuItemMove() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=copy_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'cut.png',_('Cut'), + htmlspecialchars($href),_('Copy this object to another location, a new DN, or another server'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Copy or move this entry')); + else + return sprintf($this->layout['action'],IMGDIR,'cut.png',_('Cut'), + htmlspecialchars($href),_('Copy this object to another location, a new DN, or another server'), + _('Copy or move this entry')); + } + + protected function getMenuItemInternalAttributes() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (get_request('show_internal_attrs','REQUEST')) { + $href = sprintf('cmd=template_engine&%s&junk=',$this->url_base,random_junk()); + + return sprintf($this->layout['action'],IMGDIR,'tools-no.png',_('Hide'), + htmlspecialchars($href),'',_('Hide internal attributes')); + + } else { + $href = sprintf('cmd=template_engine&show_internal_attrs=true&%s',$this->url_base); + + return sprintf($this->layout['action'],IMGDIR,'tools.png',_('Show'), + htmlspecialchars($href),'',_('Show internal attributes')); + } + } + + private function getMenuItemDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=delete_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'trash.png',_('Trash'), + htmlspecialchars($href),_('You will be prompted to confirm this decision'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Delete this entry')); + else + return sprintf($this->layout['action'],IMGDIR,'trash.png',_('Trash'), + htmlspecialchars($href),_('You will be prompted to confirm this decision'),_('Delete this entry')); + } + + protected function getMenuItemRename() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=rename_form&%s&template=%s',$this->url_base,$this->template->getID()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'rename.png',_('Rename'), + htmlspecialchars($href),_('Rename this entry'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Rename')); + else + return sprintf($this->layout['action'],IMGDIR,'rename.png',_('Rename'), + htmlspecialchars($href),_('Rename this entry'),_('Rename')); + } + + protected function getMenuItemCompare() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=compare_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'compare.png',_('Compare'), + htmlspecialchars($href),_('Compare this entry with another'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Compare with another entry')); + else + return sprintf($this->layout['action'],IMGDIR,'compare.png',_('Compare'), + htmlspecialchars($href),_('Compare this entry with another'),_('Compare with another entry')); + } + + protected function getMenuItemCreate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$this->template->getDNEncode()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'create.png',_('Create'), + htmlspecialchars($href),_('Create a child entry'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Create a child entry')); + else + return sprintf($this->layout['action'],IMGDIR,'create.png',_('Create'), + htmlspecialchars($href),_('Create a child entry'),_('Create a child entry')); + } + + protected function getMenuItemAddAttribute() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $this->template->getAvailAttrs()) + return ''; + + $href = sprintf('cmd=add_attr_form&%s',$this->url_base); + $layout = '%s%s'; + + if (isAjaxEnabled()) + return sprintf($layout,IMGDIR,'add.png',_('Add'), + htmlspecialchars($href),_('Add new attribute to this object'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Add new attribute')),_('Add new attribute')); + else + return sprintf($this->layout['action'],IMGDIR,'add.png',_('Add'), + htmlspecialchars($href),_('Add new attribute to this object'),_('Add new attribute')); + } + + protected function getMenuItemShowChildren($children_count) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=query_engine&server_id=%s&filter=%s&base=%s&scope=one&query=none&size_limit=0&search=true', + $this->getServerID(),rawurlencode('objectClass=*'),$this->template->getDNEncode()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'children.png',_('Children'), + htmlspecialchars($href),_('View the children of this object'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')), + ($children_count == 1) ? _('View 1 child') : sprintf(_('View %s children'),$children_count)); + else + return sprintf($this->layout['action'],IMGDIR,'children.png',_('Children'), + htmlspecialchars($href),_('View the children of this object'), + ($children_count == 1) ? _('View 1 child') : sprintf(_('View %s children'),$children_count)); + } + + protected function getMenuItemExportSub() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=export_form&%s&scope=%s',$this->url_base,'sub'); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'export.png',_('Save'), + htmlspecialchars($href),_('Save a dump of this object and all of its children'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Export subtree')); + else + return sprintf($this->layout['action'],IMGDIR,'export.png',_('Save'), + htmlspecialchars($href),_('Save a dump of this object and all of its children'),_('Export subtree')); + } + + /** CHOOSERS **/ + + /** + * RDN Chooser + */ + protected function drawRDNChooser() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! count($this->template->getRDNAttrs())) { + printf('%s','RDN'); + + echo ''; + + } else { + echo ''; + foreach ($this->template->getRDNAttrs() as $rdn) + printf('',htmlspecialchars($rdn)); + + if (get_request('create_base')) + echo ''; + + echo ''; + } + } + + /** + * Container Chooser + */ + protected function drawContainerChooser($default_container) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + printf('%s',_('Container')); + echo ''; + if (get_request('create_base')) + printf('%s',$default_container,htmlspecialchars($default_container)); + else { + printf('',htmlspecialchars($default_container)); + draw_chooser_link('entry_form','container'); + } + echo ''; + echo ''; + } + + /** + * Object Class Chooser + */ + protected function drawObjectClassChooser() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $socs = $this->getServer()->SchemaObjectClasses(); + if (! $socs) + $socs = array(); + + echo ''; + printf('%s',_('ObjectClasses')); + echo ''; + echo ''; + echo ''; + + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) { + printf(' Hint',IMGDIR); + echo _('Hint: You must choose exactly one structural objectClass (shown in bold above)'); + echo '
'; + } + } + + /** INTERNAL ATTRIBUTES **/ + + protected function drawInternalAttributes() { + if ($this->template->getAttributesInternal()) + foreach ($this->template->getAttributesInternal() as $attribute) + $this->draw('Internal',$attribute); + else + printf('(%s)
',_('No internal attributes')); + + echo "\n"; + } + + protected function drawInternalAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('Template',$attribute); + } + + /** FORM METHODS **/ + + public function drawFormStart() { + echo '
'; + + echo '
'; + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + echo '
'; + } + + protected function drawForm($nosubmit=false) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo '
'; + printf('',$this->getServerID()); + printf('',$this->template->getDNEncode(false)); + printf('',$this->template->getID()); + echo '
'; + + echo ''; + + $this->drawShownAttributes(); + if (! $nosubmit) + $this->drawFormSubmitButton(); + + echo '
'; + + echo '
 '; + $this->drawHiddenAttributes(); + echo '
'; + } + + public function drawFormEnd() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Include the RDN details to support creating the base + if (get_request('create_base')) { + if (get_request('rdn')) { + $rdn = explode('=',get_request('rdn')); + echo '
'; + printf('',$rdn[0],$rdn[1]); + printf('',$rdn[0]); + echo '
'; + } + } + + echo '
'; + + # Javascript + $this->drawJavascript(); + + # For debugging, show the template object. + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_debug_info') && get_request('debug','GET')) { + echo "\n\n"; + printf('Plus',IMGDIR); + echo ''; + } + } + + public function drawFormSubmitButton() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $this->template->isReadOnly()) + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Update Object')); + } + + /** STEP FORM METHODS **/ + + private function drawStepTitle($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [templateNAME:%s]
',__METHOD__,$this->template->getName()); + + # The default template needs to ask the user for objectClasses. + if ($this->template->isType('default')) { + # The default template only uses 2 pages + $this->pagelast = 2; + + echo '

'; + printf('%s: ',sprintf(_('Step %s of %s'),$page,$this->pagelast)); + + if ($page == 1) + echo _('Container and ObjectClass(es)'); + else + echo _('Specify attributes and values'); + + echo '

'; + + } elseif ($this->template->getDescription()) + printf('

%s (%s)

', + _($this->template->getDescription()), + sprintf(_('Step %s of %s'),$page,$this->pagelast)); + } + + private function drawStepFormStart($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->isType('default') && $this->template->getContext() == 'create' && $page == 1) || $page < $this->pagelast) { + echo '
'; + echo '
'; + + } else { + echo ''; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','create') && ! get_request('create_base')) + echo ''; + else + echo ''; + } + } + + protected function drawStepForm($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('',$this->getServerID()); + printf('',$this->template->getID()); + printf('',$page+1); + if (get_request('create_base')) + echo ''; + + $this->drawHiddenAttributes(); + + if ($this->template->isType('default') && $page == 1) { + echo '
'; + + echo ''; + + $this->drawContainerChooser($this->template->getContainer()); + $this->drawObjectClassChooser(); + + } else { + printf('',$this->template->getContainerEncode(false)); + echo ''; + + echo '
'; + + $this->drawRDNChooser(); + + if ($this->template->isType('default') && $this->template->getContext() == 'create') + $this->drawStepFormDefaultAttributes(); + else + $this->drawShownAttributes(); + } + + $this->drawStepFormSubmitButton($page); + + echo '
'; + } + + private function drawStepFormEnd() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormEnd(); + } + + private function drawStepFormSubmitButton($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + if ($page < $this->pagelast) + printf(' ',_('Proceed >>')); + else + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Create Object')); + echo ''; + } + + /** + * Given our known objectClass in the template, this will render the required MAY and optional MUST attributes + */ + private function drawStepFormDefaultAttributes() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Put required attributes first + $attrs = array(); + $attrs['required'] = array(); + $attrs['optional'] = array(); + foreach ($this->template->getAttributes(true) as $attribute) { + # Skip the objectclass attribute, we already know it in a default creation form. + if ($attribute->getName() == 'objectclass') + continue; + + if ($attribute->isRequired()) + array_push($attrs['required'],$attribute); + + elseif (! $attribute->getValues()) + array_push($attrs['optional'],$attribute); + } + + printf('%s',_('Required Attributes')); + if (count($attrs['required'])) + foreach ($attrs['required'] as $attribute) + $this->draw('Template',$attribute); + + else + printf('(%s)',_('none')); + + printf('%s',_('Optional Attributes')); + if (count($attrs['optional'])) + foreach ($attrs['optional'] as $attribute) + $this->draw('Template',$attribute); + + else + printf('(%s)',_('none')); + + echo "\n"; + } + + /** DRAW ATTRIBUTES **/ + + private function drawShownAttributes() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($this->template->getAttributesShown() as $attribute) + if (($attribute->getPage() == $this->page) && ($attribute->isRequired() || $attribute->isMay())) { + $this->draw('Template',$attribute); + echo "\n"; + } + } + + /** DRAW PAGE JAVACRIPT */ + + protected function drawJavascript() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo "\n"; + printf('',__METHOD__); + echo "\n"; + + printf('',JSDIR); + printf('',JSDIR); + printf('',JSDIR); + echo "\n"; + + printf('',__METHOD__); + echo ' +'; + echo "\n"; + printf('',__METHOD__); + echo "\n"; + + $this->drawTemplateJavascript(); + + # For DateAttributes, we need to set some defaults for the js_calendar. + echo ''."\n"; + echo ''."\n"; + echo ''."\n"; + echo "\n"; + + foreach ($this->template->getAttributesShown() as $attribute) + $this->draw('Javascript',$attribute); + + // @todo We need to sleep here a little bit, because our JS may not have loaded yet. + echo ''."\n"; + printf('',__METHOD__); + echo "\n"; + } + + /** + * Javascript Functions + */ + private function drawTemplateJavascript() { + printf('',__METHOD__); + echo "\n"; + foreach ($this->template->getAttributes(true) as $attribute) + if ($onchange = $attribute->getOnChange()) + if (is_array($onchange)) + foreach ($onchange as $value) + $this->template->OnChangeAdd($attribute->getName(),$value); + else + $this->template->OnChangeAdd($attribute->getName(),$onchange); + printf('',__METHOD__); + echo "\n"; + + printf('',__METHOD__); + + echo ' +'; + echo "\n"; + printf('',__METHOD__); + echo "\n"; + } + + /** ATTRIBUTE TITLE **/ + + protected function drawTitleAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + else + echo ''; + + echo ''; + $this->draw('Name',$attribute); + echo ''; + + echo ''; + + # Setup the $attr_note, which will be displayed to the right of the attr name (if any) + if ($_SESSION[APPCONFIG]->getValue('appearance','show_attribute_notes')) + $this->draw('Notes',$attribute); + + echo ''; + echo ''; + } + + /** ATTRIBUTE LINE **/ + + protected function drawStartValueLineAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + else + echo ''; + + echo ''; + } + + protected function drawEndValueLineAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + echo ''; + + if ($attribute->getSpacer()) + echo ' '; + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + } + + protected function drawTemplateAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('Title',$attribute); + $this->draw('TemplateValues',$attribute); + } + + protected function drawTemplateValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s:%s
',time(),__METHOD__); + + $this->draw('StartValueLine',$attribute); + + # Draws values + $value_count = $attribute->getValueCount(); + for ($i=0;$i<$value_count;$i++) + $this->draw('Value',$attribute,$i); + + if (! $attribute->isInternal()) { + $blankvalue_count = $attribute->getMaxValueCount(); + if ($blankvalue_count < 0) + $blankvalue_count = 1; + + $blankvalue_count -= $value_count; + + for ($j=0;$j<$blankvalue_count;$j++) + $this->draw('Value',$attribute,$i+$j); + + if (($value_count == $blankvalue_count) || ($value_count && $blankvalue_count < 1)) + $this->draw('Menu',$attribute); + } + + $this->draw('EndValueLine',$attribute); + echo "\n"; + } + + /** DRAW ICONS FOR ATTRIBUTES VALUES **/ + + protected function drawIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (is_dn_string($val) || $this->getServer()->isDNAttr($attribute->getName())) + $this->draw('DnValueIcon',$attribute,$val); + elseif (is_mail_string($val)) + $this->draw('MailValueIcon',$attribute,$val); + elseif (is_url_string($val)) + $this->draw('UrlValueIcon',$attribute,$val); + + else { + if ($icon = $attribute->getIcon()) + printf('Icon ',$icon); + } + } + + protected function drawDnValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (strlen($val) <= 0) + printf('Go ',IMGDIR); + elseif ($this->getServer()->dnExists($val)) + printf('Go ', + $this->getServerID(),rawurlencode($val),_('Go to'),$val,IMGDIR); + else + printf('Go ',_('DN not available'),$val,IMGDIR); + } + + protected function drawMailValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $img = sprintf('%s',IMGDIR,_('Mail')); + if (strlen($val) <= 0) + echo $img; + else + printf('%s',htmlspecialchars($val),$img); + echo ' '; + } + + protected function drawUrlValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $img = sprintf('%s',IMGDIR,_('URL')); + $url = explode(' +',$val,2); + + if (strlen($val) <= 0) + echo $img; + else + printf('%s',htmlspecialchars($url[0]),$img); + echo ' '; + } + + /** DEFAULT ATTRIBUTE RENDERING **/ + + /** javacript */ + + protected function drawJavascriptAttribute($attribute) { + if (! $attribute->needJS()) { + printf('',$attribute->getName()); + echo "\n"; + return; + } + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + echo ''."\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + protected function getFocusJavascriptAttribute($attribute,$component) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return ''; + } + + protected function getBlurJavascriptAttribute($attribute,$component) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $j = "\t".'fill('.$component.'.id,pla_getComponentValue('.$component.'));'."\n"; + $j .= "\t".'validate_'.$attribute->getName().'('.$component.',false);'."\n"; + + return $j; + } + + protected function drawFocusJavascriptAttribute($attribute,$component) { + echo $this->get('FocusJavascript',$attribute,$component); + } + + protected function drawBlurJavascriptAttribute($attribute,$component) { + echo $this->get('BlurJavascript',$attribute,$component); + } + + protected function drawFillJavascriptAttribute($attribute,$component_id,$component_value) { + if ($attribute->needJS('validate')) + printf("\tvalidate_%s(pla_getComponentById(%s),true);\n",$attribute->getName(),$component_id); + } + + protected function drawValidateJavascriptAttribute($attribute,$component,$silence,$var_valid) { + printf('var vals = getAttributeValues("new","%s");',$attribute->getName()); + echo 'if (vals.length <= 0) {'; + printf('%s = false;',$var_valid); + printf('alertError("%s: %s",%s);',_('This attribute is required'),$attribute->getFriendlyName(),$silence); + echo '}'; + echo "\n"; + + printf('var comp = getAttributeComponents("new","%s");',$attribute->getName()); + echo 'for (var i = 0; i < comp.length; i++) {'; + printf('comp[i].style.backgroundColor = "%s";',$var_valid ? 'white' : '#FFFFA0'); + echo '}'; + } + + /** ATTRIBUTE MENU **/ + + protected function drawMenuAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $result = ''; + $item = ''; + + foreach (array('add','modify','rename') as $action) + if ($item = $this->get('MenuItem',$attribute,$action)) + $result .= sprintf('
%s
',$item); + + if (! $result) + return; + + echo ''; + printf('',$result); + echo ''; + echo '
 %s
'; + } + + protected function getMenuItemAttribute($attribute,$action) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # If there is no DN, then this is a creating entry. + if (($this->template->getContext() == 'create') || $this->template->isReadOnly()) + return false; + + switch ($action) { + case 'add': + if ($attribute->isVisible() && ! $attribute->isReadOnly() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','add_value_form')) { + + if ($attribute->haveMoreValues()) + return $this->get('AddValueMenuItem',$attribute); + } + + return ''; + + case 'modify': + if (in_array($attribute->getName(),arrayLower($_SESSION[APPCONFIG]->getValue('modify_member','groupattr')))) { + if ($attribute->isVisible() && ! $attribute->isReadOnly() && ! $attribute->isRDN() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','modify_member_form')) + return $this->get('ModifyMemberMenuItem',$attribute); + } + + return ''; + + case 'rename': + if ($attribute->isVisible() && $attribute->isRDN() && ! $attribute->isReadOnly() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename_form') + && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename')) + return $this->get('RenameMenuItem',$attribute); + + return ''; + + default: + return false; + } + } + + protected function getAddValueMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href_parm = htmlspecialchars(sprintf('cmd=add_value_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName(false)))); + + if (isAjaxEnabled()) + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),$attribute->getName(), + $href_parm,str_replace('\'','\\\'',_('Add Value to Attribute')),_('add value')); + else + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),_('add value')); + } + + protected function getAddValueMenuItemObjectClassAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href_parm = htmlspecialchars(sprintf('cmd=add_value_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName(false)))); + + if (isAjaxEnabled()) + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false), + $href_parm,str_replace('\'','\\\'',_('Add Value to Attribute')),_('add value')); + else + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),_('add value')); + } + + protected function getModifyMemberMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=modify_member_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName())); + + if (isAjaxEnabled()) + return sprintf('(%s)', + htmlspecialchars($href),_('Modify members for'),$this->template->getDN(), + htmlspecialchars($href),str_replace('\'','\\\'',_('Modify group membership')), + _('modify group members')); + else + return sprintf('(%s)', + htmlspecialchars($href),_('Modify members for'),$this->template->getDN(),_('modify group members')); + } + + protected function getRenameMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd.php?cmd=rename_form&server_id=%s&dn=%s&template=%s', + $this->getServerID(),$this->template->getDNEncode(),$this->template->getID()); + + return sprintf('(%s)',htmlspecialchars($href),_('rename')); + } + + /** values **/ + + protected function drawValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isMultiple() && $i > 0) + return; + + $val = $attribute->getValue($i); + + if ($attribute->isVisible()) { + echo ''; + + echo ''; + + echo '
'; + $this->draw('Icon',$attribute,$val); + echo ''; + } + + if ($attribute->isInternal()) + $this->draw('FormReadOnlyValue',$attribute,$i); + else + $this->draw('FormValue',$attribute,$i); + + if ($attribute->isVisible()) { + echo ''; + $this->draw('RequiredSymbol',$attribute); + echo '
'; + } + echo "\n"; + } + + # @todo for userPasswords, we need to capture the default value of select lists, without specifying + protected function drawHelperAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $params = $attribute->getHelper(); + + # We take the first only + $id = isset($params['id']) ? $params['id'] : ''; + if (is_array($id)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many ID values, only the first one is used'),count($id)), + 'type'=>'warn')); + + $id = $id[0]; + } + + # We take the first only + $display = isset($params['display']) ? $params['display'] : ''; + if (is_array($display)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many DISPLAY values, only the first one is used'),count($display)), + 'type'=>'warn')); + + $display = $display[0]; + } + + # We take the first only + $default = isset($params['default']) ? $params['default'] : ''; + if (is_array($default)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many DISPLAY values, only the first one is used'),count($default)), + 'type'=>'warn')); + + $default = $default[0]; + } + + if ($attribute->getHelperValue()) + $vals = $this->get('Default',$attribute, + $this->template->getContainer() ? $this->template->getContainer() : $this->getServer()->getContainerPath($this->template->getDN()), + 'helpervalue'); + else + $vals = isset($params['value']) ? $params['value'] : ''; + + if ($this->template->getContext() == 'create') + $dn = $this->template->getContainer(); + else + $dn = $this->template->getDN(); + + if (is_array($vals) && count($vals) > 0) { + $found = false; + + printf(''; + + } else { + # Vals must be an empty array. + if (is_array($vals)) + $vals = ''; + + printf('', + $id,htmlspecialchars($attribute->getName()),$i, + $id,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($vals)); + } + + if ($display) { + echo '
'; + printf('%s',$display); + echo '
'; + } + } + + protected function drawRequiredSymbolAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isRequired() && ! $attribute->isReadOnly()) + echo '*'; + } + + /** BINARY ATTRIBUTE RENDERING **/ + + #@todo do we need a $this->drawJavascriptAttribute($attribute) here too ? + protected function drawJavascriptBinaryAttribute($attribute) { + # If there are no values, then this javascript doesnt need to be drawn. + if (! $attribute->getValues()) + return; + + static $drawn = false; + + # This JS may have been rendered by multiple Binary attributes + if ($drawn) + return; + else + $drawn = true; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + echo ''; + echo ''; + printf('',$this->getServerID()); + printf('',$this->template->getDNEncode(false)); + printf('',$this->template->getID()); + echo ''; + echo ''; + echo ''; + + echo ' +'; + echo "\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + /** DATE ATTRIBUTE RENDERING **/ + + protected function drawJavaScriptDateAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + $this->drawJavaScriptAttribute($attribute); + + static $drawn = false; + + # This JS may have been rendered by multiple Date attributes + if (! $drawn) { + printf('',JSDIR); + printf('',JSDIR); + printf('',JSDIR); + + $drawn = true; + } + + $config = array(); + $config['date'] = array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs')); + $config['time'] = array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs_showtime')); + $config['format'] = $_SESSION[APPCONFIG]->getValue('appearance','date'); + + if (isset($config['date'][$attribute->getName()])) + $config['format'] = $config['date'][$attribute->getName()]; + + for ($i=0;$i<=$attribute->getValueCount();$i++) { + printf('',$attribute->getName(),$i,$config['format']); + + if (in_array_ignore_case($attribute->getName(),array_keys($config['time'])) && ($config['time'][$attribute->getName()])) + printf('',$attribute->getName(),$i,'true'); + + echo "\n"; + } + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + /** + * Draws an HTML date selector button which, when clicked, pops up a date selector dialog. + */ + protected function drawSelectorPopupDateAttribute($attribute,$i) { + printf('Calendar', + $attribute->getName(),$i,_('Click to popup a dialog to select a date graphically'),IMGDIR,$attribute->getName(),$i); + } + + /** DN ATTRIBUTES **/ + + protected function drawIconDnAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('DnValueIcon',$attribute,$val); + } + + /** OBJECT CLASS ATTRIBUTE **/ + + protected function drawIconObjectClassAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return; + + if (strlen($val) > 0) { + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=objectclasses&viewvalue=%s', + $this->getServerID(),$val); + printf('Info ', + htmlspecialchars($href),_('View the schema description for this objectClass'),IMGDIR); + } + } + + /** PASSWORD ATTRIBUTES **/ + + protected function drawJavascriptPasswordAttribute($attribute) { + static $drawn = array(); + + # This JS may have been rendered by multiple Binary attributes + if (isset($drawn[$attribute->getName()]) && $drawn[$attribute->getName()]) + return; + else + $drawn[$attribute->getName()] = true; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + $this->drawJavascriptAttribute($attribute); + + # Add the javascript so we can call check password later. + echo ' +'; + echo "\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + protected function drawCheckLinkPasswordAttribute($attribute,$component_id) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('%s...
', + $component_id,$attribute->getName(),_('Check password')); + } + + /** RANDOM PASSWORD **/ + + /** + * This will draw the javascript that displays to the user the random password generated + * + * @todo This function doesnt work well if there are more than 1 RandomPasswordAttributes on the form for the same attribute (unlikely situation) + */ + protected function drawJavascriptRandomPasswordAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf("\n\n",__METHOD__); + $this->drawJavascriptPasswordAttribute($attribute); + + $pwd = password_generate(); + $pwd = str_replace("\\","\\\\",$pwd); + $pwd = str_replace("'","\\'",$pwd); + + printf("\n\n",__METHOD__); + echo ''; + printf("\n\n",__METHOD__); + } + + protected function drawDefaultHelperPasswordAttribute($attribute,$i) { + $id = 'enc'; + + if ($val = $attribute->getValue($i)) + $default = get_enc_type($val); + else + $default = $this->getServer()->getValue('appearance','password_hash'); + + if (! $attribute->getPostValue()) + printf('',$attribute->getName(),$i); + + printf(''; + } + + protected function drawDefaultHelperSambaPasswordAttribute($attribute,$i) { + $id = 'enc'; + + if (! $attribute->getPostValue()) + printf('',$attribute->getName(),$i); + + switch ($attribute->getName()) { + case 'sambalmpassword' : $enc = 'lm'; break; + case 'sambantpassword' : $enc = 'nt'; break; + + default: + return ''; + } + + printf('', + $id,htmlspecialchars($attribute->getName()),$i, + $id,htmlspecialchars($attribute->getName()),$i,$enc); + } + + /** SELECTION ATTRIBUTE RENDERING **/ + + protected function drawIconSelectionAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $attribute->isMultiple() || $attribute->isReadOnly()) + $this->drawIconAttribute($attribute,$val); + } + + protected function getMenuItemSelectionAttribute($attribute,$i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + switch ($i) { + case 'add': + if (! $attribute->isMultiple()) + return $this->getMenuItemAttribute($attribute,$i); + else + return ''; + + case 'modify': + return ''; + + default: + return $this->getMenuItemAttribute($attribute,$i); + } + } +} +?> diff --git a/lib/Tree.php b/lib/Tree.php new file mode 100644 index 0000000..e7542fc --- /dev/null +++ b/lib/Tree.php @@ -0,0 +1,351 @@ +server_id = $server_id; + } + + /** + * Create an instance of the tree - this is used when we call this class directly + * Tree::getInstance($index) + * + * @return object Tree + */ + static public function getInstance($server_id) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $tree = get_cached_item($server_id,'tree'); + + if (! $tree) { + $server = $_SESSION[APPCONFIG]->getServer($server_id); + + if (! $server) + return null; + + $treeclass = $_SESSION[APPCONFIG]->getValue('appearance','tree'); + $tree = new $treeclass($server_id); + + # If we are not logged in, just return the empty tree. + if (is_null($server->getLogin(null))) + return $tree; + + foreach ($server->getBaseDN(null) as $base) { + if ($base) { + $tree->addEntry($base); + + if ($server->getValue('appearance','open_tree')) { + $baseEntry = $tree->getEntry($base); + $baseEntry->open(); + } + } + } + + set_cached_item($server_id,'tree','null',$tree); + } + + return $tree; + } + + /** + * Get the Server ID for this tree + * + * @return int Server ID that this tree is for + */ + protected function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + return $this->server_id; + } + + /** + * Get the server Object for this tree + * + * @return object Server Object for this tree + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->server_id); + } + + /** + * Get the entries that are BaseDN entries. + * + * @return array Base DN entries + */ + public function getBaseEntries() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->entries as $details) + if ($details->isBaseDN() AND ((! $this->getServer()->getValue('server','hide_noaccess_base')) OR $details->isInLdap())) + array_push($return,$details); + + return $return; + } + + /** + * This function will take the DN, convert it to lowercase and strip unnessary + * commas. This result will be used as the index for the tree object. + * Any display of a DN should use the object->dn entry, not the index. + * The reason we need to do this is because: + * uid=User A,ou=People,c=AU and + * uid=User B, ou=PeOpLe, c=au + * are infact in the same branch, but PLA will show them inconsistently. + * + * @param dn DN to clean + * @return dn Lowercase clean DN + */ + private function indexDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $index = strtolower(implode(',',pla_explode_dn($dn))); + + if (DEBUG_ENABLED) + debug_log('Result (%s)',1,0,__FILE__,__LINE__,__METHOD__,$index); + + return $index; + } + + /** + * Get a tree entry + * + * @param dn DN to retrieve + * @return object Tree DN object + */ + public function getEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dnlower = $this->indexDN($dn); + + if (isset($this->entries[$dnlower])) + return $this->entries[$dnlower]; + else + return null; + } + + /** + * Add an entry in the tree view ; the entry is added in the + * children array of its parent + * + * @param dn DN to add + * @param string $dn the dn of the entry to create + */ + public function addEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + # @todo Temporarily removed, some non-ascii char DNs that do exist, fail here for some reason? + #if (! ($server->dnExists($dn))) + # return; + + if (isset($this->entries[$dnlower])) + debug_dump_backtrace('Calling add entry to an entry that ALREADY exists?',1); + + if (DEBUG_ENABLED) + debug_log('New ENTRY (%s).',64,0,__FILE__,__LINE__,__METHOD__,$dn); + + $tree_factory = new TreeItem($server->getIndex(),$dn); + $tree_factory->setObjectClasses($server->getDNAttrValue($dn,'objectClass')); + + if ((($isleaf = $server->getDNAttrValue($dn,'hassubordinates')) && ! strcasecmp($isleaf[0],'false'))) + $tree_factory->setLeaf(); + + $this->entries[$dnlower] = $tree_factory; + + # Is this entry in a base entry? + if (in_array_ignore_case($dn,$server->getBaseDN(null))) { + $this->entries[$dnlower]->setBase(); + + # If the parent entry is not in the tree, we add it. This routine will in itself + # recall this method until we get to the top of the tree (the base). + } else { + $parent_dn = $server->getContainer($dn); + + if (DEBUG_ENABLED) + debug_log('Parent DNs (%s)',64,0,__FILE__,__LINE__,__METHOD__,$parent_dn); + + if ($parent_dn) { + $parent_entry = $this->getEntry($parent_dn); + + if (! $parent_entry) { + $this->addEntry($parent_dn); + $parent_entry = $this->getEntry($parent_dn); + } + + # Update this DN's parent's children list as well. + $parent_entry->addChild($dn); + } + } + } + + /** + * Delete an entry from the tree view ; the entry is deleted from the + * children array of its parent + * + * @param dn DN to remote + */ + public function delEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + if (isset($this->entries[$dnlower])) + unset($this->entries[$dnlower]); + + # Delete entry from parent's children as well. + $parent_dn = $server->getContainer($dn); + $parent_entry = $this->getEntry($parent_dn); + + if ($parent_entry) + $parent_entry->delChild($dn); + } + + /** + * Rename an entry in the tree + * + * @param dn Old DN + * @param dn New DN + */ + public function renameEntry($dnOLD,$dnNEW) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlowerOLD = $this->indexDN($dnOLD); + $dnlowerNEW = $this->indexDN($dnNEW); + + $this->entries[$dnlowerNEW] = $this->entries[$dnlowerOLD]; + if ($dnlowerOLD != $dnlowerNEW) + unset($this->entries[$dnlowerOLD]); + $this->entries[$dnlowerNEW]->rename($dnNEW); + + # Update the parent's children + $parentNEW = $server->getContainer($dnNEW); + $parentOLD = $server->getContainer($dnOLD); + + $parent_entry = $this->getEntry($parentNEW); + if ($parent_entry) + $parent_entry->addChild($dnNEW); + + $parent_entry = $this->getEntry($parentOLD); + if ($parent_entry) + $parent_entry->delChild($dnOLD); + } + + /** + * Read the children of a tree entry + * + * @param dn DN of the entry + * @param boolean LDAP Size Limit + */ + public function readChildren($dn,$nolimit=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + if (! isset($this->entries[$dnlower])) + debug_dump_backtrace('Reading children on an entry that isnt set? '.$dnlower,true); + + $ldap['child_limit'] = $nolimit ? 0 : $_SESSION[APPCONFIG]->getValue('search','size_limit'); + $ldap['filter'] = $_SESSION[APPCONFIG]->getValue('appearance','tree_filter'); + $ldap['deref'] = $_SESSION[APPCONFIG]->getValue('deref','tree'); + + # Perform the query to get the children. + $ldap['children'] = $server->getContainerContents($dn,null,$ldap['child_limit'],$ldap['filter'],$ldap['deref']); + + if (! count($ldap['children'])) { + $this->entries[$dnlower]->unsetSizeLimited(); + + return; + } + + if (DEBUG_ENABLED) + debug_log('Children of (%s) are (%s)',64,0,__FILE__,__LINE__,__METHOD__,$dn,$ldap['children']); + + # Relax our execution time, it might take some time to load this + if ($nolimit) + @set_time_limit($_SESSION[APPCONFIG]->getValue('search','time_limit')); + + $this->entries[$dnlower]->readingChildren(true); + + foreach ($ldap['children'] as $child) { + if (DEBUG_ENABLED) + debug_log('Adding (%s)',64,0,__FILE__,__LINE__,__METHOD__,$child); + + if (! in_array($child,$this->entries[$dnlower]->getChildren())) + $this->entries[$dnlower]->addChild($child); + } + + $this->entries[$dnlower]->readingChildren(false); + + if (count($this->entries[$dnlower]->getChildren()) == $ldap['child_limit']) + $this->entries[$dnlower]->setSizeLimited(); + else + $this->entries[$dnlower]->unsetSizeLimited(); + } + + /** + * Return the number of children an entry has. Optionally autoread the child entry. + * + * @param dn DN of the entry + * @param boolean LDAP Size Limit + */ + protected function readChildrenNumber($dn,$nolimit=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dnlower = $this->indexDN($dn); + + if (! isset($this->entries[$dnlower])) + debug_dump_backtrace('Reading children on an entry that isnt set?',true); + + # Read the entry if we havent got it yet. + if (! $this->entries[$dnlower]->isLeaf() && ! $this->entries[$dnlower]->getChildren()) + $this->readChildren($dn,$nolimit); + + return count($this->entries[$dnlower]->getChildren()); + } +} +?> diff --git a/lib/TreeItem.php b/lib/TreeItem.php new file mode 100644 index 0000000..8c95ad8 --- /dev/null +++ b/lib/TreeItem.php @@ -0,0 +1,312 @@ +server_id = $server_id; + $this->dn = $dn; + } + + /** + * Get the DN of this tree item. + * + * @return DN The DN of this item. + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + return $this->dn; + } + + public function getDNEncode() { + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn)); + } + + /** + * Get the RDN of this tree items DN. + * + * @return RDN The RDN of this items DN. + */ + public function getRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return get_rdn($this->getDn(),0,true); + } + + /** + * Set this item as a LDAP base DN item. + */ + public function setBase() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->base_entry = true; + } + + /** + * Return if this item is a base DN item. + */ + public function isBaseDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->base_entry); + + return $this->base_entry; + } + + public function setObjectClasses($oc) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->objectclasses = $oc; + } + + public function getObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->objectclasses); + + return $this->objectclasses; + } + + public function isInLDAP() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return count($this->objectclasses) ? true : false; + } + + /** + * Returns null if the children have never be defined + * or an array of the dn of the children + */ + public function getChildren() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->children); + + if ($this->childsort && ! $this->reading_children) { + usort($this->children,'pla_compare_dns'); + $this->childsort = false; + } + + return $this->children; + } + + public function readingChildren($bool) { + $this->reading_children = $bool; + } + + /** + * Do the children require resorting + */ + public function isChildSorted() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->childsort); + + return $this->childsort; + } + + /** + * Mark the children as sorted + */ + public function childSorted() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->childsort = false; + } + + /** + * Add a child to this DN entry. + * + * @param DN The DN to add. + */ + public function addChild($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array($dn,$this->children)) + return; + + array_push($this->children,$dn); + $this->childsort = true; + } + + /** + * Delete a child from this DN entry. + * + * @param DN The DN to add. + */ + public function delChild($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->children) { + # If the parent hasnt been opened in the tree, then there wont be any children. + $index = array_search($dn,$this->children); + + if ($index !== false) + unset($this->children[$index]); + } + } + + /** + * Rename this DN. + * + * @param DN The DN to rename to. + */ + public function rename($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->dn = $dn; + } + + /** + * Return if this item has been opened. + */ + public function isOpened() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->open); + + return $this->open; + } + + /** + * Mark this node as closed. + */ + public function close() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->open = false; + } + + /** + * Opens the node ; the children of the node must have been defined + */ + public function open() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->open = true; + } + + /** + * Mark this node as a leaf. + */ + public function setLeaf() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->leaf = true; + } + + /** + * Return if this node is a leaf. + */ + public function isLeaf() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->leaf); + + return $this->leaf; + } + + /** + * Returns the path of the icon file used to represent this node ; + * If the icon hasnt been set, it will call get_icon() + */ + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + if (! $this->icon) + $this->icon = get_icon($this->server_id,$this->dn,$this->objectclasses); + + return $this->icon; + } + + /** + * Mark this node as a size limited (it wont have all its children). + */ + public function setSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size_limited = true; + } + + /** + * Clear the size limited flag. + */ + public function unsetSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size_limited = false; + } + + /** + * Return if this node has hit an LDAP size limit (and thus doesnt have all its children). + */ + public function isSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->size_limited; + } + + public function setTemplate($template) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->template = $template; + } + + public function getTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template; + } +} +?> diff --git a/lib/Visitor.php b/lib/Visitor.php new file mode 100644 index 0000000..fca5099 --- /dev/null +++ b/lib/Visitor.php @@ -0,0 +1,99 @@ +Class (%s): Method doesnt exist (%s,%s)
',$class,get_class($this),$call); + + $class = get_parent_class($class); + $call = "$method$fnct$class"; + array_push($methods,$call); + } + + if (defined('DEBUGTMP') && DEBUGTMP) + printf('Calling Methods: %s
',implode('|',$methods)); + + if (defined('DEBUGTMP') && DEBUGTMP && method_exists($this,$call)) + printf('Method Exists: %s::%s (%s)
',get_class($this),$call,$args); + + if (method_exists($this,$call)) { + $r = call_user_func_array(array($this,$call),$args); + + if (isset($r)) + return $r; + else + return; + + } elseif (DEBUG_ENABLED) { + debug_log('Doesnt exist param (%s,%s)',1,0,__FILE__,__LINE__,__METHOD__,$method,$fnct); + } + + printf('NO Methods: %s
',implode('|',$methods)); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + public function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + if (isset($this->server_id)) + return $this->server_id; + else + return null; + } + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } +} +?> diff --git a/lib/blowfish.php b/lib/blowfish.php new file mode 100644 index 0000000..1c69aa9 --- /dev/null +++ b/lib/blowfish.php @@ -0,0 +1,480 @@ + + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Mike Cochrane + * @version $Revision$ + * @since Horde 2.2 + * @package horde.cipher + */ +/** + * @package horde.cipher + */ + +// Change for phpMyAdmin by lem9: +//class Horde_Cipher_blowfish extends Horde_Cipher { +class Horde_Cipher_blowfish { + + /* Pi Array */ + public $p = array( + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B); + + /* S Boxes */ + public $s1 = array( + 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A); + public $s2 = array( + 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7); + public $s3 = array( + 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0); + public $s4 = array( + 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6); + + /* The number of rounds to do */ + public $_rounds = 16; + + /* Constructor */ + function Cipher_blowfish($params = null) + { + } + + /** + * Set the key to be used for en/decryption + * + * @param String $key The key to use + */ + function setKey($key) + { + $key = $this->_formatKey($key); + $keyPos = $keyXor = 0; + + $iMax = count($this->p); + $keyLen = count($key); + for ($i = 0; $i < $iMax; $i++) { + for ($t = 0; $t < 4; $t++) { + $keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff); + if (++$keyPos == $keyLen) { + $keyPos = 0; + } + } + $this->p[$i] = $this->p[$i] ^ $keyXor; + } + + $encZero = array('L' => 0, 'R' => 0); + for ($i = 0; $i + 1 < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->p[$i] = $encZero['L']; + $this->p[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s1); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s1[$i] = $encZero['L']; + $this->s1[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s2); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s2[$i] = $encZero['L']; + $this->s2[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s3); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s3[$i] = $encZero['L']; + $this->s3[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s4); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s4[$i] = $encZero['L']; + $this->s4[$i + 1] = $encZero['R']; + } + + } + + /** + * Return the size of the blocks that this cipher needs + * + * @return Integer The number of characters per block + */ + function getBlockSize() + { + return 8; + } + + /** + * Encrypt a block on data. + * + * @param String $block The data to encrypt + * @param optional String $key The key to use + * + * @return String the encrypted output + */ + function encryptBlock($block, $key = null) + { + if (!is_null($key)) { + $this->setKey($key); + } + + list($L, $R) = array_values(unpack('N*', $block)); + $parts = $this->_encryptBlock($L, $R); + return pack("NN", $parts['L'], $parts['R']); + } + + /** + * Encrypt a block on data. + * + * @param String $L The data to encrypt. + * @param String $R The data to encrypt. + * + * @return String The encrypted output. + */ + function _encryptBlock($L, $R) + { + $L ^= $this->p[0]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16]; + $R ^= $this->p[17]; + + return array('L' => $R, 'R' => $L); + } + + /** + * Decrypt a block on data. + * + * @param String $block The data to decrypt + * @param optional String $key The key to use + * + * @return String the decrypted output + */ + function decryptBlock($block, $key = null) + { + if (!is_null($key)) { + $this->setKey($key); + } + + $unpack = unpack('N*', $block); + + if (! is_array($unpack)) + error( + sprintf('BLOWFISH: decryptBock()
We expected unpack to produce an array, but instead it produced [%s]. This function was entered with (%s,%s). If you think that this is a bug, then please tell the PLA developers how you got here. You are using PLA [%s,%s]', + serialize($unpack),$block,$key,app_version(),phpversion()),'error','index.php'); + + list($L, $R) = array_values($unpack); + + $L ^= $this->p[17]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1]; + + $decrypted = pack("NN", $R ^ $this->p[0], $L); + return $decrypted; + } + + /** + * Converts a text key into an array. + * + * @return array The key. + */ + function _formatKey($key) + { + return array_values(unpack('C*', $key)); + } + +} +?> diff --git a/lib/common.php b/lib/common.php new file mode 100644 index 0000000..b5aaff8 --- /dev/null +++ b/lib/common.php @@ -0,0 +1,335 @@ +getValue('appearance','theme')))) + && is_file(realpath(sprintf('css/%s/%s',$_SESSION[APPCONFIG]->getValue('appearance','theme'),$_SESSION[APPCONFIG]->getValue('appearance','stylesheet'))))) + + $app['theme'] = $_SESSION[APPCONFIG]->getValue('appearance','theme'); + +define('CSSDIR',sprintf('css/%s',$app['theme'])); +define('IMGDIR',sprintf('images/%s',$app['theme'])); + +# Initialise the hooks +if (file_exists(LIBDIR.'hooks.php')) + require_once LIBDIR.'hooks.php'; + +# If we get here, and $_SESSION[APPCONFIG] is not set, then redirect the user to the index. +if (isset($_SERVER['SERVER_SOFTWARE']) && ! isset($_SESSION[APPCONFIG])) { + if ($_SERVER['QUERY_STRING']) + header(sprintf('Location: index.php?URI=%s',base64_encode($_SERVER['QUERY_STRING']))); + else + header('Location: index.php'); + + die(); + +} else { + # SF Bug #1903987 + if (! method_exists($_SESSION[APPCONFIG],'CheckCustom')) + error('Unknown situation, $_SESSION[APPCONFIG] exists, but method CheckCustom() does not','error',null,true,true); + + # Check our custom variables. + # @todo Change this so that we dont process a cached session. + $_SESSION[APPCONFIG]->CheckCustom(); +} + +# Check for safe mode. +if (@ini_get('safe_mode') && ! get_request('cmd','GET')) + system_message(array( + 'title'=>_('PHP Safe Mode'), + 'body'=>_('You have PHP Safe Mode enabled. This application may work unexpectedly in Safe Mode.'), + 'type'=>'info')); + +# Set our timezone, if it is specified in config.php +if ($_SESSION[APPCONFIG]->getValue('appearance','timezone')) + date_default_timezone_set($_SESSION[APPCONFIG]->getValue('appearance','timezone')); + +# If we are here, $_SESSION is set - so enabled DEBUGing if it has been configured. +if (($_SESSION[APPCONFIG]->getValue('debug','syslog') || $_SESSION[APPCONFIG]->getValue('debug','file')) + && $_SESSION[APPCONFIG]->getValue('debug','level')) + define('DEBUG_ENABLED',1); +else + define('DEBUG_ENABLED',0); + +if (DEBUG_ENABLED) + debug_log('Application (%s) initialised and starting with (%s).',1,0,__FILE__,__LINE__,__METHOD__, + app_version(),$_REQUEST); + +# Set our PHP timelimit. +if ($_SESSION[APPCONFIG]->getValue('session','timelimit') && ! @ini_get('safe_mode')) + set_time_limit($_SESSION[APPCONFIG]->getValue('session','timelimit')); + +# If debug mode is set, increase the time_limit, since we probably need it. +if (DEBUG_ENABLED && $_SESSION[APPCONFIG]->getValue('session','timelimit') && ! @ini_get('safe_mode')) + set_time_limit($_SESSION[APPCONFIG]->getValue('session','timelimit') * 5); + +/** + * Language configuration. Auto or specified? + * Shall we attempt to auto-determine the language? + */ +# If we are in safe mode, and LANG is not in the allowed vars, display an error. +if (@ini_get('safe_mode') && ! in_array('LANG',explode(',',@ini_get('safe_mode_allowed_env_vars')))) + error('You are running in SAFE_MODE, but LANG is not in the safe_mode_allowed_env_vars. Please add LANG to safe_mode_allowed_env_vars','error',true,false); + +$app['language'] = $_SESSION[APPCONFIG]->getValue('appearance','language'); + +if ($app['language'] == 'auto') { + + # Make sure their browser correctly reports language. If not, skip this. + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + + # Get the languages which are spetcified in the HTTP header + $app['lang_http'] = preg_split ('/[;,]+/',$_SERVER['HTTP_ACCEPT_LANGUAGE']); + foreach ($app['lang_http'] as $key => $value) { + if (substr($value,0,2) == 'q=') { + unset($app['lang_http'][$key]); + continue; + } + + $value = preg_split('/[-]+/',$value); + if (sizeof($value) == 2) + $app['lang_http'][$key] = strtolower($value[0]).'_'.strtoupper($value[1]); + else + $app['lang_http'][$key] = auto_lang(strtolower($value[0])); + } + + $app['lang_http'] = array_unique($app['lang_http']); + + foreach ($app['lang_http'] as $lang) { + $app['language_dir'] = LANGDIR.$lang; + + if ((substr($lang,0,2) == 'en') || + (file_exists($app['language_dir']) && is_readable($app['language_dir']))) { + + # Set language + putenv('LANG='.$lang); # e.g. LANG=de_DE + $lang .= '.UTF-8'; + setlocale(LC_ALL,$lang); # set LC_ALL to de_DE + bindtextdomain('messages',LANGDIR); + bind_textdomain_codeset('messages','UTF-8'); + textdomain('messages'); + header('Content-type: text/html; charset=UTF-8',true); + break; + } + } + #todo Generate an error if language doesnt exist. + } + +} else { + # Grab the language file configured in config.php + #todo Generate an error if language doesnt exist. + if ($app['language'] != null) { + if (strcmp($app['language'],'english') == 0) + $app['language'] = 'en_GB'; + + # Set language + putenv('LANG='.$app['language']); # e.g. LANG=de_DE + $app['language'] .= '.UTF-8'; + setlocale(LC_ALL,$app['language']); # set LC_ALL to de_DE + bindtextdomain('messages',LANGDIR); + bind_textdomain_codeset('messages','UTF-8'); + textdomain('messages'); + header('Content-type: text/html; charset=UTF-8',true); + } +} + +/** + * Strip slashes from GET, POST, and COOKIE variables if this + * PHP install is configured to automatically addslashes() + */ +if (@get_magic_quotes_gpc() && (! isset($slashes_stripped) || ! $slashes_stripped)) { + array_stripslashes($_REQUEST); + array_stripslashes($_GET); + array_stripslashes($_POST); + array_stripslashes($_COOKIE); + $slashes_stripped = true; +} + +# Create our application repository variable. +$app['server'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + +/** + * Look/evaluate our timeout + */ +if (! $app['server']->isSessionValid()) { + system_message(array( + 'title'=>_('Session Timed Out'), + 'body'=>sprintf('%s %s %s', + _('Your Session timed out after'),$app['server']->getValue('login','timeout'), + _('min. of inactivity. You have been automatically logged out.')), + 'type'=>'info'),sprintf('index.php?server_id=%s&refresh=SID_%s',$app['server']->getIndex(),$app['server']->getIndex())); + + die(); +} + +# If syslog is enabled, we need to include the supporting file. +if ($_SESSION[APPCONFIG]->getValue('debug','syslog')) + require LIBDIR.'syslog.php'; + +/** + * At this point we have read all our additional function PHP files and our configuration. + * If we are using hooks, run the session_init hook. + */ +if (function_exists('run_hook')) + run_hook('post_session_init',array()); +?> diff --git a/lib/config_default.php b/lib/config_default.php new file mode 100644 index 0000000..b0c05ca --- /dev/null +++ b/lib/config_default.php @@ -0,0 +1,808 @@ +custom = new stdClass; + $this->default = new stdClass; + + /* + * What to do after entry creation : + * 2 : display the creation form again + * 1 : display the new created entry + * 0 : display the choice between 1 and 2 + */ + $this->default->appearance['action_after_creation'] = array( + 'desc'=>'Display the new created entry', + 'default'=>1); + + ## Appearance Attributes + /** Anonymous implies read only + * Set to true if you want LDAP data to be displayed read-only (without input fields) + * when a user logs in to a server anonymously + */ + $this->default->appearance['anonymous_bind_implies_read_only'] = array( + 'desc'=>'Display as read only if user logs in with anonymous bind', + 'default'=>true); + + $this->default->appearance['attr_display_order'] = array( + 'desc'=>'Custom order to display attributes', + 'default'=>array()); + + /* + * @todo Compression is not working, + * purge_cache shows blank, + * tree refresh shows blank - and if view_tree_node is modified to compress output, then previously opened items show up as compressed data. + */ + $this->default->appearance['compress'] = array( + 'desc'=>'Compress Output', + 'untested'=>true, + 'default'=>false); + + $this->default->appearance['control_icons'] = array( + 'desc'=>'Show the control as icons or text', + 'default'=>false); + + $this->default->appearance['custom_templates_only'] = array( + 'desc'=>'Only display the custom templates.', + 'default'=>false); + + $this->default->appearance['date'] = array( + 'desc'=>'Date format whenever dates are shown', + 'default'=>'%A %e %B %Y'); + + $this->default->appearance['date_attrs'] = array( + 'desc'=>'Array of attributes that should show a jscalendar', + 'default'=>array('shadowExpire'=>'%es','shadowLastChange'=>'%es')); + + $this->default->appearance['date_attrs_showtime'] = array( + 'desc'=>'Array of attributes that should show a the time when showing the jscalendar', + 'default'=>array('')); + + $this->default->appearance['disable_default_template'] = array( + 'desc'=>'Disabled the Default Template', + 'default'=>false); + + $this->default->appearance['disable_default_leaf'] = array( + 'desc'=>'Disabled creating leaf entries in the Default Template', + 'default'=>false); + + $this->default->appearance['friendly_attrs'] = array( + 'desc'=>'Friendly names for attributes', + 'default'=>array()); + + $this->default->appearance['hide_attrs'] = array( + 'desc'=>'Hide attributes from display', + 'default'=>array()); + + $this->default->appearance['hide_attrs_exempt'] = array( + 'desc'=>'Group DN, where membership will exempt the users from hide_attrs', + 'default'=>null); + + $this->default->appearance['hide_debug_info'] = array( + 'desc'=>'Hide the features that may provide sensitive debugging information to the browser', + 'default'=>true); + + $this->default->appearance['hide_template_regexp'] = array( + 'desc'=>'Templates that are disabled by their regex are not shown', + 'default'=>false); + + $this->default->appearance['hide_template_warning'] = array( + 'desc'=>'Hide template errors from being displayed', + 'default'=>false); + + /** Language + * The language setting. If you set this to 'auto', phpLDAPadmin will + * attempt to determine your language automatically. Otherwise, set + * this to your applicable language in xx_XX format. + * Localization is not complete yet, but most strings have been translated. + * Please help by writing language files. + */ + $this->default->appearance['language'] = array( + 'desc'=>'Language', + 'default'=>'auto'); + + $this->default->appearance['max_add_attrs'] = array( + 'desc'=>'Maximum number of attrs to show in the add attr form', + 'default'=>10); + + /** + * If you want certain attributes to be editable as multi-line, include them in this list + * A multi-line textarea will be drawn instead of a single-line text field + */ + $this->default->appearance['multi_line_attributes'] = array( + 'desc'=>'Attributes to show as multiline attributes', + 'default'=>array('postalAddress','homePostalAddress','personalSignature','description','mailReplyText')); + + /** + * A list of syntax OIDs which support multi-line attribute values: + */ + $this->default->appearance['multi_line_syntax_oids'] = array( + 'desc'=>'Attributes to show as multiline attributes', + 'default'=>array( + // octet string syntax OID: + '1.3.6.1.4.1.1466.115.121.1.40', + // postal address syntax OID: + '1.3.6.1.4.1.1466.115.121.1.41')); + + /** Obfuscate Password + * If true, display all password hash values as "******". Note that clear-text + * passwords will always be displayed as "******", regardless of this setting. + */ + $this->default->appearance['obfuscate_password_display'] = array( + 'desc'=>'Obfuscate the display of passwords', + 'default'=>true); + + $this->default->appearance['page_title'] = array( + 'desc'=>'Change the page title to this text', + 'default'=>''); + + $this->default->appearance['rdn_all_attrs'] = array( + 'desc'=>'Whether to show all attributes in the RDN chooser, or just the required ones', + 'default'=>true); + + $this->default->appearance['readonly_attrs'] = array( + 'desc'=>'Mark these attributes as readonly', + 'default'=>array()); + + $this->default->appearance['readonly_attrs_exempt'] = array( + 'desc'=>'Group DN, where membership will exempt the users from readonly attrs', + 'default'=>null); + + $this->default->appearance['remoteurls'] = array( + 'desc'=>'Whether to include renders for remote URLs', + 'default'=>true); + + $this->default->appearance['show_clear_password'] = array( + 'desc'=>'Whether to show clear passwords if we dont obfuscate them', + 'default'=>false); + + $this->default->appearance['show_hints'] = array( + 'desc'=>'Show helpful hints', + 'default'=>true); + + $this->default->appearance['show_top_create'] = array( + 'desc'=>'Show a additional create link on the top of the list if there are more than 10 entries', + 'default'=>true); + + $this->default->appearance['show_schema_link'] = array( + 'desc'=>'Show the schema link for each attribute', + 'default'=>true); + + $this->default->appearance['show_attribute_notes'] = array( + 'desc'=>'Show notes for each attribute', + 'default'=>true); + + $this->default->appearance['stylesheet'] = array( + 'desc'=>'Style sheet to use', + 'default'=>'style.css'); + + $this->default->appearance['theme'] = array( + 'desc'=>'Which theme to use', + 'default'=>'default'); + + $this->default->appearance['timezone'] = array( + 'desc'=>'Define our timezone, if not defined in php.ini', + 'default'=>null); + + $this->default->appearance['tree'] = array( + 'desc'=>'Class name which inherits from Tree class and implements the draw() method', + 'default'=>'AJAXTree'); + + /** Tree display + * An array of format strings used to display enties in the + * tree viewer (left-hand side). The first format string that + * is completely defined (i.e., does not reference attributes + * that are not defined the object). If there is no format + * string that is completely defined, the last one is used. + * + * You can use special tokens to draw the entries as you wish. + * You can even mix in HTML to format the string. + * Here are all the tokens you can use: + * %rdn - draw the RDN of the entry (ie, "cn=Dave") + * %dn - draw the DN of the entry (ie, "cn=Dave,ou=People,dc=example,dc=com" + * %rdnValue - draw the value of the RDN (ie, instead of "cn=Dave", just draw "Dave") + * %[attrname]- draw the value (or values) of the specified attribute. + * example: %gidNumber + * + * Any multivalued attributes will be displayed as a comma separated list. + * + * Examples: + * + * To draw the gidNumber and uidNumber to the right of the RDN in a small, gray font: + * '%rdn ( %gidNumber / %uidNumber )' + * To draw the full DN of each entry: + * '%dn' + * To draw the objectClasses to the right in parenthesis: + * '%rdn ( %objectClass )' + * To draw the user-friendly RDN value (ie, instead of "cn=Dave", just draw "Dave"): + * '%rdnValue' + */ + $this->default->appearance['tree_display_format'] = array( + 'desc'=>'LDAP attribute to show in the tree', + 'default'=>array('%rdn')); + + $this->default->appearance['tree_height'] = array( + 'desc'=>'Pixel height of the tree browser', + 'default'=>null); + + $this->default->appearance['tree_width'] = array( + 'desc'=>'Pixel width of the tree browser', + 'default'=>null); + + /** Tree display filter + * LDAP filter used to search entries for the tree viewer (left-hand side) + */ + $this->default->appearance['tree_filter'] = array( + 'desc'=>'LDAP search filter for the tree entries', + 'default'=>'(objectClass=*)'); + + # PLA will not display the header and footer parts in minimal mode. + $this->default->appearance['minimalMode'] = array( + 'desc'=>'Minimal mode hides header and footer parts', + 'default'=>false); + + ## Caching + $this->default->cache['schema'] = array( + 'desc'=>'Cache Schema Activity', + 'default'=>true); + + $this->default->cache['query'] = array( + 'desc'=>'Cache Query Configuration', + 'default'=>true); + + $this->default->cache['query_time'] = array( + 'desc'=>'Cache the query configuration for atleast this amount of time in seconds', + 'default'=>5); + + $this->default->cache['template'] = array( + 'desc'=>'Cache Template Configuration', + 'default'=>true); + + $this->default->cache['template_time'] = array( + 'desc'=>'Cache the template configuration for atleast this amount of time in seconds', + 'default'=>60); + + $this->default->cache['tree'] = array( + 'desc'=>'Cache Browser Tree', + 'default'=>true); + + /** Confirm actions + */ + $this->default->confirm['copy'] = array( + 'desc'=>'Confirm copy actions', + 'default'=>true); + + $this->default->confirm['create'] = array( + 'desc'=>'Confirm creation actions', + 'default'=>true); + + $this->default->confirm['update'] = array( + 'desc'=>'Confirm update actions', + 'default'=>true); + + /** Commands + * Define command availability ; if the value of a command is true, + * the command will be available. + */ + $this->default->commands['cmd'] = array( + 'desc'=>'Define command availability', + 'default'=> array( + 'entry_internal_attributes_show' => true, + 'entry_refresh' => true, + 'oslinks' => true, + 'switch_template' => true + )); + + $this->default->commands['script'] = array( + 'desc'=>'Define scripts availability', + 'default'=> array( + 'add_attr_form' => true, + 'add_oclass_form' => true, + 'add_value_form' => true, + 'collapse' => true, + 'compare' => true, + 'compare_form' => true, + 'copy' => true, + 'copy_form' => true, + 'create' => true, + 'create_confirm' => true, + 'delete' => true, + 'delete_attr' => true, + 'delete_form' => true, + 'draw_tree_node' => true, + 'expand' => true, + 'export' => true, + 'export_form' => true, + 'import' => true, + 'import_form' => true, + 'login' => true, + 'logout' => true, + 'login_form' => true, + 'mass_delete' => true, + 'mass_edit' => true, + 'mass_update' => true, + 'modify_member_form' => true, + 'monitor' => true, + 'purge_cache' => true, + 'query_engine' => true, + 'rename' => true, + 'rename_form' => true, + 'rdelete' => true, + 'refresh' => true, + 'schema' => true, + 'server_info' => true, + 'show_cache' => true, + 'template_engine' => true, + 'update_confirm' => true, + 'update' => true + )); + + /** Aliases and Referrrals + * Similar to ldapsearch's -a option, the following options allow you to configure + * how phpLDAPadmin will treat aliases and referrals in the LDAP tree. + * For the following four settings, avaialable options include: + * + * LDAP_DEREF_NEVER - aliases are never dereferenced (eg, the contents of + * the alias itself are shown and not the referenced entry). + * LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search but + * not when locating the base object of the search. + * LDAP_DEREF_FINDING - aliases should be dereferenced when locating the base + * object but not during the search. + * LDAP_DEREF_ALWAYS - aliases should be dereferenced always (eg, the contents + * of the referenced entry is shown and not the aliasing entry) + * We superceed these definitions with @ to suppress the error if php-ldap is + * not installed. + */ + @$this->default->deref['export'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + @$this->default->deref['search'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_ALWAYS); + + @$this->default->deref['tree'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + @$this->default->deref['view'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + ## Debug Attributes + $this->default->debug['level'] = array( + 'desc'=>'Debug level verbosity', + 'default'=>0); + + $this->default->debug['syslog'] = array( + 'desc'=>'Whether to send debug messages to syslog', + 'default'=>false); + + $this->default->debug['file'] = array( + 'desc'=>'Name of file to send debug output to', + 'default'=>null); + + $this->default->debug['addr'] = array( + 'desc'=>'IP address of client to provide debugging info.', + 'default'=>null); + + $this->default->debug['append'] = array( + 'desc'=>'Whether to append to the debug file, or create it fresh each time', + 'default'=>true); + + ## Temp Directories + /** JPEG TMPDir + * This directory must be readable and writable by your web server + */ + $this->default->jpeg['tmpdir'] = array( + 'desc'=>'Temporary directory for jpegPhoto data', + 'default'=>'/tmp'); + + ## Mass update commands + $this->default->mass['enabled'] = array( + 'desc'=>'Are mass update commands enabled', + 'default'=>true); + + ## Modify members feature + /** + * Search filter setting for new members. This is used to search possible members that can be added + * to the group. See modify_member_form.php + */ + $this->default->modify_member['filter'] = array( + 'desc'=>'Search filter for member searches', + 'default'=>'(objectclass=Person)'); + + /** + * Group attributes. When these attributes are seen in template_engine.php, add "modify group members" + * link to the attribute + * See template_engine.php + */ + $this->default->modify_member['groupattr'] = array( + 'desc'=>'Group member attributes', + 'default'=>array('member','uniqueMember','memberUid')); + + /** + * Attribute that is added to the group member attribute. For groupOfNames or groupOfUniqueNames this is dn, + * for posixGroup it's uid. See modify_member_form.php + */ + $this->default->modify_member['attr'] = array( + 'desc'=>'Default attribute that is added to the group member attribute', + 'default'=>'dn'); + + /** + * Attribute that is added to the group member attribute. + * For posixGroup it's uid. See modify_member_form.php + */ + $this->default->modify_member['posixattr'] = array( + 'desc'=>'Contents of the group member attribute', + 'default'=>'uid'); + + /** + * Search filter setting for new members to group. This is used to search possible members that can be added + * to the posixGroup. See modify_member_form.php + */ + $this->default->modify_member['posixfilter'] = array( + 'desc'=>'Search filter for posixmember searches', + 'default'=>'(uid=*)'); + + /** + * posixGroup attribute. When this attribute are seen in modify_member_form.php, only posixGroup members are shown + * See modify_member_form.php + */ + $this->default->modify_member['posixgroupattr'] = array( + 'desc'=>'posixGroup member attribute', + 'default'=>'memberUid'); + + ## Session Attributes + /** Cookie Encryption + * phpLDAPadmin can encrypt the content of sensitive cookies if you set this to a big random string. + */ + $this->default->session['blowfish'] = array( + 'desc'=>'Blowfish key to encrypt cookie details', + 'default'=>null); + + /** Cookie Time + * If you used auth_type 'form' in the servers list, you can adjust how long the cookie will last + * (default is 0 seconds, which expires when you close the browser) + */ + $this->default->session['cookie_time'] = array( + 'desc'=>'Time in seconds for the life of cookies', + 'default'=>0); + + $this->default->session['http_realm'] = array( + 'desc'=>'HTTP Authentication Realm', + 'default'=>sprintf('%s %s',app_name(),_('login'))); + + $this->default->session['memorylimit'] = array( + 'desc'=>'Set the PHP memorylimit warning threshold.', + 'default'=>24); + + $this->default->session['timelimit'] = array( + 'desc'=>'Set the PHP timelimit.', + 'default'=>30); + + /** + * Session Menu + */ + $this->default->menu['session'] = array( + 'desc'=>'Menu items when logged in.', + 'default'=>array( + 'schema'=>true, + 'search'=>true, + 'refresh'=>true, + 'server_info'=>true, + 'monitor'=>true, + 'import'=>true, + 'export'=>true + )); + + ## Password Generation + $this->default->password['length'] = array( + 'desc'=>'Length of autogenerated password', + 'default'=>8); + + $this->default->password['numbers'] = array( + 'desc'=>'Number of numbers required in the password', + 'default'=>2); + + $this->default->password['lowercase'] = array( + 'desc'=>'Number of lowercase letters required in the password', + 'default'=>2); + + $this->default->password['uppercase'] = array( + 'desc'=>'Number of uppercase letters required in the password', + 'default'=>2); + + $this->default->password['punctuation'] = array( + 'desc'=>'Number of punctuation letters required in the password', + 'default'=>2); + + $this->default->password['use_similar'] = array( + 'desc'=>'Whether to use similiar characters', + 'default'=>true); + + $this->default->password['no_random_crypt_salt'] = array( + 'desc'=>'Disable random salt for crypt()', + 'default'=>false); + + /** Search display + * By default, when searching you may display a list or a table of results. + * Set this to 'table' to see table formatted results. + * Set this to 'list' to see "Google" style formatted search results. + */ + $this->default->search['display'] = array( + 'desc'=>'Display a list or table of search results', + 'default'=>'list'); + + $this->default->search['size_limit'] = array( + 'desc'=>'Limit the size of searchs on the search page', + 'default'=>50); + + /** + * The list of attributes to display in each search result entry. + * Note that you can add * to the list to display all attributes + */ + $this->default->search['result_attributes'] = array( + 'desc'=>'List of attributes to display in each search result entry', + 'default'=>array('cn','sn','uid','postalAddress','telephoneNumber')); + + $this->default->search['time_limit'] = array( + 'desc'=>'Maximum time to allow unlimited size_limit searches to the ldap server', + 'default'=>120); + } + + /** + * Access the configuration, taking into account the defaults and the customisations + */ + private function getConfigArray($usecache=true) { + static $CACHE = array(); + + if ($usecache && count($CACHE)) + return $CACHE; + + foreach ($this->default as $key => $vals) + $CACHE[$key] = $vals; + + foreach ($this->custom as $key => $vals) + foreach ($vals as $index => $val) + $CACHE[$key][$index]['value'] = $val; + + return $CACHE; + } + + /** + * Get a configuration value. + */ + public function getValue($key,$index,$fatal=true) { + $config = $this->getConfigArray(); + + if (! isset($config[$key])) + if ($fatal) + error(sprintf('A call was made in [%s] to getValue requesting [%s] that isnt predefined.', + basename($_SERVER['PHP_SELF']),$key),'error',null,true); + else + return ''; + + if (! isset($config[$key][$index])) + if ($fatal) + error(sprintf('Requesting an index [%s] in key [%s] that isnt predefined.',$index,$key),'error',null,true); + else + return ''; + + return isset($config[$key][$index]['value']) ? $config[$key][$index]['value'] : $config[$key][$index]['default']; + } + + /** + * Return the untested config items + */ + public function untested() { + $result = array(); + + foreach ($this->default as $option => $details) + foreach ($details as $param => $values) + if (isset($values['untested']) && $values['untested']) + array_push($result,sprintf('%s.%s',$option,$param)); + + return $result; + } + + /** + * Function to check and warn about any unusual defined variables. + */ + public function CheckCustom() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->custom)) { + foreach ($this->custom as $masterkey => $masterdetails) { + + if (isset($this->default->$masterkey)) { + + if (! is_array($masterdetails)) + error(sprintf('Error in configuration file, [%s] should be an ARRAY.',$masterdetails),'error',null,true); + + foreach ($masterdetails as $key => $value) { + # Test that the key is correct. + if (! in_array($key,array_keys($this->default->$masterkey))) + error(sprintf('Error in configuration file, [%s] has not been defined as a configurable variable.',$key),'error',null,true); + + # Test if its should be an array or not. + if (is_array($this->default->{$masterkey}[$key]['default']) && ! is_array($value)) + error(sprintf('Error in configuration file, %s[\'%s\'] SHOULD be an array of values.',$masterkey,$key),'error',null,true); + + if (! is_array($this->default->{$masterkey}[$key]['default']) && is_array($value)) + error(sprintf('Error in configuration file, %s[\'%s\'] should NOT be an array of values.',$masterkey,$key),'error',null,true); + } + + } else { + error(sprintf('Error in configuration file, [%s] has not been defined as a MASTER configurable variable.',$masterkey),'error',null,true); + } + } + } + } + + /** + * Get a list of available commands. + */ + public function getCommandList() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $config = $this->getConfigArray(false); + + masort($config['command'],'summary'); + + if (isset($config['command']) && is_array($config['command'])) + return $config['command']; + else + return array(); + } + + /** + * Simple ACL to see if commands can be run + */ + public function isCommandAvailable($index='cmd') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $a = func_get_args(); + array_shift($a); + $a = $a[0]; + + # Command availability list + $cmd = $this->getValue('commands',$index); + + if (! is_string($a) || ! isset($cmd[$a])) + return false; + else + return $cmd[$a]; + } + + public function configDefinition($key,$index,$config) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($config) || ! array_key_exists('desc',$config) || ! array_key_exists('default',$config)) + return; + + if (isset($this->default->$key)) + $definition = $this->default->$key; + + $definition[$index] = $config; + $this->default->$key = $definition; + } + + /** + * Return the friendly attributes names + */ + private function getFriendlyAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_change_key_case($this->getValue('appearance','friendly_attrs')); + } + + /** + * This function will return the friendly name of an attribute, if it exists. + * If the friendly name doesnt exist, the attribute name will be returned. + * + * @param attribute + * @return string friendly name|attribute + */ + public function getFriendlyName($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $friendly_attrs; + + if (! $friendly_attrs) + $friendly_attrs = $this->getFriendlyAttrs(); + + if (! is_object($attr)) + if (isset($friendly_attrs[$attr])) + return $friendly_attrs[$attr]; + else + return $attr; + + if (isset($friendly_attrs[$attr->getName()])) + return $friendly_attrs[$attr->getName()]; + else + return $attr->getName(false); + } + + /** + * This function will return true if a friendly name exists for an attribute. + * If the friendly name doesnt exist, it will return false. + * + * @param attribute + * @return boolean true|false + */ + public function haveFriendlyName($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $attr->getName(false) != $this->getFriendlyName($attr); + } + + /** + * This function will return the html for a friendly name attribute. + * + * @param attribute + * @return string html for the friendly name. + */ + public function getFriendlyHTML($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->haveFriendlyName($attr)) + return sprintf('%s', + _('Alias for'),$attr->getName(false),$this->getFriendlyName($attr)); + else + return $attr->getName(false); + } + + public function setServers($servers) { + $this->servers = $servers; + } + + public function getServer($index=null) { + return $this->servers->Instance($index); + } + + /** + * Return a list of our servers + * @param boolean $visible - Only return visible servers + */ + public function getServerList($visible=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->servers->getServerList($visible); + } +} +?> diff --git a/lib/createlm.php b/lib/createlm.php new file mode 100644 index 0000000..3dc4bb1 --- /dev/null +++ b/lib/createlm.php @@ -0,0 +1,381 @@ +permute($key, $this->perm1, 56); + + $c = array(); + $d = array(); + for ($i = 0; $i < 28; $i++) { + $c[$i] = $pk1[$i]; + $d[$i] = $pk1[28 + $i]; + } + + for ($i = 0; $i < 16; $i++) { + $c = $this->lshift($this->sc[$i], $c); + $d = $this->lshift($this->sc[$i], $d); + + $cd = $c; + for ($k = 0; $k < sizeof($d); $k++) $cd[] = $d[$k]; + $ki[$i] = $this->permute($cd, $this->perm2, 48); + } + + $pd1 = $this->permute($in, $this->perm3, 64); + + $l = array(); + $r = array(); + for ($i = 0; $i < 32; $i++) { + $l[$i] = $pd1[$i]; + $r[$i] = $pd1[32 + $i]; + } + + for ($i = 0; $i < 16; $i++) { + $er = $this->permute($r, $this->perm4, 48); + if ($forw) $erk = $this->mxor($er, $ki[$i]); + else $erk = $this->mxor($er, $ki[15 - $i]); + + for ($j = 0; $j < 8; $j++) { + for ($k = 0; $k < 6; $k++) { + $b[$j][$k] = $erk[($j * 6) + $k]; + } + } + for ($j = 0; $j < 8; $j++) { + $m = array(); + $n = array(); + $m = ($b[$j][0] << 1) | $b[$j][5]; + $n = ($b[$j][1] << 3) | ($b[$j][2] << 2) | ($b[$j][3] << 1) | $b[$j][4]; + + for ($k = 0; $k < 4; $k++) { + $b[$j][$k]=($this->sbox[$j][$m][$n] & (1 << (3-$k)))?1:0; + } + } + + for ($j = 0; $j < 8; $j++) { + for ($k = 0; $k < 4; $k++) { + $cb[($j * 4) + $k] = $b[$j][$k]; + } + } + $pcb = $this->permute($cb, $this->perm5, 32); + $r2 = $this->mxor($l, $pcb); + for ($k = 0; $k < 32; $k++) $l[$k] = $r[$k]; + for ($k = 0; $k < 32; $k++) $r[$k] = $r2[$k]; + } + $rl = $r; + for ($i = 0; $i < sizeof($l); $i++) $rl[] = $l[$i]; + return $this->permute($rl, $this->perm6, 64); + } + + /** + * str_to_key + * + * @param string $str + * @return string key + */ + private function str_to_key($str) { + $key[0] = $this->unsigned_shift_r($str[0], 1); + $key[1] = (($str[0]&0x01)<<6) | $this->unsigned_shift_r($str[1], 2); + $key[2] = (($str[1]&0x03)<<5) | $this->unsigned_shift_r($str[2], 3); + $key[3] = (($str[2]&0x07)<<4) | $this->unsigned_shift_r($str[3], 4); + $key[4] = (($str[3]&0x0F)<<3) | $this->unsigned_shift_r($str[4], 5); + $key[5] = (($str[4]&0x1F)<<2) | $this->unsigned_shift_r($str[5], 6); + $key[6] = (($str[5]&0x3F)<<1) | $this->unsigned_shift_r($str[6], 7); + $key[7] = $str[6]&0x7F; + for ($i = 0; $i < 8; $i++) { + $key[$i] = ($key[$i] << 1); + } + return $key; + } + + /** + * smb_hash + * + * @param unknown_type $in + * @param unknown_type $key + * @param unknown_type $forw + * @return unknown + */ + private function smb_hash($in, $key, $forw){ + $key2 = $this->str_to_key($key); + + for ($i = 0; $i < 64; $i++) { + $inb[$i] = ($in[$i/8] & (1<<(7-($i%8)))) ? 1:0; + $keyb[$i] = ($key2[$i/8] & (1<<(7-($i%8)))) ? 1:0; + $outb[$i] = 0; + } + $outb = $this->doHash($inb, $keyb, $forw); + for ($i = 0; $i < 8; $i++) { + $out[$i] = 0; + } + for ($i = 0; $i < 64; $i++) { + if ( $outb[$i] ) { + $out[$i/8] |= (1<<(7-($i%8))); + } + } + return $out; + } + + /** + * E_P16 + * + * @param unknown_type $in + * @return unknown + */ + private function E_P16($in) { + $p14 = array_values(unpack("C*",$in)); + $sp8 = array(0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25); + $p14_1 = array(); + $p14_2 = array(); + for ($i = 0; $i < 7; $i++) { + $p14_1[$i] = $p14[$i]; + $p14_2[$i] = $p14[$i + 7]; + } + $p16_1 = $this->smb_hash($sp8, $p14_1, true); + $p16_2 = $this->smb_hash($sp8, $p14_2, true); + $p16 = $p16_1; + for ($i = 0; $i < sizeof($p16_2); $i++) { + $p16[] = $p16_2[$i]; + } + return $p16; + } + + /** + * Calculates the LM hash of a given password. + * + * @param string $password password + * @return string hash value + */ + public function lmhash($password = "") { + $password = strtoupper($password); + $password = substr($password,0,14); + $password = str_pad($password, 14, chr(0)); + $p16 = $this->E_P16($password); + for ($i = 0; $i < sizeof($p16); $i++) { + $p16[$i] = sprintf("%02X", $p16[$i]); + } + return join("", $p16); + } + + /** + * Calculates the NT hash of a given password. + * + * @param string $password password + * @return string hash value + */ + public function nthash($password = "") { + if (function_exists('mhash')) + if (defined('MHASH_MD4')) + return strtoupper(bin2hex(mhash(MHASH_MD4,iconv('UTF-8','UTF-16LE',$password)))); + else + return strtoupper(hash('md4', iconv("UTF-8","UTF-16LE",$password))); + else + error(_('Your PHP install does not have the mhash() function. Cannot do hashes.'),'error','index.php'); + } + + /** + * Unsigned shift operation for 32bit values. + * + * PHP 4 only supports signed shifts by default. + */ + private function unsigned_shift_r($a, $b) { + $z = 0x80000000; + if ($z & $a) { + $a = ($a >> 1); + $a &= (~$z); + $a |= 0x40000000; + $a = ($a >> ($b - 1)); + } + else { + $a = ($a >> $b); + } + return $a; + } + +} + +?> diff --git a/lib/ds.php b/lib/ds.php new file mode 100644 index 0000000..e7f4589 --- /dev/null +++ b/lib/ds.php @@ -0,0 +1,731 @@ +', any custom extra connection to ds. + */ + abstract public function login($user=null,$pass=null,$method=null); + + /** + * Query the datasource + */ + abstract public function query($query,$method,$index=null,$debug=false); + + /** + * Return error details from previous operation + */ + abstract protected function getErrorMessage(); + abstract protected function getErrorNum(); + + /** + * Functions that set and verify object configuration details + */ + public function setDefaults($defaults) { + foreach ($defaults as $key => $details) + foreach ($details as $setting => $value) + $this->default->{$key}[$setting] = $value; + } + + public function isDefaultKey($key) { + return isset($this->default->$key); + } + + public function isDefaultSetting($key,$setting) { + return array_key_exists($setting,$this->default->{$key}); + } + + /** + * Return a configuration value + */ + public function getValue($key,$setting,$fatal=true) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->custom->{$key}[$setting])) + return $this->custom->{$key}[$setting]; + + elseif (isset($this->default->{$key}[$setting]) && array_key_exists('default',$this->default->{$key}[$setting])) + return $this->default->{$key}[$setting]['default']; + + elseif ($fatal) + debug_dump_backtrace("Error trying to get a non-existant value ($key,$setting)",1); + + else + return null; + } + + /** + * Set a configuration value + */ + public function setValue($key,$setting,$value) { + if (isset($this->custom->{$key}[$setting])) + system_message(array( + 'title'=>_('Configuration setting already defined.'), + 'body'=>sprintf('A call has been made to reset a configuration value (%s,%s,%s)', + $key,$setting,$value), + 'type'=>'info')); + + $this->custom->{$key}[$setting] = $value; + } + + /** + * Return the untested config items + */ + public function untested() { + $result = array(); + + foreach ($this->default as $option => $details) + foreach ($details as $param => $values) + if (isset($values['untested']) && $values['untested']) + array_push($result,sprintf('%s.%s',$option,$param)); + + return $result; + } + + /** + * Get the name of this datastore + */ + public function getName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','name'); + } + + /** + * Functions that enable login and logout of the application + */ + /** + * Return the authentication type for this object + */ + public function getAuthType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($this->getValue('login','auth_type')) { + case 'cookie': + case 'config': + case 'http': + case 'proxy': + case 'session': + case 'sasl': + return $this->getValue('login','auth_type'); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__, + $this->getValue('login','auth_type'))); + } + } + + /** + * Get the login name of the user logged into this datastore's connection method + * If this returns null, we are not logged in. + * If this returns '', we are logged in with anonymous + */ + public function getLogin($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + # For anonymous binds + if ($method == 'anon') + if (isset($_SESSION['USER'][$this->index][$method]['name'])) + return ''; + else + return null; + + switch ($this->getAuthType()) { + case 'cookie': + if (! isset($_COOKIE[$method.'-USER'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; + else + return blowfish_decrypt($_COOKIE[$method.'-USER']); + + case 'config': + if (! isset($_SESSION['USER'][$this->index][$method]['name'])) + return $this->getValue('login','bind_id'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); + + case 'proxy': + if (! isset($_SESSION['USER'][$this->index][$method]['proxy'])) + return $this->getValue('login','bind_id'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['proxy']); + + case 'http': + case 'session': + case 'sasl': + if (! isset($_SESSION['USER'][$this->index][$method]['name'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Set the login details of the user logged into this datastore's connection method + */ + protected function setLogin($user,$pass,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + switch ($this->getAuthType()) { + case 'cookie': + set_cookie($method.'-USER',blowfish_encrypt($user),NULL,'/'); + set_cookie($method.'-PASS',blowfish_encrypt($pass),NULL,'/'); + return true; + + case 'config': + return true; + + case 'proxy': + if (isset($_SESSION['USER'][$this->index][$method]['proxy'])) + unset($_SESSION['USER'][$this->index][$method]['proxy']); + + case 'http': + case 'session': + case 'sasl': + $_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user); + $_SESSION['USER'][$this->index][$method]['pass'] = blowfish_encrypt($pass); + + return true; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Get the login password of the user logged into this datastore's connection method + */ + protected function getPassword($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + # For anonymous binds + if ($method == 'anon') + if (isset($_SESSION['USER'][$this->index][$method]['name'])) + return ''; + else + return null; + + switch ($this->getAuthType()) { + case 'cookie': + if (! isset($_COOKIE[$method.'-PASS'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; + else + return blowfish_decrypt($_COOKIE[$method.'-PASS']); + + case 'config': + case 'proxy': + if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) + return $this->getValue('login','bind_pass'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); + + case 'http': + case 'session': + case 'sasl': + if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) + # If our bind_pass is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Return if this datastore's connection method has been logged into + */ + public function isLoggedIn($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + $method = $this->getMethod($method); + + if (isset($CACHE[$this->index][$method]) && ! is_null($CACHE[$this->index][$method])) + return $CACHE[$this->index][$method]; + + $CACHE[$this->index][$method] = null; + + # For some authentication types, we need to do the login here + switch ($this->getAuthType()) { + case 'config': + if (! $CACHE[$this->index][$method] = $this->login($this->getLogin($method),$this->getPassword($method),$method)) + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your configuration file has authentication set to CONFIG based authentication, however, the userid/password failed to login'), + 'type'=>'error')); + + break; + + case 'http': + # If our auth vars are not set, throw up a login box. + if (! isset($_SERVER['PHP_AUTH_USER'])) { + # If this server is not in focus, skip the basic auth prompt. + if (get_request('server_id','REQUEST') != $this->getIndex()) { + $CACHE[$this->index][$method] = false; + break; + } + + header(sprintf('WWW-Authenticate: Basic realm="%s %s"',app_name(),_('login'))); + + if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') + header('HTTP/1.0 401 Unauthorized'); // http 1.0 method + else + header('Status: 401 Unauthorized'); // http 1.1 method + + # If we still dont have login details... + if (! isset($_SERVER['PHP_AUTH_USER'])) { + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your configuration file has authentication set to HTTP based authentication, however, there was none presented'), + 'type'=>'error')); + + $CACHE[$this->index][$method] = false; + } + + # Check our auth vars are valid. + } else { + if (! $this->login($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'],$method)) { + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your HTTP based authentication is not accepted by the LDAP server'), + 'type'=>'error')); + + $CACHE[$this->index][$method] = false; + + } else + $CACHE[$this->index][$method] = true; + } + + break; + + case 'proxy': + $CACHE[$this->index][$method] = $this->login($this->getValue('login','bind_id'),$this->getValue('login','bind_pass'),$method); + + break; + + case 'sasl': + # Propogate any given Kerberos credential cache location + if (isset($_ENV['REDIRECT_KRB5CCNAME'])) + putenv(sprintf('KRB5CCNAME=%s',$_ENV['REDIRECT_KRB5CCNAME'])); + elseif (isset($_SERVER['KRB5CCNAME'])) + putenv(sprintf('KRB5CCNAME=%s',$_SERVER['KRB5CCNAME'])); + + # Map the SASL auth ID to a DN + $regex = $this->getValue('login', 'sasl_dn_regex'); + $replacement = $this->getValue('login', 'sasl_dn_replacement'); + + if ($regex && $replacement) { + $userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']); + + $CACHE[$this->index][$method] = $this->login($userDN, '', $method); + + # Otherwise, use the user name as is + # For GSSAPI Authentication + mod_auth_kerb and Basic Authentication + } else + $CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method); + + break; + + default: + $CACHE[$this->index][$method] = is_null($this->getLogin($method)) ? false : true; + } + + return $CACHE[$this->index][$method]; + } + + /** + * Logout of this datastore's connection method + */ + public function logout($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + unset ($_SESSION['cache'][$this->index]); + + switch ($this->getAuthType()) { + case 'cookie': + set_cookie($method.'-USER','',time()-3600,'/'); + set_cookie($method.'-PASS','',time()-3600,'/'); + + case 'config': + return true; + + case 'http': + case 'proxy': + case 'session': + case 'sasl': + if (isset($_SESSION['USER'][$this->index][$method])) + unset($_SESSION['USER'][$this->index][$method]); + + return true; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Functions that return the condition of the datasource + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','visible'); + } + + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! trim($this->getLogin(null)) && $_SESSION[APPCONFIG]->getValue('appearance','anonymous_bind_implies_read_only')) + return true; + else + return $this->getValue('server','read_only'); + } + + public function getIndex() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->index); + + return $this->index; + } + + /** + * Work out which connection method to use. + * If a method is passed, then it will be passed back. If no method is passed, then we'll + * check to see if the user is logged in. If they are, then 'user' is used, otherwise + * 'anon' is used. + * + * @param int Server ID + * @return string Connection Method + */ + protected function getMethod($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + # Immediately return if method is set. + if (! is_null($method)) + return $method; + + # If we have been here already, then return our result + if (isset($CACHE[$this->index]) && ! is_null($CACHE)) + return $CACHE[$this->index]; + + $CACHE[$this->index] = 'anon'; + + if ($this->isLoggedIn('user')) + $CACHE[$this->index] = 'user'; + + return $CACHE[$this->index]; + } + + /** + * This method should be overridden in application specific ds files + */ + public function isSessionValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,true); + + return true; + } + + /** + * Return the time left in seconds until this connection times out. If there is not timeout, + * this function will return null. + */ + public function inactivityTime() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->isLoggedIn() && ! in_array($this->getAuthType(),array('config','http'))) + return time()+($this->getValue('login','timeout')*60); + else + return null; + } +} + +/** + * The list of database sources + * + * @package phpLDAPadmin + * @subpackage DataStore + */ +class Datastore { + # Out DS index id + private $index; + # List of all the objects + private $objects = array(); + # Default settings + private $default; + + public function __construct() { + $this->default = new StdClass; + + $this->default->server['id'] = array( + 'desc'=>'Server ID', + 'default'=>null); + + $this->default->server['name'] = array( + 'desc'=>'Server name', + 'default'=>null); + + # Connectivity Info + $this->default->server['host'] = array( + 'desc'=>'Host Name', + 'default'=>'127.0.0.1'); + + $this->default->server['port'] = array( + 'desc'=>'Port Number', + 'default'=>null); + + # Read or write only access + $this->default->server['read_only'] = array( + 'desc'=>'Server is in READ ONLY mode', + 'default'=>false); + + $this->default->server['visible'] = array( + 'desc'=>'Whether this server is visible', + 'default'=>true); + + $this->default->server['hide_noaccess_base'] = array( + 'desc'=>'If base DNs are not accessible, hide them instead of showing create', + 'default'=>false); + + # Authentication Information + $this->default->login['auth_type'] = array( + 'desc'=>'Authentication Type', + 'default'=>'session'); + +/* + /* ID to login to this application, this assumes that there is + * application authentication on top of authentication required to + * access the data source ** + $this->default->login['auth_id'] = array( + 'desc'=>'User Login ID to login to this DS', + 'untested'=>true, + 'default'=>null); + + $this->default->login['auth_pass'] = array( + 'desc'=>'User Login Password to login to this DS', + 'untested'=>true, + 'default'=>null); +*/ + + $this->default->login['auth_text'] = array( + 'desc'=>'Text to show at the login prompt', + 'default'=>null); + + $this->default->login['bind_id'] = array( + 'desc'=>'User Login ID to bind to this DS', + 'default'=>null); + + $this->default->login['bind_pass'] = array( + 'desc'=>'User Login Password to bind to this DS', + 'default'=>null); + + $this->default->login['timeout'] = array( + 'desc'=>'Session timout in seconds', + 'default'=>session_cache_expire()-1); + + $this->default->login['sasl_dn_regex'] = array( + 'desc'=>'SASL authorization id to user dn PCRE regular expression', + 'untested'=>true, + 'default'=>null); + + $this->default->login['sasl_dn_replacement'] = array( + 'desc'=>'SASL authorization id to user dn PCRE regular expression replacement string', + 'untested'=>true, + 'default'=>null); + + # Prefix for custom pages + $this->default->custom['pages_prefix'] = array( + 'desc'=>'Prefix name for custom pages', + 'default'=>'custom_'); + } + + /** + * Create a new database object + */ + public function newServer($type) { + if (class_exists($type)) { + $this->index = count($this->objects)+1; + $this->objects[$this->index] = new $type($this->index); + + $this->objects[$this->index]->setDefaults($this->default); + return $this->index; + + } else { + printf('ERROR: Class [%s] doesnt exist',$type); + die(); + } + } + + /** + * Set values for a database object. + */ + public function setValue($key,$setting,$value) { + if (! $this->objects[$this->index]->isDefaultKey($key)) + error("ERROR: Setting a key [$key] that isnt predefined.",'error',true); + + if (! $this->objects[$this->index]->isDefaultSetting($key,$setting)) + error("ERROR: Setting a index [$key,$setting] that isnt predefined.",'error',true); + + # Test if its should be an array or not. + if (is_array($this->objects[$this->index]->getValue($key,$setting)) && ! is_array($value)) + error("Error in configuration file, {$key}['$setting'] SHOULD be an array of values.",'error',true); + + if (! is_array($this->objects[$this->index]->getValue($key,$setting)) && is_array($value)) + error("Error in configuration file, {$key}['$setting'] should NOT be an array of values.",'error',true); + + # Store the value in the object. + $this->objects[$this->index]->setValue($key,$setting,$value); + } + + /** + * Get a list of all the configured servers. + * + * @param boolean Only show visible servers. + * @return array list of all configured servers. + */ + public function getServerList($isVisible=true) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE; + + if (isset($CACHE[$isVisible])) + return $CACHE[$isVisible]; + + $CACHE[$isVisible] = array(); + + # Debugging incase objects is not set. + if (! $this->objects) { + print "
";
+			debug_print_backtrace();
+			die();
+		}
+
+		foreach ($this->objects as $id => $server)
+			if (! $isVisible || ($isVisible && $server->getValue('server','visible')))
+				$CACHE[$isVisible][$id] = $server;
+
+		masort($CACHE[$isVisible],'name');
+
+		return $CACHE[$isVisible];
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param int Index
+	 * @return object Datastore instance object.
+	 */
+	public function Instance($index=null) {
+		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# If no index defined, then pick the lowest one.
+		if (is_null($index) || ! trim($index) || ! is_numeric($index))
+			$index = min($this->GetServerList())->getIndex();
+
+		if (! isset($this->objects[$index]))
+			debug_dump_backtrace(sprintf('Error: Datastore instance [%s] doesnt exist?',htmlspecialchars($index)),1);
+
+		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED)
+			debug_log('Returning instance of database (%s)',3,0,__FILE__,__LINE__,__METHOD__,$index);
+
+		return $this->objects[$index];
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param string Name of the instance to retrieve
+	 * @return object Datastore instance object.
+	 */
+	public function InstanceName($name=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		foreach ($this->getServerList(false) as $index)
+			if ($this->objects[$index]->getName() == $name)
+				return $this->objects[$index];
+
+		# If we get here, then no object with the name exists.
+		return null;
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param string ID of the instance to retrieve
+	 * @return object Datastore instance object.
+	 */
+	public function InstanceId($id=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		foreach ($this->getServerList(false) as $index)
+			if ($this->objects[$index->getIndex()]->getValue('server','id') == $id)
+				return $this->objects[$index->getIndex()];
+
+		# If we get here, then no object with the name exists.
+		return null;
+	}
+}
+?>
diff --git a/lib/ds_ldap.php b/lib/ds_ldap.php
new file mode 100644
index 0000000..c3d4267
--- /dev/null
+++ b/lib/ds_ldap.php
@@ -0,0 +1,2413 @@
+index = $index;
+		$this->type = 'ldap';
+
+		# Additional values that can go in our config.php
+		$this->custom = new StdClass;
+		$this->default = new StdClass;
+
+/*
+ * Not used by PLA
+		# Database Server Variables
+		$this->default->server['db'] = array(
+			'desc'=>'Database Name',
+			'untested'=>true,
+			'default'=>null);
+*/
+
+		/* This was created for IDS - since it doesnt present STRUCTURAL against objectClasses
+		 * definitions when reading the schema.*/
+		$this->default->server['schema_oclass_default'] = array(
+			'desc'=>'When reading the schema, and it doesnt specify objectClass type, default it to this',
+			'default'=>null);
+
+		$this->default->server['base'] = array(
+			'desc'=>'LDAP Base DNs',
+			'default'=>array());
+
+		$this->default->server['tls'] = array(
+			'desc'=>'Connect using TLS',
+			'default'=>false);
+
+		# Login Details
+		$this->default->login['attr'] = array(
+			'desc'=>'Attribute to use to find the users DN',
+			'default'=>'dn');
+
+		$this->default->login['anon_bind'] = array(
+			'desc'=>'Enable anonymous bind logins',
+			'default'=>true);
+
+		$this->default->login['allowed_dns'] = array(
+			'desc'=>'Limit logins to users who match any of the following LDAP filters',
+			'default'=>array());
+
+		$this->default->login['base'] = array(
+			'desc'=>'Limit logins to users who are in these base DNs',
+			'default'=>array());
+
+		$this->default->login['class'] = array(
+			'desc'=>'Strict login to users containing a specific objectClasses',
+			'default'=>array());
+
+		$this->default->proxy['attr'] = array(
+			'desc'=>'Attribute to use to find the users DN for proxy based authentication',
+			'default'=>array());
+
+		# SASL configuration
+		$this->default->sasl['mech'] = array(
+			'desc'=>'SASL mechanism used while binding LDAP server',
+			'default'=>'GSSAPI');
+
+		$this->default->sasl['realm'] = array(
+			'desc'=>'SASL realm name',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id'] = array(
+			'desc'=>'SASL authorization id',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id_regex'] = array(
+			'desc'=>'SASL authorization id PCRE regular expression',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id_replacement'] = array(
+			'desc'=>'SASL authorization id PCRE regular expression replacement string',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['props'] = array(
+			'desc'=>'SASL properties',
+			'untested'=>true,
+			'default'=>null);
+	}
+
+	/**
+	 * Required ABSTRACT functions
+	 */
+	/**
+	 * Connect and Bind to the Database
+	 *
+	 * @param string Which connection method resource to use
+	 * @return resource|null Connection resource if successful, null if not.
+	 */
+	protected function connect($method,$debug=false,$new=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE = array();
+
+		$method = $this->getMethod($method);
+		$bind = array();
+
+		if (isset($CACHE[$this->index][$method]) && $CACHE[$this->index][$method])
+			return $CACHE[$this->index][$method];
+
+		# Check if we have logged in and therefore need to use those details as our bind.
+		$bind['id'] = is_null($this->getLogin($method)) && $method != 'anon' ? $this->getLogin('user') : $this->getLogin($method);
+		$bind['pass'] = is_null($this->getPassword($method)) && $method != 'anon' ? $this->getPassword('user') : $this->getPassword($method);
+
+		# If our bind id is still null, we are not logged in.
+		if (is_null($bind['id']) && ! in_array($method,array('anon','login')))
+			return null;
+
+		# If we bound to the LDAP server with these details for a different connection, return that resource
+		if (isset($CACHE[$this->index]) && ! $new)
+			foreach ($CACHE[$this->index] as $cachedmethod => $resource) {
+				if (($this->getLogin($cachedmethod) == $bind['id']) && ($this->getPassword($cachedmethod) == $bind['pass'])) {
+					$CACHE[$this->index][$method] = $resource;
+
+					return $CACHE[$this->index][$method];
+				}
+			}
+
+		$CACHE[$this->index][$method] = null;
+
+		# No identifiable connection exists, lets create a new one.
+		if (DEBUG_ENABLED)
+			debug_log('Creating NEW connection [%s] for index [%s]',16,0,__FILE__,__LINE__,__METHOD__,
+				$method,$this->index);
+
+		if (function_exists('run_hook'))
+			run_hook('pre_connect',array('server_id'=>$this->index,'method'=>$method));
+
+		if ($this->getValue('server','port'))
+			$resource = ldap_connect($this->getValue('server','host'),$this->getValue('server','port'));
+		else
+			$resource = ldap_connect($this->getValue('server','host'));
+
+		$CACHE[$this->index][$method] = $resource;
+
+		if (DEBUG_ENABLED)
+			debug_log('LDAP Resource [%s], Host [%s], Port [%s]',16,0,__FILE__,__LINE__,__METHOD__,
+				$resource,$this->getValue('server','host'),$this->getValue('server','port'));
+
+		if (! is_resource($resource))
+			debug_dump_backtrace('UNHANDLED, $resource is not a resource',1);
+
+		# Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
+		ldap_set_option($resource,LDAP_OPT_PROTOCOL_VERSION,3);
+
+		/* Disabling this makes it possible to browse the tree for Active Directory, and seems
+		 * to not affect other LDAP servers (tested with OpenLDAP) as phpLDAPadmin explicitly
+		 * specifies deref behavior for each ldap_search operation. */
+		ldap_set_option($resource,LDAP_OPT_REFERRALS,0);
+
+		# Try to fire up TLS is specified in the config
+		if ($this->isTLSEnabled())
+			$this->startTLS($resource);
+
+		# If SASL has been configured for binding, then start it now.
+		if ($this->isSASLEnabled())
+			$bind['result'] = $this->startSASL($resource,$method);
+
+		# Normal bind...
+		else
+			$bind['result'] = @ldap_bind($resource,$bind['id'],$bind['pass']);
+
+		if ($debug)
+			debug_dump(array('method'=>$method,'bind'=>$bind,'USER'=>$_SESSION['USER']));
+
+		if (DEBUG_ENABLED)
+			debug_log('Resource [%s], Bind Result [%s]',16,0,__FILE__,__LINE__,__METHOD__,$resource,$bind);
+
+		if (! $bind['result']) {
+			if (DEBUG_ENABLED)
+				debug_log('Leaving with FALSE, bind FAILed',16,0,__FILE__,__LINE__,__METHOD__);
+
+			$this->noconnect = true;
+
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
+				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
+				'type'=>'error'));
+
+			$CACHE[$this->index][$method] = null;
+
+		} else {
+			$this->noconnect = false;
+
+			# If this is a proxy session, we need to switch to the proxy user
+			if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
+				if (! $this->startProxy($resource,$method)) {
+					$this->noconnect = true;
+					$CACHE[$this->index][$method] = null;
+				}
+		}
+
+		if (function_exists('run_hook'))
+			run_hook('post_connect',array('server_id'=>$this->index,'method'=>$method,'id'=>$bind['id']));
+
+		if ($debug)
+			debug_dump(array($method=>$CACHE[$this->index][$method]));
+
+		return $CACHE[$this->index][$method];
+	}
+
+	/**
+	 * Login to the database with the application user/password
+	 *
+	 * @return boolean true|false for successful login.
+	 */
+	public function login($user=null,$pass=null,$method=null,$new=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$userDN = null;
+
+		# Get the userDN from the username.
+		if (! is_null($user)) {
+			# If login,attr is set to DN, then user should be a DN
+			if (($this->getValue('login','attr') == 'dn') || $method != 'user')
+				$userDN = $user;
+			else
+				$userDN = $this->getLoginID($user,'login');
+
+			if (! $userDN && $this->getValue('login','fallback_dn'))
+				$userDN = $user;
+
+			if (! $userDN)
+				return false;
+
+		} else {
+			if (in_array($method,array('user','anon'))) {
+				$method = 'anon';
+				$userDN = '';
+				$pass = '';
+
+			} else {
+				$userDN = $this->getLogin('user');
+				$pass = $this->getPassword('user');
+			}
+		}
+
+		if (! $this->isAnonBindAllowed() && ! trim($userDN))
+			return false;
+
+		# Temporarily set our user details
+		$this->setLogin($userDN,$pass,$method);
+
+		$connect = $this->connect($method,false,$new);
+
+		# If we didnt log in...
+		if (! is_resource($connect) || $this->noconnect || ! $this->userIsAllowedLogin($userDN)) {
+			$this->logout($method);
+
+			return false;
+
+		} else
+			return true;
+	}
+
+	/**
+	 * Perform a query to the Database
+	 *
+	 * @param string query to perform
+	 *	$query['base']
+	 *	$query['filter']
+	 *	$query['scope']
+	 *	$query['attrs'] = array();
+	 *	$query['deref']
+	 * @param string Which connection method resource to use
+	 * @param string Index items according to this key
+	 * @param boolean Enable debugging output
+	 * @return array|null Results of query.
+	 */
+	public function query($query,$method,$index=null,$debug=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$attrs_only = 0;
+
+		# Defaults
+		if (! isset($query['attrs']))
+			$query['attrs'] = array();
+		else
+			# Re-index the attrs, PHP throws an error if the keys are not sequential from 0.
+			$query['attrs'] = array_values($query['attrs']);
+
+		if (! isset($query['base'])) {
+			$bases = $this->getBaseDN();
+			$query['base'] = array_shift($bases);
+		}
+
+		if (! isset($query['deref']))
+			$query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','search');
+		if (! isset($query['filter']))
+			$query['filter'] = '(&(objectClass=*))';
+		if (! isset($query['scope']))
+			$query['scope'] = 'sub';
+		if (! isset($query['size_limit']))
+			$query['size_limit'] = 0;
+		if (! isset($query['time_limit']))
+			$query['time_limit'] = 0;
+
+		if ($query['scope'] == 'base' && ! isset($query['baseok']))
+			system_message(array(
+				'title'=>sprintf('Dont call %s',__METHOD__),
+				'body'=>sprintf('Use getDNAttrValues for base queries [%s]',$query['base']),
+				'type'=>'info'));
+
+		if (is_array($query['base'])) {
+			system_message(array(
+				'title'=>_('Invalid BASE for query'),
+				'body'=>_('The query was cancelled because of an invalid base.'),
+				'type'=>'error'));
+
+			return array();
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('%s search PREPARE.',16,0,__FILE__,__LINE__,__METHOD__,$query['scope']);
+
+		if ($debug)
+			debug_dump(array('query'=>$query,'server'=>$this->getIndex(),'con'=>$this->connect($method)));
+
+		$resource = $this->connect($method,$debug);
+
+		switch ($query['scope']) {
+			case 'base':
+				$search = @ldap_read($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+
+			case 'one':
+				$search = @ldap_list($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+
+			case 'sub':
+			default:
+				$search = @ldap_search($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+		}
+
+		if ($debug)
+			debug_dump(array('method'=>$method,'search'=>$search,'error'=>$this->getErrorMessage()));
+
+		if (DEBUG_ENABLED)
+			debug_log('Search scope [%s] base [%s] filter [%s] attrs [%s] COMPLETE (%s).',16,0,__FILE__,__LINE__,__METHOD__,
+				$query['scope'],$query['base'],$query['filter'],$query['attrs'],is_null($search));
+
+		if (! $search)
+			return array();
+
+		$return = array();
+
+		# Get the first entry identifier
+		if ($entries = ldap_get_entries($resource,$search)) {
+			# Remove the count
+			if (isset($entries['count']))
+				unset($entries['count']);
+
+			# Iterate over the entries
+			foreach ($entries as $a => $entry) {
+				if (! isset($entry['dn']))
+					debug_dump_backtrace('No DN?',1);
+
+				# Remove the none entry references.
+				if (! is_array($entry)) {
+					unset($entries[$a]);
+					continue;
+				}
+
+				$dn = $entry['dn'];
+				unset($entry['dn']);
+
+				# Iterate over the attributes
+				foreach ($entry as $b => $attrs) {
+					# Remove the none entry references.
+					if (! is_array($attrs)) {
+						unset($entry[$b]);
+						continue;
+					}
+
+					# Remove the count
+					if (isset($entry[$b]['count']))
+						unset($entry[$b]['count']);
+				}
+
+				# Our queries always include the DN (the only value not an array).
+				$entry['dn'] = $dn;
+				$return[$dn] = $entry;
+			}
+
+			# Sort our results
+			foreach ($return as $key=> $values)
+				ksort($return[$key]);
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		return $return;
+	}
+
+	/**
+	 * Get the last error string
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getErrorMessage($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return ldap_error($this->connect($method));
+	}
+
+	/**
+	 * Get the last error number
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getErrorNum($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return ldap_errno($this->connect($method));
+	}
+
+	/**
+	 * Additional functions
+	 */
+	/**
+	 * Get a user ID
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getLoginID($user,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$query['filter'] = sprintf('(&(%s=%s)%s)',
+			$this->getValue('login','attr'),$user,
+			$this->getLoginClass() ? sprintf('(objectclass=%s)',join(')(objectclass=',$this->getLoginClass())) : '');
+		$query['attrs'] = array('dn');
+
+		$result = array();
+		foreach ($this->getLoginBaseDN() as $base) {
+			$query['base'] = $base;
+			$result = $this->query($query,$method);
+
+			if (count($result) == 1)
+				break;
+		}
+
+		if (count($result) != 1)
+			return null;
+
+		$detail = array_shift($result);
+
+		if (! isset($detail['dn']))
+			die('ERROR: DN missing?');
+		else
+			return $detail['dn'];
+	}
+
+	/**
+	 * Return the login base DNs
+	 * If no login base DNs are defined, then the LDAP server Base DNs are used.
+	 */
+	private function getLoginBaseDN() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('login','base'))
+			return $this->getValue('login','base');
+		else
+			return $this->getBaseDN();
+	}
+
+	/**
+	 * Return the login classes that a user must have to login
+	 */
+	private function getLoginClass() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','class');
+	}
+
+	/**
+	 * Return if anonymous bind is allowed in the configuration
+	 */
+	public function isAnonBindAllowed() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','anon_bind');
+	}
+
+	/**
+	 * Fetches whether TLS has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use TLS in config,php thus:
+	 * 
+	 *	$servers->setValue('server','tls',true|false);
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isTLSEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('server','tls') && ! function_exists('ldap_start_tls')) {
+				error(_('TLS has been enabled in your config, but your PHP install does not support TLS. TLS will be disabled.'),'warn');
+			return false;
+
+		} else
+			return $this->getValue('server','tls');
+	}
+
+	/**
+	 * If TLS is configured, then start it
+	 */
+	private function startTLS($resource) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if (! $this->getValue('server','tls') || (function_exists('ldap_start_tls') && ! @ldap_start_tls($resource))) {
+			system_message(array(
+				'title'=>sprintf('%s (%s)',_('Could not start TLS.'),$this->getName()),
+				'body'=>sprintf('%s: %s',_('Error'),_('Could not start TLS. Please check your LDAP server configuration.')),
+				'type'=>'error'));
+
+			return false;
+
+		} else
+			return true;
+	}
+
+	/**
+	 * Fetches whether SASL has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use SASL in config,php thus:
+	 * 
+	 *	$servers->setValue('login','auth_type','sasl');
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isSASLEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('login','auth_type') != 'sasl')
+			return false;
+
+		if (! function_exists('ldap_sasl_bind')) {
+			error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
+
+			return false;
+		}
+
+		# If we get here, SASL must be configured.
+		return true;
+	}
+
+	/**
+	 * If SASL is configured, then start it
+	 * To be able to use SASL, PHP should have been compliled with --with-ldap-sasl=DIR
+	 *
+	 * @todo This has not been tested, please let the developers know if this function works as expected.
+	 */
+	private function startSASL($resource,$method) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE = array();
+
+		# We shouldnt be doing SASL binds for anonymous queries?
+		if ($method == 'anon')
+			return false;
+
+		# At the moment, we have only implemented GSSAPI
+		if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi'))) {
+			system_message(array(
+				'title'=>_('SASL Method not implemented'),
+				'body'=>sprintf('%s: %s %s',_('Error'),$this->getValue('sasl','mech'),_('has not been implemented yet')),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		if (! isset($CACHE['login_dn']))
+			$CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method);
+
+		$CACHE['authz_id'] = '';
+
+		/*
+		# Do we need to rewrite authz_id?
+		if (! isset($CACHE['authz_id']))
+			if (! trim($this->getValue('sasl','authz_id')) && strtolower($this->getValue('sasl','mech')) != 'gssapi') {
+				if (DEBUG_ENABLED)
+					debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
+						$CACHE['login_dn'],
+						$this->getValue('sasl','authz_id_regex'),
+						$this->getValue('sasl','authz_id_replacement'));
+
+				$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
+					$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
+
+				# Invalid regex?
+				if (is_null($CACHE['authz_id']))
+					error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
+						$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
+						'error','index.php');
+
+				if (DEBUG_ENABLED)
+					debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
+						$resource,
+						$this->getValue('sasl','mech'),
+						$this->getValue('sasl','realm'),
+						$CACHE['authz_id'],
+						$this->getValue('sasl','props'));
+
+			} else
+				$CACHE['authz_id'] = $this->getValue('sasl','authz_id');
+		*/
+
+		# @todo this function is different in PHP5.1 and PHP5.2
+		return @ldap_sasl_bind($resource,NULL,'',
+			$this->getValue('sasl','mech'),
+			$this->getValue('sasl','realm'),
+			$CACHE['authz_id'],
+			$this->getValue('sasl','props'));
+	}
+
+	/**
+	 * Fetches whether PROXY AUTH has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use PROXY AUTH in config,php thus:
+	 * 
+	 *	$servers->setValue('login','auth_type','proxy');
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isProxyEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','auth_type') == 'proxy' ? true : false;
+	}
+
+	/**
+	 * If PROXY AUTH is configured, then start it
+	 */
+	private function startProxy($resource,$method) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$rootdse = $this->getRootDSE();
+
+		if (! (isset($rootdse['supportedcontrol']) && in_array('2.16.840.1.113730.3.4.18',$rootdse['supportedcontrol']))) {
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+				'body'=>sprintf('%s: %s',_('Error'),_('Your LDAP server doesnt seem to support this control')),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		$filter = '(&';
+		$dn = '';
+
+		$missing = false;
+		foreach ($this->getValue('proxy','attr') as $attr => $var) {
+			if (! isset($_SERVER[$var])) {
+				system_message(array(
+					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Attribute doesnt exist'),$var),
+					'type'=>'error'));
+
+				$missing = true;
+
+			} else {
+				if ($attr == 'dn') {
+					$dn = $var;
+
+					break;
+
+				} else
+					$filter .= sprintf('(%s=%s)',$attr,$_SERVER[$var]);
+			}
+		}
+
+		if ($missing)
+			return false;
+
+		$filter .= ')';
+
+		if (! $dn) {
+			$query['filter'] = $filter;
+
+			foreach ($this->getBaseDN() as $base) {
+				$query['base'] = $base;
+
+				if ($search = $this->query($query,$method))
+					break;
+			}
+
+			if (count($search) != 1) {
+				system_message(array(
+					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Search for DN returned the incorrect number of results'),count($search)),
+					'type'=>'error'));
+
+				return false;
+			}
+
+			$search = array_pop($search);
+			$dn = $search['dn'];
+		}
+
+		$ctrl = array(
+			'oid'=>'2.16.840.1.113730.3.4.18',
+			'value'=>sprintf('dn:%s',$dn),
+			'iscritical' => true);
+
+		if (! ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		$_SESSION['USER'][$this->index][$method]['proxy'] = blowfish_encrypt($dn);
+
+		return true;
+	}
+
+	/**
+	 * Modify attributes of a DN
+	 */
+	public function modify($dn,$attrs,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# We need to supress the error here - programming should detect and report it.
+		return @ldap_mod_replace($this->connect($method),$dn,$attrs);
+	}
+
+	/**
+	 * Gets the root DN of the specified LDAPServer, or null if it
+	 * can't find it (ie, the server won't give it to us, or it isnt
+	 * specified in the configuration file).
+	 *
+	 * Tested with OpenLDAP 2.0, Netscape iPlanet, and Novell eDirectory 8.7 (nldap.com)
+	 * Please report any and all bugs!!
+	 *
+	 * Please note: On FC systems, it seems that php_ldap uses /etc/openldap/ldap.conf in
+	 * the search base if it is blank - so edit that file and comment out the BASE line.
+	 *
+	 * @param string Which connection method resource to use
+	 * @return array dn|null The root DN of the server on success (string) or null on error.
+	 * @todo Sort the entries, so that they are in the correct DN order.
+	 */
+	public function getBaseDN($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE;
+
+		$method = $this->getMethod($method);
+		$result = array();
+
+		if (isset($CACHE[$this->index][$method]))
+			return $CACHE[$this->index][$method];
+
+		# If the base is set in the configuration file, then just return that.
+		if (count($this->getValue('server','base'))) {
+			if (DEBUG_ENABLED)
+				debug_log('Return BaseDN from Config [%s]',17,0,__FILE__,__LINE__,__METHOD__,implode('|',$this->getValue('server','base')));
+
+			$CACHE[$this->index][$method] = $this->getValue('server','base');
+
+		# We need to figure it out.
+		} else {
+			if (DEBUG_ENABLED)
+				debug_log('Connect to LDAP to find BaseDN',80,0,__FILE__,__LINE__,__METHOD__);
+
+			# Set this to empty, in case we loop back here looking for the baseDNs
+			$CACHE[$this->index][$method] = array();
+
+			$results = $this->getDNAttrValues('',$method);
+
+			if (isset($results['namingcontexts'])) {
+				if (DEBUG_ENABLED)
+					debug_log('LDAP Entries:%s',80,0,__FILE__,__LINE__,__METHOD__,implode('|',$results['namingcontexts']));
+
+				$result = $results['namingcontexts'];
+			}
+
+			$CACHE[$this->index][$method] = $result;
+		}
+
+		return $CACHE[$this->index][$method];
+	}
+
+	/**
+	 * Gets whether an entry exists based on its DN. If the entry exists,
+	 * returns true. Otherwise returns false.
+	 *
+	 * @param string The DN of the entry of interest.
+	 * @param string Which connection method resource to use
+	 * @return boolean
+	 */
+	public function dnExists($dn,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$results = $this->getDNAttrValues($dn,$method);
+
+		if ($results)
+			return $results;
+		else
+			return false;
+	}
+
+	/**
+	 * Given a DN string, this returns the top container portion of the string.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @return string The container
+	 */
+	public function getContainerTop($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = $dn;
+
+		foreach ($this->getBaseDN() as $base) {
+			if (preg_match("/${base}$/i",$dn)) {
+				$return = $base;
+				break;
+			}
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		return $return;
+	}
+
+	/**
+	 * Given a DN string and a path like syntax, this returns the parent container portion of the string.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @param string Either '/', '.' or something like '../../'
+	 * @return string The container
+	 */
+	public function getContainerPath($dn,$path='..') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$top = $this->getContainerTop($dn);
+
+		if ($path[0] == '/') {
+			$dn = $top;
+			$path = substr($path,1);
+
+		} elseif ($path == '.') {
+			return $dn;
+		}
+
+		$parenttree = explode('/',$path);
+
+		foreach ($parenttree as $key => $value) {
+			if ($value == '..') {
+				if ($this->getContainer($dn))
+					$dn = $this->getContainer($dn);
+
+				if ($dn == $top)
+					break;
+
+			} elseif($value)
+				$dn = sprintf('%s,%s',$value,$dn);
+
+			else
+				break;
+		}
+
+		if (! $dn) {
+			debug_dump(array(__METHOD__,'dn'=>$dn,'path'=>$path));
+			debug_dump_backtrace('Container is empty?',1);
+		}
+
+		return $dn;
+	}
+
+	/**
+	 * Given a DN string, this returns the parent container portion of the string.
+	 * For example. given 'cn=Manager,dc=example,dc=com', this function returns
+	 * 'dc=example,dc=com'.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @return string The container
+	 */
+	public function getContainer($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$parts = $this->explodeDN($dn);
+
+		if (count($parts) <= 1)
+			$return = null;
+
+		else {
+			$return = $parts[1];
+
+			for ($i=2;$i
+	 *	dc=example,dc=com
+	 *		ou=People
+	 *			cn=Dave
+	 *			cn=Fred
+	 *			cn=Joe
+	 *		ou=More People
+	 *			cn=Mark
+	 *			cn=Bob
+	 * 
+	 *
+	 * Calling getContainerContents("ou=people,dc=example,dc=com")
+	 * would return the following list:
+	 *
+	 * 
+	 *	cn=Dave
+	 *	cn=Fred
+	 *	cn=Joe
+	 *	ou=More People
+	 * 
+	 *
+	 * @param string The DN of the entry whose children to return.
+	 * @param string Which connection method resource to use
+	 * @param int (optional) The maximum number of entries to return.
+	 *            If unspecified, no limit is applied to the number of entries in the returned.
+	 * @param string (optional) An LDAP filter to apply when fetching children, example: "(objectClass=inetOrgPerson)"
+	 * @param constant (optional) The LDAP deref setting to use in the query
+	 * @return array An array of DN strings listing the immediate children of the specified entry.
+	 */
+	public function getContainerContents($dn,$method=null,$size_limit=0,$filter='(objectClass=*)',$deref=LDAP_DEREF_NEVER) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = array();
+
+		$query = array();
+		$query['base'] = $this->escapeDN($dn);
+		$query['attrs'] = array('dn');
+		$query['filter'] = $filter;
+		$query['deref'] = $deref;
+		$query['scope'] = 'one';
+		$query['size_limit'] = $size_limit;
+		$results = $this->query($query,$method);
+
+		if ($results) {
+			foreach ($results as $index => $entry) {
+				$child_dn = $entry['dn'];
+				array_push($return,$child_dn);
+			}
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		# Sort the results
+		asort($return);
+
+		return $return;
+	}
+
+	/**
+	 * Explode a DN into an array of its RDN parts.
+	 *
+	 * @param string The DN to explode.
+	 * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details)
+	 *
+	 * @return array An array of RDN parts of this format:
+	 * 
+	 *	Array
+	 *		(
+	 *			[0] => uid=ppratt
+	 *			[1] => ou=People
+	 *			[2] => dc=example
+	 *			[3] => dc=com
+	 *		)
+	 * 
+	 *
+	 * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value';
+	 */
+	private function explodeDN($dn,$with_attributes=0) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE;
+
+		if (isset($CACHE['explode'][$dn][$with_attributes])) {
+			if (DEBUG_ENABLED)
+				debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__,
+					$CACHE['explode'][$dn][$with_attributes],$dn);
+
+			return $CACHE['explode'][$dn][$with_attributes];
+		}
+
+		$dn = addcslashes($dn,'<>+";');
+
+		# split the dn
+		$result[0] = ldap_explode_dn($this->escapeDN($dn),0);
+		$result[1] = ldap_explode_dn($this->escapeDN($dn),1);
+		if (! $result[$with_attributes]) {
+			if (DEBUG_ENABLED)
+				debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__);
+
+			return array();
+		}
+
+		# Remove our count value that ldap_explode_dn returns us.
+		unset($result[0]['count']);
+		unset($result[1]['count']);
+
+		# Record the forward and reverse entries in the cache.
+		foreach ($result as $key => $value) {
+			# translate hex code into ascii for display
+			$result[$key] = $this->unescapeDN($value);
+
+			$CACHE['explode'][implode(',',$result[0])][$key] = $result[$key];
+			$CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]);
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]);
+
+		return $result[$with_attributes];
+	}
+
+	/**
+	 * Parse a DN and escape any special characters
+	 */
+	protected function escapeDN($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if (! trim($dn))
+			return $dn;
+
+		# Check if the RDN has a comma and escape it.
+		while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn))
+			$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn);
+
+		$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn);
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$dn);
+
+		return $dn;
+	}
+
+	/**
+	 * Parse a DN and unescape any special characters
+	 */
+	private function unescapeDN($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$unescape = function ($input) {
+			return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($match) {
+				return "'" . chr(hexdec($match[1])) . "'";
+			}, $input);
+		};
+
+		if (is_array($dn)) {
+			$a = array();
+
+			foreach ($dn as $key => $rdn)
+				$a[$key] = $unescape($rdn);
+				// $a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
+
+			return $a;
+
+		} else {
+			return $unescape($dn);
+			// return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
+		}
+	}
+
+	public function getRootDSE($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$query = array();
+		$query['base'] = '';
+		$query['scope'] = 'base';
+		$query['attrs'] = $this->getValue('server','root_dse_attributes');
+		$query['baseok'] = true;
+		$results = $this->query($query,$method);
+
+		if (is_array($results) && count($results) == 1)
+			return array_change_key_case(array_pop($results));
+		else
+			return array();
+	}
+
+	/** Schema Methods **/
+	/**
+	 * This function will query the ldap server and request the subSchemaSubEntry which should be the Schema DN.
+	 *
+	 * If we cant connect to the LDAP server, we'll return false.
+	 * If we can connect but cant get the entry, then we'll return null.
+	 *
+	 * @param string Which connection method resource to use
+	 * @param dn The DN to use to obtain the schema
+	 * @return array|false Schema if available, null if its not or false if we cant connect.
+	 */
+	private function getSchemaDN($method=null,$dn='') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# If we already got the SchemaDN, then return it.
+		if ($this->_schemaDN)
+			return $this->_schemaDN;
+
+		if (! $this->connect($method))
+			return false;
+
+		$search = @ldap_read($this->connect($method),$dn,'objectclass=*',array('subschemaSubentry'),false,0,10,LDAP_DEREF_NEVER);
+
+		if (DEBUG_ENABLED)
+			debug_log('Search returned (%s)',24,0,__FILE__,__LINE__,__METHOD__,is_resource($search));
+
+		# Fix for broken ldap.conf configuration.
+		if (! $search && ! $dn) {
+			if (DEBUG_ENABLED)
+				debug_log('Trying to find the DN for "broken" ldap.conf',80,0,__FILE__,__LINE__,__METHOD__);
+
+			if (isset($this->_baseDN)) {
+				foreach ($this->_baseDN as $base) {
+					$search = @ldap_read($this->connect($method),$base,'objectclass=*',array('subschemaSubentry'),false,0,10,LDAP_DEREF_NEVER);
+
+					if (DEBUG_ENABLED)
+						debug_log('Search returned (%s) for base (%s)',24,0,__FILE__,__LINE__,__METHOD__,
+							is_resource($search),$base);
+
+					if ($search)
+						break;
+				}
+			}
+		}
+
+		if (! $search)
+			return null;
+
+		if (! @ldap_count_entries($this->connect($method),$search)) {
+			if (DEBUG_ENABLED)
+				debug_log('Search returned 0 entries. Returning NULL',25,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$entries = @ldap_get_entries($this->connect($method),$search);
+
+		if (DEBUG_ENABLED)
+			debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$entries);
+
+		if (! $entries || ! is_array($entries))
+			return null;
+
+		$entry = isset($entries[0]) ? $entries[0] : false;
+		if (! $entry) {
+			if (DEBUG_ENABLED)
+				debug_log('Entry is false, Returning NULL',80,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$sub_schema_sub_entry = isset($entry[0]) ? $entry[0] : false;
+		if (! $sub_schema_sub_entry) {
+			if (DEBUG_ENABLED)
+				debug_log('Sub Entry is false, Returning NULL',80,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$this->_schemaDN = isset($entry[$sub_schema_sub_entry][0]) ? $entry[$sub_schema_sub_entry][0] : false;
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->_schemaDN);
+
+		return $this->_schemaDN;
+	}
+
+	/**
+	 * Fetches the raw schema array for the subschemaSubentry of the server. Note,
+	 * this function has grown many hairs to accomodate more LDAP servers. It is
+	 * needfully complicated as it now supports many popular LDAP servers that
+	 * don't necessarily expose their schema "the right way".
+	 *
+	 * Please note: On FC systems, it seems that php_ldap uses /etc/openldap/ldap.conf in
+	 * the search base if it is blank - so edit that file and comment out the BASE line.
+	 *
+	 * @param string Which connection method resource to use
+	 * @param string A string indicating which type of schema to
+	 *		fetch. Five valid values: 'objectclasses', 'attributetypes',
+	 *		'ldapsyntaxes', 'matchingruleuse', or 'matchingrules'.
+	 *		Case insensitive.
+	 * @param dn (optional) This paremeter is the DN of the entry whose schema you
+	 * 		would like to fetch. Entries have the option of specifying
+	 * 		their own subschemaSubentry that points to the DN of the system
+	 * 		schema entry which applies to this attribute. If unspecified,
+	 *		this will try to retrieve the schema from the RootDSE subschemaSubentry.
+	 *		Failing that, we use some commonly known schema DNs. Default
+	 *		value is the Root DSE DN (zero-length string)
+	 * @return array an array of strings of this form:
+	 *	Array (
+	 *		[0] => "(1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...
+	 *		[1] => "(1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...
+	 *	etc.
+	 */
+	private function getRawSchema($method,$schema_to_fetch,$dn='') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$valid_schema_to_fetch = array('objectclasses','attributetypes','ldapsyntaxes','matchingrules','matchingruleuse');
+
+		if (! $this->connect($method) || $this->noconnect)
+			return false;
+
+		# error checking
+		$schema_to_fetch = strtolower($schema_to_fetch);
+
+		if (! is_null($this->_schema_entries) && isset($this->_schema_entries[$schema_to_fetch])) {
+			$schema = $this->_schema_entries[$schema_to_fetch];
+
+			if (DEBUG_ENABLED)
+				debug_log('Returning CACHED (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema);
+
+			return $schema;
+		}
+
+		# This error message is not localized as only developers should ever see it
+		if (! in_array($schema_to_fetch,$valid_schema_to_fetch))
+			error(sprintf('Bad parameter provided to function to %s::getRawSchema(). "%s" is not valid for the schema_to_fetch parameter.',
+					get_class($this),$schema_to_fetch),'error','index.php');
+
+		# Try to get the schema DN from the specified entry.
+		$schema_dn = $this->getSchemaDN($method,$dn);
+
+		# Do we need to try again with the Root DSE?
+		if (! $schema_dn && trim($dn))
+			$schema_dn = $this->getSchemaDN($method,'');
+
+		# Store the eventual schema retrieval in $schema_search
+		$schema_search = null;
+
+		if ($schema_dn) {
+			if (DEBUG_ENABLED)
+				debug_log('Using Schema DN (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_dn);
+
+			foreach (array('(objectClass=*)','(objectClass=subschema)') as $schema_filter) {
+				if (DEBUG_ENABLED)
+					debug_log('Looking for schema with Filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_filter);
+
+				$schema_search = @ldap_read($this->connect($method),$schema_dn,$schema_filter,array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER);
+
+				if (is_null($schema_search))
+					continue;
+
+				$schema_entries = @ldap_get_entries($this->connect($method),$schema_search);
+
+				if (DEBUG_ENABLED)
+					debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries);
+
+				if (is_array($schema_entries) && isset($schema_entries['count']) && $schema_entries['count']) {
+					if (DEBUG_ENABLED)
+						debug_log('Found schema with (DN:%s) (FILTER:%s) (ATTR:%s)',24,0,__FILE__,__LINE__,__METHOD__,
+							$schema_dn,$schema_filter,$schema_to_fetch);
+
+					break;
+				}
+
+				if (DEBUG_ENABLED)
+					debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_filter);
+
+				unset($schema_entries);
+				$schema_search = null;
+			}
+		}
+
+		/* Second chance: If the DN or Root DSE didn't give us the subschemaSubentry, ie $schema_search
+		 * is still null, use some common subSchemaSubentry DNs as a work-around. */
+		if (is_null($schema_search)) {
+			if (DEBUG_ENABLED)
+				debug_log('Attempting work-arounds for "broken" LDAP servers...',24,0,__FILE__,__LINE__,__METHOD__);
+
+			foreach ($this->getBaseDN() as $base) {
+				$ldap['W2K3 AD'][expand_dn_with_base($base,'cn=Aggregate,cn=Schema,cn=configuration,')] = '(objectClass=*)';
+				$ldap['W2K AD'][expand_dn_with_base($base,'cn=Schema,cn=configuration,')] = '(objectClass=*)';
+				$ldap['W2K AD'][expand_dn_with_base($base,'cn=Schema,ou=Admin,')] = '(objectClass=*)';
+			}
+
+			# OpenLDAP and Novell
+			$ldap['OpenLDAP']['cn=subschema'] = '(objectClass=*)';
+
+			foreach ($ldap as $ldap_server_name => $ldap_options) {
+				foreach ($ldap_options as $ldap_dn => $ldap_filter) {
+					if (DEBUG_ENABLED)
+						debug_log('Attempting [%s] (%s) (%s)
',24,0,__FILE__,__LINE__,__METHOD__, + $ldap_server_name,$ldap_dn,$ldap_filter); + + $schema_search = @ldap_read($this->connect($method),$ldap_dn,$ldap_filter,array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + if (is_null($schema_search)) + continue; + + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries && isset($schema_entries[0][$schema_to_fetch])) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter); + + break; + } + + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter); + + unset($schema_entries); + $schema_search = null; + } + if ($schema_search) + break; + } + } + + # Option 3: try cn=config + $olc_schema = 'olc'.$schema_to_fetch; + $olc_schema_found = false; + if (is_null($schema_search)) { + if (DEBUG_ENABLED) + debug_log('Attempting cn=config work-around...',24,0,__FILE__,__LINE__,__METHOD__); + + $ldap_dn = 'cn=schema,cn=config'; + $ldap_filter = '(objectClass=*)'; + + $schema_search = @ldap_search($this->connect($method),$ldap_dn,$ldap_filter,array($olc_schema),false,0,10,LDAP_DEREF_NEVER); + + if (! is_null($schema_search)) { + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema); + + $olc_schema_found = true; + + } else { + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema); + + unset($schema_entries); + $schema_search = null; + } + } + } + + if (is_null($schema_search)) { + /* Still cant find the schema, try with the RootDSE + * Attempt to pull schema from Root DSE with scope "base", or + * Attempt to pull schema from Root DSE with scope "one" (work-around for Isode M-Vault X.500/LDAP) */ + foreach (array('base','one') as $ldap_scope) { + if (DEBUG_ENABLED) + debug_log('Attempting to find schema with scope (%s), filter (objectClass=*) and a blank base.',24,0,__FILE__,__LINE__,__METHOD__, + $ldap_scope); + + switch ($ldap_scope) { + case 'base': + $schema_search = @ldap_read($this->connect($method),'','(objectClass=*)',array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + break; + + case 'one': + $schema_search = @ldap_list($this->connect($method),'','(objectClass=*)',array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + break; + } + + if (is_null($schema_search)) + continue; + + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries && isset($schema_entries[0][$schema_to_fetch])) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s)',24,0,__FILE__,__LINE__,__METHOD__,'(objectClass=*)'); + + break; + } + + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,'(objectClass=*)'); + + unset($schema_entries); + $schema_search = null; + } + } + + $schema_error_message = 'Please contact the phpLDAPadmin developers and let them know:
  • Which LDAP server you are running, including which version
  • What OS it is running on
  • Which version of PHP
  • As well as a link to some documentation that describes how to obtain the SCHEMA information

We\'ll then add support for your LDAP server in an upcoming release.'; + $schema_error_message_array = array('objectclasses','attributetypes'); + + # Shall we just give up? + if (is_null($schema_search)) { + # We need to have objectclasses and attribues, so display an error, asking the user to get us this information. + if (in_array($schema_to_fetch,$schema_error_message_array)) + system_message(array( + 'title'=>sprintf('%s (%s)',_('Our attempts to find your SCHEMA have failed'),$schema_to_fetch), + 'body'=>sprintf('%s: %s',_('Error'),$schema_error_message), + 'type'=>'error')); + else + if (DEBUG_ENABLED) + debug_log('Returning because schema_search is NULL ()',25,0,__FILE__,__LINE__,__METHOD__); + + # We'll set this, so if we return here our cache will return the known false. + $this->_schema_entries[$schema_to_fetch] = false; + return false; + } + + if (! $schema_entries) { + $return = false; + if (DEBUG_ENABLED) + debug_log('Returning false since ldap_get_entries() returned false.',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + if ($olc_schema_found) { + unset ($schema_entries['count']); + + foreach ($schema_entries as $entry) { + if (isset($entry[$olc_schema])) { + unset($entry[$olc_schema]['count']); + + foreach ($entry[$olc_schema] as $schema_definition) + /* Schema definitions in child nodes prefix the schema entries with "{n}" + the preg_replace call strips out this prefix. */ + $schema[] = preg_replace('/^\{\d*\}\(/','(',$schema_definition); + } + } + + if (isset($schema)) { + $this->_schema_entries[$olc_schema] = $schema; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema); + + return $schema; + + } else + return null; + } + + if (! isset($schema_entries[0][$schema_to_fetch])) { + if (in_array($schema_to_fetch,$schema_error_message_array)) { + error(sprintf('Our attempts to find your SCHEMA for "%s" have return UNEXPECTED results.

(We expected a "%s" in the $schema array but it wasnt there.)

%s

Dump of $schema_search:
%s
', + $schema_to_fetch,gettype($schema_search),$schema_error_message,serialize($schema_entries)),'error','index.php'); + + } else { + $return = false; + + if (DEBUG_ENABLED) + debug_log('Returning because (%s) isnt in the schema array. (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema_to_fetch,$return); + + return $return; + } + } + + /* Make a nice array of this form: + Array ( + [0] => "(1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...)" + [1] => "(1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...)" + etc.) */ + + $schema = $schema_entries[0][$schema_to_fetch]; + unset($schema['count']); + $this->_schema_entries[$schema_to_fetch] = $schema; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema); + + return $schema; + } + + /** + * Gets a single ObjectClass object specified by name. + * + * @param string $oclass_name The name of the objectClass to fetch. + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return ObjectClass The specified ObjectClass object or false on error. + * + * @see ObjectClass + * @see SchemaObjectClasses + */ + public function getSchemaObjectClass($oclass_name,$method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $oclass_name = strtolower($oclass_name); + $socs = $this->SchemaObjectClasses($method,$dn); + + # Default return value + $return = false; + + if (isset($socs[$oclass_name])) + $return = $socs[$oclass_name]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets a single AttributeType object specified by name. + * + * @param string $oclass_name The name of the AttributeType to fetch. + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return AttributeType The specified AttributeType object or false on error. + * + * @see AttributeType + * @see SchemaAttributes + */ + public function getSchemaAttribute($attr_name,$method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_name = strtolower($attr_name); + $sattrs = $this->SchemaAttributes($method,$dn); + + # Default return value + $return = false; + + if (isset($sattrs[$attr_name])) + $return = $sattrs[$attr_name]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets an associative array of ObjectClass objects for the specified + * server. Each array entry's key is the name of the objectClass + * in lower-case and the value is an ObjectClass object. + * + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return array An array of ObjectClass objects. + * + * @see ObjectClass + * @see getSchemaObjectClass + */ + public function SchemaObjectClasses($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','objectclasses')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'objectclasses'); + + return $return; + } + + $raw = $this->getRawSchema($method,'objectclasses',$dn); + + if ($raw) { + # Build the array of objectClasses + $return = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $object_class = new ObjectClass($line,$this); + $return[$object_class->getName()] = $object_class; + } + + # Now go through and reference the parent/child relationships + foreach ($return as $oclass) + foreach ($oclass->getSupClasses() as $parent_name) + if (isset($return[strtolower($parent_name)])) + $return[strtolower($parent_name)]->addChildObjectClass($oclass->getName(false)); + + ksort($return); + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','objectclasses',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets an associative array of AttributeType objects for the specified + * server. Each array entry's key is the name of the attributeType + * in lower-case and the value is an AttributeType object. + * + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return array An array of AttributeType objects. + */ + public function SchemaAttributes($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','attributes')) { + if (DEBUG_ENABLED) + debug_log('(): Returning CACHED [%s] (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'attributes'); + + return $return; + } + + $raw = $this->getRawSchema($method,'attributeTypes',$dn); + + if ($raw) { + # build the array of attribueTypes + $syntaxes = $this->SchemaSyntaxes($method,$dn); + $attrs = array(); + + /** + * bug 856832: create two arrays - one indexed by name (the standard + * $attrs array above) and one indexed by oid (the new $attrs_oid array + * below). This will help for directory servers, like IBM's, that use OIDs + * in their attribute definitions of SUP, etc + */ + $attrs_oid = array(); + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $attr = new AttributeType($line); + if (isset($syntaxes[$attr->getSyntaxOID()])) { + $syntax = $syntaxes[$attr->getSyntaxOID()]; + $attr->setType($syntax->getDescription()); + } + $attrs[$attr->getName()] = $attr; + + /** + * bug 856832: create an entry in the $attrs_oid array too. This + * will be a ref to the $attrs entry for maintenance and performance + * reasons + */ + $attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()]; + } + + # go back and add data from aliased attributeTypes + foreach ($attrs as $name => $attr) { + $aliases = $attr->getAliases(); + + if (is_array($aliases) && count($aliases) > 0) { + /* foreach of the attribute's aliases, create a new entry in the attrs array + * with its name set to the alias name, and all other data copied.*/ + foreach ($aliases as $alias_attr_name) { + $new_attr = clone $attr; + + $new_attr->setName($alias_attr_name); + $new_attr->addAlias($attr->getName(false)); + $new_attr->removeAlias($alias_attr_name); + $new_attr_key = strtolower($alias_attr_name); + $attrs[$new_attr_key] = $new_attr; + } + } + } + + # go back and add any inherited descriptions from parent attributes (ie, cn inherits name) + foreach ($attrs as $key => $attr) { + $sup_attr_name = $attr->getSupAttribute(); + $sup_attr = null; + + if (trim($sup_attr_name)) { + + /* This loop really should traverse infinite levels of inheritance (SUP) for attributeTypes, + * but just in case we get carried away, stop at 100. This shouldn't happen, but for + * some weird reason, we have had someone report that it has happened. Oh well.*/ + $i = 0; + while ($i++<100 /** 100 == INFINITY ;) */) { + + if (isset($attrs_oid[$sup_attr_name])) { + $attr->setSupAttribute($attrs_oid[$sup_attr_name]->getName()); + $sup_attr_name = $attr->getSupAttribute(); + } + + if (! isset($attrs[strtolower($sup_attr_name)])){ + error(sprintf('Schema error: attributeType "%s" inherits from "%s", but attributeType "%s" does not exist.', + $attr->getName(),$sup_attr_name,$sup_attr_name),'error','index.php'); + return; + } + + $sup_attr = $attrs[strtolower($sup_attr_name)]; + $sup_attr_name = $sup_attr->getSupAttribute(); + + # Does this superior attributeType not have a superior attributeType? + if (is_null($sup_attr_name) || strlen(trim($sup_attr_name)) == 0) { + + /* Since this attribute's superior attribute does not have another superior + * attribute, clone its properties for this attribute. Then, replace + * those cloned values with those that can be explicitly set by the child + * attribute attr). Save those few properties which the child can set here:*/ + $tmp_name = $attr->getName(false); + $tmp_oid = $attr->getOID(); + $tmp_sup = $attr->getSupAttribute(); + $tmp_aliases = $attr->getAliases(); + $tmp_single_val = $attr->getIsSingleValue(); + $tmp_desc = $attr->getDescription(); + + /* clone the SUP attributeType and populate those values + * that were set by the child attributeType */ + $attr = clone $sup_attr; + + $attr->setOID($tmp_oid); + $attr->setName($tmp_name); + $attr->setSupAttribute($tmp_sup); + $attr->setAliases($tmp_aliases); + $attr->setDescription($tmp_desc); + + /* only overwrite the SINGLE-VALUE property if the child explicitly sets it + * (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */ + if ($tmp_single_val) + $attr->setIsSingleValue(true); + + /* replace this attribute in the attrs array now that we have populated + new values therein */ + $attrs[$key] = $attr; + + # very important: break out after we are done with this attribute + $sup_attr_name = null; + $sup_attr = null; + break; + } + } + } + } + + ksort($attrs); + + # Add the used in and required_by values. + $socs = $this->SchemaObjectClasses($method); + if (! is_array($socs)) + return array(); + + foreach ($socs as $object_class) { + $must_attrs = $object_class->getMustAttrNames(); + $may_attrs = $object_class->getMayAttrNames(); + $oclass_attrs = array_unique(array_merge($must_attrs,$may_attrs)); + + # Add Used In. + foreach ($oclass_attrs as $attr_name) + if (isset($attrs[strtolower($attr_name)])) + $attrs[strtolower($attr_name)]->addUsedInObjectClass($object_class->getName(false)); + + # Add Required By. + foreach ($must_attrs as $attr_name) + if (isset($attrs[strtolower($attr_name)])) + $attrs[strtolower($attr_name)]->addRequiredByObjectClass($object_class->getName(false)); + + # Force May + foreach ($object_class->getForceMayAttrs() as $attr_name) + if (isset($attrs[strtolower($attr_name->name)])) + $attrs[strtolower($attr_name->name)]->setForceMay(); + } + + $return = $attrs; + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','attributes',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns an array of MatchingRule objects for the specified server. + * The key of each entry is the OID of the matching rule. + */ + public function MatchingRules($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','matchingrules')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s).',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'matchingrules'); + + return $return; + } + + # build the array of MatchingRule objects + $raw = $this->getRawSchema($method,'matchingRules',$dn); + + if ($raw) { + $rules = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $rule = new MatchingRule($line); + $key = $rule->getName(); + $rules[$key] = $rule; + } + + ksort($rules); + + /* For each MatchingRuleUse entry, add the attributes who use it to the + * MatchingRule in the $rules array.*/ + $raw = $this->getRawSchema($method,'matchingRuleUse'); + + if ($raw != false) { + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $rule_use = new MatchingRuleUse($line); + $key = $rule_use->getName(); + + if (isset($rules[$key])) + $rules[$key]->setUsedByAttrs($rule_use->getUsedByAttrs()); + } + + } else { + /* No MatchingRuleUse entry in the subschema, so brute-forcing + * the reverse-map for the "$rule->getUsedByAttrs()" data.*/ + $sattrs = $this->SchemaAttributes($method,$dn); + if (is_array($sattrs)) + foreach ($sattrs as $attr) { + $rule_key = strtolower($attr->getEquality()); + + if (isset($rules[$rule_key])) + $rules[$rule_key]->addUsedByAttr($attr->getName(false)); + } + } + + $return = $rules; + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','matchingrules',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns an array of Syntax objects that this LDAP server uses mapped to + * their descriptions. The key of each entry is the OID of the Syntax. + */ + public function SchemaSyntaxes($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','syntaxes')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s).',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'syntaxes'); + + return $return; + } + + $raw = $this->getRawSchema($method,'ldapSyntaxes',$dn); + + if ($raw) { + # build the array of attributes + $return = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $syntax = new Syntax($line); + $key = strtolower(trim($syntax->getOID())); + + if (! $key) + continue; + + $return[$key] = $syntax; + } + + ksort($return); + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','syntaxes',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * This function determines if the specified attribute is contained in the force_may list + * as configured in config.php. + * + * @return boolean True if the specified attribute is configured to be force as a may attribute + */ + function isForceMay($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return in_array($attr_name,unserialize(strtolower(serialize($this->getValue('server','force_may'))))); + } + + /** + * Much like getDNAttrValues(), but only returns the values for + * one attribute of an object. Example calls: + * + * + * print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','sn')); + * Array ( + * [0] => Smith + * ) + * + * print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','objectClass')); + * Array ( + * [0] => top + * [1] => person + * ) + * + * + * @param string The distinguished name (DN) of the entry whose attributes/values to fetch. + * @param string The attribute whose value(s) to return (ie, "objectClass", "cn", "userPassword") + * @param string Which connection method resource to use + * @param constant For aliases and referrals, this parameter specifies whether to + * follow references to the referenced DN or to fetch the attributes for + * the referencing DN. See http://php.net/ldap_search for the 4 valid + * options. + * @return array + * @see getDNAttrValues + * @todo Caching these values may be problematic with multiple calls and different deref values. + */ + public function getDNAttrValue($dn,$attr,$method=null,$deref=LDAP_DEREF_NEVER) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Ensure our attr is in lowercase + $attr = strtolower($attr); + + $values = $this->getDNAttrValues($dn,$method,$deref); + + if (isset($values[$attr])) + return $values[$attr]; + else + return array(); + } + + /** + * Gets the attributes/values of an entry. Returns an associative array whose + * keys are attribute value names and whose values are arrays of values for + * said attribute. + * + * Optionally, callers may specify true for the parameter + * $lower_case_attr_names to force all keys in the associate array (attribute + * names) to be lower case. + * + * Example of its usage: + * + * print_r(getDNAttrValues('cn=Bob,ou=pepole,dc=example,dc=com') + * Array ( + * [objectClass] => Array ( + * [0] => person + * [1] => top + * ) + * [cn] => Array ( + * [0] => Bob + * ) + * [sn] => Array ( + * [0] => Jones + * ) + * [dn] => Array ( + * [0] => cn=Bob,ou=pepole,dc=example,dc=com + * ) + * ) + * + * + * @param string The distinguished name (DN) of the entry whose attributes/values to fetch. + * @param string Which connection method resource to use + * @param constant For aliases and referrals, this parameter specifies whether to + * follow references to the referenced DN or to fetch the attributes for + * the referencing DN. See http://php.net/ldap_search for the 4 valid + * options. + * @return array + * @see getDNSysAttrs + * @see getDNAttrValue + */ + public function getDNAttrValues($dn,$method=null,$deref=LDAP_DEREF_NEVER,$attrs=array('*','+'),$nocache=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE; + + $cacheindex = null; + $method = $this->getMethod($method); + + if (in_array('*',$attrs) && in_array('+',$attrs)) + $cacheindex = '&'; + elseif (in_array('+',$attrs)) + $cacheindex = '+'; + elseif (in_array('*',$attrs)) + $cacheindex = '*'; + + if (! $nocache && ! is_null($cacheindex) && isset($CACHE[$this->index][$method][$dn][$cacheindex])) { + $results = $CACHE[$this->index][$method][$dn][$cacheindex]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$results); + + } else { + $query = array(); + $query['base'] = $this->escapeDN($dn); + $query['scope'] = 'base'; + $query['deref'] = $deref; + $query['attrs'] = $attrs; + $query['baseok'] = true; + $results = $this->query($query,$method); + + if (count($results)) + $results = array_pop($results); + + $results = array_change_key_case($results); + + # Covert all our result key values to an array + foreach ($results as $key => $values) + if (! is_array($results[$key])) + $results[$key] = array($results[$key]); + + # Finally sort the results + ksort($results); + + if (! is_null($cacheindex) && count($results)) + $CACHE[$this->index][$method][$dn][$cacheindex] = $results; + } + + return $results; + } + + /** + * Returns true if the attribute specified is required to take as input a DN. + * Some examples include 'distinguishedName', 'member' and 'uniqueMember'. + * + * @param string $attr_name The name of the attribute of interest (case insensitive) + * @return boolean + */ + function isDNAttr($attr_name,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Simple test first + $dn_attrs = array('aliasedObjectName'); + foreach ($dn_attrs as $dn_attr) + if (strcasecmp($attr_name,$dn_attr) == 0) + return true; + + # Now look at the schema OID + $sattr = $this->getSchemaAttribute($attr_name); + if (! $sattr) + return false; + + $syntax_oid = $sattr->getSyntaxOID(); + if ('1.3.6.1.4.1.1466.115.121.1.12' == $syntax_oid) + return true; + if ('1.3.6.1.4.1.1466.115.121.1.34' == $syntax_oid) + return true; + + $syntaxes = $this->SchemaSyntaxes($method); + if (! isset($syntaxes[$syntax_oid])) + return false; + + $syntax_desc = $syntaxes[ $syntax_oid ]->getDescription(); + if (strpos(strtolower($syntax_desc),'distinguished name')) + return true; + + return false; + } + + /** + * Used to determine if the specified attribute is indeed a jpegPhoto. If the + * specified attribute is one that houses jpeg data, true is returned. Otherwise + * this function returns false. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + * @see draw_jpeg_photo + */ + function isJpegPhoto($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # easy quick check + if (! strcasecmp($attr_name,'jpegPhoto') || ! strcasecmp($attr_name,'photo')) + return true; + + # go to the schema and get the Syntax OID + $sattr = $this->getSchemaAttribute($attr_name); + if (! $sattr) + return false; + + $oid = $sattr->getSyntaxOID(); + $type = $sattr->getType(); + + if (! strcasecmp($type,'JPEG') || ($oid == '1.3.6.1.4.1.1466.115.121.1.28')) + return true; + + return false; + } + + /** + * Given an attribute name and server ID number, this function returns + * whether the attrbiute contains boolean data. This is useful for + * developers who wish to display the contents of a boolean attribute + * with a drop-down. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + */ + function isAttrBoolean($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $type = ($sattr = $this->getSchemaAttribute($attr_name)) ? $sattr->getType() : null; + + if (! strcasecmp('boolean',$type) || + ! strcasecmp('isCriticalSystemObject',$attr_name) || + ! strcasecmp('showInAdvancedViewOnly',$attr_name)) + return true; + + else + return false; + } + + /** + * Given an attribute name and server ID number, this function returns + * whether the attribute may contain binary data. This is useful for + * developers who wish to display the contents of an arbitrary attribute + * but don't want to dump binary data on the page. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + * + * @see isJpegPhoto + */ + function isAttrBinary($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /** + * Determining if an attribute is binary can be an expensive operation. + * We cache the results for each attr name on each server in the $attr_cache + * to speed up subsequent calls. The $attr_cache looks like this: + * + * Array + * 0 => Array + * 'objectclass' => false + * 'cn' => false + * 'usercertificate' => true + * 1 => Array + * 'jpegphoto' => true + * 'cn' => false + */ + + static $attr_cache; + + $attr_name = strtolower($attr_name); + + if (isset($attr_cache[$this->index][$attr_name])) + return $attr_cache[$this->index][$attr_name]; + + if ($attr_name == 'userpassword') { + $attr_cache[$this->index][$attr_name] = false; + return false; + } + + # Quick check: If the attr name ends in ";binary", then it's binary. + if (strcasecmp(substr($attr_name,strlen($attr_name) - 7),';binary') == 0) { + $attr_cache[$this->index][$attr_name] = true; + return true; + } + + # See what the server schema says about this attribute + $sattr = $this->getSchemaAttribute($attr_name); + if (! is_object($sattr)) { + + /* Strangely, some attributeTypes may not show up in the server + * schema. This behavior has been observed in MS Active Directory.*/ + $type = null; + $syntax = null; + + } else { + $type = $sattr->getType(); + $syntax = $sattr->getSyntaxOID(); + } + + if (strcasecmp($type,'Certificate') == 0 || + strcasecmp($type,'Binary') == 0 || + strcasecmp($attr_name,'usercertificate') == 0 || + strcasecmp($attr_name,'usersmimecertificate') == 0 || + strcasecmp($attr_name,'networkaddress') == 0 || + strcasecmp($attr_name,'objectGUID') == 0 || + strcasecmp($attr_name,'objectSID') == 0 || + strcasecmp($attr_name,'auditingPolicy') == 0 || + strcasecmp($attr_name,'jpegPhoto') == 0 || + strcasecmp($attr_name,'krbExtraData') == 0 || + strcasecmp($attr_name,'krbPrincipalKey') == 0 || + $syntax == '1.3.6.1.4.1.1466.115.121.1.10' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.28' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.5' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.8' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.9' + ) { + + $attr_cache[$this->index][$attr_name] = true; + return true; + + } else { + $attr_cache[$this->index][$attr_name] = false; + return false; + } + } + + /** + * This function will test if a user is a member of a group. + * + * Inputs: + * @param string $user membership value that is being checked + * @param dn $group DN to see if user is a member + * @return bool true|false + */ + function userIsMember($user,$group) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $user = strtolower($user); + $group = $this->getDNAttrValues($group); + + # If you are using groupOfNames objectClass + if (array_key_exists('member',$group) && ! is_array($group['member'])) + $group['member'] = array($group['member']); + + if (array_key_exists('member',$group) && + in_array($user,arrayLower($group['member']))) + + return true; + + # If you are using groupOfUniqueNames objectClass + if (array_key_exists('uniquemember',$group) && ! is_array($group['uniquemember'])) + $group['uniquemember'] = array($group['uniquemember']); + + if (array_key_exists('uniquemember',$group) && + in_array($user,arrayLower($group['uniquemember']))) + + return true; + + return false; + } + + /** + * This function will determine if the user is allowed to login based on a filter + */ + protected function userIsAllowedLogin($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn = trim(strtolower($dn)); + + if (! $this->getValue('login','allowed_dns')) + return true; + + foreach ($this->getValue('login','allowed_dns') as $login_allowed_dn) { + if (DEBUG_ENABLED) + debug_log('Working through (%s)',80,0,__FILE__,__LINE__,__METHOD__,$login_allowed_dn); + + /* Check if $login_allowed_dn is an ldap search filter + * Is first occurence of 'filter=' (case ensitive) at position 0 ? */ + if (preg_match('/^\([&|]\(/',$login_allowed_dn)) { + $query = array(); + $query['filter'] = $login_allowed_dn; + $query['attrs'] = array('dn'); + + foreach($this->getBaseDN() as $base_dn) { + $query['base'] = $base_dn; + + $results = $this->query($query,null); + + if (DEBUG_ENABLED) + debug_log('Search, Filter [%s], BaseDN [%s] Results [%s]',16,0,__FILE__,__LINE__,__METHOD__, + $query['filter'],$query['base'],$results); + + if ($results) { + $dn_array = array(); + + foreach ($results as $result) + array_push($dn_array,$result['dn']); + + $dn_array = array_unique($dn_array); + + if (count($dn_array)) + foreach ($dn_array as $result_dn) { + if (DEBUG_ENABLED) + debug_log('Comparing with [%s]',80,0,__FILE__,__LINE__,__METHOD__,$result_dn); + + # Check if $result_dn is a user DN + if (strcasecmp($dn,trim(strtolower($result_dn))) == 0) + return true; + + # Check if $result_dn is a group DN + if ($this->userIsMember($dn,$result_dn)) + return true; + } + } + } + } + + # Check if $login_allowed_dn is a user DN + if (strcasecmp($dn,trim(strtolower($login_allowed_dn))) == 0) + return true; + + # Check if $login_allowed_dn is a group DN + if ($this->userIsMember($dn,$login_allowed_dn)) + return true; + } + + return false; + } +} +?> diff --git a/lib/ds_ldap_pla.php b/lib/ds_ldap_pla.php new file mode 100644 index 0000000..7ece393 --- /dev/null +++ b/lib/ds_ldap_pla.php @@ -0,0 +1,659 @@ +default->appearance['password_hash'] = array( + 'desc'=>'Default HASH to use for passwords', + 'default'=>'md5'); + + $this->default->appearance['show_create'] = array( + 'desc'=>'Whether to show the "Create new Entry here" in the tree browser', + 'default'=>true); + + $this->default->appearance['open_tree'] = array( + 'desc'=>'Whether to initially open each tree', + 'default'=>false); + + $this->default->login['fallback_dn'] = array( + 'desc'=>'If the attribute base login fails, see if a DN was entered', + 'default'=>false); + + $this->default->query['disable_default'] = array( + 'desc'=>'Configuration to disable the default query template', + 'default'=>false); + + $this->default->query['custom_only'] = array( + 'desc'=>'Configuration to force the usage of custom query templates', + 'default'=>false); + + $this->default->server['branch_rename'] = array( + 'desc'=>'Enable renaming of branches', + 'default'=>false); + + $this->default->server['custom_attrs'] = array( + 'desc'=>'Custom operational attributes to be treated as regular attributes', + 'default'=>array('')); + + $this->default->server['custom_sys_attrs'] = array( + 'desc'=>'Custom operational attributes to be treated as internal attributes', + 'default'=>array('+')); + + $this->default->server['jpeg_attributes'] = array( + 'desc'=>'Additional attributes to treat as Jpeg Attributes', + 'default'=>array()); + + # This was added in case the LDAP server doesnt provide them with a base +,* query. + $this->default->server['root_dse_attributes'] = array( + 'desc'=>'RootDSE attributes for use when displaying server info', + 'default'=>array( + 'namingContexts', + 'subschemaSubentry', + 'altServer', + 'supportedExtension', + 'supportedControl', + 'supportedSASLMechanisms', + 'supportedLDAPVersion', + 'currentTime', + 'dsServiceName', + 'defaultNamingContext', + 'schemaNamingContext', + 'configurationNamingContext', + 'rootDomainNamingContext', + 'supportedLDAPPolicies', + 'highestCommittedUSN', + 'dnsHostName', + 'ldapServiceName', + 'serverName', + 'supportedCapabilities', + 'changeLog', + 'tlsAvailableCipherSuites', + 'tlsImplementationVersion', + 'supportedSASLMechanisms', + 'dsaVersion', + 'myAccessPoint', + 'dseType', + '+', + '*' + )); + + $this->default->server['force_may'] = array( + 'desc'=>'Force server MUST attributes as MAY attributes', + 'default'=>array( + )); + + # Settings for auto_number + $this->default->auto_number['enable'] = array( + 'desc'=>'Enable the AUTO UID feature', + 'default'=>true); + + $this->default->auto_number['mechanism'] = array( + 'desc'=>'Mechanism to use to search for automatic numbers', + 'default'=>'search'); + + $this->default->auto_number['search_base'] = array( + 'desc'=>'Base DN to use for search mechanisms', + 'default'=>null); + + $this->default->auto_number['min'] = array( + 'desc'=>'Minimum number to start with', + 'default'=>array('uidNumber'=>1000,'gidNumber'=>500)); + + $this->default->auto_number['dn'] = array( + 'desc'=>'DN to use when evaluating numbers', + 'default'=>null); + + $this->default->auto_number['pass'] = array( + 'desc'=>'Password for DN to use when evaluating numbers', + 'default'=>null); + + $this->default->unique['attrs'] = array( + 'desc'=>'Attributes to check for uniqueness before allowing updates', + 'default'=>array('mail','uid','uidNumber')); + + $this->default->unique['dn'] = array( + 'desc'=>'DN to use when evaluating attribute uniqueness', + 'default'=>null); + + $this->default->unique['pass'] = array( + 'desc'=>'Password for DN to use when evaluating attribute uniqueness', + 'default'=>null); + } + + public function __get($key) { + switch ($key) { + case 'name': + return $this->getValue('server','name'); + + default: + system_message(array( + 'title'=>_('Unknown request for Object value.'), + 'body'=>sprintf(_('Attempt to obtain value %s from %s'),$key,get_class($this)), + 'type'=>'error')); + } + } + + /** + * Gets whether the admin has configured phpLDAPadmin to show the "Create New" link in the tree viewer. + * + * $servers->setValue('appearance','show_create',true|false); + * + * If NOT set, then default to show the Create New item. + * If IS set, then return the value (it should be true or false). + * + * The entry creation command must be available. + * + * $config->custom->commands['script'] = array('create' => true); + * + * + * @return boolean true if the feature is enabled and false otherwise. + */ + function isShowCreateEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','create')) + return false; + else + return $this->getValue('appearance','show_create'); + } + + /** + * Fetch whether the user has configured a certain server login to be non anonymous + * + * + * $servers->setValue('login','anon_bind',true|false); + * + * + * @return boolean + */ + public function isAnonBindAllowed() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If only_login_allowed_dns is set, then we cant have anonymous. + if (count($this->getValue('login','allowed_dns')) > 0) + $return = false; + else + $return = $this->getValue('login','anon_bind'); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns true if the user has configured the specified server to enable branch (non-leaf) renames. + * + * This is configured in config.php thus: + * + * $servers->setValue('server','branch_rename',true|false); + * + * + * @return boolean + */ + function isBranchRenameEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','branch_rename'); + } + + /** + * Determines if an attribute's value can contain multiple lines. Attributes that fall + * in this multi-line category may be configured in config.php. Hence, this function + * accesses the global variable $_SESSION[APPCONFIG]->custom->appearance['multi_line_attributes']; + * + * Usage example: + * + * if ($ldapserver->isMultiLineAttr('postalAddress')) + * echo ''; + * else + * echo ''; + * + * + * @param string The name of the attribute of interested (case insensivite) + * @param string (optional) The current value of the attribute (speeds up the process by searching for carriage returns already in the attribute value) + * @return boolean + */ + function isMultiLineAttr($attr_name,$val=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = false; + + # First, check the optional val param for a \n or a \r + if (! is_null($val) && (strpos($val,"\n") || strpos($val,"\r"))) + $return = true; + + # Next, compare strictly by name first + else + foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_attributes') as $multi_line_attr_name) + if (strcasecmp($multi_line_attr_name,$attr_name) == 0) { + $return = true; + break; + } + + # If unfound, compare by syntax OID + if (! $return) { + $sattr = $this->getSchemaAttribute($attr_name); + + if ($sattr) { + $syntax_oid = $sattr->getSyntaxOID(); + + if ($syntax_oid) + foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_syntax_oids') as $multi_line_syntax_oid) + if ($multi_line_syntax_oid == $syntax_oid) { + $return = true; + break; + } + } + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns true if the specified attribute is configured according to + * the test enabled in config.php + * + * @param string The name of the attribute to test. + * @param array The attributes to test against. + * @param dn A DN that is exempt from these tests. + * @return boolean + */ + private function isAttrTest($attr,$attrs,$except_dn) { + $attr = trim($attr); + if (! trim($attr) || ! count($attrs)) + return false; + + # Is the user excluded? + if ($except_dn && $this->userIsMember($this->getLogin(),$except_dn)) + return false; + + foreach ($attrs as $attr_name) + if (strcasecmp($attr,trim($attr_name)) == 0) + return true; + + return false; + } + + /** + * Returns true if the specified attribute is configured as read only + * in config.php. + * Attributes are configured as read-only in config.php thus: + * + * $config->custom->appearance['readonly_attrs'] = array('objectClass'); + * + * + * @param string The name of the attribute to test. + * @return boolean + */ + public function isAttrReadOnly($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attrs = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs'); + $except_dn = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs_exempt'); + + return $this->isAttrTest($attr,$attrs,$except_dn); + } + + /** + * Returns true if the specified attribute is configured as hidden + * in config.php. + * Attributes are configured as hidden in config.php thus: + * + * $config->custom->appearance['hide_attrs'] = array('objectClass'); + * + * + * @param string The name of the attribute to test. + * @return boolean + */ + public function isAttrHidden($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attrs = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs'); + $except_dn = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs_exempt'); + + return $this->isAttrTest($attr,$attrs,$except_dn); + } + + /** + * Add objects + */ + public function add($dn,$entry_array,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($entry_array as $attr => $val) + $entry_array[$attr] = dn_unescape($val); + + $result = false; + + # Check our unique attributes. + if (! $this->checkUniqueAttrs($dn,$entry_array)) + return false; + + if (run_hook('pre_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array))) { + $result = @ldap_add($this->connect($method),dn_escape($dn),$entry_array); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + + # If we created the base, delete it, then add it back + if (get_request('create_base')) + $tree->delEntry($dn); + + $tree->addEntry($dn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array)); + + } else { + system_message(array( + 'title'=>_('Could not add the object to the LDAP server.'), + 'body'=>ldap_error_msg($this->getErrorMessage(null),$this->getErrorNum(null)), + 'type'=>'error')); + } + } + + return $result; + } + + /** + * Delete objects + */ + public function delete($dn,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = false; + + if (run_hook('pre_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn))) { + $result = @ldap_delete($this->connect($method),dn_escape($dn)); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + $tree->delEntry($dn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn)); + } + } + + return $result; + } + + /** + * Rename objects + */ + public function rename($dn,$new_rdn,$container,$deleteoldrdn,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = false; + + if (run_hook('pre_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container))) { + $result = @ldap_rename($this->connect($method),$dn,$new_rdn,$container,$deleteoldrdn); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + $newdn = sprintf('%s,%s',$new_rdn,$container); + $tree->renameEntry($dn,$newdn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container)); + } + } + + return $result; + } + + /** + * Modify objects + */ + public function modify($dn,$attrs,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Check our unique attributes. + if (! $this->checkUniqueAttrs($dn,$attrs)) + return false; + + $result = false; + $summary = array(); + $current_attrs = $this->getDNAttrValues($dn,$method,LDAP_DEREF_NEVER,array('*')); + + # Go through our attributes and call our hooks for each attribute changing its value + foreach ($attrs as $attr => $values) { + # For new attributes + if (count($values) && ! isset($current_attrs[$attr])) { + if (! run_hook('pre_attr_add', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not added'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_add prevented attribute from being added'),$attr), + 'type'=>'warn')); + + } else + $summary['add'][$attr]['new'] = $values; + + # For modify attributes + } elseif (count($values)) { + if (! run_hook('pre_attr_modify', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr],'newvalue'=>$values))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not modified'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_modify prevented attribute from being modified'),$attr), + 'type'=>'warn')); + + } else { + $summary['modify'][$attr]['new'] = $values; + $summary['modify'][$attr]['old'] = $current_attrs[$attr]; + } + + # For delete attributes + } else { + if (! run_hook('pre_attr_delete', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr]))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not deleted'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_delete prevented attribute from being deleted'),$attr), + 'type'=>'warn')); + + } else + $summary['delete'][$attr]['old'] = $current_attrs[$attr]; + } + } + + if (! count($attrs)) + return false; + + if (run_hook('pre_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs))) { + $result = @ldap_modify($this->connect($method),$dn,$attrs); + + if ($result) { + run_hook('post_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs)); + + foreach (array('add','modify','delete') as $mode) + if (isset($summary[$mode])) + foreach ($summary[$mode] as $attr => $values) + switch ($mode) { + case 'add': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values['new'])); + break; + + case 'modify': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'],'newvalue'=>$values['new'])); + break; + + case 'delete': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'])); + break; + + default: + debug_dump_backtrace(sprintf('Unkown mode %s',$mode),1); + } + } else { + system_message(array( + 'title'=>_('Could not perform ldap_modify operation.'), + 'body'=>ldap_error_msg($this->getErrorMessage($method),$this->getErrorNum($method)), + 'type'=>'error')); + } + } + + return $result; + } + + /** + * Returns true if the specified attribute is configured as unique + * in config.php. + * Attributes are configured as hidden in config.php thus: + * + * $servers->setValue('unique','attrs',array('mail','uid','uidNumber')); + * + * + * @param string $attr The name of the attribute to test. + * @return boolean + */ + public function isAttrUnique($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Should this attribute value be unique + if (in_array_ignore_case($attr,$this->getValue('unique','attrs'))) + return true; + else + return false; + } + + /** + * This function will check whether the value for an attribute being changed + * is already assigned to another DN. + * + * Returns the bad value, or null if all values are OK + * + * @param dn DN that is being changed + * @param string Attribute being changed + * @param string|array New values for the attribute + */ + public function checkUniqueAttrs($dn,$attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If none of the attributes are defined unique, we'll return immediately; + if (! $checkattrs = array_intersect(arrayLower($this->getValue('unique','attrs')),array_keys(array_change_key_case($attrs)))) + return true; + + # Check see and use our alternate uid_dn and password if we have it. + if (! $this->login($this->getValue('unique','dn'),$this->getValue('unique','pass'),'unique')) { + system_message(array( + 'title'=>_('UNIQUE invalid login/password'), + 'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the unique login/password, please check your configuration.'), + $this->getName()), + 'type'=>'warn')); + + return false; + } + + $query = array(); + + # Build our search filter to double check each attribute. + $query['filter'] = '(|'; + foreach ($checkattrs as $attr) + foreach ($attrs[$attr] as $val) + if ($val) + $query['filter'] .= sprintf('(%s=%s)',$attr,$val); + $query['filter'] .= ')'; + + $query['attrs'] = $checkattrs; + + # Search through our bases and see if we have match + foreach ($this->getBaseDN() as $base) { + $query['base'] = $base; + + # Do the search + $results = $this->query($query,'unique'); + + # If we have a match. + if (count($results)) + foreach ($results as $values) + # If one of the attributes is owned to somebody else, then we may as well die here. + if ($values['dn'] != $dn) { + $href = sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&scope=sub&query=none&format=list&search=true',$this->index,$query['filter']); + + system_message(array( + 'title'=>_('Attribute value would not be unique'), + 'body'=>sprintf('%s (%s)', + _('This update has been or will be cancelled, it would result in an attribute value not being unique. You might like to search the LDAP server for the offending entry.'), + htmlspecialchars($href), + _('Search')), + 'type'=>'warn')); + + return false; + } + } + + # If we get here, then it must be OK? + return true; + } + + /** + * Check if the session timeout has occured for this LDAP server. + */ + public function isSessionValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If inactiveTime() returns a value, we need to check that it has not expired. + if (is_null($this->inactivityTime()) || ! $this->isLoggedIn()) + return true; + + # If session has expired + if ((isset($_SESSION['ACTIVITY'][$this->getIndex()])) && ($_SESSION['ACTIVITY'][$this->getIndex()] < time())) { + $this->logout(); + unset($_SESSION['ACTIVITY'][$this->getIndex()]); + + return false; + } + + $_SESSION['ACTIVITY'][$this->getIndex()] = $this->inactivityTime(); + return true; + } +} +?> diff --git a/lib/emuhash_functions.php b/lib/emuhash_functions.php new file mode 100644 index 0000000..7818f7f --- /dev/null +++ b/lib/emuhash_functions.php @@ -0,0 +1,112 @@ + + * + * 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 + * + ******************************************************************************/ + +/******************************************************************************/ +/* Do we have builtin mhash support in this PHP version ? */ +/******************************************************************************/ + +if (! function_exists('mhash') && ! function_exists('mhash_keygen_s2k')) { + $emuhash_emu = array(); + + if (! isset($emuhash_emu['openssl'])) + $emuhash_emu['openssl'] = '/usr/bin/openssl'; + + # Don't create mhash functions if we don't have a working openssl + if (! file_exists($emuhash_emu['openssl'])) + unset($emuhash_emu['openssl']); + + elseif (function_exists('is_executable') && ! is_executable($emuhash_emu['openssl'])) + unset($emuhash_emu['openssl']); + + else { + if (! isset($emuhash_emu['tmpdir'])) + $emuhash_emu['tmpdir'] = '/tmp'; + +/******************************************************************************/ +/* Define constants used in the mhash emulation code. */ +/******************************************************************************/ + + define('MHASH_MD5','md5'); + define('MHASH_SHA1','sha1'); + define('MHASH_RIPEMD160','rmd160'); + +/******************************************************************************/ +/* Functions to emulate parts of php-mash. */ +/******************************************************************************/ + + function openssl_hash($openssl_hash_id,$password_clear) { + global $emuhash_emu; + + if (PHP_VERSION < 6) { + $current_magic_quotes = @get_magic_quotes_runtime(); + @set_magic_quotes_runtime(0); + } + + $tmpfile = tempnam($emuhash_emu['tmpdir'],'emuhash'); + $pwhandle = fopen($tmpfile,'w'); + + if (! $pwhandle) + error(sprintf('Unable to create a temporary file %s to create hashed password',$tmpfile) ,'error','index.php'); + + fwrite($pwhandle,$password_clear); + fclose($pwhandle); + $cmd = sprintf('%s %s -binary <%s',$emuhash_emu['openssl'],$openssl_hash_id,$tmpfile); + $prog = popen($cmd,'r'); + $pass = fread($prog,1024); + pclose($prog); + unlink($tmpfile); + + if (PHP_VERSION < 6) + @set_magic_quotes_runtime($current_magic_quotes); + + return $pass; + } + + function mhash($hash_id,$password_clear) { + switch($hash_id) { + case MHASH_MD5: + $emuhash = openssl_hash(MHASH_MD5,$password_clear); + break; + + case MHASH_SHA1: + $emuhash = openssl_hash(MHASH_SHA1,$password_clear); + break; + + case MHASH_RIPEMD160: + $emuhash = openssl_hash(MHASH_RIPEMD160,$password_clear); + break; + + default: + $emuhash = FALSE; + } + + return $emuhash; + } + + function mhash_keygen_s2k($hash_id,$password_clear,$salt,$bytes) { + return substr(pack('H*',bin2hex(mhash($hash_id,($salt.$password_clear)))),0,$bytes); + } + } +} +?> diff --git a/lib/export_functions.php b/lib/export_functions.php new file mode 100644 index 0000000..d98df2c --- /dev/null +++ b/lib/export_functions.php @@ -0,0 +1,643 @@ +server_id = $server_id; + $this->template_id = $template_id; + + $this->accept(); + } + + static function types() { + $type = array(); + + $details = ExportCSV::getType(); + $type[$details['type']] = $details; + $details = ExportDSML::getType(); + $type[$details['type']] = $details; + $details = ExportLDIF::getType(); + $type[$details['type']] = $details; + $details = ExportVCARD::getType(); + $type[$details['type']] = $details; + + return $type; + } + + private function accept() { + switch($this->template_id) { + case 'CSV': + $this->template = new ExportCSV(); + break; + + case 'DSML': + $this->template = new ExportDSML(); + break; + + case 'LDIF': + $this->template = new ExportLDIF(); + break; + + case 'VCARD': + $this->template = new ExportVCARD(); + break; + + default: + system_message(array( + 'title'=>sprintf('%s %s',_('Unknown Export Type'),$this->template_id), + 'body'=>_('phpLDAPadmin has not been configured for that export type'), + 'type'=>'warn'),'index.php'); + die(); + } + + $this->template->accept(); + } + + public function getTemplate() { + return $this->template; + } +} + +/** + * Export Class + * + * This abstract classes provides all the common methods and variables for the + * custom export classes. + * + * @package phpLDAPadmin + * @subpackage Export + */ +abstract class Export { + # Line Break + protected $br; + # Compress the output + protected $compress; + # Export Results + protected $results; + protected $resultsdata; + protected $items = 0; + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + protected function getServerID() { + return get_request('server_id','REQUEST'); + } + + public function accept() { + $server = $this->getServer(); + + # Get the data to be exported + $query = array(); + $base = get_request('dn','REQUEST'); + $query['baseok'] = true; + $query['filter'] = get_request('filter','REQUEST',false,'objectclass=*'); + $query['scope'] = get_request('scope','REQUEST',false,'base'); + $query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','export'); + $query['size_limit'] = 0; + $attrs = get_request('attributes','REQUEST'); + + $attrs = preg_replace('/\s+/','',$attrs); + if ($attrs) + $query['attrs'] = explode(',',$attrs); + else + $query['attrs'] = array('*'); + + if (get_request('sys_attr')) { + if (! in_array('*',$query['attrs'])) + array_push($query['attrs'],'*'); + array_push($query['attrs'],'+'); + } + + if (! $base) + $bases = $server->getBaseDN(); + else + $bases = array($base); + + foreach ($bases as $base) { + $query['base'] = $base; + + $time_start = utime(); + $this->results[$base] = $server->query($query,null); + $time_end = utime(); + + usort($this->results[$base],'pla_compare_dns'); + $this->resultsdata[$base]['time'] = round($time_end-$time_start,2); + + # If no result, there is a something wrong + if (! $this->results[$base] && $server->getErrorNum(null)) + system_message(array( + 'title'=>_('Encountered an error while performing search.'), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + + $this->items += count($this->results[$base]); + } + + $this->resultsdata['scope'] = $query['scope']; + $this->resultsdata['filter'] = $query['filter']; + $this->resultsdata['attrs'] = $query['attrs']; + + # Other settings + switch (get_request('format','POST',false,'unix')) { + case 'win': + $this->br = "\r\n"; + break; + + case 'mac': + $this->br = "\r"; + break; + + case 'unix': + default: + $this->br = "\n"; + } + + if (get_request('compress','REQUEST') == 'on') + $this->compress = true; + } + + public function isCompressed() { + return $this->compress; + } + + protected function getHeader() { + $server = $this->getServer(); + $type = $this->getType(); + + $output = ''; + + $output .= sprintf('# %s %s %s%s',$type['description'],_('for'),implode('|',array_keys($this->results)),$this->br); + $output .= sprintf('# %s: %s (%s)%s',_('Server'),$server->getName(),$server->getValue('server','host'),$this->br); + $output .= sprintf('# %s: %s%s',_('Search Scope'),$this->resultsdata['scope'],$this->br); + $output .= sprintf('# %s: %s%s',_('Search Filter'),$this->resultsdata['filter'],$this->br); + $output .= sprintf('# %s: %s%s',_('Total Entries'),$this->items,$this->br); + $output .= sprintf('#%s',$this->br); + $output .= sprintf('# Generated by %s (%s) on %s%s',app_name(),get_href('web'),date('F j, Y g:i a'),$this->br); + $output .= sprintf('# Version: %s%s',app_version(),$this->br); + + $output .= $this->br; + + return $output; + } + + /** + * Helper method to check if the attribute value should be base 64 encoded. + * + * @param The string to check. + * @return boolean true if the string is safe ascii, false otherwise. + */ + protected function isSafeAscii($str) { + for ($i=0;$i 127) + return false; + + return true; + } +} + +/** + * Export entries to CSV + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportCSV extends Export { + private $separator = ','; + private $qualifier = '"'; + private $multivalue_separator = ' | '; + private $escapeCode = '"'; + + static public function getType() { + return array('type'=>'CSV','description' => 'CSV (Spreadsheet)','extension'=>'csv'); + } + + function export() { + $server = $this->getServer(); + + /* Go thru and find all the attribute names first. This is needed, because, otherwise we have + * no idea as to which search attributes were actually populated with data */ + $headers = array('dn'); + $entries = array(); + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + array_push($entries,$dndetails); + + unset($dndetails['dn']); + foreach (array_keys($dndetails) as $key) + if (! in_array($key,$headers)) + array_push($headers,$key); + + } + } + + $output = ''; + $num_headers = count($headers); + + # Print out the headers + for ($i=0; $i<$num_headers; $i++) { + $output .= sprintf('%s%s%s',$this->qualifier,$headers[$i],$this->qualifier); + + if ($i < $num_headers-1) + $output .= $this->separator; + } + + # Drop out our DN header. + array_shift($headers); + $num_headers--; + + $output .= $this->br; + + # Loop on every entry + foreach ($entries as $index => $entry) { + $dn = $entry['dn']; + unset($entry['dn']); + $output .= sprintf('%s%s%s%s',$this->qualifier,$this->LdapEscape($dn),$this->qualifier,$this->separator); + + # Print the attributes + for ($j=0; $j<$num_headers; $j++) { + $attr = $headers[$j]; + $output .= $this->qualifier; + + if (array_key_exists($attr,$entry)) { + $binary_attribute = $server->isAttrBinary($attr) ? 1 : 0; + + if (! is_array($entry[$attr])) + $attr_values = array($entry[$attr]); + else + $attr_values = $entry[$attr]; + + $num_attr_values = count($attr_values); + + for ($i=0; $i<$num_attr_values; $i++) { + if ($binary_attribute) + $output .= base64_encode($attr_values[$i]); + else + $output .= $this->LdapEscape($attr_values[$i]); + + if ($i < $num_attr_values-1) + $output .= $this->multivalue_separator; + } + } + + $output .= $this->qualifier; + + if ($j < $num_headers-1) + $output .= $this->separator; + } + + $output .= $this->br; + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } + + /** + * Function to escape data, where the qualifier happens to also + * be in the data. + */ + private function LdapEscape ($var) { + return str_replace($this->qualifier,$this->escapeCode.$this->qualifier,$var); + } +} + +/** + * Export entries to DSML v.1 + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportDSML extends Export { + static public function getType() { + return array('type'=>'DSML','description' => _('DSML V.1 Export'),'extension'=>'xml'); + } + + /** + * Export entries to DSML format + */ + function export() { + $server = $this->getServer(); + + # Not very elegant, but do the job for the moment as we have just 4 level + $indent = array(); + $indent['dir'] = ' '; + $indent['ent'] = ' '; + $indent['att'] = ' '; + $indent['val'] = ' '; + + # Print declaration + $output = sprintf('%s',$this->br); + + # Print root element + $output .= sprintf('%s',$this->br); + + # Print info related to this export + $output .= sprintf('%s',$this->br); + $output .= $this->br; + + $output .= sprintf('%s%s',$indent['dir'],$this->br); + + # Sift through the entries. + $counter = 0; + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $counter++; + + $dn = $dndetails['dn']; + unset($dndetails['dn']); + ksort($dndetails); + + # Display DN + $output .= sprintf('%s%s',$indent['ent'],htmlspecialchars($dn),$this->br); + + # Display the objectClass attributes first + if (isset($dndetails['objectClass'])) { + if (! is_array($dndetails['objectClass'])) + $dndetails['objectClass'] = array($dndetails['objectClass']); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + + foreach ($dndetails['objectClass'] as $ocValue) + $output .= sprintf('%s%s%s',$indent['val'],$ocValue,$this->br); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + unset($dndetails['objectClass']); + } + + # Display the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + $output .= sprintf('%s%s',$indent['att'],$key,$this->br); + + # If the attribute is binary, set the flag $binary_mode to true + $binary_mode = $server->isAttrBinary($key) ? 1 : 0; + + foreach ($attr as $value) + $output .= sprintf('%s%s%s', + $indent['val'],($binary_mode ? base64_encode($value) : htmlspecialchars($value)),$this->br); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + } + + $output .= sprintf('%s%s',$indent['ent'],$this->br); + } + } + + $output .= sprintf('%s%s',$indent['dir'],$this->br); + $output .= sprintf('%s',$this->br); + + if ($this->compress) + return gzencode($output); + else + return $output; + } +} + +/** + * Export from LDAP using an LDIF format + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportLDIF extends Export { + # The maximum length of the ldif line + private $line_length = 76; + + static public function getType() { + return array('type'=>'LDIF','description' => _('LDIF Export'),'extension'=>'ldif'); + } + + /** + * Export entries to LDIF format + */ + public function export() { + if (! $this->results) { + echo _('Nothing to export'); + return; + } + + $server = $this->getServer(); + + $output = $this->getHeader(); + + # Add our version. + $output .= 'version: 1'; + $output .= $this->br; + $output .= $this->br; + + # Sift through the entries. + $counter = 0; + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $counter++; + + $dn = $dndetails['dn']; + unset($dndetails['dn']); + ksort($dndetails); + + $title_string = sprintf('# %s %s: %s%s',_('Entry'),$counter,$dn,$this->br); + + if (strlen($title_string) > $this->line_length-3) + $title_string = substr($title_string,0,$this->line_length-3).'...'.$this->br; + + $output .= $title_string; + + # Display dn + if ($this->isSafeAscii($dn)) + $output .= $this->multiLineDisplay(sprintf('dn: %s',$dn)); + else + $output .= $this->multiLineDisplay(sprintf('dn:: %s',base64_encode($dn))); + + # display the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + foreach ($attr as $value) + if (! $this->isSafeAscii($value) || $server->isAttrBinary($key)) + $output .= $this->multiLineDisplay(sprintf('%s:: %s',$key,base64_encode($value))); + else + $output .= $this->multiLineDisplay(sprintf('%s: %s',$key,$value)); + } + + $output .= $this->br; + } + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } + + /** + * Helper method to wrap ldif lines + * + * @param The line to be wrapped if needed. + */ + private function multiLineDisplay($str) { + $length_string = strlen($str); + $length_max = $this->line_length; + + $output = ''; + while ($length_string > $length_max) { + $output .= substr($str,0,$length_max).$this->br.' '; + $str = substr($str,$length_max,$length_string); + $length_string = strlen($str); + + /* Need to do minus one to align on the right + * the first line with the possible following lines + * as these will have an extra space. */ + $length_max = $this->line_length-1; + } + + $output .= $str.$this->br; + + return $output; + } +} + +/** + * Export entries to VCARD v2.1 + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportVCARD extends Export { + static public function getType() { + return array('type'=>'VCARD','description' => _('VCARD 2.1 Export'),'extension'=>'vcf'); + } + + # Mappping one to one attribute + private $mapping = array( + 'cn' => 'FN', + 'title' => 'TITLE', + 'homephone' => 'TEL;HOME', + 'mobile' => 'TEL;CELL', + 'mail' => 'EMAIL;Internet', + 'labeleduri' =>'URL', + 'o' => 'ORG', + 'audio' => 'SOUND', + 'facsmiletelephoneNumber' =>'TEL;WORK;HOME;VOICE;FAX', + 'jpegphoto' => 'PHOTO;ENCODING=BASE64', + 'businesscategory' => 'ROLE', + 'description' => 'NOTE' + ); + + private $deliveryAddress = array( + 'postofficebox', + 'street', + 'l', + 'st', + 'postalcode', + 'c'); + + /** + * Export entries to VCARD format + */ + function export() { + $server = $this->getServer(); + $output = ''; + + # Sift through the entries. + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $dndetails = array_change_key_case($dndetails); + + # Check the attributes needed for the delivery address field + $addr = 'ADR:'; + foreach ($this->deliveryAddress as $attr) { + if (isset($dndetails[$attr])) { + $addr .= $dndetails[$attr]; + unset($dndetails[$attr]); + } + + $addr .= ';'; + } + + $output .= sprintf('BEGIN:VCARD%s',$this->br); + + # Loop for the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + # If an attribute of the ldap entry exist in the mapping array for vcard + if (isset($this->mapping[$key])) { + + # Case of organisation. Need to append the possible ou attribute + if ($key == 'o') { + $output .= sprintf('%s:%s',$this->mapping[$key],$attr[0]); + + if (isset($entry['ou'])) + foreach ($entry['ou'] as $ou_value) + $output .= sprintf(';%s',$ou_value); + + # The attribute is binary. (to do : need to fold the line) + } elseif (in_array($key,array('audio','jpegphoto'))) { + $output .= $this->mapping[$key].':'.$this->br; + $output .= ' '.base64_encode($attr[0]); + + } else { + $output .= $this->mapping[$key].':'.$attr[0]; + } + + $output .= $this->br; + } + } + + $output .= sprintf('UID:%s%s',isset($dndetails['entryUUID']) ? $dndetails['entryUUID'] : $dndetails['dn'],$this->br); + $output .= sprintf('VERSION:2.1%s',$this->br); + $output .= sprintf('%s%s',$addr,$this->br); + $output .= sprintf('END:VCARD%s',$this->br); + } + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } +} +?> diff --git a/lib/functions.php b/lib/functions.php new file mode 100644 index 0000000..13ce4ca --- /dev/null +++ b/lib/functions.php @@ -0,0 +1,3209 @@ +_('Generic Error'), + 'body'=>sprintf('%s: %s [%s]', + __METHOD__,_('Called to load a class that cant be found'),$className), + 'type'=>'error')); +} + +/** + * Strips all slashes from the specified array in place (pass by ref). + * @param Array The array to strip slashes from, typically one of + * $_GET, $_POST, or $_COOKIE. + */ +function array_stripslashes(&$array) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_array($array)) + while (list($key) = each($array)) + if (is_array($array[$key]) && $key != $array) + array_stripslashes($array[$key]); + else + $array[$key] = stripslashes($array[$key]); +} + +/** + * Compatibility Functions + * These functions exist, so that a standard function can be used in new applications, and they + * map to already defined functions in older applications. + */ + +/** + * If gettext is not available in PHP, then this will provide compatibility for it. + */ +if (! function_exists('_')) { + function _($msg) { + return $msg; + } +} + +/** + * Generic Utility Functions + */ + +/** + * Custom error handling function. + * When a PHP error occurs, PHP will call this function rather than printing + * the typical PHP error string. This provides the application the ability to + * format an error message so that it looks better. + * Optionally, it can present a link so that a user can search/submit bugs. + * This function is not to be called directly. It is exclusively for the use of + * PHP internally. If this function is called by PHP from within a context + * where error handling has been disabled (ie, from within a function called + * with "@" prepended), then this function does nothing. + * + * @param int The PHP error number that occurred (ie, E_ERROR, E_WARNING, E_PARSE, etc). + * @param string The PHP error string provided (ie, "Warning index "foo" is undefined) + * @param string The file in which the PHP error ocurred. + * @param int The line number on which the PHP error ocurred + * @see set_error_handler + */ +function app_error_handler($errno,$errstr,$file,$lineno) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /** + * error_reporting will be 0 if the error context occurred + * within a function call with '@' preprended (ie, @ldap_bind() ); + * So, don't report errors if the caller has specifically + * disabled them with '@' + */ + if (ini_get('error_reporting') == 0 || error_reporting() == 0) + return; + + $file = basename($file); + $caller = basename($_SERVER['PHP_SELF']); + $errtype = ''; + + switch ($errno) { + case E_STRICT: $errtype = 'E_STRICT'; break; + case E_ERROR: $errtype = 'E_ERROR'; break; + case E_WARNING: $errtype = 'E_WARNING'; break; + case E_PARSE: $errtype = 'E_PARSE'; break; + case E_NOTICE: $errtype = 'E_NOTICE'; break; + case E_CORE_ERROR: $errtype = 'E_CORE_ERROR'; break; + case E_CORE_WARNING: $errtype = 'E_CORE_WARNING'; break; + case E_COMPILE_ERROR: $errtype = 'E_COMPILE_ERROR'; break; + case E_COMPILE_WARNING: $errtype = 'E_COMPILE_WARNING'; break; + case E_USER_ERROR: $errtype = 'E_USER_ERROR'; break; + case E_USER_WARNING: $errtype = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $errtype = 'E_USER_NOTICE'; break; + case E_ALL: $errtype = 'E_ALL'; break; + + default: $errtype = sprintf('%s: %s',_('Unrecognized error number'),$errno); + } + + # Take out extra spaces in error strings. + $errstr = preg_replace('/\s+/',' ',$errstr); + + if ($errno == E_NOTICE) { + return; + /* $body = ''; + $body .= sprintf('',_('Error'),$errstr,$errtype); + $body .= sprintf('', + _('File'),$file,_('line'),$lineno,_('caller'),$caller); + $body .= sprintf('', + app_version(),phpversion(),php_sapi_name()); + $body .= sprintf('',isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'SCRIPT'); + + if (function_exists('get_href')) + $body .= sprintf('', + get_href('search_bug',"&summary_keyword=".rawurlencode($errstr)), + _('Please check and see if this bug has been reported')); + $body .= '
%s:%s (%s)
%s:%s %s %s, %s %s
Versions:PLA: %s, PHP: %s, SAPI: %s
Web server:%s
%s.
'; + + system_message(array( + 'title'=>_('You found a non-fatal phpLDAPadmin bug!'), + 'body'=>$body, + 'type'=>'error')); + + return; */ + } + + # If this is a more serious error, call the error call. + error(sprintf('%s: %s',$errtype,$errstr),'error',null,true,true); +} + +/** + * Returns the application name. + */ +function app_name() { + return 'phpLDAPadmin'; +} + +/** + * Returns the application version currently running. The version + * is read from the file named VERSION. + * + * @return string The current version as read from the VERSION file. + */ +function app_version() { + static $CACHE = null; + + if ($CACHE) + return $CACHE; + + $version_file = realpath(LIBDIR.'../VERSION'); + if (! file_exists($version_file)) + $CACHE = 'UNKNOWN'; + + else { + $version = rtrim(file_get_contents($version_file)); + + $CACHE = preg_replace('/^RELEASE-([0-9\.]+(-.*)*)$/','$1',$version); + + # Check if we are a CVS copy. + if (preg_match('/^(DEVEL)?$/',$CACHE)) + $CACHE = 'DEVEL'; + + # Check if we are special DEVEL version + elseif (preg_match('/^DEVEL-([0-9\.]+)+$/',$CACHE)) {} + + # If return is still the same as version, then the tag is not one we expect. + elseif ($CACHE == $version) + $CACHE = 'UNKNOWN'; + } + + return $CACHE; +} + +/** + * This function will convert the browser two character language into the + * default 5 character language, where the country portion should NOT be + * assumed to be upper case characters of the first two characters. + */ +function auto_lang($lang) { + switch ($lang) { + case 'ja': return 'ja_JP'; + case 'cs': return 'cs_CZ'; + default: return sprintf('%s_%s',$lang,strtoupper($lang)); + } +} + +/** + * Makes sure that the config file is properly setup. + */ +function check_config($config_file) { + # Read in config_default.php + require_once LIBDIR.'config_default.php'; + + # Make sure their PHP version is current enough + if (strcmp(phpversion(),REQUIRED_PHP_VERSION) < 0) + system_message(array( + 'title'=>_('Incorrect version of PHP'), + 'body'=>sprintf('phpLDAPadmin requires PHP version %s or greater.
(You are using %s)', + REQUIRED_PHP_VERSION,phpversion()), + 'type'=>'error')); + + $config = new Config; + + if (file_exists(LIBDIR.'config_custom.php') && is_readable(LIBDIR.'config_custom.php')) + include LIBDIR.'config_custom.php'; + + ob_start(); + require $config_file; + $str = ''; + if (ob_get_level()) { + $str = ob_get_contents(); + ob_end_clean(); + } + + if ($str) { + $str = strip_tags($str); + $matches = array(); + preg_match('/(.*):\s+(.*):.*\s+on line (\d+)/',$str,$matches); + + if (isset($matches[1]) && isset($matches[2]) && isset($matches[3])) { + $error_type = $matches[1]; + $error = $matches[2]; + $line_num = $matches[3]; + + $file = file($config_file); + + $body = '

Config file ERROR

'; + $body .= sprintf('

%s (%s) on line %s

',$error_type,$error,$line_num); + + $body .= '
'; + $body .= sprintf('Looks like your config file has an ERROR on line %s.
',$line_num); + $body .= 'Here is a snippet around that line
'; + $body .= '
'."\n"; + + $body .= '
'; + + for ($i = $line_num-9; $i<$line_num+5; $i++) { + if ($i+1 == $line_num) + $body .= '
'; + + if ($i < 0) + continue; + + $body .= sprintf('%s: %s
',$i+1,$file[$i]); + + if ($i+1 == $line_num) + $body .= '
'; + } + + $body .= '
'; + $body .= '
'; + $body .= 'Hint: Sometimes these errors are caused by lines preceding the line reported.'; + $body .= '
'; + + $block = new block(); + $block->SetBody($body); + $www['page'] = new page(); + $www['page']->block_add('body',$block); + $www['page']->display(); + + die(); + } + } + + # Check for server definitions. + if (! isset($servers) || count($servers->GetServerList()) == 0) + error(_('Your config.php is missing Server Definitions. Please see the sample file config/config.php.example.'),'error','index.php',true); + + $config->setServers($servers); + + # Check the memory limit parameter. + if ((ini_get('memory_limit') > -1) && ini_get('memory_limit') < $config->getValue('session','memorylimit')) + system_message(array( + 'title'=>_('Memory Limit low.'), + 'body'=>sprintf('Your php memory limit is low - currently %s, you should increase it to atleast %s. This is normally controlled in /etc/php.ini.', + ini_get('memory_limit'),$config->getValue('session','memorylimit')), + 'type'=>'error')); + + return $config; +} + +/** + * Commands available in the control_panel of the page + * + * @return array + */ +function cmd_control_pane($type) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($type) { + case 'main' : + return array( + 'home'=>array( + 'title'=>_('Home'), + 'enable'=>true, + 'link'=>sprintf('href="index.php" title="%s"',_('Home')), + 'image'=>sprintf('%s',IMGDIR,_('Home'))), + + 'purge'=>array( + 'title'=>_('Purge caches'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','purge_cache') : false, + 'link'=>sprintf('href="cmd.php?cmd=purge_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=purge_cache\',\'%s\');" title="%s"', + _('Clearing cache'),_('Purge caches')), + 'image'=>sprintf('%s',IMGDIR,_('Purge caches'))), + + 'hide_debug_info'=>array( + 'title'=>_('Show Cache'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','show_cache') : false, + 'link'=>sprintf('href="cmd.php?cmd=show_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=show_cache\',\'%s\');" title="%s"', + _('Loading'),_('Show Cache'),_('Show Cache')), + 'image'=>sprintf('%s',IMGDIR,_('Show Cache'))), + ); + + break; + + case 'top' : + return array( + 'forum'=>array( + 'title'=>_('Forum'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('forum'),_('Forum')), + 'image'=>sprintf('%s',IMGDIR,_('Forum'))), + + 'feature'=>array( + 'title'=>_('Request feature'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_rfe'),_('Request feature')), + 'image'=>sprintf('%s',IMGDIR,_('Request feature'))), + + 'bug'=>array( + 'title'=>_('Report a bug'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_bug'),_('Report a bug')), + 'image'=>sprintf('%s',IMGDIR,_('Report a bug'))), + + 'donation'=>array( + 'title'=>_('Donate'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('donate'),_('Donate')), + 'image'=>sprintf('%s',IMGDIR,_('Donate'))), + + 'help'=>array( + 'title'=>_('Help'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('documentation'),_('Help')), + 'image'=>sprintf('%s',IMGDIR,_('Help'))) + ); + + break; + } +} + +/** + * This function dumps the $variable for debugging purposes + * + * @param string|array Variable to dump + * @param boolean Whether to stop execution or not. + */ +function debug_dump($variable,$die=false,$onlydebugaddr=false) { + if ($onlydebugaddr && + isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('debug','addr') && + $_SERVER['HTTP_X_FORWARDED_FOR'] != $_SESSION[APPCONFIG]->getValue('debug','addr') && + $_SERVER['REMOTE_ADDR'] != $_SESSION[APPCONFIG]->getValue('debug','addr')) + return; + + $backtrace = debug_backtrace(); + $caller['class'] = isset($backtrace[0]['class']) ? $backtrace[0]['class'] : 'N/A'; + $caller['function'] = isset($backtrace[0]['function']) ? $backtrace[0]['function'] : 'N/A'; + $caller['file'] = isset($backtrace[0]['file']) ? $backtrace[0]['file'] : 'N/A'; + $caller['line'] = isset($backtrace[0]['line']) ? $backtrace[0]['line'] : 'N/A'; + $caller['debug'] = $variable; + + print '
';
+	print_r($caller);
+	print '
'; + + if ($die) + die(); +} + +/** + * This function generates a backtrace + * + * @param boolean Whether to stop execution or not. + */ +function debug_dump_backtrace($msg='Calling BackTrace',$die=false) { + error($msg,'note',null,$die,true); +} + +/** + * Send a debug as a sys message + */ +function debug_sysmsg($msg) { + system_message(array('title'=>_('Debug'),'body'=>$msg,'type'=>'debug')); +} + +/** + * Debug Logging + * + * The global debug level is turned on in your configuration file by setting: + * + * $config->custom->debug['level'] = 255; + * + * together with atleast one output direction (currently file and syslog are supported). + * + * $config->custom->debug['file'] = '/tmp/app_debug.log'; + * $config->custom->debug['syslog'] = true; + * + * + * The debug level is turned into binary, then if the message levels bit is on + * the message will be sent to the debug log. (Thus setting your debug level to 255, + * all bits on, will results in all messages being printed.) + * + * The message level bits are defined here. + * 0( 1) = Entry/Return results from function calls. + * 1( 2) = Configuration Processing + * 2( 4) = Template Processing + * 3( 8) = Schema Processing + * 4( 16) = LDAP Server Communication + * 5( 32) = Tree Processing + * 7( 64) = Other non generic messages + * 8(128) = Page Processing + * 9(256) = Hooks Processing + * @param string Message to send to syslog + * @param int Log bit number for this message. + * @see syslog.php + */ +function debug_log($msg,$level,$indent) { + static $debug_file; + + # In case we are called before we are fully initialised or if debugging is not set. + if (! isset($_SESSION[APPCONFIG]) + || ! ($_SESSION[APPCONFIG]->getValue('debug','file') || $_SESSION[APPCONFIG]->getValue('debug','syslog'))) + return; + + $debug_level = $_SESSION[APPCONFIG]->getValue('debug','level'); + if (! $debug_level || (! ($level & $debug_level))) + return; + + if ($_SESSION[APPCONFIG]->getValue('debug','addr')) + if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) + $debugaddr = true; + elseif ($_SERVER['REMOTE_ADDR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) + $debugaddr = true; + else + $debugaddr = false; + + else + $debugaddr = true; + + if (! $debugaddr) + return; + + # If we are limiting debug to a browser, then check that + $caller = basename($_SERVER['PHP_SELF']); + + $args = func_get_args(); + # Discard our first three arguments. + array_shift($args); + array_shift($args); + array_shift($args); + + # Pull the file/line/method + if (is_string($args[0]) && preg_match('/.php$/',$args[0])) { + $file = preg_replace('/.php$/','',array_shift($args)); + $line = array_shift($args); + $method = array_shift($args); + + } else { + $file = 'UNKNOWN'; + $line = 'UNKNOWN'; + $method = 'UNKNOWN'; + } + + # TEMP: New debuglog format + if (preg_match('/%%/',$msg) && $args[0] != 'NOARGS') + $args = array_shift($args); + + $fargs = array(); + foreach ($args as $key) { + if (is_array($key)) + array_push($fargs,serialize($key)); + elseif (is_object($key)) + array_push($fargs,sprintf('OBJECT:%s',get_class($key))); + else + array_push($fargs,$key); + } + + if (preg_match('/%%/',$msg)) + $msg = preg_replace('/%%/',join('|',$fargs),$msg); + else + $msg = vsprintf($msg,array_values($fargs)); + + if (function_exists('stopwatch')) + $timer = stopwatch(); + else + $timer = null; + + $debug_message = sprintf('[%2.3f] %15s(%04s-%03s): %s%s: %s',$timer,basename($file),$line,$level,str_repeat('.',$indent),$method,substr($msg,0,200)); + + if ($debug_file || $_SESSION[APPCONFIG]->getValue('debug','file')) { + if (! $debug_file) + $debug_file = fopen($_SESSION[APPCONFIG]->getValue('debug','file'), + $_SESSION[APPCONFIG]->getValue('debug','append') ? 'a' : 'w'); + + fwrite($debug_file,$debug_message."\n"); + } + + if ($_SESSION[APPCONFIG]->getValue('debug','syslog') && function_exists('syslog_notice')) + syslog_notice($debug_message); +} + +/** + * Display an error message in the system message panel of the page. + */ +function error($msg,$type='note',$redirect=null,$fatal=false,$backtrace=false) { + global $www; + static $counter; + + # Just a check to see that we are called right. + if (! isset($www['page']) && ! $fatal) + die("Function error called incorrectly [$msg]"); + + # If the error is fatal, we'll need to stop here. + if (! isset($www['page'])) + $www['page'] = new page(); + + if ($fatal) + $www['page']->setsysmsg(array('title'=>_('Error'),'body'=>$msg,'type'=>$type)); + else + system_message(array('title'=>_('Error'),'body'=>$msg,'type'=>$type),$redirect); + + # Spin loop detection + if ($counter++ > 20) { + debug_dump('Spin loop detection.'); + debug_dump(array('msg'=>$msg,'session'=>$_SESSION['sysmsg'],'www'=>$www),1); + } + + # Do we have a backtrace to display? + if ($backtrace) { + $backtraceblock = new block(); + $backtraceblock->SetTitle('PHP Debug Backtrace'); + + $body = ''; + $body .= "\n"; + + foreach (debug_backtrace() as $error => $line) { + $_SESSION['backtrace'][$error]['file'] = isset($line['file']) ? $line['file'] : 'unknown'; + $_SESSION['backtrace'][$error]['line'] = isset($line['line']) ? $line['line'] : 'unknown'; + $body .= sprintf('', + _('File'),isset($line['file']) ? $line['file'] : $last['file'],isset($line['line']) ? $line['line'] : ''); + + $_SESSION['backtrace'][$error]['function'] = $line['function']; + $body .= sprintf(''; + $body .= "\n"; + + if (isset($line['file'])) + $last['file'] = $line['file']; + } + + $body .= '
%s%s (%s)
 %s%s', + _('Function'),$line['function']); + + if (isset($line['args'])) { + $display = print_r($line['args'], TRUE);/* strlen(serialize($line['args'])) < 50 ? htmlspecialchars(serialize($line['args'])) : htmlspecialchars(substr(serialize($line['args']),0,50)).'...'; */ + $_SESSION['backtrace'][$error]['args'] = $line['args']; + if (file_exists(LIBDIR.'../tools/unserialize.php')) + $body .= sprintf(' (%s)', + '../tools/unserialize.php',$error,$display); + else + $body .= sprintf(' (%s)',$display); + } + $body .= '
'; + $body .= "\n"; + $backtraceblock->SetBody($body); + + $www['page']->block_add('body',$backtraceblock); + } + + if ($fatal) { + $www['page']->display(array('tree'=>false)); + die(); + } +} + +/** + * Return the result of a form variable, with optional default + * + * @return The form GET/REQUEST/SESSION/POST variable value or its default + */ +function get_request($attr,$type='POST',$die=false,$default=null) { + switch($type) { + case 'GET': + $value = isset($_GET[$attr]) ? (is_array($_GET[$attr]) ? $_GET[$attr] : (empty($_GET['nodecode'][$attr]) ? rawurldecode($_GET[$attr]) : $_GET[$attr])) : $default; + break; + + case 'REQUEST': + $value = isset($_REQUEST[$attr]) ? (is_array($_REQUEST[$attr]) ? $_REQUEST[$attr] : (empty($_REQUEST['nodecode'][$attr]) ? rawurldecode($_REQUEST[$attr]) : $_REQUEST[$attr])) : $default; + break; + + case 'SESSION': + $value = isset($_SESSION[$attr]) ? (is_array($_SESSION[$attr]) ? $_SESSION[$attr] : (empty($_SESSION['nodecode'][$attr]) ? rawurldecode($_SESSION[$attr]) : $_SESSION[$attr])) : $default; + break; + + case 'POST': + default: + $value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : (empty($_POST['nodecode'][$attr]) ? rawurldecode($_POST[$attr]) : $_POST[$attr])) : $default; + break; + } + + if ($die && is_null($value)) + system_message(array( + 'title'=>_('Generic Error'), + 'body'=>sprintf('%s: Called "%s" without "%s" using "%s"', + basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),$attr,$type), + 'type'=>'error'), + 'index.php'); + + return $value; +} + +/** + * Record a system message. + * This function can be used as an alternative to generate a system message, if page hasnt yet been defined. + */ +function system_message($msg,$redirect=null) { + if (! is_array($msg)) + return null; + + if (! isset($msg['title']) && ! isset($msg['body'])) + return null; + + if (! isset($msg['type'])) + $msg['type'] = 'info'; + + if (! isset($_SESSION['sysmsg']) || ! is_array($_SESSION['sysmsg'])) + $_SESSION['sysmsg'] = array(); + + # Try and detect if we are in a redirect loop + if (get_request('redirect','GET') && $msg['type'] != 'debug') { + foreach ($_SESSION['sysmsg'] as $detail) { + if ($msg == $detail && ! isset($detail['special'])) { + debug_dump(array('Incoming MSG'=>$msg,'existing'=>$_SESSION['sysmsg'])); + debug_dump_backtrace('Redirect Loop Detected',true); + } + } + } + + array_push($_SESSION['sysmsg'],$msg); + + if ($redirect) { + if (preg_match('/\?/',$redirect)) + $redirect .= '&'; + else + $redirect .= '?'; + $redirect .= 'redirect=true'; + + # Check if we were an ajax request, and only render the ajax message + if (get_request('meth','REQUEST') == 'ajax') + $redirect .= '&meth=ajax'; + + header("Location: $redirect"); + die(); + } +} + +/** + * Other Functions + */ + +/** + * Encryption using blowfish algorithm + * + * @param string Original data + * @param string The secret + * @return string The encrypted result + * @author lem9 (taken from the phpMyAdmin source) + */ +function blowfish_encrypt($data,$secret=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If our secret is null or blank, get the default. + if ($secret === null || ! trim($secret)) + $secret = $_SESSION[APPCONFIG]->getValue('session','blowfish') ? $_SESSION[APPCONFIG]->getValue('session','blowfish') : session_id(); + + # If the secret isnt set, then just return the data. + if (! trim($secret)) + return $data; + + if (function_exists('mcrypt_module_open') && ! empty($data)) { + $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); + $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); + mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); + $encrypted_data = base64_encode(mcrypt_generic($td,$data)); + mcrypt_generic_deinit($td); + + return $encrypted_data; + } + + if (file_exists(LIBDIR.'blowfish.php')) + require_once LIBDIR.'blowfish.php'; + else + return $data; + + $pma_cipher = new Horde_Cipher_blowfish; + $encrypt = ''; + + for ($i=0; $iencryptBlock($block, $secret); + } + + return base64_encode($encrypt); +} + +/** + * Decryption using blowfish algorithm + * + * @param string Encrypted data + * @param string The secret + * @return string Original data + * @author lem9 (taken from the phpMyAdmin source) + */ +function blowfish_decrypt($encdata,$secret=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # This cache gives major speed up for stupid callers :) + static $CACHE = array(); + + if (isset($CACHE[$encdata])) + return $CACHE[$encdata]; + + # If our secret is null or blank, get the default. + if ($secret === null || ! trim($secret)) + $secret = $_SESSION[APPCONFIG]->getValue('session','blowfish') ? $_SESSION[APPCONFIG]->getValue('session','blowfish') : session_id(); + + # If the secret isnt set, then just return the data. + if (! trim($secret)) + return $encdata; + + if (function_exists('mcrypt_module_open') && ! empty($encdata)) { + $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); + $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); + mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); + $decrypted_data = trim(mdecrypt_generic($td,base64_decode($encdata))); + mcrypt_generic_deinit($td); + + return $decrypted_data; + } + + if (file_exists(LIBDIR.'blowfish.php')) + require_once LIBDIR.'blowfish.php'; + else + return $encdata; + + $pma_cipher = new Horde_Cipher_blowfish; + $decrypt = ''; + $data = base64_decode($encdata); + + for ($i=0; $idecryptBlock(substr($data, $i, 8), $secret); + + // Strip off our \0's that were added. + $return = preg_replace("/\\0*$/",'',$decrypt); + $CACHE[$encdata] = $return; + return $return; +} + +/** + * String padding + * + * @param string Input string + * @param integer Length of the result + * @param string The filling string + * @param integer Padding mode + * @return string The padded string + */ +function full_str_pad($input,$pad_length,$pad_string='',$pad_type=0) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $str = ''; + $length = $pad_length - strlen($input); + + if ($length > 0) { // str_repeat doesn't like negatives + if ($pad_type == STR_PAD_RIGHT) { // STR_PAD_RIGHT == 1 + $str = $input.str_repeat($pad_string, $length); + } elseif ($pad_type == STR_PAD_BOTH) { // STR_PAD_BOTH == 2 + $str = str_repeat($pad_string, floor($length/2)); + $str .= $input; + $str .= str_repeat($pad_string, ceil($length/2)); + } else { // defaults to STR_PAD_LEFT == 0 + $str = str_repeat($pad_string, $length).$input; + } + + } else { // if $length is negative or zero we don't need to do anything + $str = $input; + } + return $str; +} + +/** + * Returns the cached array of LDAP resources. + * + * Note that internally, this function utilizes a two-layer cache, + * one in memory using a static variable for multiple calls within + * the same page load, and one in a session for multiple calls within + * the same user session (spanning multiple page loads). + * + * @return Returns the cached attributed requested, + * or null if there is nothing cached.. + */ +function get_cached_item($index,$item,$subitem='null') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + # Check config to make sure session-based caching is enabled. + if ($_SESSION[APPCONFIG]->getValue('cache',$item) && isset($_SESSION['cache'][$index][$item][$subitem])) + $return = $_SESSION['cache'][$index][$item][$subitem]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Caches the specified $item for the specified $index. + * + * Returns true on success of false on failure. + */ +function set_cached_item($index,$item,$subitem='null',$data) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Check config to make sure session-based caching is enabled. + if ($_SESSION[APPCONFIG]->getValue('cache',$item)) { + global $CACHE; + + $CACHE[$index][$item][$subitem] = $data; + $_SESSION['cache'][$index][$item][$subitem] = $data; + + return true; + + } else + return false; +} + +/** + * Deletes the cache for a specified $item for the specified $index + */ +function del_cached_item($index,$item,$subitem='null') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + global $CACHE; + + # Check config to make sure session-based caching is enabled. + if (isset($_SESSION['cache'][$index][$item][$subitem])) + unset($_SESSION['cache'][$index][$item][$subitem]); + + if (isset($CACHE[$index][$item][$subitem])) + unset($CACHE[$index][$item][$subitem]); +} + +/** + * Utility wrapper for setting cookies, which takes into consideration + * application configuration values. On success, true is returned. On + * failure, false is returned. + * + * @param string The name of the cookie to set. + * @param string The value of the cookie to set. + * @param int (optional) The duration in seconds of this cookie. If unspecified, $cookie_time is used from config.php + * @param string (optional) The directory value of this cookie (see php.net/setcookie) + * @return boolean + */ +function set_cookie($name,$val,$expire=null,$dir=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = false; + + if ($expire == null) { + $cookie_time = $_SESSION[APPCONFIG]->getValue('session','cookie_time'); + $expire = $cookie_time == 0 ? null : time() + $cookie_time; + } + + if ($dir == null) + $dir = dirname($_SERVER['PHP_SELF']); + + if (@setcookie($name,$val,$expire,$dir)) { + $_COOKIE[$name] = $val; + $return = true; + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Get a customized file for a server + * We don't need any caching, because it's done by PHP + * + * @param int The ID of the server + * @param string The requested filename + * + * @return string The customized filename, if exists, or the standard one + */ +function get_custom_file($index,$filename,$path) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = $path.$filename; + $server = $_SESSION[APPCONFIG]->getServer($index); + + $custom = $server->getValue('custom','pages_prefix'); + if (! is_null($custom) && is_file(realpath($path.$custom.$filename))) + $return = $path.$custom.$filename; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Sort a multi dimensional array. + * + * @param array Multi demension array passed by reference + * @param string Comma delimited string of sort keys. + * @param boolean Whether to reverse sort. + * @return array Sorted multi demension array. + */ +function masort(&$data,$sortby,$rev=0) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # if the array to sort is null or empty, or if we have some nasty chars + if (! preg_match('/^[a-zA-Z0-9_]+(\([a-zA-Z0-9_,]*\))?$/',$sortby) || ! $data) + return; + + static $CACHE = array(); + + + + if (empty($CACHE[$sortby])) { + /* $code = "\$c=0;\n"; + + foreach (explode(',',$sortby) as $key) { + $code .= "if (is_object(\$a) || is_object(\$b)) {\n"; + + $code .= " if (is_array(\$a->$key)) {\n"; + $code .= " asort(\$a->$key);\n"; + $code .= " \$aa = array_shift(\$a->$key);\n"; + $code .= " } else\n"; + $code .= " \$aa = \$a->$key;\n"; + + $code .= " if (is_array(\$b->$key)) {\n"; + $code .= " asort(\$b->$key);\n"; + $code .= " \$bb = array_shift(\$b->$key);\n"; + $code .= " } else\n"; + $code .= " \$bb = \$b->$key;\n"; + + $code .= " if (\$aa != \$bb)"; + if ($rev) + $code .= " return (\$aa < \$bb ? 1 : -1);\n"; + else + $code .= " return (\$aa > \$bb ? 1 : -1);\n"; + + $code .= "} else {\n"; + + $code .= " \$a = array_change_key_case(\$a);\n"; + $code .= " \$b = array_change_key_case(\$b);\n"; + + $key = strtolower($key); + + $code .= " if ((! isset(\$a['$key'])) && isset(\$b['$key'])) return 1;\n"; + $code .= " if (isset(\$a['$key']) && (! isset(\$b['$key']))) return -1;\n"; + + $code .= " if ((isset(\$a['$key'])) && (isset(\$b['$key']))) {\n"; + $code .= " if (is_array(\$a['$key'])) {\n"; + $code .= " asort(\$a['$key']);\n"; + $code .= " \$aa = array_shift(\$a['$key']);\n"; + $code .= " } else\n"; + $code .= " \$aa = \$a['$key'];\n"; + + $code .= " if (is_array(\$b['$key'])) {\n"; + $code .= " asort(\$b['$key']);\n"; + $code .= " \$bb = array_shift(\$b['$key']);\n"; + $code .= " } else\n"; + $code .= " \$bb = \$b['$key'];\n"; + + $code .= " if (\$aa != \$bb)\n"; + $code .= " if (is_numeric(\$aa) && is_numeric(\$bb)) {\n"; + + if ($rev) + $code .= " return (\$aa < \$bb ? 1 : -1);\n"; + else + $code .= " return (\$aa > \$bb ? 1 : -1);\n"; + + $code .= " } else {\n"; + + if ($rev) + $code .= " if ( (\$c = strcasecmp(\$bb,\$aa)) != 0 ) return \$c;\n"; + else + $code .= " if ( (\$c = strcasecmp(\$aa,\$bb)) != 0 ) return \$c;\n"; + + $code .= " }\n"; + $code .= " }\n"; + $code .= "}\n"; + } + + $code .= 'return $c;'; */ + + $CACHE[$sortby] = function ($a, $b) use ($rev) { + $c = 0; + + foreach (explode(',',$sortby) as $key) { + if (is_object($a) || is_object($b)) { + if (is_array($a->$key)) { + asort($a->$key); + $aa = array_shift($a->$key); + } else { + $aa = $a->$key; + } + + if (is_array($b->$key)) { + asort($b->$key); + $bb = array_shift($b->$key); + } else { + $bb = $b->$key; + } + + if ($aa != $bb) { + if ($rev) { + return ($aa < $bb) ? 1 : -1; + } + + return ($aa > $bb) ? 1 : -1; + } else { + $a = array_change_key_case((array)$a); + $b = array_change_key_case((array)$b); + + $key = strtolower($key); + + if ((! isset($a[$key])) && isset($b[$key])) return 1; + if (isset($a[$key]) && (! isset($b[$key]))) return -1; + + if ((isset($a[$key])) && (isset($b[$key]))) { + if (is_array($a[$key])) { + asort($a[$key]); + $aa = array_shift($a[$key]); + } else { + $aa = $a[$key]; + } + + if (is_array($b[$key])) { + asort($b[$key]); + $bb = array_shift($b[$key]); + } else { + $bb = $b[$key]; + } + + if ($aa !== $bb) { + if (is_numeric($aa) && is_numeric($bb)) { + if ($rev) { + return ($aa < $bb) ? 1 : -1; + } + + return ($aa > $bb) ? 1 : -1; + } else { + if (($c = strcasecmp($bb, $aa)) != 0) return $c; + if (($c = strcasecmp($aa, $bb)) != 0) return $c; + } + } + } + } + } + } + + return $c; + };// masort_function($a, $b, $rev);//create_function('$a, $b',$code); + } + + uasort($data,$CACHE[$sortby]); +} + +/** + * Is compression enabled for output + */ +function isCompress() { + return (isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('appearance','compress') + && ! ini_get('zlib.output_compression') + && preg_match('/gzip/',$_SERVER['HTTP_ACCEPT_ENCODING'])); +} + +/** + * PLA specific Functions + */ + +/** + * Fetches whether the user has configured phpLDAPadmin to obfuscate passwords + * with "*********" when displaying them. + * + * This is configured in config.php thus: + * + * $config->custom->appearance['obfuscate_password_display'] = true; + * + * + * Or if it is OK to show encrypted passwords but not clear text passwords + * + * $config->custom->appearance['show_clear_password'] = false; + * + * + * @param string Password encoding type + * @return boolean + */ +function obfuscate_password_display($enc=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','obfuscate_password_display')) + $return = true; + + elseif (! $_SESSION[APPCONFIG]->getValue('appearance','show_clear_password') && (is_null($enc) || $enc == 'clear')) + $return = true; + + else + $return = false; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Returns an HTML-beautified version of a DN. + * Internally, this function makes use of pla_explode_dn() to break the + * the DN into its components. It then glues them back together with + * "pretty" HTML. The returned HTML is NOT to be used as a real DN, but + * simply displayed. + * + * @param string The DN to pretty-print. + * @return string + */ +function pretty_print_dn($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn_save = $dn; + $dn = pla_explode_dn($dn); + + if (! $dn) + return $dn_save; + + foreach ($dn as $i => $element) { + $element = htmlspecialchars($element); + $element = explode('=',$element,2); + $element = implode('=',$element); + $dn[$i] = $element; + } + + $dn = implode(',',$dn); + + return $dn; +} + +/** + * Given a string, this function returns true if the string has the format + * of a DN (ie, looks like "cn=Foo,dc=example,dc=com"). Returns false otherwise. + * The purpose of this function is so that developers can examine a string and + * know if it looks like a DN, and draw a hyperlink as needed. + * + * (See unit_test.php for test cases) + * + * @param string The attribute to examine for "DNness" + * @return boolean + */ +function is_dn_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /* Try to break the string into its component parts if it can be done + ie, "uid=Manager" "dc=example" and "dc=com" */ + $parts = pla_explode_dn($str); + if (! is_array($parts) || ! count($parts)) + return false; + + /* Foreach of the "parts", look for an "=" character, + and make sure neither the left nor the right is empty */ + foreach ($parts as $part) { + if (! strpos($part,"=")) + return false; + + $sub_parts = explode('=',$part,2); + $left = $sub_parts[0]; + $right = $sub_parts[1]; + + if ( ! strlen(trim($left)) || ! strlen(trim($right))) + return false; + + if (strpos($left,'#') !== false) + return false; + } + + # We survived the above rigor. This is a bonified DN string. + return true; +} + +/** + * Get whether a string looks like an email address (user@example.com). + * + * @param string The string to analyze. + * @return boolean Returns true if the specified string looks like an email address or false otherwise. + */ +function is_mail_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/"; + + if (preg_match($mail_regex,$str)) + return true; + else + return false; +} + +/** + * Get whether a string looks like a web URL (http://www.example.com/) + * + * @param string The string to analyze. + * @return boolean Returns true if the specified string looks like a web URL or false otherwise. + */ +function is_url_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $url_regex = '/^(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/'; + + if (preg_match($url_regex,$str)) + return true; + else + return false; +} + +/** + * Compares 2 DNs. If they are equivelant, returns 0, otherwise, + * returns their sorting order (similar to strcmp()): + * Returns < 0 if dn1 is less than dn2. + * Returns > 0 if dn1 is greater than dn2. + * + * The comparison is performed starting with the top-most element + * of the DN. Thus, the following list: + * + * ou=people,dc=example,dc=com + * cn=Admin,ou=People,dc=example,dc=com + * cn=Joe,ou=people,dc=example,dc=com + * dc=example,dc=com + * cn=Fred,ou=people,dc=example,dc=org + * cn=Dave,ou=people,dc=example,dc=org + * + * Will be sorted thus using usort( $list, "pla_compare_dns" ): + * + * dc=com + * dc=example,dc=com + * ou=people,dc=example,dc=com + * cn=Admin,ou=People,dc=example,dc=com + * cn=Joe,ou=people,dc=example,dc=com + * cn=Dave,ou=people,dc=example,dc=org + * cn=Fred,ou=people,dc=example,dc=org + * + * + * @param string The first of two DNs to compare + * @param string The second of two DNs to compare + * @return int + */ +function pla_compare_dns($dn1,$dn2) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If pla_compare_dns is passed via a tree, then we'll just get the DN part. + if (is_array($dn1)) + if (isset($dn1['dn'])) + $dn1 = $dn1['dn']; + else + $dn1 = implode('+',$dn1); + if (is_array($dn2)) + if (isset($dn2['dn'])) + $dn2 = $dn2['dn']; + else + $dn2 = implode('+',$dn2); + + # If they are obviously the same, return immediately + if (! strcasecmp($dn1,$dn2)) + return 0; + + $dn1_parts = pla_explode_dn(pla_reverse_dn($dn1)); + $dn2_parts = pla_explode_dn(pla_reverse_dn($dn2)); + assert(is_array($dn1_parts)); + assert(is_array($dn2_parts)); + + # Foreach of the "parts" of the smaller DN + for ($i=0; $i < count($dn1_parts) && $i < count($dn2_parts); $i++) { + /* dnX_part is of the form: "cn=joe" or "cn = joe" or "dc=example" + ie, one part of a multi-part DN. */ + $dn1_part = $dn1_parts[$i]; + $dn2_part = $dn2_parts[$i]; + + /* Each "part" consists of two sub-parts: + 1. the attribute (ie, "cn" or "o") + 2. the value (ie, "joe" or "example") */ + $dn1_sub_parts = explode('=',$dn1_part,2); + $dn2_sub_parts = explode('=',$dn2_part,2); + + $dn1_sub_part_attr = trim($dn1_sub_parts[0]); + $dn2_sub_part_attr = trim($dn2_sub_parts[0]); + + if (0 != ($cmp = strcasecmp($dn1_sub_part_attr,$dn2_sub_part_attr))) + return $cmp; + + $dn1_sub_part_val = trim($dn1_sub_parts[1]); + $dn2_sub_part_val = trim($dn2_sub_parts[1]); + if (0 != ($cmp = strcasecmp($dn1_sub_part_val,$dn2_sub_part_val))) + return $cmp; + } + + /* If we iterated through all entries in the smaller of the two DNs + (ie, the one with fewer parts), and the entries are different sized, + then, the smaller of the two must be "less than" than the larger. */ + if (count($dn1_parts) > count($dn2_parts)) { + return 1; + + } elseif (count($dn2_parts) > count($dn1_parts)) { + return -1; + + } else { + return 0; + } +} + +/** + * For LDAP servers with auto_number enabled, this function will get the next + * available number using the host's preferred mechanism (pool or search). + * + * This is configured in config.php by server: + * + * + * $servers->setValue('auto_number','enable',true|false); + * + * + * The available mechanisms are: + * pool: + * The pool mechanism uses a user-configured entry in the LDAP server to + * store the last used "number". This mechanism simply fetches and increments + * and returns that value. + * + * search: + * The search mechanism will search the LDAP server that has the attribute + * set. It will then find the smallest value and "fills in the gaps" by + * incrementing the smallest attribute until an unused value is found. + * + * NOTE: Both mechanisms do NOT prevent race conditions or toe-stomping, so + * care must be taken when actually creating the entry to check that the number + * returned here has not been used in the mean time. Note that the two different + * mechanisms may (will!) return different values as they use different algorithms + * to arrive at their result. Do not be alarmed if (when!) this is the case. + * + * See config.php.example for more notes on the two mechanisms. + * + * @param string Base to start the search from + * @param string Attribute to query + * @param boolean Increment the result (for pool searches) + * @param string LDAP filter to use (for pool searches) + * @return int + */ +function get_next_number($base,$attr,$increment=false,$filter=false,$startmin=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $attr = strtolower($attr); + $query = array(); + + if (! $server->getValue('auto_number','enable')) { + system_message(array( + 'title'=>_('AUTO_NUMBER is disabled for this server'), + 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, it is disabled for this server'),$attr), + 'type'=>'warn')); + + return false; + } + + # Check see and use our alternate uid_dn and password if we have it. + if (! $server->login($server->getValue('auto_number','dn'),$server->getValue('auto_number','pass'),'auto_number')) { + system_message(array( + 'title'=>_('AUTO_NUMBER invalid login/password'), + 'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the auto_number login/password, please check your configuration.'), + $server->getName()), + 'type'=>'warn')); + + return false; + } + + # Some error checking + if (! $base) { + $query['base'] = $server->getValue('auto_number','search_base'); + + if (! trim($query['base'])) { + system_message(array( + 'title'=>_('No AUTO_NUMBER search_base configured for this server'), + 'body'=>_('A call was made to get_next_number(), however, the base to search is empty.'), + 'type'=>'warn')); + + return false; + } + + } else + $query['base'] = $base; + + if (! $server->dnExists($query['base'])) { + system_message(array( + 'title'=>_('No AUTO_NUMBER search_base exists for this server'), + 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, the base to search does not exist for this server.'),$query['base']), + 'type'=>'warn')); + + return false; + } + + if (! is_string($attr) || ! $server->getSchemaAttribute($attr)) { + system_message(array( + 'title'=>_('AUTO_NUMBER search attribute invalid'), + 'body'=>sprintf('%s (%s)',_('The search attribute for AUTO_NUMBER is invalid, expecting a single valid attribute.'),$attr), + 'type'=>'warn')); + + return false; + } + + $query['attrs'] = array($attr); + + # Based on the configured mechanism, go get the next available uidNumber! + switch ($server->getValue('auto_number','mechanism')) { + case 'search': + $query['filter'] = sprintf('(%s=*)',$attr); + $search = $server->query($query,'auto_number'); + + # Construct a list of used numbers + $autonum = array(0); + + foreach ($search as $dn => $values) { + $values = array_change_key_case($values); + foreach ($values[$attr] as $value) + array_push($autonum,$value); + } + + $autonum = array_unique($autonum); + sort($autonum); + + # Start with the least existing autoNumber and add 1 + $minNumber = is_null($startmin) ? intval($autonum[0])+1 : $startmin; + + # Override our minNumber by the configuration if it exists. + if (count($server->getValue('auto_number','min'))) { + $min = array_change_key_case($server->getValue('auto_number','min')); + + if (isset($min[$attr])) + $minNumber = $min[$attr] > $minNumber ? $min[$attr] : $minNumber; + } + + for ($i=0;$i $num+1) + return $autonum[$i] >= $num ? $num+1 : $num; + } + + # If we didnt find a suitable gap and are all above the minNumber, we'll just return the $minNumber + return $minNumber; + + break; + + case 'pool': + switch ($attr) { + case 'gidnumber': + $query['filter'] = '(objectClass=gidPool)'; + + break; + + case 'uidnumber': + $query['filter'] = '(objectClass=uidPool)'; + + break; + } + + # If we are called with a filter, we'll use the one from the configuration. + if (! empty($filter)) + $query['filter'] = $filter; + + $search = $server->query($query,'auto_number'); + + switch (count($search)) { + case '1': + break; + + case '0': + system_message(array( + 'title'=>_('AUTO_NUMBER pool filter didnt return any DNs'), + 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), + 'type'=>'warn')); + + return false; + + default: + system_message(array( + 'title'=>_('AUTO_NUMBER pool filter returned too many DNs'), + 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), + 'type'=>'warn')); + + return false; + } + + # This should only iterate once. + foreach ($search as $dn => $values) { + $values = array_change_key_case($values); + + $autonum = $values[$attr][0]; + $poolDN = $values['dn']; + } + + if ($increment) { + $updatedattr = array($attr=>$autonum+1); + $server->modify($poolDN,$updatedattr); + } + + return $autonum; + + # No other cases allowed. The user has an error in the configuration + default: + system_message(array( + 'title'=>_('Invalid AUTO_NUMBER mechanism'), + 'body'=>sprintf('%s (%s)',_('Your config file specifies an unknown AUTO_NUMBER search mechanism.'),$server->getValue('auto_number','mechanism')), + 'type'=>'warn')); + + return false; + } +} + +/** + * Given a DN and server ID, this function reads the DN's objectClasses and + * determines which icon best represents the entry. The results of this query + * are cached in a session variable so it is not run every time the tree + * browser changes, just when exposing new DNs that were not displayed + * previously. That means we can afford a little bit of inefficiency here + * in favor of coolness. :) + * + * This function returns a string like "country.png". All icon files are assumed + * to be contained in the /images/ directory of phpLDAPadmin. + * + * Developers are encouraged to add new icons to the images directory and modify + * this function as needed to suit their types of LDAP entries. If the modifications + * are general to an LDAP audience, the phpLDAPadmin team will gladly accept them + * as a patch. + * + * @param string The DN of the entry whose icon you wish to fetch. + * @return string + */ +function get_icon($server_id,$dn,$object_classes=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer($server_id); + + # Fetch and lowercase all the objectClasses in an array + if (! count($object_classes)) + $object_classes = $server->getDNAttrValue($dn,'objectClass'); + + foreach ($object_classes as $index => $value) + $object_classes[$index] = strtolower($value); + + $rdn = get_rdn($dn); + $rdn_parts = explode('=',$rdn,2); + $rdn_value = isset($rdn_parts[0]) ? $rdn_parts[0] : null; + $rdn_attr = isset($rdn_parts[1]) ? $rdn_parts[1] : null; + unset($rdn_parts); + + # Return icon filename based upon objectClass value + if (in_array('sambaaccount',$object_classes) && + '$' == $rdn{ strlen($rdn) - 1 }) + return 'nt_machine.png'; + + if (in_array('sambaaccount',$object_classes)) + return 'nt_user.png'; + + elseif (in_array('person',$object_classes) || + in_array('organizationalperson',$object_classes) || + in_array('inetorgperson',$object_classes) || + in_array('account',$object_classes) || + in_array('posixaccount',$object_classes)) + + return 'ldap-user.png'; + + elseif (in_array('organization',$object_classes)) + return 'ldap-o.png'; + + elseif (in_array('organizationalunit',$object_classes)) + return 'ldap-ou.png'; + + elseif (in_array('organizationalrole',$object_classes)) + return 'ldap-uid.png'; + + elseif (in_array('dcobject',$object_classes) || + in_array('domainrelatedobject',$object_classes) || + in_array('domain',$object_classes) || + in_array('builtindomain',$object_classes)) + + return 'ldap-dc.png'; + + elseif (in_array('alias',$object_classes)) + return 'ldap-alias.png'; + + elseif (in_array('room',$object_classes)) + return 'door.png'; + + elseif (in_array('iphost',$object_classes)) + return 'host.png'; + + elseif (in_array('device',$object_classes)) + return 'device.png'; + + elseif (in_array('document',$object_classes)) + return 'document.png'; + + elseif (in_array('country',$object_classes)) { + $tmp = pla_explode_dn($dn); + $cval = explode('=',$tmp[0],2); + $cval = isset($cval[1]) ? $cval[1] : false; + if ($cval && false === strpos($cval,'..') && + file_exists(realpath(sprintf('%s/../countries/%s.png',IMGDIR,strtolower($cval))))) + + return sprintf('../countries/%s.png',strtolower($cval)); + + else + return 'country.png'; + } + + elseif (in_array('jammvirtualdomain',$object_classes)) + return 'mail.png'; + + elseif (in_array('locality',$object_classes)) + return 'locality.png'; + + elseif (in_array('posixgroup',$object_classes) || + in_array('groupofnames',$object_classes) || + in_array('group',$object_classes)) + + return 'ldap-ou.png'; + + elseif (in_array('applicationprocess',$object_classes)) + return 'process.png'; + + elseif (in_array('groupofuniquenames',$object_classes)) + return 'ldap-uniquegroup.png'; + + elseif (in_array('nlsproductcontainer',$object_classes)) + return 'n.png'; + + elseif (in_array('ndspkikeymaterial',$object_classes)) + return 'lock.png'; + + elseif (in_array('server',$object_classes)) + return 'server-small.png'; + + elseif (in_array('volume',$object_classes)) + return 'hard-drive.png'; + + elseif (in_array('ndscatcatalog',$object_classes)) + return 'catalog.png'; + + elseif (in_array('resource',$object_classes)) + return 'n.png'; + + elseif (in_array('ldapgroup',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('ldapserver',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('nisserver',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('rbscollection',$object_classes)) + return 'ldap-ou.png'; + + elseif (in_array('dfsconfiguration',$object_classes)) + return 'nt_machine.png'; + + elseif (in_array('applicationsettings',$object_classes)) + return 'server-settings.png'; + + elseif (in_array('aspenalias',$object_classes)) + return 'mail.png'; + + elseif (in_array('container',$object_classes)) + return 'folder.png'; + + elseif (in_array('ipnetwork',$object_classes)) + return 'network.png'; + + elseif (in_array('samserver',$object_classes)) + return 'server-small.png'; + + elseif (in_array('lostandfound',$object_classes)) + return 'find.png'; + + elseif (in_array('infrastructureupdate',$object_classes)) + return 'server-small.png'; + + elseif (in_array('filelinktracking',$object_classes)) + return 'files.png'; + + elseif (in_array('automountmap',$object_classes) || + in_array('automount',$object_classes)) + + return 'hard-drive.png'; + + elseif (strpos($rdn_value,'ipsec') === 0 || + strcasecmp($rdn_value,'IP Security') == 0|| + strcasecmp($rdn_value,'MSRADIUSPRIVKEY Secret') == 0 || + strpos($rdn_value,'BCKUPKEY_') === 0) + + return 'lock.png'; + + elseif (strcasecmp($rdn_value,'MicrosoftDNS') == 0) + return 'ldap-dc.png'; + + # Oh well, I don't know what it is. Use a generic icon. + else + return 'ldap-default.png'; +} + +/** + * Appends a servers base to a "sub" dn or returns the base. + * + * @param string The baseDN to be added if the DN is relative + * @param string The DN to be made absolute + * @return string|null Returns null if both base is null and sub_dn is null or empty + */ +function expand_dn_with_base($base,$sub_dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $empty_str = (is_null($sub_dn) || (($len=strlen(trim($sub_dn))) == 0)); + + if ($empty_str) + return $base; + + # If we have a string which doesn't need a base + elseif ($sub_dn[$len-1] != ',') + return $sub_dn; + + else + return sprintf('%s%s',$sub_dn,$base); +} + +/** + * Used to generate a random salt for crypt-style passwords. Salt strings are used + * to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses + * not only the user's password but also a randomly generated string. The string is + * stored as the first N characters of the hash for reference of hashing algorithms later. + * + * @param int The length of the salt string to generate. + * @return string The generated salt string. + */ +function random_salt($length) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $possible = '0123456789'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + './'; + $str = ''; + mt_srand((double)microtime() * 1000000); + + while (strlen($str) < $length) + $str .= substr($possible,(rand()%strlen($possible)),1); + + return $str; +} + +/** + * Given a DN string, this returns the 'RDN' portion of the string. + * For example. given 'cn=Manager,dc=example,dc=com', this function returns + * 'cn=Manager' (it is really the exact opposite of ds_ldap::getContainer()). + * + * @param string The DN whose RDN to return. + * @param boolean If true, include attributes in the RDN string. See http://php.net/ldap_explode_dn for details + * @return string The RDN + */ +function get_rdn($dn,$include_attrs=0,$decode=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_null($dn)) + return null; + + $rdn = pla_explode_dn($dn,$include_attrs); + if (! count($rdn) || ! isset($rdn[0])) + return $dn; + + if ($decode) + $rdn = dn_unescape($rdn[0]); + else + $rdn = $rdn[0]; + + return $rdn; +} + +/** + * Split an RDN into its attributes + */ +function rdn_explode($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Setup to work out our RDN. + $rdnarray = explode('\+',$rdn); + + # Capture items that have +, but are not an attribute + foreach ($rdnarray as $index => $val) { + if (preg_match('/=/',$val)) + $validindex = $index; + + if (! preg_match('/=/',$val)) { + $rdnarray[$validindex] .= '+'.$val; + unset($rdnarray[$index]); + } + } + + return $rdnarray; +} + +/** + * Given an LDAP error number, returns a verbose description of the error. + * This function parses ldap_error_codes.txt and looks up the specified + * ldap error number, and returns the verbose message defined in that file. + * + * + * Array ( + * [title] => "Invalid Credentials" + * [description] => "An invalid username and/or password was supplied to the LDAP server." + * ) + * + * + * @param string The hex error number (ie, "0x42") of the LDAP error of interest. + * @return array An associative array contianing the error title and description like so: + */ +function pla_verbose_error($key) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + if (! count($CACHE)) { + $source_file = LIBDIR.'ldap_error_codes.txt'; + + if (! file_exists($source_file) || ! is_readable($source_file) || ! ($f = fopen($source_file,'r'))) + return false; + + $contents = fread($f,filesize($source_file)); + fclose($f); + $entries = array(); + preg_match_all("/0x[A-Fa-f0-9][A-Za-z0-9]\s+[0-9A-Za-z_]+\s+\"[^\"]*\"\n/", + $contents,$entries); + + foreach ($entries[0] as $values) { + $entry = array(); + preg_match("/(0x[A-Za-z0-9][A-Za-z0-9])\s+([0-9A-Za-z_]+)\s+\"([^\"]*)\"/",$values,$entry); + + $hex_code = isset($entry[1]) ? $entry[1] : null; + $title = isset($entry[2]) ? $entry[2] : null; + $desc = isset($entry[3]) ? $entry[3] : null; + $desc = preg_replace('/\s+/',' ',$desc); + $CACHE[$hex_code] = array('title'=>$title,'desc'=>$desc); + } + } + + if (isset($CACHE[$key])) + return $CACHE[$key]; + else + return array('title' => null,'desc' => null); +} + +/** + * Given an LDAP OID number, returns a verbose description of the OID. + * This function parses ldap_supported_oids.txt and looks up the specified + * OID, and returns the verbose message defined in that file. + * + * + * Array ( + * [title] => All Operational Attribute + * [ref] => RFC 3673 + * [desc] => An LDAP extension which clients may use to request the return of all operational attributes. + * ) + * + * + * @param string The OID number (ie, "1.3.6.1.4.1.4203.1.5.1") of the OID of interest. + * @return array An associative array contianing the OID title and description like so: + */ +function support_oid_to_text($key) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + $unknown = array(); + $unknown['desc'] = 'We have no description for this OID, if you know what this OID provides, please let us know. Please also include an RFC reference if it is available.'; + $unknown['title'] = 'Can you help with this OID info?'; + + if (! count($CACHE)) { + $source_file = LIBDIR.'ldap_supported_oids.txt'; + + if (! file_exists($source_file) || ! is_readable($source_file) || ! ($f = fopen($source_file,'r'))) + return false; + + $contents = fread($f,filesize($source_file)); + fclose($f); + $entries = array(); + preg_match_all("/[0-9]\..+\s+\"[^\"]*\"\n/",$contents,$entries); + + foreach ($entries[0] as $values) { + $entry = array(); + preg_match("/([0-9]\.([0-9]+\.)*[0-9]+)(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?/",$values,$entry); + $oid_id = isset($entry[1]) ? $entry[1] : null; + + if ($oid_id) { + $CACHE[$oid_id]['title'] = isset($entry[4]) ? $entry[4] : null; + $CACHE[$oid_id]['ref'] = isset($entry[6]) ? $entry[6] : null; + $desc = isset($entry[8]) ? $entry[8] : sprintf('%s',$unknown['desc'],$unknown['title']); + $CACHE[$oid_id]['desc'] = preg_replace('/\s+/',' ',$desc); + } + } + } + + if (isset($CACHE[$key])) + return $CACHE[$key]; + else + return array( + 'title'=>$key, + 'ref'=>null, + 'desc'=>sprintf('%s',$unknown['desc'],$unknown['title'])); +} + +/** + * Print an LDAP error message + */ +function ldap_error_msg($msg,$errnum) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $body = ''; + + $errnum = ('0x'.str_pad(dechex($errnum),2,0,STR_PAD_LEFT)); + $verbose_error = pla_verbose_error($errnum); + + $body .= sprintf('',_('LDAP said'),$msg); + + if ($verbose_error) { + $body .= sprintf('',_('Error number'),$errnum,$verbose_error['title']); + $body .= sprintf('',_('Description'),$verbose_error['desc']); + + } else { + $body .= sprintf('',_('Error number'),$errnum); + $body .= sprintf('',_('Description'),_('no description available')); + } + + $body .= '
%s:%s
%s:%s (%s)
%s:%s
%s:%s
%s:(%s)
'; + + return $body; +} + +/** + * Draw the jpegPhoto image(s) for an entry wrapped in HTML. Many options are available to + * specify how the images are to be displayed. + * + * Usage Examples: + * + * draw_jpeg_photo(0,'cn=Bob,ou=People,dc=example,dc=com',"jpegPhoto",0,true,array('img_opts'=>"border: 1px; width: 150px")); + * draw_jpeg_photo(1,'cn=Fred,ou=People,dc=example,dc=com',null,1); + * + * + * @param object The Server to get the image from. + * @param string The DN of the entry that contains the jpeg attribute you want to draw. + * @param string The name of the attribute containing the jpeg data (usually 'jpegPhoto'). + * @param int Index of the attribute to draw + * @param boolean If true, draws a button beneath the image titled 'Delete' allowing the user + * to delete the jpeg attribute by calling JavaScript function deleteAttribute() provided + * in the default modification template. + * @param array Specifies optional image and CSS style attributes for the table tag. Supported keys are + * fixed_width, fixed_height, img_opts. + */ +function draw_jpeg_photo($server,$dn,$attr_name='jpegphoto',$index,$draw_delete_buttons=false,$options=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $fixed = array(); + $fixed['width'] = isset($options['fixed_width']) ? $options['fixed_width'] : false; + $fixed['height'] = isset($options['fixed_height']) ? $options['fixed_height'] : false; + + if (is_null($server)) + $jpeg_data = $_SESSION['tmp']; + else + $jpeg_data = $server->getDNAttrValues($dn,null,LDAP_DEREF_NEVER,array($attr_name)); + + if (! isset($jpeg_data[$attr_name][$index]) || ! $jpeg_data[$attr_name][$index]) { + system_message(array( + 'title'=>_('Unable to retrieve image'), + 'body'=>sprintf('%s %s', + _('Could not fetch jpeg data for attribute'),$attr_name), + 'type'=>'warn')); + + # This should atleast generate some text that says "Image not available" + printf('Photo',$attr_name); + + return; + } + + $width = 0; + $height = 0; + + if (function_exists('getimagesize')) { + $jpeg_temp_dir = realpath($_SESSION[APPCONFIG]->getValue('jpeg','tmpdir').'/'); + if (! is_writable($jpeg_temp_dir)) + system_message(array( + 'title'=>_('Unable to write to jpeg tmp directory'), + 'body'=>_('Please set jpeg,tmpdir to a writable directory in the phpLDAPadmin config.php'), + 'type'=>'warn')); + + else { + # We have an image to display + $jpeg_filename = tempnam($jpeg_temp_dir.'/','pla'); + $outjpeg = @file_put_contents($jpeg_filename,$jpeg_data[$attr_name][$index]); + + if (! $outjpeg) { + system_message(array( + 'title'=>_('Error writing to jpeg tmp directory'), + 'body'=>sprintf(_('Please check jpeg,tmpdir is a writable directory in the phpLDAPadmin config.php'),$jpeg_temp_dir), + 'type'=>'warn')); + + } elseif ($outjpeg < 6) { + system_message(array( + 'title'=>sprintf('%s %s',$attr_name,_('contains errors')), + 'body'=>_('It appears that the jpeg image may not be a jpeg image'), + 'type'=>'warn')); + + } else { + $jpeg_dimensions = getimagesize($jpeg_filename); + $width = $jpeg_dimensions[0]; + $height = $jpeg_dimensions[1]; + } + + unlink($jpeg_filename); + } + } + + if ($width > 300) { + $scale_factor = 300 / $width; + $img_width = 300; + $img_height = intval($height * $scale_factor); + + } else { + $img_width = $width; + $img_height = $height; + } + + $href = sprintf('view_jpeg_photo.php?dn=%s&index=%s&attr=%s',rawurlencode($dn),$index,$attr_name); + + printf('',number_format($outjpeg),_('bytes'),$width,$height,_('pixels')); + + printf('Photo', + htmlspecialchars($href), + is_null($server) ? 'location=session' : sprintf('server_id=%s',$server->getIndex()), + (! $img_width || $fixed['width'] ? '' : sprintf('width="%s"',$img_width)), + (! $img_height || $fixed['height'] ? '' : sprintf('height="%s"',$img_height)), + (isset($options['img_opts']) ? $options['img_opts'] : '')); + + echo ''; + + if ($draw_delete_buttons) + # + printf('
%s', + $attr_name,_('Delete photo')); +} + +/** + * Return the list of available password types + * + * @todo Dynamically work this list out so we only present hashes that we can encrypt + */ +function password_types() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array( + ''=>'clear', + 'blowfish'=>'blowfish', + 'crypt'=>'crypt', + 'ext_des'=>'ext_des', + 'md5'=>'md5', + 'k5key'=>'k5key', + 'md5crypt'=>'md5crypt', + 'sha'=>'sha', + 'smd5'=>'smd5', + 'ssha'=>'ssha', + 'sha512'=>'sha512', + ); +} + +/** + * Hashes a password and returns the hash based on the specified enc_type. + * + * @param string The password to hash in clear text. + * @param string Standard LDAP encryption type which must be one of + * crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, sha512, or clear. + * @return string The hashed password. + */ +function hash_password($password_clear,$enc_type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $enc_type = strtolower($enc_type); + + switch($enc_type) { + case 'blowfish': + if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0) + error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php'); + + # Hardcoded to second blowfish version and set number of rounds + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$2a$12$'.random_salt(13))); + + break; + + case 'crypt': + if ($_SESSION[APPCONFIG]->getValue('password', 'no_random_crypt_salt')) + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,substr($password_clear,0,2))); + else + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,random_salt(2))); + + break; + + case 'ext_des': + # Extended des crypt. see OpenBSD crypt man page. + if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0) + error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php'); + + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'_'.random_salt(8))); + + break; + + case 'k5key': + $new_value = sprintf('{K5KEY}%s',$password_clear); + + system_message(array( + 'title'=>_('Unable to Encrypt Password'), + 'body'=>'phpLDAPadmin cannot encrypt K5KEY passwords', + 'type'=>'warn')); + + break; + + case 'md5': + $new_value = sprintf('{MD5}%s',base64_encode(pack('H*',md5($password_clear)))); + break; + + case 'md5crypt': + if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0) + error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php'); + + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$1$'.random_salt(9))); + + break; + + case 'sha': + # Use php 4.3.0+ sha1 function, if it is available. + if (function_exists('sha1')) + $new_value = sprintf('{SHA}%s',base64_encode(pack('H*',sha1($password_clear)))); + elseif (function_exists('mhash')) + $new_value = sprintf('{SHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear))); + else + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + + break; + + case 'ssha': + if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { + mt_srand((double)microtime()*1000000); + $salt = mhash_keygen_s2k(MHASH_SHA1,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4); + $new_value = sprintf('{SSHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear.$salt).$salt)); + + } else { + error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php'); + } + + break; + + case 'smd5': + if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { + mt_srand((double)microtime()*1000000); + $salt = mhash_keygen_s2k(MHASH_MD5,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4); + $new_value = sprintf('{SMD5}%s',base64_encode(mhash(MHASH_MD5,$password_clear.$salt).$salt)); + + } else { + error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php'); + } + + break; + + case 'sha512': + if (function_exists('openssl_digest') && function_exists('base64_encode')) { + $new_value = sprintf('{SHA512}%s', base64_encode(openssl_digest($password_clear, 'sha512', true))); + + } else { + error(_('Your PHP install doest not have the openssl_digest() or base64_encode() function. Cannot do SHA512 hashes. '),'error','index.php'); + } + + break; + + case 'clear': + default: + $new_value = $password_clear; + } + + return $new_value; +} + +/** + * Given a clear-text password and a hash, this function determines if the clear-text password + * is the password that was used to generate the hash. This is handy to verify a user's password + * when all that is given is the hash and a "guess". + * @param String The hash. + * @param String The password in clear text to test. + * @return Boolean True if the clear password matches the hash, and false otherwise. + */ +function password_check($cryptedpassword,$plainpassword,$attribute='userpassword') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array($attribute,array('sambalmpassword','sambantpassword'))) { + $smb = new smbHash; + + switch($attribute) { + case 'sambalmpassword': + if (strcmp($smb->lmhash($plainpassword),strtoupper($cryptedpassword)) == 0) + return true; + else + return false; + + case 'sambantpassword': + if (strcmp($smb->nthash($plainpassword),strtoupper($cryptedpassword)) == 0) + return true; + else + return false; + } + + return false; + } + + if (preg_match('/{([^}]+)}(.*)/',$cryptedpassword,$matches)) { + $cryptedpassword = $matches[2]; + $cypher = strtolower($matches[1]); + + } else { + $cypher = null; + } + + switch($cypher) { + # SSHA crypted passwords + case 'ssha': + # Check php mhash support before using it + if (function_exists('mhash')) { + $hash = base64_decode($cryptedpassword); + + # OpenLDAP uses a 4 byte salt, SunDS uses an 8 byte salt - both from char 20. + $salt = substr($hash,20); + $new_hash = base64_encode(mhash(MHASH_SHA1,$plainpassword.$salt).$salt); + + if (strcmp($cryptedpassword,$new_hash) == 0) + return true; + else + return false; + + } else { + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + } + + break; + + # Salted MD5 + case 'smd5': + # Check php mhash support before using it + if (function_exists('mhash')) { + $hash = base64_decode($cryptedpassword); + $salt = substr($hash,16); + $new_hash = base64_encode(mhash(MHASH_MD5,$plainpassword.$salt).$salt); + + if (strcmp($cryptedpassword,$new_hash) == 0) + return true; + else + return false; + + } else { + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + } + + break; + + # SHA crypted passwords + case 'sha': + if (strcasecmp(password_hash($plainpassword,'sha'),'{SHA}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # MD5 crypted passwords + case 'md5': + if( strcasecmp(password_hash($plainpassword,'md5'),'{MD5}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # Crypt passwords + case 'crypt': + # Check if it's blowfish crypt + if (preg_match('/^\\$2+/',$cryptedpassword)) { + + # Make sure that web server supports blowfish crypt + if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0) + error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php'); + + list($version,$rounds,$salt_hash) = explode('$',$cryptedpassword); + + if (crypt($plainpassword,'$'.$version.'$'.$rounds.'$'.$salt_hash) == $cryptedpassword) + return true; + else + return false; + } + + # Check if it's an crypted md5 + elseif (strstr($cryptedpassword,'$1$')) { + + # Make sure that web server supports md5 crypt + if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0) + error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php'); + + list($dummy,$type,$salt,$hash) = explode('$',$cryptedpassword); + + if (crypt($plainpassword,'$1$'.$salt) == $cryptedpassword) + return true; + else + return false; + } + + # Check if it's extended des crypt + elseif (strstr($cryptedpassword,'_')) { + + # Make sure that web server supports ext_des + if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0) + error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php'); + + if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword) + return true; + else + return false; + } + + # Password is plain crypt + else { + + if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword) + return true; + else + return false; + } + + break; + + # SHA512 crypted passwords + case 'sha512': + if (strcasecmp(password_hash($plainpassword,'sha512'),'{SHA512}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # No crypt is given assume plaintext passwords are used + default: + if ($plainpassword == $cryptedpassword) + return true; + else + return false; + } +} + +/** + * Detects password encryption type + * + * Returns crypto string listed in braces. If it is 'crypt' password, + * returns crypto detected in password hash. Function should detect + * md5crypt, blowfish and extended DES crypt. If function fails to detect + * encryption type, it returns NULL. + * @param string Hashed password + * @return string + */ +function get_enc_type($user_password) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Capture the stuff in the { } to determine if this is crypt, md5, etc. + $enc_type = null; + + if (preg_match('/{([^}]+)}/',$user_password,$enc_type)) + $enc_type = strtolower($enc_type[1]); + else + return null; + + # Handle crypt types + if (strcasecmp($enc_type,'crypt') == 0) { + + # No need to check for standard crypt, because enc_type is already equal to 'crypt'. + if (preg_match('/{[^}]+}\\$1\\$+/',$user_password)) + $enc_type = 'md5crypt'; + + elseif (preg_match('/{[^}]+}\\$2+/',$user_password)) + $enc_type = 'blowfish'; + + elseif (preg_match('/{[^}]+}_+/',$user_password)) + $enc_type = 'ext_des'; + } + + return $enc_type; +} + +/** + * Draws an HTML browse button which, when clicked, pops up a DN chooser dialog. + * @param string The name of the form element to which this chooser + * dialog will publish the user's choice. The form element must be a member + * of a form with the "name" or "id" attribute set in the form tag, and the element + * must also define "name" or "id" for JavaScript to uniquely identify it. + * Example $form_element values may include "creation_form.container" or + * "edit_form.member_uid". See /templates/modification/default.php for example usage. + * @param boolean (optional) If true, the function draws the localized text "choose" to the right of the button. + */ +function draw_chooser_link($form,$element,$include_choose_text=true,$rdn='none') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $href = sprintf("javascript:dnChooserPopup('%s','%s','%s');",$form,$element,$rdn == 'none' ? '' : rawurlencode($rdn)); + $title = _('Click to popup a dialog to select an entry (DN) graphically'); + + printf('Find',$href,$title,IMGDIR); + + if ($include_choose_text) + printf('%s',$href,$title,_('browse')); +} + +/** + * Explode a DN into an array of its RDN parts. + * + * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value'; + * + * + * Array ( + * [0] => uid=ppratt + * [1] => ou=People + * [2] => dc=example + * [3] => dc=com + * ) + * + * + * @param string The DN to explode. + * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details) + * @return array An array of RDN parts of this format: + */ +function pla_explode_dn($dn,$with_attributes=0) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + global $CACHE; + + if (isset($CACHE['explode'][$dn][$with_attributes])) { + if (DEBUG_ENABLED) + debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__, + $CACHE['explode'][$dn][$with_attributes],$dn); + + return $CACHE['explode'][$dn][$with_attributes]; + } + + $dn = addcslashes($dn,'<>+";'); + + # split the dn + $result[0] = ldap_explode_dn(dn_escape($dn),0); + $result[1] = ldap_explode_dn(dn_escape($dn),1); + if (! $result[$with_attributes]) { + if (DEBUG_ENABLED) + debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__); + + return array(); + } + + # Remove our count value that ldap_explode_dn returns us. + unset($result[0]['count']); + unset($result[1]['count']); + + # Record the forward and reverse entries in the cache. + foreach ($result as $key => $value) { + # translate hex code into ascii for display + $result[$key] = dn_unescape($value); + + $CACHE['explode'][implode(',',$result[0])][$key] = $result[$key]; + $CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]); + + return $result[$with_attributes]; +} + +/** + * Parse a DN and escape any special characters + */ +function dn_escape($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $olddn = $dn; + + # Check if the RDN has a comma and escape it. + while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn)) + $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn); + + $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$dn); + + return $dn; +} + +/** + * Parse a DN and unescape any special characters + */ +function dn_unescape($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $unescape = function ($input) { + return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($match) { + return "'" . chr(hexdec($match[1])) . "'"; + }, $input); + }; + + if (is_array($dn)) { + $a = array(); + + foreach ($dn as $key => $rdn) + $a[$key] = $unescape($rdn); + // $a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn); + + return $a; + + } else { + return $unescape($dn); + // return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn); + } +} + +/** + * Fetches the URL for the specified item. This is a convenience function for + * fetching project HREFs (like bugs) + * + * @param string One of "open_bugs", "add_bug", "donate", or "add_rfe" + * (rfe = request for enhancement) + * @return string The URL to the requested item. + */ +function get_href($type,$extra_info='') { + $sf = 'https://sourceforge.net'; + $pla = 'http://phpldapadmin.sourceforge.net'; + $group_id = '61828'; + $bug_atid = '498546'; + $rfe_atid = '498549'; + $forum_id = 'phpldapadmin-users'; + + switch($type) { + case 'add_bug': + return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$bug_atid); + case 'add_rfe': + return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$rfe_atid); + case 'credits': + return sprintf('%s/Credits',$pla); + case 'documentation': + return sprintf('%s/Documentation',$pla); + case 'donate': + return sprintf('%s/donate/index.php?group_id=%s',$sf,$group_id); + case 'forum': + return sprintf('%s/mailarchive/forum.php?forum_name=%s',$sf,$forum_id); + case 'logo': + if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') + $proto = 'http'; + else + $proto = 'https'; + + return isset($_SESSION) && ! $_SESSION[APPCONFIG]->getValue('appearance','remoteurls') ? '' : sprintf('%s://sflogo.sourceforge.net/sflogo.php?group_id=%s&type=10',$proto,$group_id); + case 'sf': + return sprintf('%s/projects/phpldapadmin',$sf); + case 'web': + return sprintf('%s',$pla); + default: + return null; + } +} + +/** + * Returns the current time as a double (including micro-seconds). + * + * @return double The current time in seconds since the beginning of the UNIX epoch (Midnight Jan. 1, 1970) + */ +function utime() { + $time = explode(' ',microtime()); + $usec = (double)$time[0]; + $sec = (double)$time[1]; + return $sec + $usec; +} + +/** + * Converts an array to a query-string with the option to exclude certain variables + * from the returned query string. This is convenient if callers want to convert the + * current GET query string or POST array into a string and replace certain + * variables with their own. + * + * @param array The associate array to convert whose form is such that the keys are the + * names of the variables and the values are said variables' values like this: + * + * Array ( + * [server_id] = 0, + * [dn] = "dc=example,dc=com", + * [attr] = "sn" + * ) + * + * This will produce a string like this: "server_id=0&dn=dc=example,dc=com&attr=sn" + * @param array (optional) An array of variables to exclude in the resulting string + * @return string The string created from the array. + */ +function array_to_query_string($array,$exclude_vars=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($array) || ! count($array)) + return ''; + + $str = ''; + $i = 0; + foreach ($array as $name => $val) + if (! in_array($name,$exclude_vars)) + if (is_array($val)) + foreach ($val as $v) { + if ($i++ > 0) + $str .= '&'; + + $str .= sprintf('%s[]=%s',rawurlencode($name),rawurlencode($v)); + } + + else { + if ($i++ > 0) + $str .= '&'; + + $str .= sprintf('%s=%s',rawurlencode($name),rawurlencode($val)); + } + + return $str; +} + +/** + * Reverses a DN such that the top-level RDN is first and the bottom-level RDN is last + * For example: + * + * cn=Brigham,ou=People,dc=example,dc=com + * + * Becomes: + * + * dc=com,dc=example,ou=People,cn=Brigham + * + * This makes it possible to sort lists of DNs such that they are grouped by container. + * + * @param string The DN to reverse + * @return string The reversed DN + * + * @see pla_compare_dns + * @see pla_explode_dns + */ +function pla_reverse_dn($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return (implode(',',array_reverse(pla_explode_dn($dn)))); +} + +/** + * Attribute sorting + */ +function sortAttrs($a,$b) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($a == $b) + return 0; + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $attrs_display_order = arrayLower($_SESSION[APPCONFIG]->getValue('appearance','attr_display_order')); + + # Check if $a is in $attrs_display_order, get its key + $a_key = array_search($a->getName(),$attrs_display_order); + $b_key = array_search($b->getName(),$attrs_display_order); + + if ((! $a_key) && ($a_key !== 0)) + if ((! $a_key = array_search(strtolower($a->getFriendlyName()),$attrs_display_order)) && ($a_key !== 0)) + $a_key = count($attrs_display_order)+1; + + if ((! $b_key) && ($b_key !== 0)) + if ((! $b_key = array_search(strtolower($b->getFriendlyName()),$attrs_display_order)) && ($b_key !== 0)) + $b_key = count($attrs_display_order)+1; + + # Case where neither $a, nor $b are in $attrs_display_order, $a_key = $b_key = one greater than num elements. + # So we sort them alphabetically + if ($a_key === $b_key) + return strcasecmp($a->getFriendlyName(),$b->getFriendlyName()); + + # Case where at least one attribute or its friendly name is in $attrs_display_order + # return -1 if $a before $b in $attrs_display_order + return ($a_key < $b_key) ? -1 : 1; +} + +/** + * Reads an array and returns the array values back in lower case + * + * @param array $array The array to convert the values to lowercase. + * @returns array Array with values converted to lowercase. + */ +function arrayLower($array) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($array)) + return $array; + + $newarray = array(); + foreach ($array as $key => $value) + $newarray[$key] = strtolower($value); + + return $newarray; +} + +/** + * Checks if a string exists in an array, ignoring case. + * + * @param string What you are looking for + * @param array The array that you think it is in. + * @return boolean True if its there, false if its not. + */ +function in_array_ignore_case($needle,$haystack) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($haystack)) + return false; + + if (! is_string($needle)) + return false; + + $return = false; + + foreach ($haystack as $element) { + if (is_string($element) && (strcasecmp($needle,$element) == 0)) { + $return = true; + break; + } + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Gets a DN string using the user-configured tree_display_format string to format it. + */ +function draw_formatted_dn($server,$entry) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn = $entry->getDn(); + + $formats = $_SESSION[APPCONFIG]->getValue('appearance','tree_display_format'); + + foreach ($formats as $format) { + $has_none = false; + preg_match_all('/%[a-zA-Z_0-9]+/',$format,$tokens); + $tokens = $tokens[0]; + + if (DEBUG_ENABLED) + debug_log('The tokens are (%s)',1,0,__FILE__,__LINE__,__METHOD__,$tokens); + + foreach ($tokens as $token) { + if (strcasecmp($token,'%dn') == 0) + $format = str_replace($token,pretty_print_dn($dn),$format); + + elseif (strcasecmp($token,'%rdn') == 0) + $format = str_replace($token,pretty_print_dn($entry->getRDN()),$format); + + elseif (strcasecmp($token,'%rdnvalue') == 0) { + $rdn = get_rdn($dn,0,true); + $rdn_value = explode('=',$rdn,2); + $rdn_value = $rdn_value[1]; + $format = str_replace($token,$rdn_value,$format); + + } else { + $attr_name = str_replace('%','',$token); + $attr_values = $server->getDNAttrValue($dn,$attr_name); + + if (is_null($attr_values) || (count($attr_values) <= 0)) { + $display = '<'._('none').'>'; + $has_none = true; + + } elseif (is_array($attr_values)) + $display = implode(', ',$attr_values); + + else + $display = $attr_values; + + $format = str_replace($token,$display,$format); + } + } + + # If this format has all values available, use it. Otherwise, try the next one + if (!$has_none) + return $format; + } + + return $format; +} + +/** + * Server html select list + */ +function server_select_list($selected=null,$logged_on=false,$name='index',$isVisible=true,$js=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $count = 0; + $server_menu_html = sprintf(''; + + if ($count > 1) + return $server_menu_html; + + elseif ($count) + return sprintf('%s ', + $selected_server->getName(),$name,$selected_server->getIndex()); + + else + return ''; +} + +/** + * Converts a little-endian hex-number to one, that 'hexdec' can convert + */ +function littleEndian($hex) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = ''; + + for ($x=strlen($hex)-2;$x>= 0;$x=$x-2) + $result .= substr($hex,$x,2); + + return $result; +} + +function binSIDtoText($binsid) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $hex_sid = bin2hex($binsid); + $rev = hexdec(substr($hex_sid,0,2)); // Get revision-part of SID + $subcount = hexdec(substr($hex_sid,2,2)); // Get count of sub-auth entries + $auth = hexdec(substr($hex_sid,4,12)); // SECURITY_NT_AUTHORITY + + $result = "$rev-$auth"; + + for ($x=0;$x<$subcount;$x++) { + $subauth[$x] = hexdec(littleEndian(substr($hex_sid,16+($x*8),8))); // get all SECURITY_NT_AUTHORITY + $result .= sprintf('-%s',$subauth[$x]); + } + + return $result; +} + +/** + * Query LDAP and return a hash. + * + * @param string The base DN to use. + * @param string LDAP Query filter. + * @param string LDAP attribute to use as key. + * @param array Attributes to use as values. + * @param boolean Specify false to not sort results by DN + * or true to have the returned array sorted by DN (uses ksort) + * or an array of attribute names to sort by attribute values + * @return array Array of values keyed by $key. + */ +function return_ldap_hash($base,$filter,$key,$attrs,$sort=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $key = strtolower($key); + + $query = array(); + $query['base'] = $base; + $query['filter'] = $filter; + $query['attrs'] = $attrs; + $search = $server->query($query,null); + + $results = array(); + + foreach ($search as $dn => $values) + if (isset($values[$key])) + if (is_array($values[$key])) + foreach ($values[$key] as $i => $k) + foreach ($attrs as $attr) { + $lattr = strtolower($attr); + if (isset($values[$lattr])) { + $v = ''; + + if (is_array($values[$lattr]) && isset($values[$lattr][$i])) + $v = $values[$lattr][$i]; + + if (is_string($v) && (strlen($v) > 0)) + $results[$k][$attr] = $v; + } + } + + else + foreach ($attrs as $attr) { + $lattr = strtolower($attr); + if (isset($values[$lattr])) + $results[$values[$key]][$attr] = $values[$lattr]; + } + + if ($sort) + masort($results,is_array($sort) ? implode(',',$sort) : 'dn'); + + return $results; +} + +/** + * This function returns a string automatically generated + * based on the criteria defined in the array $criteria in config.php + */ +function password_generate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $no_use_similiar = ! $_SESSION[APPCONFIG]->getValue('password','use_similar'); + $lowercase = $_SESSION[APPCONFIG]->getValue('password','lowercase'); + $uppercase = $_SESSION[APPCONFIG]->getValue('password','uppercase'); + $digits = $_SESSION[APPCONFIG]->getValue('password','numbers'); + $punctuation = $_SESSION[APPCONFIG]->getValue('password','punctuation'); + $length = $_SESSION[APPCONFIG]->getValue('password','length'); + + $outarray = array(); + + if ($no_use_similiar) { + $raw_lower = 'a b c d e f g h k m n p q r s t u v w x y z'; + $raw_numbers = '2 3 4 5 6 7 8 9'; + $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } :'; + + } else { + $raw_lower = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'; + $raw_numbers = '1 2 3 4 5 6 7 8 9 0'; + $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } : |'; + } + + $llower = explode(' ',$raw_lower); + shuffle($llower); + $lupper = explode(' ',strtoupper($raw_lower)); + shuffle($lupper); + $numbers = explode(' ',$raw_numbers); + shuffle($numbers); + $punc = explode(' ',$raw_punc); + shuffle($punc); + + if ($lowercase > 0) + $outarray = array_merge($outarray,a_array_rand($llower,$lowercase)); + + if ($uppercase > 0) + $outarray = array_merge($outarray,a_array_rand($lupper,$uppercase)); + + if ($digits > 0) + $outarray = array_merge($outarray,a_array_rand($numbers,$digits)); + + if ($punctuation > 0) + $outarray = array_merge($outarray,a_array_rand($punc,$punctuation)); + + $num_spec = $lowercase + $uppercase + $digits + $punctuation; + + if ($num_spec < $length) { + $leftover = array(); + if ($lowercase > 0) + $leftover = array_merge($leftover,$llower); + if ($uppercase > 0) + $leftover = array_merge($leftover,$lupper); + if ($digits > 0) + $leftover = array_merge($leftover,$numbers); + if ($punctuation > 0) + $leftover = array_merge($leftover,$punc); + + if (count($leftover) == 0) + $leftover = array_merge($leftover,$llower,$lupper,$numbers,$punc); + + shuffle($leftover); + $outarray = array_merge($outarray,a_array_rand($leftover,$length-$num_spec)); + } + + shuffle($outarray); + $return = implode('',$outarray); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * This function returns an array of $num_req values + * randomly picked from the $input array + * + * @param array Array of values + * @param integer Number of values in returned array + * @return string The padded string + */ +function a_array_rand($input,$num_req) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (count($input) == 0) + return array(); + + if ($num_req < 1) + return array(); + + $return = array(); + if ($num_req > count($input)) { + for($i = 0; $i < $num_req; $i++) { + $idx = array_rand($input,1); + $return[] = $input[$idx]; + } + + } else { + $idxlist = array_rand($input,$num_req); + if ($num_req == 1) + $idxlist = array($idxlist); + + for($i = 0; $i < count($idxlist); $i++) + $return[] = $input[$idxlist[$i]]; + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * This is for Opera. By putting "random junk" in the query string, it thinks + * that it does not have a cached version of the page, and will thus + * fetch the page rather than display the cached version + */ +function random_junk() { + $time = gettimeofday(); + return md5(strtotime('now').$time['usec']); +} + +/** + * Returns a HTML id that can be used in the URL after the #. + * + * @param string The DN to pretty-print. + * @return string + */ +function htmlid($sid,$dn) { + return sprintf('SID%s:%s',$sid,preg_replace('/[\ =,]/','_',$dn)); +} + +/** + * Is PLA configured for AJAX display + */ +function isAjaxEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($_SESSION[APPCONFIG])) + return ($_SESSION[APPCONFIG]->getValue('appearance','tree') == 'AJAXTree'); + else + return false; +} +?> diff --git a/lib/hooks.php b/lib/hooks.php new file mode 100644 index 0000000..57066ed --- /dev/null +++ b/lib/hooks.php @@ -0,0 +1,201 @@ + and AlcÃ?ve + * @package phpLDAPadmin + */ + +/** + * Compares two arrays by numerically comparing their 'prority' + * value. Standard `cmp-like' function. + * + * @param a First element to compare. + * @param b Second element to compare. + * + * @return -1 if priority of first element is smaller than second + * element priority. 1 otherwise. + */ +function sort_array_by_priority($a,$b) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return (($a['priority'] < $b['priority']) ? -1 : 1 ); +} + +/** + * Runs procedures attached to a hook. + * + * @param hook_name Name of hook to run. + * @param args Array of optional arguments set by phpldapadmin. It is normally in a form known by call_user_func_array() : + * + *
[ 'server_id' => 0,
+ * 'dn' => 'uid=epoussa,ou=tech,o=corp,o=fr' ]
+ * + * @return true if all procedures returned true, false otherwise. + */ +function run_hook($hook_name,$args) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $hooks = isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->hooks : array(); + + if (! count($hooks) || ! array_key_exists($hook_name,$hooks)) { + if (DEBUG_ENABLED) + debug_log('Returning, HOOK not defined (%s)',257,0,__FILE__,__LINE__,__METHOD__,$hook_name); + + return true; + } + + $rollbacks = array(); + reset($hooks[$hook_name]); + + /* Execution of procedures attached is done using a numeric order + * since all procedures have been attached to the hook with a + * numerical weight. */ + while (list($key,$hook) = each($hooks[$hook_name])) { + if (DEBUG_ENABLED) + debug_log('Calling HOOK Function (%s)(%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function'],$args); + + array_push($rollbacks,$hook['rollback_function']); + + $result = call_user_func_array($hook['hook_function'],$args); + if (DEBUG_ENABLED) + debug_log('Called HOOK Function (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function']); + + /* If a procedure fails (identified by a false return), its optional rollback is executed with + * the same arguments. After that, all rollbacks from + * previously executed procedures are executed in the reverse + * order. */ + if (! is_null($result) && $result == false) { + if (DEBUG_ENABLED) + debug_log('HOOK Function [%s] return (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function'],$result); + + while ($rollbacks) { + $rollback = array_pop($rollbacks); + + if ($rollback != false) { + if (DEBUG_ENABLED) + debug_log('HOOK Function Rollback (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $rollback); + + call_user_func_array($rollback,$args); + } + } + + return false; + } + } + + return true; +} + +/** + * Adds a procedure to a hook for later execution. + * + * @param hook_name Name of the hook. + * @param hook_function Name of the php function called upon hook trigger. + * @param priority Numeric priority. Lowest means procedure will be executed before. + * @param rollback_function Name of the php rollback function called upon failure. + */ +function add_hook($hook_name,$hook_function,$priority=0,$rollback_function=null) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # First, see if the hook function exists. + if (! function_exists($hook_function)) { + system_message(array( + 'title'=>_('Hook function does not exist'), + 'body'=>sprintf('Hook name: %s
Hook function: %s',$hook_name,$hook_function), + 'type'=>'warn')); + + return; + } + + if (! array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) + $_SESSION[APPCONFIG]->hooks[$hook_name] = array(); + + remove_hook($hook_name,$hook_function,-1,null); + + array_push($_SESSION[APPCONFIG]->hooks[$hook_name],array( + 'priority' => $priority, + 'hook_function' => $hook_function, + 'rollback_function' => $rollback_function)); + + uasort($_SESSION[APPCONFIG]->hooks[$hook_name],'sort_array_by_priority'); +} + +/** + * Removes a procedure from a hook, based on a filter. + * + * @param hook_name Name of the hook. + * @param priority Numeric priority. If set, all procedures of that priority will be removed. + * @param hook_function Name of the procedure function. If set, all procedures that call this function will be removed. + * @param rollback_function Name of the php rollback function called upon failure. If set, all + * procedures that call this function as a rollback will be removed. + */ +function remove_hook($hook_name,$hook_function,$priority,$rollback_function) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) { + reset($_SESSION[APPCONFIG]->hooks[$hook_name]); + + while (list($key,$hook) = each($_SESSION[APPCONFIG]->hooks[$hook_name])) { + if (($priority >= 0 && $priority == $hook['priority']) || + ($hook_function && $hook_function == $hook['hook_function']) || + ($rollback_function && $rollback_function == $hook['rollback_function'])) { + + unset($_SESSION[APPCONFIG]->hooks[$hook_name][$key]); + } + } + } +} + +/** + * Removes all procedures from a hook. + * + * @param hook_name Name of hook to clear. + */ +function clear_hooks($hook_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) + unset($_SESSION[APPCONFIG]->hooks[$hook_name]); +} + +$hooks = array(); + +# Evaluating user-made hooks +if (is_dir(HOOKSDIR.'functions')) { + $hooks['dir'] = dir(HOOKSDIR.'functions'); + + while ($hooks['file'] = $hooks['dir']->read()) { + $script = sprintf('%s/%s/%s',HOOKSDIR,'functions',$hooks['file']); + + if (is_file($script) && preg_match('/php[0-9]?$/',$hooks['file'])) + require_once $script; + } + + $hooks['dir']->close(); +} +?> diff --git a/lib/import_functions.php b/lib/import_functions.php new file mode 100644 index 0000000..23a52f4 --- /dev/null +++ b/lib/import_functions.php @@ -0,0 +1,609 @@ +server_id = $server_id; + $this->template_id = $template_id; + + $this->accept(); + } + + static function types() { + $type = array(); + + $details = ImportLDIF::getType(); + $type[$details['type']] = $details; + + return $type; + } + + private function accept() { + switch($this->template_id) { + case 'LDIF': + $this->template = new ImportLDIF($this->server_id); + break; + + default: + system_message(array( + 'title'=>sprintf('%s %s',_('Unknown Import Type'),$this->template_id), + 'body'=>_('phpLDAPadmin has not been configured for that import type'), + 'type'=>'warn'),'index.php'); + + die(); + } + + $this->template->accept(); + } + + public function getTemplate() { + return $this->template; + } +} + +/** + * Import Class + * + * This abstract classes provides all the common methods and variables for the + * custom import classes. + * + * @package phpLDAPadmin + * @subpackage Import + */ +abstract class Import { + protected $server_id = null; + protected $input = null; + protected $source = array(); + + public function __construct($server_id) { + $this->server_id = $server_id; + } + + public function accept() { + if (get_request('ldif','REQUEST')) { + $this->input = explode("\n",get_request('ldif','REQUEST')); + $this->source['name'] = 'STDIN'; + $this->source['size'] = strlen(get_request('ldif','REQUEST')); + + } elseif (isset($_FILES['ldif_file']) && is_array($_FILES['ldif_file']) && ! $_FILES['ldif_file']['error']) { + $input = file_get_contents($_FILES['ldif_file']['tmp_name']); + $this->input = preg_split("/\n|\r\n|\r/",$input); + $this->source['name'] = $_FILES['ldif_file']['name']; + $this->source['size'] = $_FILES['ldif_file']['size']; + + } else { + system_message(array( + 'title'=>_('No import input'), + 'body'=>_('You must either upload a file or provide an import in the text box.'), + 'type'=>'error'),sprintf('cmd.php?cmd=import_form&server_id=%s',get_request('server_id','REQUEST'))); + + die(); + } + } + + public function getSource($attr) { + if (isset($this->source[$attr])) + return $this->source[$attr]; + else + return null; + } + + # @todo integrate hooks + public function LDAPimport() { + $template = $this->getTemplate(); + $server = $this->getServer(); + + switch ($template->getType()) { + case 'add': + return $server->add($template->getDN(),$template->getLDAPadd()); + + case 'modify': + return $server->modify($template->getDN(),$template->getLDAPmodify()); + + case 'moddn': + case 'modrdn': + return $server->rename($template->getDN(),$template->modrdn['newrdn'],$template->modrdn['newsuperior'],$template->modrdn['deleteoldrdn']); + + default: + debug_dump_backtrace(sprintf('Unknown template type %s',$template->getType()),1); + } + + return true; + } +} + +/** + * Import entries from LDIF + * + * The LDIF spec is described by RFC2849 + * http://www.ietf.org/rfc/rfc2849.txt + * + * @package phpLDAPadmin + * @subpackage Import + */ +class ImportLDIF extends Import { + private $_currentLineNumber = 0; + private $_currentLine = ''; + private $template; + public $error = array(); + + static public function getType() { + return array('type'=>'LDIF','description' => _('LDIF Import'),'extension'=>'ldif'); + } + + protected function getTemplate() { + return $this->template; + } + + protected function getServer() { + return $_SESSION[APPCONFIG]->getServer($this->server_id); + } + + public function readEntry() { + static $haveVersion = false; + + if ($lines = $this->nextLines()) { + + # If we have a version line. + if (! $haveVersion && preg_match('/^version:/',$lines[0])) { + list($text,$version) = $this->getAttrValue(array_shift($lines)); + + if ($version != 1) + return $this->error(sprintf('%s %s',_('LDIF import only suppports version 1'),$version),$lines); + + $haveVersion = true; + $lines = $this->nextLines(); + } + + $server = $this->getServer(); + + # The first line should be the DN + if (preg_match('/^dn:/',$lines[0])) { + list($text,$dn) = $this->getAttrValue(array_shift($lines)); + + # The second line should be our changetype + if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) { + $attrvalue = $this->getAttrValue($lines[0]); + $changetype = $attrvalue[1]; + array_shift($lines); + + } else + $changetype = 'add'; + + $this->template = new Template($this->server_id,null,null,$changetype); + + switch ($changetype) { + case 'add': + $rdn = get_rdn($dn); + $container = $server->getContainer($dn); + + $this->template->setContainer($container); + $this->template->accept(); + + $this->getAddDetails($lines); + $this->template->setRDNAttributes($rdn); + + return $this->template; + + break; + + case 'modify': + if (! $server->dnExists($dn)) + return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines); + + $this->template->setDN($dn); + $this->template->accept(false,true); + + return $this->getModifyDetails($lines); + + break; + + case 'moddn': + case 'modrdn': + if (! $server->dnExists($dn)) + return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines); + + $this->template->setDN($dn); + $this->template->accept(); + + return $this->getModRDNAttributes($lines); + + break; + + default: + if (! $server->dnExists($dn)) + return $this->error(_('Unkown change type'),$lines); + } + + } else + return $this->error(_('A valid dn line is required'),$lines); + + } else + return false; + } + + /** + * Get the Attribute and Decoded Value + */ + private function getAttrValue($line) { + list($attr,$value) = explode(':',$line,2); + + # Get the DN + if (substr($value,0,1) == ':') + $value = base64_decode(trim(substr($value,1))); + else + $value = trim($value); + + return array($attr,$value); + } + + /** + * Get the lines of the next entry + * + * @return The lines (unfolded) of the next entry + */ + private function nextLines() { + $current = array(); + $endEntryFound = false; + + if ($this->hasMoreEntries() && ! $this->eof()) { + # The first line is the DN one + $current[0]= trim($this->_currentLine); + + # While we end on a blank line, fetch the attribute lines + $count = 0; + while (! $this->eof() && ! $endEntryFound) { + # Fetch the next line + $this->nextLine(); + + /* If the next line begin with a space, we append it to the current row + * else we push it into the array (unwrap)*/ + if ($this->isWrappedLine()) + $current[$count] .= trim($this->_currentLine); + elseif ($this->isCommentLine()) {} + # Do nothing + elseif (! $this->isBlankLine()) + $current[++$count] = trim($this->_currentLine); + else + $endEntryFound = true; + } + + # Return the LDIF entry array + return $current; + + } else + return array(); + } + + /** + * Private method to check if there is more entries in the input. + * + * @return boolean true if an entry was found, false otherwise. + */ + private function hasMoreEntries() { + $entry_found = false; + + while (! $this->eof() && ! $entry_found) { + # If it's a comment or blank line, switch to the next line + if ($this->isCommentLine() || $this->isBlankLine()) { + # Do nothing + $this->nextLine(); + + } else { + $this->_currentDnLine = $this->_currentLine; + $this->dnLineNumber = $this->_currentLineNumber; + $entry_found = true; + } + } + + return $entry_found; + } + + /** + * Helper method to switch to the next line + */ + private function nextLine() { + $this->_currentLineNumber++; + $this->_currentLine = array_shift($this->input); + } + + /** + * Check if it's a comment line. + * + * @return boolean true if it's a comment line,false otherwise + */ + private function isCommentLine() { + return substr(trim($this->_currentLine),0,1) == '#' ? true : false; + } + + /** + * Check if it's a wrapped line. + * + * @return boolean true if it's a wrapped line,false otherwise + */ + private function isWrappedLine() { + return substr($this->_currentLine,0,1) == ' ' ? true : false; + } + + /** + * Check if is the current line is a blank line. + * + * @return boolean if it is a blank line,false otherwise. + */ + private function isBlankLine() { + return(trim($this->_currentLine) == '') ? true : false; + } + + /** + * Returns true if we reached the end of the input. + * + * @return boolean true if it's the end of file, false otherwise. + */ + public function eof() { + return count($this->input) > 0 ? false : true; + } + + private function error($msg,$data) { + $this->error['message'] = sprintf('%s [%s]',$msg,$this->template ? $this->template->getDN() : ''); + $this->error['line'] = $this->_currentLineNumber; + $this->error['data'] = $data; + $this->error['changetype'] = $this->template ? $this->template->getType() : 'Not set'; + + return false; + } + + /** + * Method to retrieve the attribute value of a ldif line, + * and get the base 64 decoded value if it is encoded + */ + private function getAttributeValue($value) { + $return = ''; + + if (substr($value,0,1) == '<') { + $url = trim(substr($value,1)); + + if (preg_match('^file://',$url)) { + $filename = substr(trim($url),7); + + if ($fh = @fopen($filename,'rb')) { + if (! $return = @fread($fh,filesize($filename))) + return $this->error(_('Unable to read file for'),$value); + + @fclose($fh); + + } else + return $this->error(_('Unable to open file for'),$value); + + } else + return $this->error(_('The url attribute value should begin with file:// for'),$value); + + # It's a string + } else + $return = $value; + + return trim($return); + } + + /** + * Build the attributes array when the change type is add. + */ + private function getAddDetails($lines) { + foreach ($lines as $line) { + list($attr,$value) = $this->getAttrValue($line); + + if (is_null($attribute = $this->template->getAttribute($attr))) { + $attribute = $this->template->addAttribute($attr,array('values'=>array($value))); + $attribute->justModified(); + + } else + if ($attribute->hasBeenModified()) + $attribute->addValue($value); + else + $attribute->setValue(array($value)); + } + } + + /** + * Build the attributes array for the entry when the change type is modify + */ + private function getModifyDetails($lines) { + if (! count($lines)) + return $this->error(_('Missing attributes for'),$lines); + + # While the array is not empty + while (count($lines)) { + $processline = false; + $deleteattr = false; + + # Get the current line with the action + $currentLine = array_shift($lines); + $attrvalue = $this->getAttrValue($currentLine); + $action_attribute = $attrvalue[0]; + $action_attribute_value = $attrvalue[1]; + + if (! in_array($action_attribute,array('add','delete','replace'))) + return $this->error(_('Missing modify command add, delete or replace'),array_merge(array($currentLine),$lines)); + + $processline = true; + switch ($action_attribute) { + case 'add': + + break; + + case 'delete': + $attribute = $this->template->getAttribute($action_attribute_value); + + if (is_null($attribute)) + return $this->error(sprintf('%s %s',_('Attempting to delete a non existant attribute'),$action_attribute_value), + array_merge(array($currentLine),$lines)); + + $deleteattr = true; + + break; + + case 'replace': + $attribute = $this->template->getAttribute($action_attribute_value); + + if (is_null($attribute)) + return $this->error(sprintf('%s %s',_('Attempting to replace a non existant attribute'),$action_attribute_value), + array_merge(array($currentLine),$lines)); + + break; + + default: + debug_dump_backtrace(sprintf('Unknown action %s',$action_attribute),1); + } + + # Fetch the attribute for the following line + $currentLine = array_shift($lines); + + while ($processline && trim($currentLine) && (trim($currentLine) != '-')) { + $processline = false; + + # If there is a valid line + if (preg_match('/:/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attr = $attrvalue[0]; + $attribute_value_part = $attrvalue[1]; + + # Check that it correspond to the one specified before + if ($attr == $action_attribute_value) { + # Get the value part of the attribute + $attribute_value = $this->getAttributeValue($attribute_value_part); + + $attribute = $this->template->getAttribute($attr); + + # This should be a add/replace operation + switch ($action_attribute) { + case 'add': + if (is_null($attribute)) + $attribute = $this->template->addAttribute($attr,array('values'=>array($attribute_value_part))); + else + $attribute->addValue($attribute_value_part,-1); + + $attribute->justModified(); + + break; + + case 'delete': + $deleteattr = false; + + if (($key = array_search($attribute_value_part,$attribute->getValues())) !== false) + $attribute->delValue($key); + else + return $this->error(sprintf('%s %s',_('Delete value doesnt exist in DN'),$attribute_value_part), + array_merge(array($currentLine),$lines)); + + + break; + + case 'replace': + if ($attribute->hasBeenModified()) + $attribute->addValue($attribute_value_part,-1); + else + $attribute->setValue(array($attribute_value_part)); + + break; + + default: + debug_dump_backtrace(sprintf('Unexpected operation %s',$action_attribute)); + } + + } else + return $this->error(sprintf('%s %s',_('The attribute to modify doesnt match the one specified by'),$action_attribute), + array_merge(array($currentLine),$lines)); + + } else + return $this->error(sprintf('%s %s',_('Attribute not valid'),$currentLine), + array_merge(array($currentLine),$lines)); + + $currentLine = array_shift($lines); + if (trim($currentLine)) + $processline = true; + } + + if ($action_attribute == 'delete' && $deleteattr) + $attribute->setValue(array()); + + } + + return $this->template; + } + + /** + * Build the attributes for the entry when the change type is modrdn + */ + function getModRDNAttributes($lines) { + $server = $this->getServer(); + $attrs = array(); + + # MODRDN MODDN should only be 2 or 3 lines. + if (count($lines) != 2 && count($lines) !=3) + return $this->error(_('Invalid entry'),$lines); + + else { + $currentLine = array_shift($lines); + + # First we need to check if there is an new rdn specified + if (preg_match('/^newrdn:(:?)/',$currentLine)) { + + $attrvalue = $this->getAttrValue($currentLine); + $attrs['newrdn'] = $attrvalue[1]; + + $currentLine = array_shift($lines); + + if (preg_match('/^deleteoldrdn:[ ]*(0|1)/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attrs['deleteoldrdn'] = $attrvalue[1]; + + # Switch to the possible new superior attribute + if (count($lines)) { + $currentLine = array_shift($lines); + + # then the possible new superior attribute + if (preg_match('/^newsuperior:/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attrs['newsuperior'] = $attrvalue[1]; + + } else + return $this->error(_('A valid newsuperior attribute should be specified'),$lines); + + } else + $attrs['newsuperior'] = $server->getContainer($this->template->getDN()); + + } else + return $this->error(_('A valid deleteoldrdn attribute should be specified'),$lines); + + } else + return $this->error(_('A valid newrdn attribute should be specified'),$lines); + } + + # Well do something out of the ordinary here, since our template doesnt handle mod[r]dn yet. + $this->template->modrdn = $attrs; + return $this->template; + } +} +?> diff --git a/lib/ldap_error_codes.txt b/lib/ldap_error_codes.txt new file mode 100644 index 0000000..8d4a2cc --- /dev/null +++ b/lib/ldap_error_codes.txt @@ -0,0 +1,94 @@ +0x00 LDAP_SUCCESS "The operation completed successfully." +0x01 LDAP_OPERATIONS_ERROR "An operations error occurred. This is + typically the result of an internal error on your LDAP server." +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 server 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). This generally applies when + adding a new value to a binary attribute, or removing a single value from a + multi-valued binary attribute." +0x13 LDAP_CONSTRAINT_VIOLATION "Some constraint would be violated by performing the action. This can happen when + you try to add a second value to a single-valued attribute, for example." +0x14 LDAP_TYPE_OR_VALUE_EXISTS "An attribute type or attribute value + 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 + specified (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. This usually + means that you tried to change the value of an attribute that is used in the + DN. For example, if you change the 'cn' value of an entry whose DN is 'cn=Bob + Jones,dc=example,dc=com', you must also rename the entry to reflect the + change." +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. This can also occur if you do not + specify a structural objectClass when creating an entry, or if you specify + more than one structural objectClass." +0x42 LDAP_NOT_ALLOWED_ON_NONLEAF "The entry you tried to operate on has children. Usually this means you + tried to delete or rename the entry, which you cannot do to an entry + with children." +0x43 LDAP_NOT_ALLOWED_ON_RDN "You cannot preform that operation on a the relative distinguished name + (RDN) of an object." +0x44 LDAP_ALREADY_EXISTS "The object already exists. Usually you are trying to create a new object + on top of an existing one." +0x45 LDAP_NO_OBJECT_CLASS_MODS "ObjectClass modifications are not allowed." +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 "A 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/lib/ldap_supported_oids.txt b/lib/ldap_supported_oids.txt new file mode 100644 index 0000000..9fc5a66 --- /dev/null +++ b/lib/ldap_supported_oids.txt @@ -0,0 +1,187 @@ +# If you find some reliable and more meaningful descriptions to this OIDS, +# then please let the phpldapadmin development know so that this file can be +# more descriptive. + +1.2.826.0.1.334810.2.3 "LDAP_CONTROL_VALUESRETURNFILTER" +1.2.826.0.1.3344810.2.3 "Matched Values Control" "RFC 3876" "Describes a control for the LDAP v3 that is used to return a subset of attribute values from an entry. Specifically, only those values that match a 'values return' filter. Without support for this control, a client must retrieve all of an attribute's values and search for specific values locally." +1.2.826.0.1050.11.1.1 "Read-Only LDAP Server" +1.2.826.0.1050.11.2.1 "Read-Write LDAP Server" +1.2.826.0.1050.11.3.1 "White Pages Application LDAP Server" +1.2.826.0.1050.11.4.1 "Certificate Application LDAP Server" +1.2.826.0.1050.11.5.1 "Single Sign On Application LDAP Server" +1.2.840.113549.6.0.0 "Signed Operation" +1.2.840.113549.6.0.1 "Demand Signed Result" +1.2.840.113549.6.0.2 "Signed Result RFC 2649" +1.2.840.113556.1.4.319 "Simple Paged Results Manipulation Control Extension" "RFC 2696" "This control extension allows a client to control the rate at which an LDAP server returns the results of an LDAP search operation. This control may be useful when the LDAP client has limited resources and may not be able to process the entire result set from a given LDAP query, or when the LDAP client is connected over a low-bandwidth connection." +1.2.840.113556.1.4.417 "Show deleted control" "" "The LDAP_SERVER_SHOW_DELETED_OID control is used with an extended LDAP search function to specify that the search results include any deleted objects that match the search filter." +1.2.840.113556.1.4.473 "LDAP Server Sort Result extension" "draft-ietf-ldapext-sorting-01" "This control is included in the searchRequest message as part of the controls field of the LDAPMessage." +1.2.840.113556.1.4.474 "LDAP Server Sort Result extension response control" "" "This control is included in the searchResultDone message as part of the controls field of the LDAPMessage" +1.2.840.113556.1.4.521 "Cross-domain move control" "" "The LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID control is used with an extended LDAP rename function to move an LDAP object from one domain to another. The control specifies the DNS hostname of the domain controller in the destination domain." +1.2.840.113556.1.4.528 "Server search notification control" "" "The LDAP_SERVER_NOTIFICATION_OID control is used with an extended LDAP asynchronous search function to register the client to be notified when changes are made to an object in Active Directory." +1.2.840.113556.1.4.529 "Extended DN control" "" "The LDAP_SERVER_EXTENDED_DN_OID control is used with an extended LDAP search function to request an extended form of an Active Directory object distinguished name. The extended form includes a string representation of the object objectGUID property. For security principal objects such as users, groups, and computers, the extended form also includes a string representation of the object objectSID property." +1.2.840.113556.1.4.616 "LDAP_CONTROL_REFERRALS" +1.2.840.113556.1.4.619 "Lazy commit control" "" "The LDAP_SERVER_LAZY_COMMIT_OID control is used to instruct the server to return the results of a DS modification command, such as add, delete, or replace, after it has been completed in memory, but before it has been committed to disk. The server can then return results quickly, and save the data to disk without holding the client." +1.2.840.113556.1.4.800 "LDAP_CAP_ACTIVE_DIRECTORY_OID" "" "This is an Actrive Directory Server (Win2k and later)." +1.2.840.113556.1.4.801 "Security descriptor flags control" "" "The LDAP_SERVER_SD_FLAGS_OID control is used to pass flags to the server to control various security descriptor results." +1.2.840.113556.1.4.802 "Attribute Range Option" "" "Server supports the Range property enabling clients to incremental retrieve values from multivalue attributes." +1.2.840.113556.1.4.803 "LDAP_MATCHING_RULE_BIT_AND" +1.2.840.113556.1.4.804 "LDAP_MATCHING_RULE_BIT_OR" +1.2.840.113556.1.4.805 "Tree Delete" "" "The LDAP_SERVER_TREE_DELETE_OID control is used with an extended LDAP delete function to delete an entire subtree in the directory." +1.2.840.113556.1.4.841 "Directory synchronization control" "" "The LDAP_SERVER_DIRSYNC_OID control enables an application to search the directory for objects changed from a previous state. It is also used with the extended LDAP search functions such as ldap_search_ext." +1.2.840.113556.1.4.906 "Microsoft Large Integer" +1.2.840.113556.1.4.970 "Get stats control (Stateless)" +1.2.840.113556.1.4.1302 "Microsoft OID used with DEN Attributes" +1.2.840.113556.1.4.1338 "Verify name control" "" "The LDAP_SERVER_VERIFY_NAME_OID control is used with extended LDAP add and modify requests to instruct the DC accepting the update which DC it should verify with, the existence of any DN attribute values." +1.2.840.113556.1.4.1339 "LDAP_SERVER_DOMAIN_SCOPE_OID" "" "The LDAP_SERVER_DOMAIN_SCOPE_OID control is used to instruct the LDAP server not to generate any referrals when completing a request. This control also limits any search using it to a single naming context." +1.2.840.113556.1.4.1340 "Search options control" "" " The LDAP_SERVER_SEARCH_OPTIONS_OID control is used to pass flags to the server to control various search behaviors." +1.2.840.113556.1.4.1413 "LDAP ease modify restrictions" "" "Allows an LDAP modify to work under less restrictive conditions. Without it, a delete will fail if an attribute does not exist, and an add will fail if an attribute already exists." +1.2.840.113556.1.4.1504 "Attribute scoped query control" "" "The LDAP_SERVER_ASQ_OID control is used with an extended LDAP search function to force the query to be based on a specific DN-valued attribute. Only one source attribute can be specified with this control and the search request is limited to base object scoped queries." +1.2.840.113556.1.4.1670 "LDAP_CAP_ACTIVE_DIRECTORY_V51_OID" "" "This server is a Whistler Active Directory server (Win2k3 and later)." +1.2.840.113556.1.4.1781 "Fast concurrent bind extended operation" "" "The Microsoft LDAP API will send an extended request with this name to Active Directory to request that all binds on this connection be processed as 'fast' binds." +1.2.840.113556.1.4.1791 "LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID" "" "LDAP server is capable of doing signing and sealing on an NTLM authenticated connection, and that the server is capable of performing subsequent binds on a signed or sealed connection." +1.2.840.113556.1.4.1852 "LDAP_SERVER_QUOTA_CONTROL_OID" "" "The LDAP_SERVER_QUOTA_CONTROL_OID control is used to pass the SID of a security principal, whose quota is being queried, to the server in a LDAP search operation." +1.3.6.1.1.7.1 "LCUP Sync Request Control. RFC 3928 control" +1.3.6.1.1.7.2 "LCUP Sync Update Control. RFC 3928 control" +1.3.6.1.1.7.3 "LCUP Sync Done Control. RFC 3928 control" +1.3.6.1.1.8 "Cancel Operation. RFC 3909 extension" +1.3.6.1.1.12 "Assertion Control" "RFC 4511" "The assertion control allows the client to specify a condition that must be true for the operation to be processed normally." +1.3.6.1.1.13.1 "Pre-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned." +1.3.6.1.1.13.2 "Post-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned." +1.3.6.1.1.14 "Modify-Increment Extension" "RFC 4525" "An extension to the Lightweight Directory Access Protocol (LDAP) Modify operation to support an increment capability." +1.3.6.1.4.1.42.2.27.8.5.1 "passwordPolicyRequest" +1.3.6.1.4.1.42.2.27.9.5.2 "GetEffectiveRights control" "" "May be used to determine what operations a given user may perform on a specified entry." +1.3.6.1.4.1.1466.101.119.1 "Dynamic Directory Services Refresh Request" "RFC 2589" +1.3.6.1.4.1.1466.20036 "LDAP_NOTICE_OF_DISCONNECTION" +1.3.6.1.4.1.1466.20037 "Transport Layer Security Extension" "RFC 2830" "This operation provides for TLS establishment in an LDAP association and is defined in terms of an LDAP extended request." +1.3.6.1.4.1.1466.29539.1 "LDAP_CONTROL_ATTR_SIZELIMIT" +1.3.6.1.4.1.1466.29539.2 "LDAP_CONTROL_NO_COPY" +1.3.6.1.4.1.1466.29539.3 "LDAP_CONTROL_PARTIAL_COPY" +1.3.6.1.4.1.1466.29539.5 "LDAP_CONTROL_NO_CHAINING" +1.3.6.1.4.1.1466.29539.7 "LDAP_CONTROL_ALIAS_ON_UPDATE" +1.3.6.1.4.1.1466.29539.10 "LDAP_CONTROL_TRIGGER" +1.3.6.1.4.1.1466.29539.12 "nsTransmittedControl" +1.3.6.1.4.1.4203.1.5.1 "All Operational Attribute" "RFC 3673" "An LDAP extension which clients may use to request the return of all operational attributes." +1.3.6.1.4.1.4203.1.5.2 "Requesting Attributes by Object Class" "draft-zeilenga-ldap-adlist-10.txt" "Extends LDAP to support a mechanism that LDAP clients may use to request the return of all attributes of an object class." +1.3.6.1.4.1.4203.1.5.3 "LDAP Absolute True and False Filters" "draft-zeilenga-ldap-t-f-10.txt" "Implementations of this extension SHALL allow 'and' and 'or' choices with zero filter elements." +1.3.6.1.4.1.4203.1.5.4 "Language Tags" "RFC 3866" "Supports storing attributes with language tag options in the DIT" +1.3.6.1.4.1.4203.1.5.5 "Language Ranges" "RFC 3866" "Supports language range matching of attributes with language tag options stored in the DIT" +1.3.6.1.4.1.4203.1.9.1.1 "LDAP Content Synchronization Control" "draft=zeilenga-ldup-sync-06.txt" "The operation allows a client to maintain a copy of a fragment of directory information tree. It supports both polling for changes and listening for changes. The operation is defined as an extension of the LDAP Search Operation." +1.3.6.1.4.1.4203.1.10.1 "Subentries in LDAP" "RFC 3672" "The subentries control MAY be sent with a searchRequest to control the visibility of entries and subentries which are within scope. Non-visible entries or subentries are not returned in response to the request." +1.3.6.1.4.1.4203.1.10.2 "LDAP No-Op Control" "draft-zeilenga-ldap-noop-02.txt" "The No-Op control can be used to disable the normal effect of an operation. The control can be used to discover how a server might react to a particular update request without updating the directory." +1.3.6.1.4.1.4203.1.11.1 "LDAP Password Modify Extended Operation" "RFC 3062" "An LDAP extended operation to allow modification of user passwords which is not dependent upon the form of the authentication identity nor the password storage mechanism used." +1.3.6.1.4.1.4203.1.11.2 "LDAP Cancel Extended Operation" +1.3.6.1.4.1.4203.1.11.3 "Who Am I? Extended Operation" "draft-zeilenga-ldap-authzid-10.txt" "This specification provides a mechanism for Lightweight Directory Access Protocol (LDAP) clients to obtain the authorization identity which the server has associated with the user or application entity." +1.3.6.1.4.1.4203.666.5.1 "Subentries Control" +1.3.6.1.4.1.4203.666.5.2 "NO OP Control" +1.3.18.0.2.12.1 "The ACL credential controls provide a method to flow a subject's credentials associated with a bind." +1.3.18.0.2.12.5 "tranExtOpInit" +1.3.18.0.2.12.6 "tranExtOpInit" +2.16.840.1.113531.18.2.1 "LDAP_C_SETOPTIONS_OID" +2.16.840.1.113531.18.2.2 "LDAP_C_SETDONTUSECOPY_OID" +2.16.840.1.113531.18.2.3 "LDAP_C_SETLOCALSCOPE_OID" +2.16.840.1.113531.18.2.4 "Return operational attributes as well as user attributes" +2.16.840.1.113531.18.2.5 "Return only subentries" +2.16.840.1.113531.18.2.6 "LDAP_C_SETUSEALIAS_OID" +2.16.840.1.113531.18.2.7 "LDAP_C_SETPREFERCHAIN_OID" +2.16.840.1.113531.18.2.8 "LDAP_C_SETX500DN_OID" +2.16.840.1.113531.18.2.9 "LDAP_C_SETCOPYSHALLDO_OID" +2.16.840.1.113531.18.2.10 "LDAP_C_SETDONTMAPATTRS_OID" +2.16.840.1.113531.18.2.11 "Return normal entries as well as sub-entries" +2.16.840.1.113719.1.27.99.1 "Superior References" +2.16.840.1.113719.1.27.100.1 "ndsToLdapResponse" +2.16.840.1.113719.1.27.100.2 "ndsToLdapRequest" +2.16.840.1.113719.1.27.100.3 "createNamingContextRequest" +2.16.840.1.113719.1.27.100.4 "createNamingContextResponse" +2.16.840.1.113719.1.27.100.5 "mergeNamingContextRequest" +2.16.840.1.113719.1.27.100.6 "mergeNamingContextResponse" +2.16.840.1.113719.1.27.100.7 "addReplicaRequest" +2.16.840.1.113719.1.27.100.8 "addReplicaResponse" +2.16.840.1.113719.1.27.100.9 "refreshLDAPServerRequest" +2.16.840.1.113719.1.27.100.10 "refreshLDAPServerResponse" +2.16.840.1.113719.1.27.100.11 "removeReplicaRequest" +2.16.840.1.113719.1.27.100.12 "removeReplicaResponse" +2.16.840.1.113719.1.27.100.13 "namingContextEntryCountRequest" +2.16.840.1.113719.1.27.100.14 "namingContextEntryCountResponse" +2.16.840.1.113719.1.27.100.15 "changeReplicaTypeRequest" +2.16.840.1.113719.1.27.100.16 "changeReplicaTypeResponse" +2.16.840.1.113719.1.27.100.17 "getReplicaInfoRequest" +2.16.840.1.113719.1.27.100.18 "getReplicaInfoResponse" +2.16.840.1.113719.1.27.100.19 "listReplicaRequest" +2.16.840.1.113719.1.27.100.20 "listReplicaResponse" +2.16.840.1.113719.1.27.100.21 "receiveAllUpdatesRequest" +2.16.840.1.113719.1.27.100.22 "receiveAllUpdatesResponse" +2.16.840.1.113719.1.27.100.23 "sendAllUpdatesRequest" +2.16.840.1.113719.1.27.100.24 "sendAllUpdatesResponse" +2.16.840.1.113719.1.27.100.25 "requestNamingContextSyncRequest" +2.16.840.1.113719.1.27.100.26 "requestNamingContextSyncResponse" +2.16.840.1.113719.1.27.100.27 "requestSchemaSyncRequest" +2.16.840.1.113719.1.27.100.28 "requestSchemaSyncResponse" +2.16.840.1.113719.1.27.100.29 "abortNamingContextOperationRequest" +2.16.840.1.113719.1.27.100.30 "abortNamingContextOperationResponse" +2.16.840.1.113719.1.27.100.31 "Get Bind DN Request" +2.16.840.1.113719.1.27.100.32 "Get Bind DN Response" +2.16.840.1.113719.1.27.100.33 "Get Effective Privileges Request" +2.16.840.1.113719.1.27.100.34 "Get Effective Privileges Response" +2.16.840.1.113719.1.27.100.35 "Set Replication Filter Request" +2.16.840.1.113719.1.27.100.36 "Set Replication Filter Response" +2.16.840.1.113719.1.27.100.37 "Get Replication Filter Request" +2.16.840.1.113719.1.27.100.38 "Get Replication Filter Response" +2.16.840.1.113719.1.27.100.39 "Create Orphan Partition Request" +2.16.840.1.113719.1.27.100.40 "Create Orphan Partition Response" +2.16.840.1.113719.1.27.100.41 "Remove Orphan Partition Request" +2.16.840.1.113719.1.27.100.42 "Remove Orphan Partition Response" +2.16.840.1.113719.1.27.100.43 "Trigger Backlinker Request" +2.16.840.1.113719.1.27.100.44 "Trigger Backlinker Response" +2.16.840.1.113719.1.27.100.47 "Trigger Janitor Request" +2.16.840.1.113719.1.27.100.48 "Trigger Janitor Response" +2.16.840.1.113719.1.27.100.49 "Trigger Limber Request" +2.16.840.1.113719.1.27.100.50 "Trigger Limber Response" +2.16.840.1.113719.1.27.100.51 "Trigger Skulker Request" +2.16.840.1.113719.1.27.100.52 "Trigger Skulker Response" +2.16.840.1.113719.1.27.100.53 "Trigger Schema Synch Request" +2.16.840.1.113719.1.27.100.54 "Trigger Schema Synch Response" +2.16.840.1.113719.1.27.100.55 "Trigger Partition Purge Request" +2.16.840.1.113719.1.27.100.56 "Trigger Partition Purge Response" +2.16.840.1.113719.1.27.100.79 "Monitor Events Request" +2.16.840.1.113719.1.27.100.80 "Monitor Events Response" +2.16.840.1.113719.1.27.100.81 "Event Notification" +2.16.840.1.113719.1.27.101.1 "Duplicate Entry Request" +2.16.840.1.113719.1.27.101.2 "DuplicateSearchResult" +2.16.840.1.113719.1.27.101.3 "DuplicateEntryResponseDone" +2.16.840.1.113719.1.27.101.5 "Simple Password" +2.16.840.1.113719.1.27.101.6 "Forward Reference" +2.16.840.1.113719.1.142.100.1 "startFramedProtocolRequest" +2.16.840.1.113719.1.142.100.2 "startFramedProtocolResponse" +2.16.840.1.113719.1.142.100.3 "ReplicationUpdate" +2.16.840.1.113719.1.142.100.4 "endFramedProtocolRequest" +2.16.840.1.113719.1.142.100.5 "endFramedProtocolResponse" +2.16.840.1.113719.1.142.100.6 "lburpOperationRequest" +2.16.840.1.113719.1.142.100.7 "lburpOperationResponse" +2.16.840.1.113730.3.4 "Netscape LDAPv3 controls" +2.16.840.1.113730.3.4.2 "ManageDsaIT Control" "RFC 3296" "The client may provide the ManageDsaIT control with an operation to indicate that the operation is intended to manage objects within the DSA (server) Information Tree. The control causes Directory-specific entries (DSEs), regardless of type, to be treated as normal entries allowing clients to interrogate and update these entries using LDAP operations." +2.16.840.1.113730.3.4.3 "Persistent Search LDAPv3 control" +2.16.840.1.113730.3.4.4 "Netscape Password Expired LDAPv3 control" +2.16.840.1.113730.3.4.5 "Netscape Password Expiring LDAPv3 control" +2.16.840.1.113730.3.4.6 "Netscape NT Synchronization Client LDAPv3 control" +2.16.840.1.113730.3.4.7 "Entry Change Notification LDAPv3 control" +2.16.840.1.113730.3.4.8 "Transaction ID Request Control" +2.16.840.1.113730.3.4.9 "VLV Request LDAPv3 control" "" "As defined in the 'LDAPv3 Extensions for Virtual List View' IETF document." +2.16.840.1.113730.3.4.10 "VLV Response LDAPv3 control" "" "As defined in the 'LDAPv3 Extensions for Virtual List View' IETF document." +2.16.840.1.113730.3.4.11 "Transaction ID Response Control" +2.16.840.1.113730.3.4.12 "Proxied Authorization (version 1) control" "draft-weltman-ldapv3-proxy-05" "For assuming the identity of another entry for the duration of a request. This has been replaced by a new 'version 2' Proxied Authorization control." +2.16.840.1.113730.3.4.13 "iPlanet Directory Server Replication Update Information Control" +2.16.840.1.113730.3.4.14 "iPlanet Directory Server 'search on specific backend' control" +2.16.840.1.113730.3.4.15 "Authentication Response Control" +2.16.840.1.113730.3.4.16 "Authentication Request Control" +2.16.840.1.113730.3.4.17 "Real Attributes Only Request Control" +2.16.840.1.113730.3.4.18 "LDAP Proxied Authorization Control" "draft-weltman-ldapv3-proxy-06.txt" "The Proxied Authorization Control allows a client to request that an operation be processed under a provided authorization identity [AUTH] instead of as the current authorization identity associated with the connection." +2.16.840.1.113730.3.4.19 "Virtual Attributes Only Request Control" +2.16.840.1.113730.3.4.20 "Use One Backend" +2.16.840.1.113730.3.4.999 "iPlanet Replication Modrdn Extra Mods Control" +2.16.840.1.113730.3.5.3 "iPlanet Start Replication Request Extended Operation" +2.16.840.1.113730.3.5.4 "iPlanet Replication Response Extended Operation" +2.16.840.1.113730.3.5.5 "iPlanet End Replication Request Extended Operation" +2.16.840.1.113730.3.5.6 "iPlanet Replication Entry Request Extended Operation" +2.16.840.1.113730.3.5.7 "iPlanet Bulk Import Start Extended Operation" +2.16.840.1.113730.3.5.8 "iPlanet Bulk Import Finished Extended Operation" +2.16.840.1.113730.3.5.9 "iPlanet Digest authentication calculation" diff --git a/lib/page.php b/lib/page.php new file mode 100644 index 0000000..59927ce --- /dev/null +++ b/lib/page.php @@ -0,0 +1,519 @@ + + protected $_head; + + # Settings for this application + protected $_app; + + # Default values array. + protected $_default; + + public function __construct($index=null) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If we done have a configuration, then our IMGDIR and CSS are not defined + if (! defined('IMGDIR')) + define('IMGDIR','images/default'); + if (! defined('CSSDIR')) + define('CSSDIR','css/default'); + + $this->index = $index; + + # To be defined in a configuration file. + $this->_app['title'] = app_name(); + $this->_app['logo'] = IMGDIR.'/logo-small.png'; + + if (! is_null($index)) + $this->_app['urlcss'] = sprintf('%s/%s',CSSDIR,$_SESSION[APPCONFIG]->getValue('appearance','stylesheet')); + else + $this->_app['urlcss'] = sprintf('%s/%s',CSSDIR,'style.css'); + + # Default Values for configurable items. + $this->_default['sysmsg']['error'] = IMGDIR.'/error-big.png'; + $this->_default['sysmsg']['warn'] = IMGDIR.'/warn-big.png'; + $this->_default['sysmsg']['info'] = IMGDIR.'/info-big.png'; + + # Capture any output so far (in case we send some headers below) - there shouldnt be any output anyway. + $preOutput = ''; + + # Try and work around if php compression is on, or the user has set compression in the config. + # type = 1 for user gzip, 0 for php.ini gzip. + $obStatus = ob_get_status(); + if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) { + $preOutput = ob_get_contents(); + ob_end_clean(); + } + + header('Content-type: text/html; charset="UTF-8"'); + if (isCompress()) { + header('Content-Encoding: gzip'); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sent COMPRESSED header to browser and discarded (%s)',129,0,__FILE__,__LINE__,__METHOD__,$preOutput); + } + + if (isset($_SESSION[APPCONFIG]) + && $_SESSION[APPCONFIG]->getValue('appearance','compress') + && ini_get('zlib.output_compression')) + $this->setsysmsg(array('title'=>_('Warning'),'body'=>_('WARNING: You cannot have PHP compression and application compression enabled at the same time. Please unset zlib.output_compression or set $config->custom->appearance[\'compress\']=false'),'type'=>'warn')); + + # Turn back on output buffering. + ob_start(); + + # Initial Values + $this->_pageheader[] = ''; + $this->_pageheader[] .= ''."\n"; + } + + /* Add to the HTML Header */ + public function head_add($html) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->_head[] .= $html; + } + + /* Print out the HTML header */ + private function pageheader_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # HTML prepage requirements. + foreach ($this->_pageheader as $line) + echo $line."\n"; + + # Page Title + echo ''; + printf(''); + + $DNs = get_request('dn','REQUEST'); + if (is_array($DNs)) + $DNs = ''; + + if (isset($_SESSION[APPCONFIG])) + printf('%s (%s) - %s%s', + $this->_app['title'], + app_version(), + $DNs ? htmlspecialchars($DNs).' ' : '', + $_SESSION[APPCONFIG]->getValue('appearance','page_title')); + else + printf('%s - %s',$this->_app['title'],app_version()); + + echo ''; + # Style sheet. + printf('',$this->_app['urlcss']); + + if (defined('JSDIR')) { + printf('',JSDIR); + echo "\n"; + printf('',JSDIR); + printf('',JSDIR); + echo "\n"; + } + + # HTML head requirements. + if (is_array($this->_head) && count($this->_head)) + foreach ($this->_head as $line) + echo $line."\n"; + + echo ''; + echo "\n"; + } + + private function head_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($_SESSION[APPCONFIG])) + $pagetitle = $_SESSION[APPCONFIG]->getValue('appearance','page_title') ? ' - '.$_SESSION[APPCONFIG]->getValue('appearance','page_title') : ''; + else + $pagetitle = ''; + + echo ''; + + echo '
'; + printf('',get_href('sf'),$this->_app['logo']); + + echo ''; + echo '
'; + $empty = true; + if (function_exists('cmd_control_pane')) + foreach (cmd_control_pane('top') as $cmddetails) + if ((isset($cmddetails['enable']) && $cmddetails['enable']) || ! isset($cmddetails['enable'])) { + if (! $empty) + echo ' '; + + printf('%s',$cmddetails['link'],$cmddetails['image']); + + $empty = false; + } + + if ($empty) + echo ' '; + + echo '
'; + echo ''; + echo "\n"; + } + + private function control_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + echo ''; + echo ''; + if ($empty) + echo ''; + + echo ''; + echo '
'; + + $empty = true; + if (function_exists('cmd_control_pane')) + foreach (cmd_control_pane('main') as $cmddetails) + if ((isset($cmddetails['enable']) && trim($cmddetails['enable'])) || ! isset($cmddetails['enable'])) { + if (! $empty) + echo ' | '; + + printf('%s',$cmddetails['link'], + (isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('appearance','control_icons')) ? $cmddetails['image'] : $cmddetails['title']); + + $empty = false; + } + + echo ' 
'; + } + + protected function tree() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($_SESSION[APPCONFIG])) + return; + + if (is_null($this->index)) + $this->index = min(array_keys($_SESSION[APPCONFIG]->getServerList())); + + if (count($_SESSION[APPCONFIG]->getServerList()) > 1) { + echo '
'; + echo '
'; + printf('%s:
%s',_('Server Select'), + server_select_list($this->index,false,'index',true,sprintf("onchange=\"tree_unhide('index',%s)\"",$this->index))); + echo '
'; + echo '
'; + echo "\n\n"; + } + + foreach ($_SESSION[APPCONFIG]->getServerList() as $index => $server) { + printf('
',$server->getIndex(),($server->getIndex() == $this->index) ? 'block' : 'none'); + $tree = Tree::getInstance($server->getIndex()); + $tree->draw(); + echo '
'; + echo "\n\n"; + } + } + + public function block_add($side,$object) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_object($object)) + error(sprintf('block_add called with [%s], but it is not an object',serialize($object))); + + $this->_block[$side][] = $object; + } + + private function block_print($side) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($this->_block[$side])) + return; + + printf('',$side); + foreach ($this->_block[$side] as $object) + echo $object->draw($side); + echo ''; + } + + private function sysmsg() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->sysmsg)) { + foreach ($this->sysmsg as $index => $details) { + switch ($details['type']) { + case 'error': + $icon = $this->_default['sysmsg']['error']; + break; + + case 'warn': + $icon = $this->_default['sysmsg']['warn']; + break; + + case 'info': + default: + $icon = $this->_default['sysmsg']['info']; + break; + } + + if (isset($details['title'])) + printf('%s%s', + $icon,$details['type'],$details['title']); + + if (isset($details['body'])) + if (is_array($details['body'])) { + echo ''; + foreach ($details['body'] as $line) + printf('%s
',$line); + echo ''; + + } else + printf('%s',$details['body']); + } + } + } + + private function body($raw=false) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Add the Session System Messages + if (isset($_SESSION['sysmsg']) && is_array($_SESSION['sysmsg'])) { + foreach ($_SESSION['sysmsg'] as $msg) + $this->setsysmsg($msg); + + unset($_SESSION['sysmsg']); + } + + if (isset($this->sysmsg)) { + echo ''; + $this->sysmsg(); + echo '
'; + echo "\n"; + } + + if (isset($this->_block['body'])) + foreach ($this->_block['body'] as $object) + echo $object->draw('body',$raw); + } + + private function footer_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + printf('%s
%s
%s', + isCompress() ? '[C]' : ' ', + app_version(), + get_href('logo') ? sprintf('SourceForge.net Logo',get_href('sf'),get_href('logo')) : ' '); + } + + /** + * Only show a particular page frame - used by an AJAX call + */ + public function show($frame,$compress=false,$raw=false) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If the body is called via AJAX, and compression is enable, we need to compress the output + if ($compress && ob_get_level() && isCompress()) { + ob_end_clean(); + ob_start(); + } + + switch ($frame) { + case 'BODY': + $this->body($raw); + break; + + case 'TREE': + $this->tree(); + break; + + default: + error(sprintf('show called with unknown frame [%s]',$frame),'error','index.php'); + } + + if ($compress && ob_get_level() && isCompress()) { + $output = ob_get_contents(); + ob_end_clean(); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sending COMPRESSED output to browser[(%s),%s]',129,0,__FILE__,__LINE__,__METHOD__, + strlen($output),$output); + + print gzencode($output); + } + } + + public function display($filter=array()) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Control what is displayed. + $display = array( + 'HEAD'=>true, + 'CONTROL'=>true, + 'TREE'=>true, + 'FOOT'=>true + ); + + if ($_SESSION[APPCONFIG]->getValue('appearance','minimalMode')) { + $display = array( + 'HEAD'=>false, + 'CONTROL'=>false, + 'TREE'=>true, + 'FOOT'=>false + ); + } + + $display = array_merge($display,$filter); + + # HTML Header + $this->pageheader_print(); + + # Start of body + # Page Header + echo ''; + echo "\n"; + echo ''; + + if ($display['HEAD']) + $this->head_print(); + + # Control Line + if ($display['CONTROL']) { + echo ''; + echo "\n"; + } + + # Left Block + echo ''; + + if ($display['TREE']) { + echo ''; + } + + echo ''; + echo ''; + echo "\n"; + + # Page Footer + if ($display['FOOT']) + $this->footer_print(); + + # Finish HTML + echo '
'; + echo '
'; + $this->control_print(); + echo '
'; + printf('',_('Hide/Unhide the tree'),IMGDIR); + echo '
'; + $this->tree(); + echo '
'; + echo '
'; + echo '
'; + echo "\n"; + $this->body(); + echo '
'; + echo '
'; + echo ''; + echo ''; + + # compress output + if (ob_get_level() && isCompress()) { + $output = ob_get_contents(); + ob_end_clean(); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sending COMPRESSED output to browser[(%s),%s]',129,0,__FILE__,__LINE__,__METHOD__, + strlen($output),$output); + + print gzencode($output); + } + } + + public function setsysmsg($data) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($data)) + return; + + if (isset($this->sysmsg)) + $msgnum = count($this->sysmsg) + 1; + else + $msgnum = 1; + + foreach (array('title','body','type') as $index) + if (isset($data[$index])) + $this->sysmsg[$msgnum][$index] = $data[$index]; + } +} + +/** + * This class draws a block. + * + * @package phpLDAPadmin + * @subpackage Page + */ +class block { + private $title; + private $body; + private $foot; + + public function setTitle($html) { + $this->title = $html; + } + + public function setBody($html) { + $this->body = $html; + } + + public function setFooter($html) { + $this->foot = $html; + } + + public function draw($side,$raw=false) { + $output = ''; + + if ($raw) + $output .= $this->body; + + else { + $output .= sprintf('',$side); + + if (isset($this->title)) + $output .= sprintf('',$this->title); + + if (isset($this->body)) + $output .= sprintf('',$this->body); + + if (isset($this->footer)) + $output .= sprintf('',$this->foot); + + $output .= '
%s
%s
%s
'; + } + + return $output; + } +} +?> diff --git a/lib/query_functions.php b/lib/query_functions.php new file mode 100644 index 0000000..de47630 --- /dev/null +++ b/lib/query_functions.php @@ -0,0 +1,22 @@ + diff --git a/lib/schema_functions.php b/lib/schema_functions.php new file mode 100644 index 0000000..efa0cbc --- /dev/null +++ b/lib/schema_functions.php @@ -0,0 +1,1539 @@ +oid = $oid; + } + + public function setDescription($desc) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->description = $desc; + } + + public function getOID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oid); + + return $this->oid; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + /** + * Gets whether this objectClass is flagged as obsolete by the LDAP server. + */ + public function getIsObsolete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_obsolete); + + return $this->is_obsolete; + } + + /** + * Return the objects name. + * + * param boolean $lower Return the name in lower case (default) + * @return string The name + */ + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return $lower ? strtolower($this->name) : $this->name; + } +} + +/** + * Represents an LDAP objectClass + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class ObjectClass extends SchemaItem { + # The server ID that this objectclass belongs to. + private $server_id = null; + # Array of objectClass names from which this objectClass inherits + private $sup_classes = array(); + # One of STRUCTURAL, ABSTRACT, or AUXILIARY + private $type; + # Arrays of attribute names that this objectClass requires + private $must_attrs = array(); + # Arrays of attribute names that this objectClass allows, but does not require + private $may_attrs = array(); + # Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration + private $force_may = array(); + # Array of objectClasses which inherit from this one (must be set at runtime explicitly by the caller) + private $children_objectclasses = array(); + # The objectclass hierarchy + private $hierarchy = array(); + + /** + * Creates a new ObjectClass object given a raw LDAP objectClass string. + */ + public function __construct($class,$server) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->server_id = $server->getIndex(); + $this->type = $server->getValue('server','schema_oclass_default'); + + $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); + $str_count = count($strings); + + for ($i=0; $i < $str_count; $i++) { + + switch ($strings[$i]) { + case '(': + break; + + case 'NAME': + if ($strings[$i+1]!='(') { + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace('/^\'/','',$this->name); + $this->name = preg_replace('/\'$/','',$this->name); + + if (DEBUG_ENABLED) + debug_log('Case NAME returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->name); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description) == 0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + if (DEBUG_ENABLED) + debug_log('Case DESC returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->description); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case OBSOLETE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_obsolete); + break; + + case 'SUP': + if ($strings[$i+1] != '(') { + $i++; + array_push($this->sup_classes,preg_replace("/'/",'',$strings[$i])); + + } else { + $i++; + do { + $i++; + if ($strings[$i] != '$') + array_push($this->sup_classes,preg_replace("/'/",'',$strings[$i])); + + } while (! preg_match('/\)+\)?/',$strings[$i+1])); + } + + if (DEBUG_ENABLED) + debug_log('Case SUP returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sup_classes); + break; + + case 'ABSTRACT': + $this->type = 'abstract'; + + if (DEBUG_ENABLED) + debug_log('Case ABSTRACT returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'STRUCTURAL': + $this->type = 'structural'; + + if (DEBUG_ENABLED) + debug_log('Case STRUCTURAL returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'AUXILIARY': + $this->type = 'auxiliary'; + + if (DEBUG_ENABLED) + debug_log('Case AUXILIARY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'MUST': + $attrs = array(); + + $i = $this->parseList(++$i,$strings,$attrs); + + if (DEBUG_ENABLED) + debug_log('parseList returned %d (%s)',8,0,__FILE__,__LINE__,__METHOD__,$i,$attrs); + + foreach ($attrs as $string) { + $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); + + if ($server->isForceMay($attr->getName())) { + array_push($this->force_may,$attr); + array_push($this->may_attrs,$attr); + + } else + array_push($this->must_attrs,$attr); + } + + if (DEBUG_ENABLED) + debug_log('Case MUST returned (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->must_attrs,$this->force_may); + break; + + case 'MAY': + $attrs = array(); + + $i = $this->parseList(++$i,$strings,$attrs); + + if (DEBUG_ENABLED) + debug_log('parseList returned %d (%s)',8,0,__FILE__,__LINE__,__METHOD__,$i,$attrs); + + foreach ($attrs as $string) { + $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); + array_push($this->may_attrs,$attr); + } + + if (DEBUG_ENABLED) + debug_log('Case MAY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->may_attrs); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { + $this->setOID($strings[$i]); + + if (DEBUG_ENABLED) + debug_log('Case default returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->getOID()); + } + break; + } + } + + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + + if (DEBUG_ENABLED) + debug_log('Returning () - NAME (%s), DESCRIPTION (%s), MUST (%s), MAY (%s), FORCE MAY (%s)',9,0,__FILE__,__LINE__,__METHOD__, + $this->name,$this->description,$this->must_attrs,$this->may_attrs,$this->force_may); + } + + /** + * Parse an LDAP schema list + */ + private function parseList($i,$strings,&$attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /* + * A list starts with a ( followed by a list of attributes separated by $ terminated by ) + * The first token can therefore be a ( or a (NAME or a (NAME) + * The last token can therefore be a ) or NAME) + * The last token may be terminate by more than one bracket + */ + + $string = $strings[$i]; + if (! preg_match('/^\(/',$string)) { + # A bareword only - can be terminated by a ) if the last item + if (preg_match('/\)+$/',$string)) + $string = preg_replace('/\)+$/','',$string); + + array_push($attrs,$string); + + } elseif (preg_match('/^\(.*\)$/',$string)) { + $string = preg_replace('/^\(/','',$string); + $string = preg_replace('/\)+$/','',$string); + array_push($attrs,$string); + + } else { + # Handle the opening cases first + if ($string == '(') { + $i++; + + } elseif (preg_match('/^\(./',$string)) { + $string = preg_replace('/^\(/','',$string); + array_push($attrs,$string); + $i++; + } + + # Token is either a name, a $ or a ')' + # NAME can be terminated by one or more ')' + while (! preg_match('/\)+$/',$strings[$i])) { + $string = $strings[$i]; + if ($string == '$') { + $i++; + continue; + } + + if (preg_match('/\)$/',$string)) + $string = preg_replace('/\)+$/','',$string); + else + $i++; + + array_push($attrs,$string); + } + } + + sort($attrs); + + if (DEBUG_ENABLED) + debug_log('Returning (%d,[%s],[%s])',9,0,__FILE__,__LINE__,__METHOD__,$i,$strings,$attrs); + + return $i; + } + + /** + * This will return all our parent ObjectClass Objects + */ + public function getParents() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ((count($this->sup_classes) == 1) && ($this->sup_classes[0] == 'top')) + return array(); + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $return = array(); + + foreach ($this->sup_classes as $object_class) { + array_push($return,$object_class); + + $oc = $server->getSchemaObjectClass($object_class); + + if ($oc) + $return = array_merge($return,$oc->getParents()); + } + + return $return; + } + + /** + * Gets an array of AttributeType objects that entries of this ObjectClass must define. + * This differs from getMustAttrNames in that it returns an array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass requires. + * @return array The array of required AttributeType objects. + * + * @see getMustAttrNames + * @see getMayAttrs + * @see getMayAttrNames + */ + public function getMustAttrs($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $parents) + return $this->must_attrs; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $attrs = $this->must_attrs; + + foreach ($this->getParents() as $sup_class) { + $sc = $server->getSchemaObjectClass($sup_class); + $attrs = array_merge($attrs,$sc->getMustAttrs()); + } + + masort($attrs,'name,source'); + + # Remove any duplicates + foreach ($attrs as $index => $attr) + if (isset($allattr[$attr->getName()])) + unset($attrs[$index]); + else + $allattr[$attr->getName()] = 1; + + return $attrs; + } + + /** + * Gets an array of AttributeType objects that entries of this ObjectClass may define. + * This differs from getMayAttrNames in that it returns an array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed AttributeType objects. + * + * @see getMustAttrNames + * @see getMustAttrs + * @see getMayAttrNames + * @see AttributeType + */ + public function getMayAttrs($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $parents) + return $this->may_attrs; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $attrs = $this->may_attrs; + + foreach ($this->getParents() as $sup_class) { + $sc = $server->getSchemaObjectClass($sup_class); + $attrs = array_merge($attrs,$sc->getMayAttrs()); + } + + masort($attrs,'name,source'); + + # Remove any duplicates + foreach ($attrs as $index => $attr) + if (isset($allattr[$attr->name])) + unset($attrs[$index]); + else + $allattr[$attr->name] = 1; + + return $attrs; + } + + public function getForceMayAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->force_may; + } + + /** + * Gets an array of attribute names (strings) that entries of this ObjectClass must define. + * This differs from getMustAttrs in that it returns an array of strings rather than + * array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed attribute names (strings). + * + * @see getMustAttrs + * @see getMayAttrs + * @see getMayAttrNames + */ + public function getMustAttrNames($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_names = array(); + + foreach ($this->getMustAttrs($parents) as $attr) + array_push($attr_names,$attr->getName()); + + return $attr_names; + } + + /** + * Gets an array of attribute names (strings) that entries of this ObjectClass must define. + * This differs from getMayAttrs in that it returns an array of strings rather than + * array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed attribute names (strings). + * + * @see getMustAttrs + * @see getMayAttrs + * @see getMustAttrNames + */ + public function getMayAttrNames($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_names = array(); + + foreach ($this->getMayAttrs($parents) as $attr) + array_push($attr_names,$attr->getName()); + + return $attr_names; + } + + /** + * Adds an objectClass to the list of objectClasses that inherit + * from this objectClass. + * + * @param String $name The name of the objectClass to add + * @return boolean Returns true on success or false on failure (objectclass already existed for example) + */ + public function addChildObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $name = trim($name); + + foreach ($this->children_objectclasses as $existing_objectclass) + if (strcasecmp($name,$existing_objectclass) == 0) + return false; + + array_push($this->children_objectclasses,$name); + } + + /** + * Returns the array of objectClass names which inherit from this objectClass. + * + * @return Array Names of objectClasses which inherit from this objectClass. + */ + public function getChildObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->children_objectclasses; + } + + /** + * Gets the objectClass names from which this objectClass inherits. + * + * @return array An array of objectClass names (strings) + */ + public function getSupClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->sup_classes; + } + + /** + * Return if this objectClass is related to $oclass + * + * @param array ObjectClasses that this attribute may be related to + */ + public function isRelated($oclass) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If I am in the array, we'll just return false + if (in_array_ignore_case($this->name,$oclass)) + return false; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + + foreach ($oclass as $object_class) { + $oc = $server->getSchemaObjectClass($object_class); + + if ($oc->isStructural() && in_array_ignore_case($this->getName(),$oc->getParents())) + return true; + } + + return false; + } + + /** + * Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY. + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Adds the specified array of attributes to this objectClass' list of + * MUST attributes. The resulting array of must attributes will contain + * unique members. + * + * @param array $attr An array of attribute names (strings) to add. + */ + private function addMustAttrs($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($attr) || ! count($attr)) + return; + + $this->must_attrs = array_values(array_unique(array_merge($this->must_attrs,$attr))); + } + + /** + * Behaves identically to addMustAttrs, but it operates on the MAY + * attributes of this objectClass. + * + * @param array $attr An array of attribute names (strings) to add. + */ + private function addMayAttrs($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($attr) || ! count($attr)) + return; + + $this->may_attrs = array_values(array_unique(array_merge($this->may_attrs,$attr))); + } + + /** + * Determine if an array is listed in the force_may attrs + */ + public function isForceMay($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->force_may as $forcemay) + if ($forcemay->getName() == $attr) + return true; + + return false; + } + + public function isStructural() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->type == 'structural') + return true; + else + return false; + } +} + +/** + * A simple class for representing AttributeTypes used only by the ObjectClass class. + * Users should never instantiate this class. It represents an attribute internal to + * an ObjectClass. If PHP supported inner-classes and variable permissions, this would + * be interior to class ObjectClass and flagged private. The reason this class is used + * and not the "real" class AttributeType is because this class supports the notion of + * a "source" objectClass, meaning that it keeps track of which objectClass originally + * specified it. This class is therefore used by the class ObjectClass to determine + * inheritance. + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class ObjectClass_ObjectClassAttribute { + # This Attribute's name (needs to be public, as we sort on it with masort). + public $name; + # This Attribute's root (needs to be public, as we sort on it with masort). + public $source; + + /** + * Creates a new ObjectClass_ObjectClassAttribute with specified name and source objectClass. + * + * @param string $name the name of the new attribute. + * @param string $source the name of the ObjectClass which specifies this attribute. + */ + public function __construct($name,$source) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->name = $name; + $this->source = $source; + } + + # Gets this attribute's name + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return $lower ? strtolower($this->name) : $this->name; + } + + # Gets the name of the ObjectClass which originally specified this attribute. + public function getSource() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source); + + return $this->source; + } +} + +/** + * Represents an LDAP AttributeType + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class AttributeType extends SchemaItem { + # The attribute from which this attribute inherits (if any) + private $sup_attribute = null; + # The equality rule used + private $equality = null; + # The ordering of the attributeType + private $ordering = null; + # Boolean: supports substring matching? + private $sub_str = null; + # The full syntax string, ie 1.2.3.4{16} + private $syntax = null; + private $syntax_oid = null; + # boolean: is single valued only? + private $is_single_value = false; + # boolean: is collective? + private $is_collective = false; + # boolean: can use modify? + private $is_no_user_modification = false; + # The usage string set by the LDAP schema + private $usage = null; + # An array of alias attribute names, strings + private $aliases = array(); + # The max number of characters this attribute can be + private $max_length = null; + # A string description of the syntax type (taken from the LDAPSyntaxes) + private $type = null; + # An array of objectClasses which use this attributeType (must be set by caller) + private $used_in_object_classes = array(); + # A list of object class names that require this attribute type. + private $required_by_object_classes = array(); + # This attribute has been forced a MAY attribute by the configuration. + private $forced_as_may = false; + + /** + * Creates a new AttributeType object from a raw LDAP AttributeType string. + */ + public function __construct($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$attr,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $iname)==0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + # This attribute has no aliases + $this->aliases = array(); + + } else { + $i++; + do { + # In case we came here becaues of a (' + if (preg_match('/^\(/',$strings[$i])) + $strings[$i] = preg_replace('/^\(/','',$strings[$i]); + else + $i++; + + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + # Add alias names for this attribute + while ($strings[++$i] != ')') { + $alias = $strings[$i]; + $alias = preg_replace("/^\'/",'',$alias); + $alias = preg_replace("/\'$/",'',$alias); + $this->addAlias($alias); + } + } + + if (DEBUG_ENABLED) + debug_log('Case NAME returned (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->name,$this->aliases); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description)==0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + if (DEBUG_ENABLED) + debug_log('Case DESC returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->description); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case OBSOLETE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_obsolete); + break; + + case 'SUP': + $i++; + $this->sup_attribute = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case SUP returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sup_attribute); + break; + + case 'EQUALITY': + $i++; + $this->equality = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case EQUALITY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->equality); + break; + + case 'ORDERING': + $i++; + $this->ordering = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case ORDERING returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->ordering); + break; + + case 'SUBSTR': + $i++; + $this->sub_str = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case SUBSTR returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sub_str); + break; + + case 'SYNTAX': + $i++; + $this->syntax = $strings[$i]; + $this->syntax_oid = preg_replace('/{\d+}$/','',$this->syntax); + + # Does this SYNTAX string specify a max length (ie, 1.2.3.4{16}) + if (preg_match('/{(\d+)}$/',$this->syntax,$this->max_length)) + $this->max_length = $this->max_length[1]; + else + $this->max_length = null; + + if ($i < count($strings) - 1 && $strings[$i+1] == '{') { + do { + $i++; + $this->name .= ' '.$strings[$i]; + } while ($strings[$i] != '}'); + } + + if (DEBUG_ENABLED) + debug_log('Case SYNTAX returned (%s) (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__, + $this->syntax,$this->syntax_oid,$this->max_length); + break; + + case 'SINGLE-VALUE': + $this->is_single_value = TRUE; + if (DEBUG_ENABLED) + debug_log('Case SINGLE-VALUE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_single_value); + break; + + case 'COLLECTIVE': + $this->is_collective = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case COLLECTIVE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_collective); + break; + + case 'NO-USER-MODIFICATION': + $this->is_no_user_modification = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case NO-USER-MODIFICATION returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_no_user_modification); + break; + + case 'USAGE': + $i++; + $this->usage = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case USAGE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->usage); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { + $this->setOID($strings[$i]); + + if (DEBUG_ENABLED) + debug_log('Case default returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->getOID()); + } + } + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + $this->syntax = preg_replace("/^\'/",'',$this->syntax); + $this->syntax = preg_replace("/\'$/",'',$this->syntax); + $this->syntax_oid = preg_replace("/^\'/",'',$this->syntax_oid); + $this->syntax_oid = preg_replace("/\'$/",'',$this->syntax_oid); + $this->sup_attribute = preg_replace("/^\'/",'',$this->sup_attribute); + $this->sup_attribute = preg_replace("/\'$/",'',$this->sup_attribute); + + if (DEBUG_ENABLED) + debug_log('Returning ()',9,0,__FILE__,__LINE__,__METHOD__); + } + + /** + * Gets this attribute's usage string as defined by the LDAP server + * + * @return string + */ + public function getUsage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->usage); + + return $this->usage; + } + + /** + * Gets this attribute's parent attribute (if any). If this attribute does not + * inherit from another attribute, null is returned. + * + * @return string + */ + public function getSupAttribute() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->sup_attribute); + + return $this->sup_attribute; + } + + /** + * Gets this attribute's equality string + * + * @return string + */ + public function getEquality() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->equality); + + return $this->equality; + } + + /** + * Gets this attribute's ordering specification. + * + * @return string + */ + public function getOrdering() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ordering); + + return $this->ordering; + } + + /** + * Gets this attribute's substring matching specification + * + * @return string + */ + public function getSubstr() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->sub_str); + + return $this->sub_str; + } + + /** + * Gets the names of attributes that are an alias for this attribute (if any). + * + * @return array An array of names of attributes which alias this attribute or + * an empty array if no attribute aliases this object. + */ + public function getAliases() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases); + + return $this->aliases; + } + + /** + * Returns whether the specified attribute is an alias for this one (based on this attribute's alias list). + * + * @param string $attr_name The name of the attribute to check. + * @return boolean True if the specified attribute is an alias for this one, or false otherwise. + */ + public function isAliasFor($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->aliases as $alias_attr_name) + if (strcasecmp($alias_attr_name,$attr_name) == 0) + return true; + + return false; + } + + /** + * Gets this attribute's raw syntax string (ie: "1.2.3.4{16}"). + * + * @return string The raw syntax string + */ + public function getSyntaxString() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax); + + return $this->syntax; + } + + /** + * Gets this attribute's syntax OID. Differs from getSyntaxString() in that this + * function only returns the actual OID with any length specification removed. + * Ie, if the syntax string is "1.2.3.4{16}", this function only retruns + * "1.2.3.4". + * + * @return string The syntax OID string. + */ + public function getSyntaxOID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax_oid); + + return $this->syntax_oid; + } + + /** + * Gets this attribute's the maximum length. If no maximum is defined by the LDAP server, null is returned. + * + * @return int The maximum length (in characters) of this attribute or null if no maximum is specified. + */ + public function getMaxLength() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->max_length); + + return $this->max_length; + } + + /** + * Gets whether this attribute is single-valued. If this attribute only supports single values, true + * is returned. If this attribute supports multiple values, false is returned. + * + * @return boolean Returns true if this attribute is single-valued or false otherwise. + */ + public function getIsSingleValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_single_value); + + return $this->is_single_value; + } + + /** + * Sets whether this attribute is single-valued. + * + * @param boolean $is + */ + public function setIsSingleValue($is) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->is_single_value = $is; + } + + /** + * Gets whether this attribute is collective. + * + * @return boolean Returns true if this attribute is collective and false otherwise. + */ + public function getIsCollective() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_collective); + + return $this->is_collective; + } + + /** + * Gets whether this attribute is not modifiable by users. + * + * @return boolean Returns true if this attribute is not modifiable by users. + */ + public function getIsNoUserModification() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_no_user_modification); + + return $this->is_no_user_modification; + } + + /** + * Gets this attribute's type + * + * @return string The attribute's type. + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Removes an attribute name from this attribute's alias array. + * + * @param string $remove_alias_name The name of the attribute to remove. + * @return boolean true on success or false on failure (ie, if the specified + * attribute name is not found in this attribute's list of aliases) + */ + public function removeAlias($remove_alias_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->aliases as $i => $alias_name) { + + if (strcasecmp($alias_name,$remove_alias_name) == 0) { + unset($this->aliases[$i]); + + $this->aliases = array_values($this->aliases); + return true; + } + } + return false; + } + + /** + * Adds an attribute name to the alias array. + * + * @param string $alias The name of a new attribute to add to this attribute's list of aliases. + */ + public function addAlias($alias) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + array_push($this->aliases,$alias); + } + + /** + * Sets this attriute's name. + * + * @param string $name The new name to give this attribute. + */ + public function setName($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->name = $name; + } + + /** + * Sets this attriute's SUP attribute (ie, the attribute from which this attribute inherits). + * + * @param string $attr The name of the new parent (SUP) attribute + */ + public function setSupAttribute($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->sup_attribute = $attr; + } + + /** + * Sets this attribute's list of aliases. + * + * @param array $aliases The array of alias names (strings) + */ + public function setAliases($aliases) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->aliases = $aliases; + } + + /** + * Sets this attribute's type. + * + * @param string $type The new type. + */ + public function setType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->type = $type; + } + + /** + * Adds an objectClass name to this attribute's list of "used in" objectClasses, + * that is the list of objectClasses which provide this attribute. + * + * @param string $name The name of the objectClass to add. + */ + public function addUsedInObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->used_in_object_classes as $used_in_object_class) { + if (DEBUG_ENABLED) + debug_log('Checking (%s) with (%s)',8,0,__FILE__,__LINE__,__METHOD__,$used_in_object_class,$name); + + if (strcasecmp($used_in_object_class,$name) == 0) + return false; + } + + array_push($this->used_in_object_classes,$name); + } + + /** + * Gets the list of "used in" objectClasses, that is the list of objectClasses + * which provide this attribute. + * + * @return array An array of names of objectclasses (strings) which provide this attribute + */ + public function getUsedInObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_in_object_classes); + + return $this->used_in_object_classes; + } + + /** + * Adds an objectClass name to this attribute's list of "required by" objectClasses, + * that is the list of objectClasses which must have this attribute. + * + * @param string $name The name of the objectClass to add. + */ + public function addRequiredByObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->required_by_object_classes as $required_by_object_class) + if (strcasecmp($required_by_object_class,$name) == 0) + return false; + + array_push($this->required_by_object_classes,$name); + } + + /** + * Gets the list of "required by" objectClasses, that is the list of objectClasses + * which provide must have attribute. + * + * @return array An array of names of objectclasses (strings) which provide this attribute + */ + public function getRequiredByObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->required_by_object_classes); + + return $this->required_by_object_classes; + } + + /** + * This function will mark this attribute as a forced MAY attribute + */ + public function setForceMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->forced_as_may = true; + } + + public function isForceMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forced_as_may); + + return $this->forced_as_may; + } +} + +/** + * Represents an LDAP Syntax + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class Syntax extends SchemaItem { + /** + * Creates a new Syntax object from a raw LDAP syntax string. + */ + public function __construct($class) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $idescription) == 0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + } +} + +/** + * Represents an LDAP MatchingRule + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class MatchingRule extends SchemaItem { + # This rule's syntax OID + private $syntax = null; + # An array of attribute names who use this MatchingRule + private $used_by_attrs = array(); + + /** + * Creates a new MatchingRule object from a raw LDAP MatchingRule string. + */ + function __construct($strings) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); + + for ($i=0; $iname) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description)==0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + break; + + case 'SYNTAX': + $this->syntax = $strings[++$i]; + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + } + + /** + * Sets the list of used_by_attrs to the array specified by $attrs; + * + * @param array $attrs The array of attribute names (strings) which use this MatchingRule + */ + public function setUsedByAttrs($attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->used_by_attrs = $attrs; + } + + /** + * Adds an attribute name to the list of attributes who use this MatchingRule + * + * @return true if the attribute was added and false otherwise (already in the list) + */ + public function addUsedByAttr($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->used_by_attrs as $attr_name) + if (strcasecmp($attr_name,$attr) == 0) + return false; + + array_push($this->used_by_attrs,$attr); + + return true; + } + + /** + * Gets an array of attribute names (strings) which use this MatchingRule + * + * @return array The array of attribute names (strings). + */ + public function getUsedByAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_by_attrs); + + return $this->used_by_attrs; + } +} + +/** + * Represents an LDAP schema matchingRuleUse entry + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class MatchingRuleUse extends SchemaItem { + # An array of attribute names who use this MatchingRule + private $used_by_attrs = array(); + + function __construct($strings) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $iname) || strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + break; + + case 'APPLIES': + if ($strings[$i+1] != '(') { + # Has a single attribute name + $i++; + $this->used_by_attrs = array($strings[$i]); + + } else { + # Has multiple attribute names + $i++; + while ($strings[$i] != ')') { + $i++; + $new_attr = $strings[$i]; + $new_attr = preg_replace("/^\'/",'',$new_attr); + $new_attr = preg_replace("/\'$/",'',$new_attr); + array_push($this->used_by_attrs,$new_attr); + $i++; + } + } + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + + sort($this->used_by_attrs); + } + + /** + * Gets an array of attribute names (strings) which use this MatchingRuleUse object. + * + * @return array The array of attribute names (strings). + */ + public function getUsedByAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_by_attrs); + + return $this->used_by_attrs; + } +} +?> diff --git a/lib/session_functions.php b/lib/session_functions.php new file mode 100644 index 0000000..30ae3c9 --- /dev/null +++ b/lib/session_functions.php @@ -0,0 +1,176 @@ +_('Configuration cache stale.'), + 'body'=>_('Your configuration has been automatically refreshed.'), + 'type'=>'info','special'=>true)); + + $config_file = CONFDIR.'config.php'; + $config = check_config($config_file); + if (! $config) + debug_dump_backtrace('config is empty?',1); + + } else { + # Sanity check, specially when upgrading from a previous release. + if (isset($_SESSION['cache'])) + foreach (array_keys($_SESSION['cache']) as $id) + if (isset($_SESSION['cache'][$id]['tree']['null']) && ! is_object($_SESSION['cache'][$id]['tree']['null'])) + unset($_SESSION['cache'][$id]); + } + } + + # If we came via index.php, then set our $config. + if (! isset($_SESSION[APPCONFIG]) && isset($config)) + $_SESSION[APPCONFIG] = $config; + + # Restore our sysmsg's if there were any. + if ($sysmsg) { + if (! isset($_SESSION['sysmsg']) || ! is_array($_SESSION['sysmsg'])) + $_SESSION['sysmsg'] = array(); + + $_SESSION['sysmsg'] = array_merge($_SESSION['sysmsg'],$sysmsg); + } +} + +/** + * Stops the current session. + */ +function app_session_close() { + @session_write_close(); +} +?> diff --git a/lib/syslog.php b/lib/syslog.php new file mode 100644 index 0000000..25ca16c --- /dev/null +++ b/lib/syslog.php @@ -0,0 +1,88 @@ + and Alcôve + * @package phpLDAPadmin + */ + +# If config_default.php hasnt been called yet, then return. +if (! defined('APPCONFIG') || ! isset($_SESSION[APPCONFIG])) + return; + +# Initialize syslog +if ($_SESSION[APPCONFIG]->getValue('debug','syslog') && function_exists('syslog')) { + openlog('phpldapadmin',LOG_ODELAY,LOG_DAEMON); +} + +/** + * Verify that syslog logging is activated in the config via the + * debug->syslog variable and does a call to the syslog() function is it + * is true. + * + * @param emergency Syslog emergency. + * @param log_string String to log. + */ +function syslog_msg($emergency,$log_string) { + if (! function_exists('syslog') || ! isset($_SESSION[APPCONFIG]) || ! $_SESSION[APPCONFIG]->getValue('debug','syslog')) + return; + + return syslog($emergency,$log_string); +} + +/** + * Issue an error message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_err($log_string) { + return syslog_msg(LOG_ERR,$log_string); +} + +/** + * Issue a warning message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_warning($log_string) { + return syslog_msg(LOG_WARNING,$log_string); +} + +/** + * Issue a notice message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_notice($log_string) { + return syslog_msg(LOG_NOTICE,$log_string); +} + +/** + * Issue a debug message via syslog, only if $log_level is set to + * 'debug' from the config file. + * + * @param log_string Log message to send to syslog. + * @return true on success or if debug log is not activated. + */ +function syslog_debug($log_string) { + return syslog_msg(LOG_DEBUG,$log_string); +} +?> diff --git a/lib/template_functions.php b/lib/template_functions.php new file mode 100644 index 0000000..bb3b606 --- /dev/null +++ b/lib/template_functions.php @@ -0,0 +1,23 @@ + diff --git a/lib/xml2array.php b/lib/xml2array.php new file mode 100644 index 0000000..d260c9e --- /dev/null +++ b/lib/xml2array.php @@ -0,0 +1,144 @@ +stack[count($this->stack)] = &$pos; + $this->stack_ref = &$pos; + } + + private function pop_pos() { + unset($this->stack[count($this->stack) - 1]); + $this->stack_ref = &$this->stack[count($this->stack) - 1]; + } + + public function parseXML($strInputXML,$filename) { + $this->resParser = xml_parser_create(); + xml_set_object($this->resParser,$this); + xml_set_element_handler($this->resParser,'tagOpen','tagClosed'); + + xml_set_character_data_handler($this->resParser,'tagData'); + + $this->push_pos($this->arrOutput); + + $this->strXmlData = xml_parse($this->resParser,$strInputXML); + + if (! $this->strXmlData) + die(sprintf('XML error: %s at line %d in file %s', + xml_error_string(xml_get_error_code($this->resParser)), + xml_get_current_line_number($this->resParser), + $filename)); + + xml_parser_free($this->resParser); + + $output = array(); + foreach ($this->arrOutput as $key => $values) + $output[$key] = $this->cleanXML($values); + + #return $this->arrOutput; + return $output; + } + + private function tagOpen($parser,$name,$attrs) { + $name = strtolower($name); + + if (isset($this->stack_ref[$name])) { + if (! isset($this->stack_ref[$name][0])) { + $tmp = $this->stack_ref[$name]; + unset($this->stack_ref[$name]); + $this->stack_ref[$name][0] = $tmp; + } + + $cnt = count($this->stack_ref[$name]); + $this->stack_ref[$name][$cnt] = array(); + if (isset($attrs)) + $this->stack_ref[$name][$cnt] = $attrs; + + $this->push_pos($this->stack_ref[$name][$cnt]); + + } else { + $this->stack_ref[$name]=array(); + + if (isset($attrs)) + $this->stack_ref[$name]=$attrs; + + $this->push_pos($this->stack_ref[$name]); + } + } + + private function tagData($parser,$tagData) { + if (trim($tagData) != '') { + + if (isset($this->stack_ref['#text'])) + $this->stack_ref['#text'] .= $tagData; + else + $this->stack_ref['#text'] = $tagData; + } + } + + private function tagClosed($parser,$name) { + $this->pop_pos(); + } + + /** + * This function will parse an XML array and make a normal array. + * + * @return array - Clean XML data + */ + private function cleanXML($details) { + # Quick processing for the final branch of the XML array. + if (is_array($details) && isset($details['#text'])) + return $details['#text']; + + elseif (is_array($details) && isset($details['ID']) && count($details) == 1) + return $details['ID']; + + $cleanXML = array(); + + # Quick processing for the final branch, when it holds the ID and values. + if (is_array($details) && isset($details['ID']) && count($details) > 1) { + $key = $details['ID']; + unset($details['ID']); + $cleanXML[$key] = $this->cleanXML($details); + $details = array(); + } + + # More detailed processing... + if (is_array($details)) + foreach ($details as $key => $values) + if (is_numeric($key) && isset($values['ID']) && count($values) > 1) { + $key = $values['ID']; + unset($values['ID']); + $cleanXML[$key] = $this->cleanXML($values); + + } elseif (isset($values['#text'])) + $cleanXML[$key] = $this->cleanXML($values); + + elseif (is_array($values)) + $cleanXML[$key] = $this->cleanXML($values); + + if (! $cleanXML) + return $details; + else + return $cleanXML; + } +} diff --git a/lib/xmlTemplates.php b/lib/xmlTemplates.php new file mode 100644 index 0000000..1749bac --- /dev/null +++ b/lib/xmlTemplates.php @@ -0,0 +1,496 @@ +server_id = $server_id; + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $custom_prefix = $server->getValue('custom','pages_prefix'); + $class = $this->getClassVars(); + $changed = false; + + # Try to get the templates from our CACHE. + if ($this->templates = get_cached_item($server_id,$class['item'])) { + if (DEBUG_ENABLED) + debug_log('Using CACHED templates',4,0,__FILE__,__LINE__,__METHOD__); + + # See if the template_time has expired to see if we should reload the templates. + foreach ($this->templates as $index => $template) { + # If the file no longer exists, we'll delete the template. + if (! file_exists($template->getFileName())) { + unset($this->templates[$index]); + $changed = true; + + system_message(array( + 'title'=>_('Template XML file removed.'), + 'body'=>sprintf('%s %s (%s)',_('Template XML file has removed'),$template->getName(false),$template->getType()), + 'type'=>'info','special'=>true)); + + continue; + } + + if (($template->getReadTime() < (time()-$class['cachetime'])) + && (filectime($template->getFileName()) > $template->getReadTime())) { + + system_message(array( + 'title'=>_('Template XML file changed.'), + 'body'=>sprintf('%s %s (%s)',_('Template XML file has changed and been reread'),$template->getName(false),$template->getType()), + 'type'=>'info','special'=>true)); + + $changed = true; + $this->templates[$index] = new $class['name']($this->server_id,$template->getName(false),$template->getFileName(),$template->getType(),$index); + } + } + + if (DEBUG_ENABLED) + debug_log('Templates refreshed',4,0,__FILE__,__LINE__,__METHOD__); + + # See if there are any new template files + $index = max(array_keys($this->templates))+1; + foreach ($class['types'] as $type) { + $dir = $class['dir'].$type; + $dh = opendir($dir); + if (! $type) + $type = 'template'; + + while ($file = readdir($dh)) { + # Ignore any files that are not XML files. + if (! preg_match('/.xml$/',$file)) + continue; + + # Ignore any files that are not the predefined custom files. + if ($_SESSION[APPCONFIG]->getValue('appearance','custom_templates_only') + && ! preg_match("/^${custom_prefix}/",$file)) + continue; + + $filename = sprintf('%s/%s',$dir,$file); + + if (! in_array($filename,$this->getTemplateFiles())) { + $templatename = preg_replace('/.xml$/','',$file); + + $this->templates[$index] = new $class['name']($this->server_id,$templatename,$filename,$type,$index); + $index++; + + $changed = true; + + system_message(array( + 'title'=>_('New Template XML found.'), + 'body'=>sprintf('%s %s (%s)',_('A new template XML file has been loaded'),$file,$type), + 'type'=>'info','special'=>true)); + } + } + } + + } else { + if (DEBUG_ENABLED) + debug_log('Parsing templates',4,0,__FILE__,__LINE__,__METHOD__); + + # Need to reset this, as get_cached_item() returns null if nothing cached. + $this->templates = array(); + $changed = true; + + $counter = 0; + foreach ($class['types'] as $type) { + $dir = $class['dir'].$type; + $dh = opendir($class['dir'].$type); + if (! $type) + $type = 'template'; + + while ($file = readdir($dh)) { + # Ignore any files that are not XML files. + if (! preg_match('/.xml$/',$file)) + continue; + + # Ignore any files that are not the predefined custom files. + if ($_SESSION[APPCONFIG]->getValue('appearance','custom_templates_only') + && ! preg_match("/^${custom_prefix}/",$file)) + continue; + + $filename = sprintf('%s/%s',$dir,$file); + + # Store the template + $templatename = preg_replace('/.xml$/','',$file); + $this->templates[$counter] = new $class['name']($this->server_id,$templatename,$filename,$type,$counter); + $counter++; + } + } + } + + if (DEBUG_ENABLED) + debug_log('Templates loaded',4,0,__FILE__,__LINE__,__METHOD__); + + if ($changed) { + masort($this->templates,'title'); + set_cached_item($server_id,$class['item'],'null',$this->templates); + } + } + + /** + * This will return our custom class variables, used by the parent to create objects. + */ + private function getClassVars() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $class = array(); + + switch (get_class($this)) { + case 'Queries': + $class['item'] = 'query'; + $class['name'] = 'Query'; + $class['cachetime'] = $_SESSION[APPCONFIG]->getValue('cache','query_time'); + $class['types'] = array(''); + $class['dir'] = QUERYDIR; + + break; + + case 'Templates': + $class['item'] = 'template'; + $class['name'] = 'Template'; + $class['cachetime'] = $_SESSION[APPCONFIG]->getValue('cache','template_time'); + $class['types'] = array('creation','modification'); + $class['dir'] = TMPLDIR; + + break; + + default: + debug_dump_backtrace(sprintf('Unknown class %s',get_class($this)),1); + } + + return $class; + } + + /** + * Return a list of templates by their type + * This function should return a sorted list, as the array is built sorted. + * + * @param string Type of template, eg: creation, modification + * @param boolean Exclude templates purposely disabled. + * @return array List of templates of the type + */ + public function getTemplates($type=null,$container=null,$disabled=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (is_array($this->templates)) + foreach ($this->templates as $details) { + + # Clone this, as we'll disable some templates, as a result of the container being requested. + $template = clone $details; + if (! is_null($container) && ($regexp = $template->getRegExp()) && (! @preg_match('/'.$regexp.'/i',$container))) { + $template->setInvalid(_('This template is not valid in this container'),true); + + if ($_SESSION[APPCONFIG]->getValue('appearance','hide_template_regexp')) + $template->setInvisible(); + } + + if ($template->isVisible() && (! $disabled || ! $template->isAdminDisabled())) + if (is_null($type) || (! is_null($type) && $template->isType($type))) + array_push($result,$template); + } + + return $result; + } + + /** + * Return a template by its ID + * + * @param string The template ID as it was when it was generated (normally used in $_REQUEST vars). + * @return object Template (or default template if the ID doesnt exist) + */ + function getTemplate($templateid) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $class = $this->getClassVars(); + + foreach ($this->templates as $template) + if ($template->getID() === $templateid) + return clone $template; + + # If we get here, the template ID didnt exist, so return a blank template, which be interpreted as the default template + $object = new $class['name']($this->server_id,null,null,'default'); + return $object; + } + + /** + * Get a list of template filenames. + */ + private function getTemplateFiles() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->templates as $template) + array_push($result,$template->getFileName()); + + return $result; + } +} + +/** + * XML Template Class + * + * @package phpLDAPadmin + * @subpackage Templates + */ +abstract class xmlTemplate { + # Server ID that the template is linked to + protected $server_id; + # Template unique ID + protected $id; + # Template name - as extracted from the filename + protected $name; + # Template type - creation/modification + protected $type; + # Time this object was created + protected $readtime; + # Template file name + protected $filename; + # The TEMPLATE attributes as per the template definition, or the DN entry + protected $attributes = array(); + + public function __construct($server_id,$name=null,$filename=null,$type=null,$id=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->server_id = $server_id; + $this->name = $name; + $this->type = $type; + $this->filename = $filename; + $this->readtime = time(); + $this->id = $id; + + # If there is no filename, then this template is a default template. + if (is_null($filename)) + return; + + # If we have a filename, parse the template file and build the object. + $objXML = new xml2array(); + $xmldata = $objXML->parseXML(file_get_contents($filename),$filename); + $this->storeTemplate($xmldata); + } + + /** + * Get an attribute ID + * + * @param string The Attribute being searched. + * @return int Attribute ID in the array + */ + protected function getAttrID($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->attributes as $index => $attribute) + if (strtolower($attr) == $attribute->getName() || in_array(strtolower($attr),$attribute->getAliases())) + return $index; + + return null; + } + + /** + * Get the Template filename. + */ + public function getFileName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->filename); + + return $this->filename; + } + + /** + * Return the template by ID + */ + public function getID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->id); + + if ($this->name) + return sprintf('%s:%s',$this->getName(false),$this->id); + else + return 'none'; + } + + /** + * Return the template name + * + * @param boolean Force the name to be lowercase (default) + */ + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + if ($lower) + return strtolower($this->name); + else + return $this->name; + } + + /** + * Get the Template read time. + */ + public function getReadTime() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readtime); + + return $this->readtime; + } + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + protected function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + return $this->server_id; + } + + /** + * Test if a template is of a type + * + * @return boolean + */ + public function isType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + if ($this->type == $type) + return true; + else + return false; + } + + /** + * Return the template type + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Get template title + */ + public function getTitle() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($this->title) && ! isset($this->description)) + return ''; + + return isset($this->title) ? $this->title : $this->description; + } + + /** + * Add another attribute to this template + * + * @return int Attribute ID + */ + public function addAttribute($name,$value,$source=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($value)) + debug_dump_backtrace('Value should be an array()',1); + + $server = $this->getServer(); + + # Initialise the Attribute Factory. + $attribute_factory = new AttributeFactory(); + + if (preg_match('/;/',$name)) + system_message(array( + 'title'=>'phpLDAPadmin doesnt support RFC3866.', + 'body'=>sprintf('%s {%s} (%s)','PLA might not do what you expect...',$name,(is_array($value) ? serialize($value) : $value)), + 'type'=>'warn')); + + # If there isnt a schema item for this attribute + $attribute = $attribute_factory->newAttribute($name,$value,$server->getIndex(),$source); + + $attrid = $this->getAttrID($attribute->getName()); + + if (is_null($attrid)) + array_push($this->attributes,$attribute); + + return $attribute; + } + + /** + * Get the attribute names + * + * @return array Array of attributes Names + */ + public function getAttributeNames() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + return $result; + } + + /** + * Get a specific Attribute + * + * @param string Name of attribute to retrieve + * @return object Attribute + */ + public function getAttribute($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->attributes as $attribute) + if (($attribute->getName() == strtolower($name)) || in_array(strtolower($name),$attribute->getAliases())) + return $attribute; + + return null; + } + + /** + * May be overloaded in other classes + */ + public function isAdminDisabled() {} +} +?> diff --git a/locale/ca_ES/LC_MESSAGES/messages.mo b/locale/ca_ES/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..b3dabc8 Binary files /dev/null and b/locale/ca_ES/LC_MESSAGES/messages.mo differ diff --git a/locale/cs_CZ/LC_MESSAGES/messages.mo b/locale/cs_CZ/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..fb39b76 Binary files /dev/null and b/locale/cs_CZ/LC_MESSAGES/messages.mo differ diff --git a/locale/da_DK/LC_MESSAGES/messages.mo b/locale/da_DK/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..350f4ee Binary files /dev/null and b/locale/da_DK/LC_MESSAGES/messages.mo differ diff --git a/locale/de_DE/LC_MESSAGES/messages.mo b/locale/de_DE/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..c683d73 Binary files /dev/null and b/locale/de_DE/LC_MESSAGES/messages.mo differ diff --git a/locale/es_ES/LC_MESSAGES/messages.mo b/locale/es_ES/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..a03a9a4 Binary files /dev/null and b/locale/es_ES/LC_MESSAGES/messages.mo differ diff --git a/locale/fi_FI/LC_MESSAGES/messages.mo b/locale/fi_FI/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..0318b4d Binary files /dev/null and b/locale/fi_FI/LC_MESSAGES/messages.mo differ diff --git a/locale/fr_FR/LC_MESSAGES/messages.mo b/locale/fr_FR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..da77e75 Binary files /dev/null and b/locale/fr_FR/LC_MESSAGES/messages.mo differ diff --git a/locale/gn_PY/LC_MESSAGES/messages.mo b/locale/gn_PY/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..c7a17b7 Binary files /dev/null and b/locale/gn_PY/LC_MESSAGES/messages.mo differ diff --git a/locale/hu_HU/LC_MESSAGES/messages.mo b/locale/hu_HU/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..029ceec Binary files /dev/null and b/locale/hu_HU/LC_MESSAGES/messages.mo differ diff --git a/locale/it_IT/LC_MESSAGES/messages.mo b/locale/it_IT/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..cace961 Binary files /dev/null and b/locale/it_IT/LC_MESSAGES/messages.mo differ diff --git a/locale/ja_JP/LC_MESSAGES/messages.mo b/locale/ja_JP/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..e96e6e4 Binary files /dev/null and b/locale/ja_JP/LC_MESSAGES/messages.mo differ diff --git a/locale/nb_NO/LC_MESSAGES/messages.mo b/locale/nb_NO/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..d2ebacd Binary files /dev/null and b/locale/nb_NO/LC_MESSAGES/messages.mo differ diff --git a/locale/nl_BE/LC_MESSAGES/messages.mo b/locale/nl_BE/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..bafeef9 Binary files /dev/null and b/locale/nl_BE/LC_MESSAGES/messages.mo differ diff --git a/locale/oc_FR/LC_MESSAGES/messages.mo b/locale/oc_FR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..7823c66 Binary files /dev/null and b/locale/oc_FR/LC_MESSAGES/messages.mo differ diff --git a/locale/pl_PL/LC_MESSAGES/messages.mo b/locale/pl_PL/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..ed781a0 Binary files /dev/null and b/locale/pl_PL/LC_MESSAGES/messages.mo differ diff --git a/locale/pt_BR/LC_MESSAGES/messages.mo b/locale/pt_BR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..ab7cad5 Binary files /dev/null and b/locale/pt_BR/LC_MESSAGES/messages.mo differ diff --git a/locale/ru_RU/LC_MESSAGES/messages.mo b/locale/ru_RU/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..feeb91e Binary files /dev/null and b/locale/ru_RU/LC_MESSAGES/messages.mo differ diff --git a/locale/sk_SK/LC_MESSAGES/messages.mo b/locale/sk_SK/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..d02eb47 Binary files /dev/null and b/locale/sk_SK/LC_MESSAGES/messages.mo differ diff --git a/locale/sv_FI/LC_MESSAGES/messages.mo b/locale/sv_FI/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..83f78db Binary files /dev/null and b/locale/sv_FI/LC_MESSAGES/messages.mo differ diff --git a/locale/tr_TR/LC_MESSAGES/messages.mo b/locale/tr_TR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..d547e71 Binary files /dev/null and b/locale/tr_TR/LC_MESSAGES/messages.mo differ diff --git a/locale/uk_UA/LC_MESSAGES/messages.mo b/locale/uk_UA/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..c461e15 Binary files /dev/null and b/locale/uk_UA/LC_MESSAGES/messages.mo differ diff --git a/locale/zh_CN/LC_MESSAGES/messages.mo b/locale/zh_CN/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..b49a118 Binary files /dev/null and b/locale/zh_CN/LC_MESSAGES/messages.mo differ diff --git a/locale/zh_TW/LC_MESSAGES/messages.mo b/locale/zh_TW/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..7a20875 Binary files /dev/null and b/locale/zh_TW/LC_MESSAGES/messages.mo differ diff --git a/queries/SambaUsers.xml b/queries/SambaUsers.xml new file mode 100644 index 0000000..70220f6 --- /dev/null +++ b/queries/SambaUsers.xml @@ -0,0 +1,32 @@ + + + + +Samba User List + + + + +Samba Users +ldap-user.png +sub +1 + + + + Common Name + 1 + 2 + + + User ID + 2 + 1 + + + Samba Home Directory + 3 + 3 + + + diff --git a/queries/UserList.xml b/queries/UserList.xml new file mode 100644 index 0000000..b670fc1 --- /dev/null +++ b/queries/UserList.xml @@ -0,0 +1,42 @@ + + + + +User List + + + + +User List +ldap-user.png +sub +1 + + + + Common Name + 1 + 2 + + + User ID + 2 + 1 + + + Home Directory + 3 + 3 + + + Telephone Number + 4 + 4 + + + Photo + 5 + 5 + + + diff --git a/queries/query.dtd b/queries/query.dtd new file mode 100644 index 0000000..99a8213 --- /dev/null +++ b/queries/query.dtd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/creation/alias.xml b/templates/creation/alias.xml new file mode 100644 index 0000000..3c803d1 --- /dev/null +++ b/templates/creation/alias.xml @@ -0,0 +1,32 @@ + + + + diff --git a/templates/creation/courierMailAccount.xml b/templates/creation/courierMailAccount.xml new file mode 100644 index 0000000..b7602ab --- /dev/null +++ b/templates/creation/courierMailAccount.xml @@ -0,0 +1,91 @@ + + + + diff --git a/templates/creation/courierMailAlias.xml b/templates/creation/courierMailAlias.xml new file mode 100644 index 0000000..9a53196 --- /dev/null +++ b/templates/creation/courierMailAlias.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/dNSDomain.xml b/templates/creation/dNSDomain.xml new file mode 100644 index 0000000..4a98054 --- /dev/null +++ b/templates/creation/dNSDomain.xml @@ -0,0 +1,32 @@ + + + + diff --git a/templates/creation/example.xml b/templates/creation/example.xml new file mode 100644 index 0000000..812b707 --- /dev/null +++ b/templates/creation/example.xml @@ -0,0 +1,38 @@ + + + + diff --git a/templates/creation/inetOrgPerson.xml b/templates/creation/inetOrgPerson.xml new file mode 100644 index 0000000..6469221 --- /dev/null +++ b/templates/creation/inetOrgPerson.xml @@ -0,0 +1,96 @@ + + + + diff --git a/templates/creation/kolabPerson.xml b/templates/creation/kolabPerson.xml new file mode 100644 index 0000000..8be2e6b --- /dev/null +++ b/templates/creation/kolabPerson.xml @@ -0,0 +1,109 @@ + + + + diff --git a/templates/creation/mozillaOrgPerson.xml b/templates/creation/mozillaOrgPerson.xml new file mode 100644 index 0000000..dc39a73 --- /dev/null +++ b/templates/creation/mozillaOrgPerson.xml @@ -0,0 +1,161 @@ + + + + diff --git a/templates/creation/organizationalRole.xml b/templates/creation/organizationalRole.xml new file mode 100644 index 0000000..85e595a --- /dev/null +++ b/templates/creation/organizationalRole.xml @@ -0,0 +1,77 @@ + + + + diff --git a/templates/creation/ou.xml b/templates/creation/ou.xml new file mode 100644 index 0000000..6e0f45a --- /dev/null +++ b/templates/creation/ou.xml @@ -0,0 +1,27 @@ + + + + diff --git a/templates/creation/posixAccount.xml b/templates/creation/posixAccount.xml new file mode 100644 index 0000000..ce4a474 --- /dev/null +++ b/templates/creation/posixAccount.xml @@ -0,0 +1,95 @@ + + + + diff --git a/templates/creation/posixGroup.xml b/templates/creation/posixGroup.xml new file mode 100644 index 0000000..6f8d26b --- /dev/null +++ b/templates/creation/posixGroup.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sambaDomain.xml b/templates/creation/sambaDomain.xml new file mode 100644 index 0000000..563828e --- /dev/null +++ b/templates/creation/sambaDomain.xml @@ -0,0 +1,33 @@ + + + + diff --git a/templates/creation/sambaGroupMapping.xml b/templates/creation/sambaGroupMapping.xml new file mode 100644 index 0000000..c93745c --- /dev/null +++ b/templates/creation/sambaGroupMapping.xml @@ -0,0 +1,70 @@ + + + + diff --git a/templates/creation/sambaMachine.xml b/templates/creation/sambaMachine.xml new file mode 100644 index 0000000..fe5e5d3 --- /dev/null +++ b/templates/creation/sambaMachine.xml @@ -0,0 +1,67 @@ + + + + diff --git a/templates/creation/sambaSamAccount.xml b/templates/creation/sambaSamAccount.xml new file mode 100644 index 0000000..d44fad8 --- /dev/null +++ b/templates/creation/sambaSamAccount.xml @@ -0,0 +1,133 @@ + + + + diff --git a/templates/creation/sendmailMTAAliasObject.xml b/templates/creation/sendmailMTAAliasObject.xml new file mode 100644 index 0000000..86688b6 --- /dev/null +++ b/templates/creation/sendmailMTAAliasObject.xml @@ -0,0 +1,48 @@ + + + + diff --git a/templates/creation/sendmailMTAClass.xml b/templates/creation/sendmailMTAClass.xml new file mode 100644 index 0000000..9bbde8e --- /dev/null +++ b/templates/creation/sendmailMTAClass.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sendmailMTACluster.xml b/templates/creation/sendmailMTACluster.xml new file mode 100644 index 0000000..08bba5c --- /dev/null +++ b/templates/creation/sendmailMTACluster.xml @@ -0,0 +1,26 @@ + + + + diff --git a/templates/creation/sendmailMTAMapObject.xml b/templates/creation/sendmailMTAMapObject.xml new file mode 100644 index 0000000..5f4afd5 --- /dev/null +++ b/templates/creation/sendmailMTAMapObject.xml @@ -0,0 +1,53 @@ + + + + + + diff --git a/templates/creation/sendmailVirtualDomain.xml b/templates/creation/sendmailVirtualDomain.xml new file mode 100644 index 0000000..b2c1047 --- /dev/null +++ b/templates/creation/sendmailVirtualDomain.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sendmailVirtualUser.xml b/templates/creation/sendmailVirtualUser.xml new file mode 100644 index 0000000..c046991 --- /dev/null +++ b/templates/creation/sendmailVirtualUser.xml @@ -0,0 +1,54 @@ + + + + + + diff --git a/templates/creation/simpleSecurityObject.xml b/templates/creation/simpleSecurityObject.xml new file mode 100644 index 0000000..2cb2000 --- /dev/null +++ b/templates/creation/simpleSecurityObject.xml @@ -0,0 +1,37 @@ + + + + diff --git a/templates/modification/inetOrgPerson.xml b/templates/modification/inetOrgPerson.xml new file mode 100644 index 0000000..b7f17e9 --- /dev/null +++ b/templates/modification/inetOrgPerson.xml @@ -0,0 +1,85 @@ + + + + diff --git a/templates/modification/posixGroup.xml b/templates/modification/posixGroup.xml new file mode 100644 index 0000000..f761c3a --- /dev/null +++ b/templates/modification/posixGroup.xml @@ -0,0 +1,43 @@ + + + + diff --git a/templates/template.dtd b/templates/template.dtd new file mode 100644 index 0000000..64ed786 --- /dev/null +++ b/templates/template.dtd @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/po/Makefile b/tools/po/Makefile new file mode 100644 index 0000000..0f596d1 --- /dev/null +++ b/tools/po/Makefile @@ -0,0 +1,65 @@ +#!/bin/bash +# +# Makefile Utility to manipulate PO and POT files +# Copyright (c) 2009 Alessandro De Zorzi - +# +# This code is part of phpLDAPadmin +# http://phpldapadmin.wiki.sourceforge.net +# Released under the same licence of phpldapadmin +# +# Current target list: +# +# all display target +# all-mo compile .mo files from .po translation available +# pot create a update main POT file +# all-merge merge last POT with each current translations (re-create POT) +# all-merge-pot merge last POT with each current translations + +LOCALEDIR = ../../locale +TEMPLATEFILES=`find ../../templates -iname *xml -exec echo -m {} \;|grep -v /test_|grep -v /custom_` +EXPORTFILE = $(shell echo $${EXPORTFILE:-/tmp/launchpad-export.tar.gz}) + +all: + @echo Please, specify a target [pot, xml-pot, all-mo, all-merge, all-merge-pot, launchpad-export] + +all-mo: + @for i in `ls -1 $(LOCALEDIR)` ; \ + do \ + if [ -f $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po ]; then \ + echo Processing: $$i ; \ + msgfmt -v -c --statistics $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po -o $(LOCALEDIR)/$$i/LC_MESSAGES/messages.mo; \ + fi \ + done + + +pot: + @po4a-gettextize -o tags=" <description> <display> <hint>" -o tagsonly=1 -f xml $(TEMPLATEFILES) -p messages.pot + @find ../../ -name *.php -exec xgettext --keyword=_ -L PHP -j --omit-header -o messages.pot -s {} \; + @find ../../ -name *.inc -exec xgettext --keyword=_ -L PHP -j --omit-header -o messages.pot -s {} \; + @echo messages.pot created, you might like to change the header with contents of messages.header + +all-merge: pot +all-merge-pot: + @for i in `ls -1 $(LOCALEDIR)` ; \ + do \ + if [ -f $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po ]; then \ + echo Processing: $$i ; \ + msgmerge -v $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po messages.pot -o $$i.po; \ + mv $$i.po $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po; \ + fi \ + done + +launchpad-extract: + @[ ! -r $(EXPORTFILE) ] && echo "No export file [$(EXPORTFILE)] found?" && exit 1 || true + @cd $(LOCALEDIR); tar xzf $(EXPORTFILE) + @rm -f $(LOCALEDIR)/phpldapadmin/phpldapadmin-uk.po + @rm -f $(LOCALEDIR)/phpldapadmin/phpldapadmin.pot + @find $(LOCALEDIR) -name phpldapadmin-\*.po | while read i; do newi=$$(echo $$i| sed -r 's/phpldapadmin-(.*).po/..\/\1\*\/LC_MESSAGES\/messages.po/'); mv $$i $$newi; done + rmdir $(LOCALEDIR)/phpldapadmin + +launchpad-export: launchpad-extract all-mo + +launchpad-import: + @[ -d /tmp/pla ] && rmdir /tmp/pla + @mkdir /tmp/pla + @for i in $(LOCALEDIR)/*/LC_MESSAGES/messages.po; do echo $$i; x=$${i##$(LOCALEDIR)/}; x=$${x/_??\/LC_MESSAGES\/messages/}; [ ! -e /tmp/pla/$$x ] && cp $$i /tmp/pla/$$x || echo "$$x Already exists!"; done diff --git a/tools/po/messages.header b/tools/po/messages.header new file mode 100644 index 0000000..9cfb2fe --- /dev/null +++ b/tools/po/messages.header @@ -0,0 +1,15 @@ +# phpLDAPadmin +# + +msgid "" +msgstr "" +"Project-Id-Version: phpldapadmin\n" +"Report-Msgid-Bugs-To: phpldapadmin-devel@lists.sourceforge.net\n" +"POT-Creation-Date: 2004-01-14 17:45+0200\n" +"PO-Revision-Date: 2004-01-14 17:45+0200\n" +"Last-Translator: Unknown <Unknown>\n" +"Language-Team: phpLDAPadmin <phpldapadmin-devel@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + diff --git a/tools/unserialize.php b/tools/unserialize.php new file mode 100644 index 0000000..2a35e60 --- /dev/null +++ b/tools/unserialize.php @@ -0,0 +1,26 @@ +<?php + +require '../lib/common.php'; + +echo '<head><link type="text/css" rel="stylesheet" href="../htdocs/css/style.css" /></head>'; +echo '<body>'."\n"; +$index = get_request('index','REQUEST'); +if (! isset($_SESSION['backtrace'][$index])) + die('No backtrace available...?'); + +$line = $_SESSION['backtrace'][$index]; +echo '<table class="result_table">'; +printf('<tr class="hightlight"><td colspan="2"><b><small>%s</small></b></td><td>%s (%s)</td></tr>', + _('File'),isset($line['file']) ? $line['file'] : $last['file'],isset($line['line']) ? $line['line'] : ''); + +printf('<tr><td> </td><td><b><small>%s</small></b></td>', + _('Function'),$line['function']); + +echo '<td><small><pre>'; +print_r($line['args']); +echo '</pre></small></td>'; + +echo '</tr>'; +echo '</table>'; +echo '</body>'; +?>