phpQLAdmin 2.3 Change Log phpQLAdmin 2.3.7 Release (May 10 2007) Bug fixes - Almost a complete rewrite of the automount manager: + Support creating a submount (mountpoint link) + Function to get the all the mountpoints recursivly (mountpoint link on a mountpoint link) using attribute_find_mountpoints(). + Catch the iso9660 mount options already availible in the form. + Option to specify to which physical host to add the mountpoint - Doh! + No longer any need to fetch the physical host DN - we're already called with that information. + Simplification on retreiving the automount information about specific mountpoint when modifying an existing object - we already know the DN of the mountpoint! + Also no need to retreive/'calculate' the base mount for the mountpoint in question - that information is also already availible in the call to attrib.automount.inc:attribute_save(). + Remove the option to insert the 'Search DN' of the new automount link. To complicated - that can be calculated... + If the host never had a automount before, the auto.master object must first be created when adding an automount. + Fix the very broken 'modify automount' part which used '$_REQUEST["domain"]' which isn't availible and is also wrong. + Catch a new object (if changing mountpoint for example) when asked to modify. - Small fixes in regards of deleting DNS host(s) when we're removing a web server virtual host. + Don't do this by default if we have round-robin hosts for this vhost. + The 'Delete any DNS host entries' question must be a radio button, not a checkbox - we must be able to distinguish set and unset. - Reword 'Create DNS object' to 'Create or Update DNS object' in creating web server (etc) which is more in line what it actually does... + Don't check the 'Update QLC object(s)' by default. + Urldecode the $_REQUEST["host"] before use (so that it can be used in the setting of $_REQUEST["server"] which is needed to be able to show the new object). - Fix the changing of record type (from CNAME to A record for example) in the DNS manager - Catch a physical host with a webserver container, but no virtual hosts. > Make sure this container is 'remembered'. GUI layout changes - Support for copying or moving a virtual host from one physical webserver to another. - Disable the 'Create DNS object' checkbox when adding a new physical host. It's not implemented in host_add.php anyway and the question is missleading. - Enable a 'Create or Update DNS object' when copying or moving a virtual host from one webserver to another. + Also change the IP address of/in the virtual host to the new location. - Long standing problem/bug finaly fixed - initial folded branch tree in Opera! Many thanx to Jose Silva @ PT for this fix! API changes Misc changes - Move all the 'if debug die, othervise call pql_header()'. Had to make a small API change to pql_header() for this to work propperly - a 'force' option which bypasses the 'if debug die' thing... - When deleting a virtual host/webserver or physical host, don't try to show the just deleted object! Unset the relevant variable(s) and show the object 'one step up'. phpQLAdmin 2.3.6 Release (Mar 5 2007) Bug fixes - Also removed lan password auth from samba, almost all windows users using at least win2k by this point and the lan man protocol can be easily cracked - Fixed the samba code to no longer rely on the mkntpasswd program, you can now download and use Crypt_CHAP from pear - Fixed sudo plugin to display when selected - Better regexp to try to find out if a value is a DN in include/pql_formating.inc:pql_format_table_single()' - If there's no web server containers, we must still return the list of physical hosts in include/pql_websrv.inc:pql_websrv_get_data(). This so that we can retreive any QLC objects in those physical hosts. - Enclose all DN's in any ldapsearch command line within citation marks. This to escape any space(s) in the DN's. - In the file tables/host_details-websrv.inc, we need to check if physical_data is both an array AND contain more than one entry (count() don't seem to work correctly if the variable is unset/empty!). - PHP parse error fixed in tables/host_details-websrv.inc. - Don't use '$server_dn' in referencing the physical host (in tables/host_details-websrv.inc). Use '$_REQUEST["host"]' instead (which is always set/correct). - Make sure the link_url variable is unset before going through the Round-Robin stuff. This so that we don't get the links from the PREVIOUS table entry (Rewrite Rules). - Remove third param (server FQDN) to include/pql_search.inc:pql_get_automount_maps(). - When moving automount maps (with scripts/upgrade_hostmerge.pl), we must remember each object DN. + Before adding a automount map/entry, make sure it's not a LDAP link/reference. = This so that we can change any 'automountInformation' which is LDAP mountpoints (i.e. LDAP referenced). Add any LDAP links/references at the end of all addition. - Only cache an object (in include/pql_search.inc:pql_search()) if there's more than one attribute in the retreived object (this so that we don't cache an 'empty' - only objectClass retreived - object). - IDNA decode all DN's found in include/pql_search.inc:pql_get_dn(). - IDNA decode the branch DN in the domain/branch details page. - If a domain/branch have a default domain and (multiple) additional domains, the user/admin chooses one of the domains as his/her primary - make sure we don't add the same domain TWICE (by making sure it's not equal to the primary mail address domain)! - In domain_add.php, initialize and increase '$j', but check for '$i < count($admins)'. Oups! + Also when adding 'admin[$i]' to 'entry[administrator]', '$j' was used. - In newer PHP (> 4.3), there can be NO (!) output before a header("location: ...") command. So only include header.html and output a page header in domain_add.php if running in debug mode. - Simplify addin admin to PQL_CONF_REFERENCE_DOMAINS_WITH attribute ACI in include/config.inc.CHANGE_ME:user_generate_aci() (branch option). + There's TWO lines of action when adding an admin to 'full access' ACI lines. - Fix so that domain_edit_attributes.php knows WHICH attributes (exactly!) that uses the 'fulldomain' option (there's only four). - Force additionalDomainName variable in user_add.php to array. - As of PHP 4.3, the header() function have changed behaviour! It no longer allows overriding the HTML header. It dies if data have already been sent (or {ob_}flush() have been called which it is in pql_flush()). Solution: Don't call {ob_}flush() if headers have already been sent. - Redundant retrieval of objectClasses in user_add.php removed. - Optimize include/pql_search.inc:pql_get_subschemas() by making sure that the cn=Subschema (or whatever subschemaSubentry in DN '') is cached. + Fix some API use error in include/pql_search.inc:pql_get_subschemas(). + Figure out if to use caching in include/pql_search.inc:pql_search() ONCE, then use that information in the rest of the function. - Finish/fix the 'User picture upload': + More error checking. + Retreive file from $_FILES, not $_REQUEST. + Delete uploaded file after loading it into LDAP. + Add the ./tmp' directory (and a .htaccess which denies read). - The include/pql_control.inc:pql_control_update_domains() needs to do a SUB search, not a ONELEVEL to find all QLC objects. - Don't add new additional domain name to QLC objects if not PQL_ATTR_CONTROL_USE is set. - Support _removing_ a value in include/attrib.outlook.inc. - When giving specific user Super admin rights, don't forget to add all the OLD values to the list/array of administrators in include/attrib.administrator.inc:attribute_save(). - Make sure that there ARE any forwarding addresses to the user to delete in include/pql_write.inc:pql_user_del(). - Add the domain (and 'ou=') to the user DN if subbranch is defined. - Move the check for debugging from include/attrib.dnszone.inc:attribute_save() to bind9_edit_attributes.php:attribute_forward(). - Make sure that 'type' is always set as a hidden value (to make sure it survive to bind9_edit_attributes.php). - Catch flat object returned by pql_search() in include/pql_bind9.inc:pql_bind9_get_ttl(). - Don't modify a QLC when adding a domain if the domain already exists. - Only create the sub-zone in include/pql_bind9.inc:pql_bind9_add_host() if it's not a PTR record we're adding. Function is already called with correct information. - Fix PTR host additions in bind9_add.php: + No point in binding to LDAP server again - we're already bound. + The PTR record (IP address) is in '$_REQUEST["dest"]', not '$_REQUEST["hostname"]'! + The PTR record (host name) is in '$_REQUEST["hostname"]', not '$_REQUEST["dest"]'! + Be smarter when setting up the reverse/in-addr.arpa entry from IP address. - I can't ever remember which is which when creating a PTR record, so allow IP/Hostname to be set in any of the Source/Destination inputs of bind9_add.php. - Disable debugging temporarily in config_ldaptest.php if enabled - this so that a true test can actually be done even if debugging. - Must lowercase the user DN from 'host_users' when compared to (already lowercased) value from 'users' in tables/host_details-acl.inc. - Don't do ONELEVEL search when looking for QLC object(s) - do sub (below ou=Computers,). - host_edit_attribute.php:attribute_forward() needs to call host=XXX with the DN of the host, not it's FQDN. + Faulty use of ! (not) - s/if(!attribute_check())/if(attribute_check())/. - When adding a object in include/pql_write.inc:pql_write_add(), make sure that the DN entry of the object isn't set - ldap_add() refuses to add the object if it is. - Fix the tables/host_details-automount.inc to call host_edit_attribute.php instead of host_modify.php (which is used to modify 'Host Control' information). + Don't call with 'submit=X', it confuses host_edit_attribute.php. + Call with 'attrib=autoMountInformation' to make sure the correct plugin is used. - Add support for ext2/ext3 in include/attrib.automount.inc:attribute_setup() to create a correct mount info line with all options choosen. + Ask for (and insert) the device if it's a filesystem that uses it. + Setup the DN to mountpoint(s) based on the physical host DN, not $_REQUEST["host"], PQL_CONF_SUBTREE_AUTOMOUNTS $_REQUEST["domain"] etc. That way it's ALWAYS correct. + Default filesystem for form is ext3. + If form is reloaded, make sure that all checkbox/radio buttons selected STAYS selected. + When saving new automount object, retreive the ACI's from it's parent and use that (unmodified) for the new automount object as well. - When creating a new user, it's possible that the subbranch contains ALL that's needed (ou=People,, etc). Catch this. - When changing [ug]idNumber, REPLACE value, don't ADD it. - Rearrange code in domain_add.php - first check if debuging, THEN if to run create domain script. - Replace ldap_explode_dn() with split() in left.php. The former didn't do the job it was supposed to... - If port isn't known in class _pql->connect(), then don't call ldap_connect() with it... - Don't run domain/branch DN through IDNA decode in tables/domain_details-default.inc. Already done. - If $_REQUEST["pwscheme"] is already known (reload's etc) in tables/user_add-details.inc, then use that as scheme. - Don't decode the user DN in include/attrib.administrator.inc:attribute_print_form() - it's already done. - Don't output error on faulty regexp (in a eregi() call) in include/attrib.dnszone.inc:attribute_print_form(). - For include/attrib.dnszone.inc:attribute_print_form() to work propperly (insert old value), all options to bind9_edit_attributes.php have a 'type='. But there must also be a '=' option... - websrv_edit_attributes.php should call host_detail.php, not domain_detail.php. + rootdn and domain values are not used/known. Use host instead. - In include/attrib.dnszone.inc we need to generate/figure out the SOA DN (for updating the SOA version) for the object we're modifying a LOT earlier. This because if the object is removed, it's not possible to find the SOA. + When modifying an object (such as when removing ONE IP from a round-robin host), we shouldn't remove the whole object, but only the specific value. If there's only one, THEN remove the whole object... + Include record type and record value in call to bind9_edit_attributes.php if it's a host AND action is delete. This so that we should be able to delete ONE entry of a round-robin host. + Duplicate check for PQL_CONF_DEBUG_ME - it's already done in pql_write_del(). - In include/attrib.websrv.inc, remember the host value. It's needed in the attribute_forward(). - Include physical server in call to websrv_edit_attributes.php in all webserver details links. This so that any modification is correctly redirected to the correct virtual host etc. + When showing virtual server aliases, if the value returned isn't an array (as when there's only ONE alias), then MAKE it an array. This instead of adding more almost-duplicate code (showing of the value(s)). - Make sure to unset the links value in left.php which is used in pql_left_htmlify_userlist() to get a list of users in a branch/subunit fold. + Fix the output in frame if showUsers is unset. - Increase the parent counter correctly in config_ldap.php to make fold/unfold work on the correct fold. - Fix some array usage bugs in dump_object.php + Don't output the '--- DEBUG ---' stuf. - Change the way host_modify.php finds physical hosts (previosly it also found webserver stuff). - When changing deliveryMode, make sure that any combination of change is really saved to the LDAP database - previosly only ADDITIONS was done. - If user specifies quota value(s), but forgot to tick 'User defined', this should be changed in the code - broke sometime ago for some reason. - Simplify/bugfix retreival of additional groups in user_detail.php. - Don't hardcode the DN to the additional group in include/attrib.additionalgroup.inc:attribute_save(). Try to find it by doing a search. - Fix changing password - scheme was empty, so it was known which to use. - Changing a login shell should REPLACE the existing value, not add to it. - When giving a user controls/webserver administration rights, DON'T give them FULL access. I.e. they should NOT have access to create physical hosts etc - that's only for the super admin. Hence, don't give them access to the control search DN nor the physical hosts, only to the QLC _or_ the webserver containers (and their localtion objects). GUI layout changes - Don't show the Kerberos info in the user add details page if KERBEROS isn't an option to choose from. - Don't output the '@' separator between recipient part and email domain if there IS no domain to output in the user add details page. - Change wording of 'Miscellaneous' in tables/domain_details-owner.inc to 'Additional information' which is ... better. - When adding a webserver or DNS domain to a domain/branch, offer to update additionalDomainName and QLC object(s). + 'Update QLC object(s)' checked by default. + Change 'Create DNS object' to checked by default. - Decode DN and all values in pql_create_ldif(). - Separate the 'PHP Extensions needed' in 'Home->phpQLAdmin Configuration->Test LDAP-Connection'. + Add checks for more modules: idn, mhash, memcache, gd and krb5. + Note about enabling ACI's if test w/o ACI failed, but test w/ ACI worked. - Move the 'Force Strong Passwords' out of 'Plugin configuration' and into 'Behaviour config' (a couple of lines down). - Manage (i.e. SHOW only) Sudo Administration in Computers->Global and Computers-[physical server]. - Show a 'DNS Administration' in Computers->Global (and a list of ALL DNS domains in a 'DNS Zones - Global' below the Global branch). - Support setting TXT records for hosts in DNS manager. - Support changing aRecords globaly (replace IP1 with IP2 in the whole database). + Also replace some other attributes with IP address in them. + Put link to this in both 'Computers->Global->DNS Administration->Actions' as well as below the 'Global->DNS Zones - Global' branch. - Separate the User and LDAP server info, logout button, advanced mode selector and the 'Home' branch from user lists into two separate tables. - Refuse login to phpQLAdmin if user status isn't active or nopop. In all other cases, refuse login with "Can't find you in the database". - In the user details->Forwarders to other accounts view, show the deliveryMode value(s). - Change wording of 'Forwarders to other accounts' to simply 'Mail forwarding'. - When changing dot mode, there's an option that reads 'default taken from ldapDefaultDotMode'. Get that value and inform user about it. - If user is super administrator, there's litte point in showing/retreiving information about which branches the user is administrator of - a super admin have access to ALL branches! - In pql->search() method, save the jpegPhoto in the array as a base64 encoded value. + base64_decode() the photo value before use in tables/user_details-personal.inc. - Put a counter next to the email alias in User details->Registered address to keep track on how MANY aliases there are. - Instead of showing the uid value of a user allowed access to a physical host in 'Domain details->Host Control->Host Control Access', "translate" to a 'human readable' value using pql_left_htmlify_userlist() - Add support for the Password Policy overlay in OpenLDAP >2.3. Not complete, but the core is there with new objectclass phpQLAdminPasswordPolicy which should be used in combination with pwdPolicy. - Support the Accesslog overlay with filtering possibilities from config_ldap.php. API changes - Rewrite (simplify) the API. Move the following function into include/pql.inc as methods of the pql class: include/pql_search.inc:pql_search(), include/pql_search.inc:pql_get_attribute(), include/pql_search.inc:pql_get_dn() include/pql_write.inc:pql_write_add() include/pql_write.inc:pql_write_mod() include/pql_write.inc:pql_write_del() include/pql_write.inc:pql_write_ren() + This lead to changes in the rest of the API as well. No need to call functions with the LDAP linkid any more. Instead, since the pql class handle is global any way, just import it in any functions that need it. - Prefix the kadmin_* functions with the usual 'pql_' prefix. - Rewrite the sudoers plugin to be more like rest of phpQLAdmin (i.e. file include/attrib.sudoers.inc, sudo_add.php, sudo_detail.php and sudo_modify.php instead of one, big, huge 'sudo_modify.php' which did everything. - Extra option to pql->search() added: encode (yes or no - default no for backward compability). + Make sure to leave (if encode=1) all values un-decoded. This so it/they can be used in/by dump_object.php to create a usable LDIF from/of the object(s) where encoded values won't be usable if (re)loaded into an LDAP database.. - Speed up domain_detail.php by only retreving the attributes of interest for the specific view. - Move all HTML from config_ldap.php to tables/config_ldap-monitor.inc - Move all HTML, verification and saving from config_template_add.php to include/attrib.config.template.inc. - Speed up pql_templates_check_attribute() (which previosly was VERY expensive) by removing the retreival of the template attributes (using pql_templates_attributes()). This in turn retreives all subschemas using pql_get_subschema(). Even if cached, it's still a couple of meg of data that have to be retreived EVERY TIME an attribute is checked - hence VERY expensive. Insted do this (retreiving the template attributes) ONCE (in user_add.php just after getting the template. Misc changes - Added Strong password option to meet SOX & DSS/PCI compliance - Added branch option to start in users own account when logging in (this is experimental don't use in production) - Prettier debug output in include/pql_search.inc:pql_search() - Explain 'null host' in 'include/attrib.control.smtproutes.inc:smtproutes_help()' - When adding a branch admin in include/attrib.administrator.inc:attribute_save(), we must make sure that any user templates' ACI is also updated. This so that a branch admin can READ templates (so he/she will be able to add users!). - Lowercase home/mail directory values when creating domain. - Support for global memory cache for speed increase. Uses memcached and memcache.so PECL module. See doc/README.Memcache. - Find out if we're running OpenLDAP v2.2 or v2.3. This is used in figuring out if the Scope should/could be changed. + Add 'public' to the list of actions. + Take the next number of ACI's as OID. - Support multiple A records to domain in tools/dnszonetemplate.php. + IDNA decode hostname. - Just before saving (adding) an object to the database, check the ACI's. OpenLDAP change the syntax in 2.3 and I didn't notice because I never upgraded). - Split tables/domain_details-dnszone.inc into three files/parts. One with the retreival etc, one with the SOA display and one with HOST display. phpQLAdmin 2.3.5 Dec 2 2006 Bug fixes - Correctly verify user (different depending on what PQL_CONF_REFERENCE_USERS_WITH is set to - uid or sn). - pql_format_error_span() needs to be prefixed/called with 'echo' to get any output. - Faulty include/attrib.dnszone.inc:attribute_translate_type(). Tried to verify $_REQUEST["attrib"] instead of param to function ('$attrib'). - Form value 'type' was overwritten by a hidden input in include/attrib.dnszone.inc:attribute_print_form(). - The pql_search() might return a 'flat' array in include/pql_bind9.inc:pql_bind9_update_serial(), therefor check both 'is_array($object[0])' AND 'is_array($object)'. - Setup missing $_REQUEST["view"] value _before_ any pql_generate_button(). - Send '&mark=yes' to tools/navbutton.php IF the button is mentioned in $_REQUEST["view"]. - In tools/navbutton.php, make the text red if called with the 'mark' value. - pql_get_status() might return empty array in status_ldap.php, so can't check for just '$tmp'. Use $tmp[createtimestamp] and $tmp[monitortimestamp]. - In include/pql_status.inc:pql_get_status(), the call to count($entry[0][$attrib]) might return '2'. This mean '0' and '1' but '1' is empty. Deduct one from the count to make sure we get the value correctly. - ldap_read() must be called with additional fourth parameter (attributes to retreive) as 'array(+)' if one wants the operational attributes. This works on OpenLDAP, but might break other LDAP servers... - Ignore a missing serverip form value if more than one web server container is selected. - Calculate (and extract all hosts) selected at the 'Create virtual host' link as early as possible - before checking if 'serverip' is set (not needed if more than one web server container is selected). - Don't add a trailing slash after server URL (hu?!?). - When creating the DNS SOA record object, include 'dNSTTL=xxx ' in the DN. - Bug fix merges from BRANCH_HOST_MERGE: + De-globalize 'ok' value in bind9_del.php + Remember the 'type' throughout the additionalDomainName form. + When _adding_ a additionalDomainName, the object needs to be setup. + Be more restrictive on WHEN to add the ACI attributes in attrib.administrator.inc. + Faulty use of pql_modify_attribute() in attrib.control.ldapcluster.inc (need fourth param to be '1', not ''). + Duplicate (and wrong!) define of PQL_ATTR_WEBSRV_SRV_NAME removed. + The values returned with pql_search() in include/pql_bind9.inc:pql_bind9_get_acis() can be a flat array. Catch this. + Make sure that pql_bind9_add_host() isn't adding a value that already exists. + Can't use 'if(empty(...))' in include/pql_config.inc:pql_set_define(). It doesn't catch if the value is '0'! use 'if(!isset(...))' instead. + Bugfix for #203 accidently CREATED an empty array entry if 'domain' value didn't exists. Rewrite it so it doesn't happen. Prettier debugging :) + Only generate the ACI entry if there isn't already ACI values! + Catch flat objects returned by pql_search() in include/pql_websrv.inc:pql_websrv_get_virtual_host_objects(). + Make sure that the 'super_admin' value isn't overwritten in tables/user_details-access.inc. If there are _more_ than one root/suffix in the database and the user is super admin in the first, but not in the second, then the value was overwritten... + Don't show the option (in domain details->default) for Mailinglist administrators if useEzmlm isn't true. + The branch links doesn't have the 'view=' value. And instead of having the root DN twice (first in the 'rootdn=' option and then in the 'view='), 'convert' it in config_detail.php + If there's only ONE branch, this is the one we look for users in (previously it was either MORE than one or LESS than one, not 'less than or equal to one'). + An update to left.php 'previosly' changed the filter for retreiving users: '(&(uid=*)(|(mail=*)(samaSID=*)))'. If there's no mail accounts and no Samba accounts, phpQLAdmin won't find users. Update the demo database with some mail addresses. + Don't do a ldap_read() to find out if cn=Monitor exists. It never returns false it seems! Use pql_get_attribute() instead... + Catch possible flat object from pql_search() in pql_bind9_get_zone(). + The DN of a SOA record object must have a '+' between the dNSTTL section and relativeDomainName. + Managed to swap the minus/plus icons as initial state of the tree view. GUI layout changes - RDN and FQDN should not be shown in if we're viewing the 'Global' QmailLDAP/Control frame. - Bug fix merges from BRANCH_HOST_MERGE: + Don't show the DN in Mailserver header. Use the FQDN instead. + Don't show a blue background if left-head.html isn't called from left*.php + Verbose about loading the include/defaults.inc file (if .DEBUG_ME exists) in include/pql_config.inc. + Cleanup the HTML in include/pql_formating.inc:pql_generate_button(). Buttons is yet again left justified (I'm not sure if the 'center' justification was on purpose or not, but I didn't like it). - Same fix for pql_format_status_msg(). Message was center justified, and it wasn't very pretty. + Fix calculation on how many ' 's to output in include/pql_formating.inc:pql_format_tree_span(). It's now more aligned with line(s) above. + Merge all host/computer related things into ONE frame (the one previosly called 'QmailLDAP/Controls', now just 'Computers'). From there, one accesses physical hosts, their webserver containers and _their_ virtual hosts. Via the physical host link, it's possible to also access the RADIUS and Automount information for that host. + Some wording changed here and there. + Separate EZMLM and Kerberos configuration in tables/config_details-global.inc into 'hidden' tables if not manager(s) is not enabled. + Move the domain access information into it's own view table - 'Branch access' - instead of having it clutter the 'Branch Defaults' view. + Move the user access information into it's own view table - 'User access' - instead of having it clutter the 'User data' view. + No more Automounts information details in the branch/domain views. It is moved to host details instead due to the new 'concentrated host view' system. + Now only possible to create a template zone (in the domain/branch DNS view) file if super admin. + Rewrite the way webserver information is displayed in the domain/branch details view. Now only shows the virtual host(s) the domain have access to (choosen with the help of default and additional domain name(s)). + Only show the 'Delete user' link if it's not yourself. No point in offering to delete your own object, since phpQLAdmin won't let you any way. Schema changes - Merge from BRANCH_HOST_MERGE: + Support setting (simple) debug mode in LDAP. Replace all checks for the file './.DEBUG_ME' with pql_get_define("PQL_CONF_DEBUG_ME") commands. runInDebugMode 1.3.6.1.4.1.8767.3.2.1.37 (toggle) + Support for having (simple) RADIUS information in LDAP. useRadius 1.3.6.1.4.1.8767.3.2.1.36 (toggle) radiusConfigIdentity 1.3.6.1.4.1.8767.3.2.4.26 (string) + Support for setting access control over web and mail information. webSrvAdministrator 1.3.6.1.4.1.8767.3.2.4.27 (dn) dNSAdministrator 1.3.6.1.4.1.8767.3.2.4.28 (dn) phpQLAdminWebACL 1.3.6.1.4.1.8767.3.1.9 (objectClass) API changes - Merge from BRANCH_HOST_MERGE: + Quite extensive rewrite of a lot of file, to numerous to mention, to suite the new 'concentrated host view' system. Retreive web/mail admins, setup main view buttons + A lot of new files (mainly host_* and tables/host*) which deals with showing relevant information and modifying existing. + New files to deal with RADIUS information. + Almost a complete rewrite of the include/attrib.administrator.inc which have annoyed me for quite some time due it's sheer complexity. Should be somewhat easier to maintain now (mainly due to 'smarter' variables to check for in it's calling). + In all include/attrib.control.*.inc files, don't put toghether the DN of the specific host using $_SESSION["USER_SEARCH_DN_CTR"] (which have changed to 'ou=Computers,'. Instead use the '$host' variable it's called with. + The pql_add2array() no longer REQUIRE that the return value be retreived. The old array it's called with is updated via references. + Accept a third option to pql_generate_button() - a URL value. This was needed to call 'host_detail.php' in control_cat.php (for example) instead of PHP_SELF. + New function pql_separate_host_domain(fqdn) to separate hostname from domainname in an FQDN. Smarter than just accepting the first word before the first dot as hostname and all the rest as domainname. + Rewritten ./include/pql_search.inc:pql_get_automount_maps() to accept a computer DN instead using the domain/branch DN. This for the new 'concentrated host view' system. + Rewrite the include/pql_websrv.inc:pql_websrv_add_server() to not try to find/add the PQL_CONF_SUBTREE_APACHE subtree. It's no more due to the 'concentrated host view' system. + Try to catch flat arrays from pql_search() (i.e. when pql_search() only returns ONE value, not an array of values) in more places. + New function include/pql_websrv.inc:pql_websrv_get_virtual_host() that retreivs all necessary information about a specific virtual host. + New function include/pql_websrv.inc:pql_websrv_get_data() that will retreive all physical hosts, web server containers and all virtual hosts a user (should) have access to view/modify. + Remove the domain/branch option from include/pql_write.inc:pql_add_computer(). This due to the 'concentrated host view' system. Misc changes - Add support for searching for DNS hostname/ip address in search page. - Extra debugging in include/pql_search.inc:pql_search() regarding cache. - Merge from BRANCH_HOST_MERGE: + Support for the mailSizeMax attribute. + Rewrite the demo LDIF files to suit the new 'concentrated host view' system. + Document the demo LDIF files and how to create a database from them in demo/README. + Remove the 'Control base' value from PQL_CONF_HOST. + Remove the defines PQL_CONF_SUBTREE_COMPUTERS, PQL_CONF_SUBTREE_SUDOERS, PQL_CONF_SUBTREE_APACHE and PQL_CONF_SUBTREE_AUTOMOUNTS. They where no longer needed with the new 'concentrated host view' system. + Slightly prettier .DEBUG_DEFINES debugging (easier to distinguish between default and retreived values). + Possibility to output a clean LDIF without the '--- DEBUG ...' lines by creating the file './.DEBUG_LDIF'. phpQLAdmin 2.3.4 Release (Oct 20 2006) Bug fixes - Retreiving ALL operational attributes with '+' is an OpenLDAP thing ONLY. On all other (?), one must specify the attributes in question directly. - Instead of doing urldecode() all over the place and to normalize the DN (of users and domains etc), create a pql_format_normalize_dn() function that will: urldecode, strtolower, replace ', ' with ',' and lastly country encode the DN. - Duplicate functions _chmod(). The later should have been named _chown(). GUI layout changes - Add a Automount manager. Closes: #307 - Possibility to lock account type, -username, -password, -email and account domain address. Done in the Domain details->default values table. Schema changes - Add attribute 'useAutoMount' (oid 1.3.6.1.4.1.8767.3.2.1.30) for use with the Automount manager. - Possibility to lock account type, -username, -password, -email and account domain address. + Add attribute 'lockUserName' (oid 1.3.6.1.4.1.8767.3.2.1.31) + Add attribute 'lockEmailAddress' (oid 1.3.6.1.4.1.8767.3.2.1.32) + Add attribute 'lockDomainAddress' (oid 1.3.6.1.4.1.8767.3.2.1.33) + Add attribute 'lockPassword' (oid 1.3.6.1.4.1.8767.3.2.1.34) + Add attribute 'lockAccountType' (oid 1.3.6.1.4.1.8767.3.2.1.35) =>Add these as MAY to object class 'phpQLAdminBranch' - Possibility to set a default account type + Add attribute 'defaultAccountType' (oid 1.3.6.1.4.1.8767.3.2.4.25) =>Add this attribute as a MAY to object class phpQLAdminGlobal. API changes Misc changes - When using posixAccount in a user/template, the 'autoCreateUGidNumber' attribute is required. Change all templates to have this attribute set. + Also document this in doc/README.samba. - When only having ONE domain/organization and this is also the top DN (suffix), phpQLAdmin won't offer to change domain/organization values. This because the domain/branch _isn't_ the domain/organization, but the 'ou' _below_ it. Describe the problem with this in the doc/README file. - Note about not running PHP with 'error_reporting = E_ALL'. - Add support for adding extra mail headers in the 'Antispam configuration' table. phpQLAdmin 2.3.3 Release (Jul 9 2006) Bug fixes - Account status time fixes from Aaron Collins. - When giving a user admin access to branch, I forgot to add the user DN to the ACI lists of all leafs below the branch he/she got access to. - Fixing some parse errors in some of the include/attrib.*, host_modify.php files. - Make sure that host_modify.php:$computer_results is a numbered array. It isn't if there's only ONE computer object in the database... - Some missing and faulty hidden input's in host_modify.php fixed. - Some bugfixes for sudo_modify.php, include/pql_hostctrl.inc by Aaron Collins. + Computer must be used in call to pql_add_sudo_role(). + Use 'dn' not 'user' in the select option. + Include left-head.html. + Fix some translations in include/pql_hostctrl.inc:pql_list_expand(). + The missing functions include/pql_write.inc:pql_add_computer() and include/pql_write.inc:pql_add_sudo_role() sent to me months ago, is now added. - If the last user from a host ACL is removed, LDAP throws an error. The uniqueMember attribute (where the user is located) is REQUIRED so one can't remove the last one. + Retreive users and computers FIRST (before any action check) + Count the number of uniqueMember attribute values in the specific computer object. If the last, remove the object all together... - Since users/computers is now retreived before add/delete/modification of a host ACL, we need to manually update the array so that displayed content in the frame is correct. GUI layout changes - Add a 'Global' branch tree in the left-controls.php page - Get (and later modify) ALL QLC object attributes in one 'simple' swoop. - Support LDAP URI's ('ldap://', 'ldaps://' and 'ldapi://') and not just hostnames in 'ldapserver' - Setup a attribute aliases file to translate the more/most obscure attributes to more 'humanly readable' word. Closes: #126 - The 'Host control' and 'Sudoers access' buttons in the domain details page should only be visable if running in advanced mode. - Only show the '[domain]->Host control->Host Control Access' stuff if there actually IS any computers in the database. This to avoid information that is of no use (can't add a user to a non-existent computer!). + If no computers, output a little notify about this, and what to do next. - Add support for Opera in host_modify.php. Faulty DOM implementation and I use Opera... - Cleanup/fix the showing of the hosts IP address. Got a little 'of-beat'. - Some slight changes to debug message(s) when removing/renaming an object. Schema changes API changes - Remove the redundant pql_get_uid() function. It didn't work in the first place, and I find it cleaner to use the pql_get_attribute(). - Remove all hardcoded 'ou=DNS' with propper pql_get_define()'s. Closes: #304 - Remove all hardcoded 'ou=WEB' with propper pql_get_define()'s. Closes: #305 Misc changes - Add useSimScan to the list of attributes that 'users' need read access to. - When debugging the pql_config.inc:pql_set_define() function, only output debugging if: File .DEBUG_DEFINES exists _AND_ it's a '_CONF_' define (i.e. ignore any _ATTR_ definition). - Rewrite the part that goes through the $PQL_ATTRIBUTE array and sets config and attribute defines. Should be a little easier to follow now... phpQLAdmin 2.3.2 Release (Mar 11 2006) Bug fixes GUI layout changes - Allow for picture to be added to user. Closes: #72 - Add a 'Allow all chars in passwds' to the branch configuration page (and check this new value whenever we verify the password). Closes: #262 - Fix group management code. Patch by Aaron Collins. Schema changes - Add attribute to specify if autogenerate uidNumber and gidNumber. 1.3.6.1.4.1.8767.3.2.1.26 => 'autoCreateUGidNumber' API changes - Option to specify in the user template(s) whether to autogenerate uid- and gid numbers or if to use the 'virtual user' within QmailLDAP. Misc changes - Include a working Apache/mod_ldap_cfg config snippet and database branch example. - Update the Apache readme (doc/README.apache) with the new Apache/mod_ldap_cfg demo files. - To stop PHP warnings when running with 'error_reporting=E_NOTICE': + Make sure variables are initialized before use. + Use 'counter < count(array)' in for loop instead of 'array[counter]'. + Use 'if(empty(array))' instead of 'if(!array[part])' or 'if(!isset(array[part]))'. + Use '@array[part]' instead of 'array[part]'. - Possibility to export user, branch or QmailLDAP/Controls object as LDIF (either output to local browser frame or save as local file). Closes: #250 - Misc changes to the Webserver manager: + The AccessDeny and AccessAllow must be arrays, not flat. Convert if not already an array... + Sort servers alphabetically. + Cleanup the generation of the server buttons. Previosly only two in a row, now fills the table as much as possible. + Reword the 'headers' to the Apache information. + The "PQL_ATTR_WEBSRV_OPTIONS" define was renamed to "PQL_ATTR_WEBSRV_SRV_REWRITE_OPTIONS". + Add rewrite stuff (use pql_format_table_single() for Access{Deny,Allow}). + Actually support the three levels of Apache objects described in doc/README.apache! 1. Server FQDN Container object (a very simple 'device' object). 2. Apache Virtual Host object (a 'ApacheServerName'd object). 3. Apache Location object (a 'ApacheSectionArg'd object). This now reflects true in both the 'domain details->webserver manager' page AND in creation and modifications of the three different type of objects. - Host ACL and Sudo manager. Patch by Aaron Collins. phpQLAdmin 2.3.1 Release (Aug 22 2005) Bug fixes - Remove a duplicated 'if user is (super)admin' check in tables/user_details-access.inc. - It is (very) possible for a user to have only ONE mail alias. In that case, additionals isn't an array. So only do a foreach() if it IS and send the alias directly to LDAP if it ISN'T. - To be able to figure out if we should auto add locals or not, we're using the root DN value for (this) host. But the root DN isn't supplied, so get it. - Spelling error in the pql_get_define() that retreives the 'auto add locals' value: s/branch/rootdn/. - Don't send each itteration of locals retreival to the LDAP server. Do that ONCE _AFTER_ all values have been gathered... - In the pql_add2array() wrapper, make sure that 'old' really exists, not only isn't array... - Catch DNS TTL RDN's in pql_domain_del() as well (there's a space in it that ldap_list() croacs about... - Allow for additional domain name to be set (in tables/domain_details-default.inc) even if it isn't an array... - Allow for empty default domain value. This if one wants/need to clear the current value. - Do not force locals and rcpthosts as array if automatic replication is set (when asking for new value). - Allow old values fetched from LDAP to be set but not array. - Support ADDING and REPLACING additional domain name(s) by fixing hardcoded call to 'array(delval, '')' for pql_control_update_domains(). - Missing semi-colon added after a pql_modify_attribute() call. - Spelling error fixed in include/attrib.defaultdomain.inc: 's/$delval/$oldvalue/g' GUI layout changes - Attachement (#64) for bug #275 changes the way the left-controls frame looks (restrucured and more 'humane' wordings), changes the way 'multiple values' are drawn. It also fixes sub-category buttons for/in all pages, much the way the Domain/User views look like. - The tables/control_details-nonprimmx.inc file is no longer used/needed since include/attrib.control.nonprimmx.inc now works like the other control files (with a print_view() and a print_form() function etc). - If a password have been autogenerated, tick the 'Autogenerate password' checkbox in the 'User data' create user page. - Correctly retreive additional groups the user is member of. Patch by Aaron Collins. - Add the 'memberuid' to list of attributes to allow editing (user_edit_attribute.php). Patch by Aaron Collins. - Instead of checking for 'system' type, check if the objectclass(es) we're using to create the user with contains the 'posixAccount'. If it does, THEN create the group object. Patch by Aaron Collins. - Remove some 'MUST' and 'MAY' parameters from the pql_templates_check_attribute() calls in tables/user_add-save.inc. If it's allowed, it's allowed! We don't need to care if it's required or optional... Patch by Aaron Collins. - Deglobalize the "subbranch" value in tables/user_add-details.inc. - Allow the creation of a Samba account. Patch by Aaron Collins. - Show the NS, MX and AFSDB values correctly in the DNS view. - Add 'empty table lines' between each template in the (user) templates view. - In the pql_create_ldif() function, add a 'LDIF command separator' before each command (not the very first though). This so that it can even easier be cut-and-pasted... Schema changes - Missing attributes 'relayMailFrom', 'maxRcptCount' and 'qmqpcIp' added. 1.3.6.1.4.1.7006.1.2.1.79 => 'relayMailFrom' 1.3.6.1.4.1.7006.1.2.1.80 => 'maxRcptCount' 1.3.6.1.4.1.7006.1.2.1.81 => 'qmqpcIp' API changes - Rewrite and correctly implement caching. Not that I gained much, but still. Example: Loading the left frame with my database (99 users) took 9 seconds without caching and 6 seconds with... No other speed increases where found (adding domains etc which usually take some time). - Complete rewrite of the include/attrib.config.inc:attribute_save() function. Closes: #221 - Not so much a rewrite as cleanup of the include/pql_control.inc:pql_control_update_domains() function. Move some parts as separate functions into include/pql_search.inc. Closes: #258 - Not so much a rewrite as a cleanup of the include/attrib.additionaldomainname.inc file. Remove duplication and redundant code. Simplify add/del/change decision(s). Closes: #274 + Duplicate this fix in include/attrib.defaultdomain.inc. - Changed the order parameters to pql_plugin_register() was specified. - Add a parameter (label=...) to tools/navbutton.php instead of just sending the label in argv[1]. - Remove the first parameter to pql_cache_add() - the DN. Better to take it from the object (the previos second paramater, now the first and only). That way we don't risk caching the object in the wrong place. - New function - pql_format_table_empty() - to simplify the output of 'empty table lines' (empty room between parts in a table). - Some fixes in the pql_format_bool() function: + If the input value is '0' or empty, don't do anything. + Check for UPPER or lower cased true/false values. - When retreiving a DN for a object and it (the object) IS cached, then pql_search() will return a flat (one) object, so '$object[0]' isn't set... Instead, '$object['dn']' IS set so return that... Misc changes - Support sub-zones in the DNS manager. Only one level is supported at this time though... - Do some output buffer flushing at the end of each page. Might improve performance somewhat (even though it don't seem like it). Done with my own wrapper pql_flush(). - Use the PHP function empty() to check for set/unset variable. Patch by Aaron Collins. - Include my templates as an LDIF in the demo directory. - Support the file .DEBUG_PROFILING - show what time it is (as a UNIX timestamp) at the start and end of the script. Might give SOME indication where speed problems exists. - Make sure that the browser don't cache the page(s). Add a 'Pragma: no-cache' to header.html (which is included in almost every output script page). - Rename the .DEBUG_ME_DEFINES to .DEBUG_DEFINES. More in line with the other debug files... - Create the file DEBUGGING.txt which describes how debuing can be done. - Include a working Apache/mod_ldap_cfg config snippet and database branch example. - Update the Apache readme (doc/README.apache) with the new Apache/mod_ldap_cfg demo files. phpQLAdmin 2.3.0 Release (Jun 8 2005) Bug fixes - Session was started with the path specified in php.ini:session.cookie_path. For me that was '/' which meant that if I have two (or more) phpQLAdmin installations on the same server (which I do - stable, devel and demo etc), they overwrote each others session variable. To avoid this, we must set the 'session.cookie_path' using ini_set() BEFORE session is started. Instead of doing this in every place where session_start() is called, we include the new file 'include/pql_session.inc' which does some additional magic. + The 'session.cookie_path' init value must always end with a slash, so make sure it does... Should fix some problems with sessions that won't die or get's overwritten. + Getting what type of browser the user is using is a session thing so move it from left-head.html to include/pql_session.inc where it belongs... This should REALLY fix the disappearance of the frame borders... + Don't hardcode require()/include() (etc) calls to './'. Use the session value 'path' as prefix in _ALL_ (?) calls to require()/include(). - Overloading of variables in tables/domain_details-websrv.inc fixed ($server* to $web_srv*). - If one enters a mailForwardingAddress and: + qmailDotMode != none + deliveryMode != noprogram + deliveryProgramPath != NULL + ldapDefaultDotMode == ldapwithprog then there will be a COPY in the users local mailbox. Solve this by changing the 'qmailDotMode' and 'deliveryMode'. + Make sure to re-enable local delivery for the user if not forwarding (any more). - When (if) retreiving object classes the LDAP server understands, we must catch attribute alias(es). A MAY/MUST on 'domainComponent' must translate to 'dc' and back... - Change the way 'cn' is modified. If we're called with an old value, we replace _only_ that specific value. If no old value, replace the whole attribute list. - When adding a user, the inclusion of the home directory must be done outside of the 'if mailhost is allowed'. - When _editing_ (changing) a common name for a user, include the old value in the change. + Support additions and deletions of 'cn' value(s). - When retreiving domain details information, don't retreive 'facsimileTelephoneNumber' twice... - The 'pql_split_oldvalues(pql_get_define("PQL_CONF_WEBSRV_OC"))' directly returns an array() so no need to go through them and add them to a two dimensional array (which was named wrong - use pql_get_define("PQL_ATTR_OBJECTCLASS") as we're supposed to). + Use 'PQL_CONF_WEBSRV_OC' instead of the faulty 'PQL_ATTR_WEBSRV_OC'. + Add define for 'ApacheSectionName', used by the webserver object manager. - Include 'ApacheSectionName=VirtualHost' when creating a web server object, othervise mod_ldap_cfg won't get it's virtual hosts... - If the user logging in can't be found, we must clear the '_POST' value between attempts, othervise we're trying to authenticate again (and again...) - When an object class violation occured when adding an attribute to a object, the combination of the old and the new object classes failed. - If the root DN don't contain the user reference value, retreival of domains/branches fails. Use a 'resonable default' (uid). - If the root DN is a 'dc' object and domain/branch reference is 'ou', we must use 'organizationalUnit' in the object class filter when retreiving domains/branches... => 'ou=domain2.tld,dc=domain2,dc=tld'. Ugly, but ok. GUI layout changes - Rewrite the way users are listed in the left frame. The attribute 'cn' is the most obvious to show and the way that's shown is also rewritten. + If a user have more than two fields (space separated - 'Ulf Turbo Fredriksson'), then the _last_ part is the lastname and all the others are first names... If memory serves me correctly, this isn't true for arabic/chinese names, but... + After 'cn' comes 'givenName' and 'sn' and after that comes 'gecos'. Last chance is the 'user reference attribute' (whatever that might be - it MUST exists however). - When creating a 'forwarding account' there are two possibilities. Either with local delivery (as well as forwarding) or no local delivery (i.e. only forwarding). Allow this with two radio buttons in the 'Additional account properties' page - 'Copy to' (default) or 'Forward to'. + Create objects with real home dirs... - Include a 'NOT' option for user search. Describe what it does and how it works. - Add a 'Force no local delivery' checkbox when _creating_ a mail forwarding address. ('Bug fixes' point 3 - mailForwardingAddress creation - above) - If there is no MAY attributes in the user templates, we must say so (None) instead of having an empty line. - Change the sizes of the left frames (QmailLDAP/Controls an ezmlm should be WAY smaller). - Change wording from 'Server URL' to 'Server FQDN'. - Have a resonable default welcome message (phpQLAdmin @ ) if we don't have a PQL_CONF_WHOAREWE define. - Change/fix the way the USER_HOST session value is set. I'm splitting and combining in a way that was quite redundant - we ended up with the exact same value as we started with! Wonder what I was thinking... :) - Sort the domain/branch list according to the branch name value NOT the DN. This means we must explode()/split() the DN into parts, recustruct a new temporary array which we sort and then use that array as a base for putting the new, correctly sorted array togheter. + The function pql_get_domains() is now sorting the domains/branch list better than asort() can do so no need to call asort() after pql_get_domains(). - Better/More debugging support. I forgot to die() (and not forward to view) if the file .DEBUG_ME existed in some places. Schema changes - Because of the change in the way 'forwarding accounts' where used/created, I lost all purpose of the 'virtualBaseHomeDir' global attribute/configuration! Remove all references to it. - Four new attributes for remote ezmlm lists added to the 'phpQLAdminGlobal' object class: ezmlmRemote 1.3.6.1.4.1.8767.3.2.1.21 ezmlmRemoteHost 1.3.6.1.4.1.8767.3.2.4.20 ezmlmRemoteUser 1.3.6.1.4.1.8767.3.2.4.21 ezmlmRemoteRetreiveScript 1.3.6.1.4.1.8767.3.2.2.21 - To be able to remember localy added rcptHosts, I (phpQLAdmin) must put them in another attribute. This to protected the value(s) from a manual replication. The example comes from bug #257 - if the QLC host is only _listenening_ ('backup MX') then there is no branch(es) that have the domain(s) configured as primary nor additional domainname. If a manual replication takes place, then the information about the domain(s) can't be found anywhere... A new object class and a new attribute to add to the QLC object(s): phpQLAdminMXHostAddition 1.3.6.1.4.1.8767.3.1.8 (object class) nonPrimaryRcptHosts 1.3.6.1.4.1.8767.3.2.4.22 (attribute) - Support SimScan configuration (added as MAY to phpQLAdminMXHostAddition and phpQLAdminGlobal): useSimScan 1.3.6.1.4.1.8767.3.2.1.22 simScanSpamAssassin 1.3.6.1.4.1.8767.3.2.1.23 simScanClamAntiVirus 1.3.6.1.4.1.8767.3.2.1.24 simScanTrophie 1.3.6.1.4.1.8767.3.2.1.25 simScanSpamAssassinHits 1.3.6.1.4.1.8767.3.2.4.23 simScanAttachmentSuffix 1.3.6.1.4.1.8767.3.2.4.24 + Configured/enabled in two places: * Globaly per MX host (in a QmailLDAP/Controls object). * Per branch object + Script to extract and generate the simcontrol file (scripts/extract_simscan.pl) is only started, not finished! Documentation changes - Map the QmailLDAP/Controls manager -> doc/README.QmailLDAP_Controls-GUI. - Include httpd.conf configuration snippet for web server manager README. API changes - Administration of mailinglists located on remote server (i.e. not on the same host where phpQLAdmin is running). ==> See WARNING.txt! <== - Native support for Kerberos V, using the php4-kadm5 module (from the URL http://freshmeat.net/projects/php-kadm5). + Do not export variables PQL_KADMIN_* to the support scripts. + Closes bug 273. - New function - pql_format_return_unixtime() - to return current time as a UNIX timestamp. Good for profiling - Slight API cleanup. To be able to introduce caching, I need to remove all calls to the PHP functions ldap_*() and instead use my own wrappers: ldap_delete() pql_write_del() NEW! ldap_add() pql_write_add() - Started fixing the 'stupid URL's bug' (#212). + Combind 'submit ==1' and 'action == del' into one if() in websrv_edit_attributes.php. + All but domain and user edit is finished. - Setup PQL_CONF_WEBSRV_OC in include/defaults.inc instead of in include/config_attributes.inc. - After using header() one MUST (!) use 'exit' so that the following code isn't executed! Replace all calls to header() with my own wrapper that does just that - calls header() (including the URI session value) and then 'exit'... - Merging two arrays don't work any more, so new PQL function: pql_add2array(old, new) which adds the 'new' array to the 'old' via a foreach() loop. Misc changes - Lot's more folding tags added. - Some more de-globalization (mainly in the ezmlm manager). - When calling pql_create_ldif(), make sure we know which 'function' that called it. + Additional fourth param: add HTML newline or not. - Slight rewrite in the user addition. + Retreive enryption schemes ONCE (in user_add.php instead of tables/user_add-details.inc) + New function pql_user_add_retreive_encryption_schemes() that takes care of this easier. + Allow password/scheme to be entered if password is allowed by the template in addition to if the default password scheme is empty, or we're running in advanced mode. - The attribute 'cn' (common name) is very good/nice to have multi-valued so this is now supported in the [user]->User data page. + This forced a small change to include/pql_formating.inc:pql_format_table_single(), namely the inclusion of a modify link/text entry (to get the edit button). + Use include/pql_formating.inc:pql_format_table_single() in the [user]->User data page instead of hardcoded HTML table rows etc. Not only was that cleaner, it gave a nicer look when using/allowing multiple values... - Add the ACI attribute(s) in the branch object as well. + Simplify the ACI attributes - one line is enough. [all changelog for <2.3 branch have been removed for space reasons]