Dbut ajout gestion utilisateurs ldap

Modification de la classe ldap.lib.php en authldap.lib.php
This commit is contained in:
Regis Houssin 2006-06-24 15:13:29 +00:00
parent e7dc5ceb39
commit ccf1fc8f91
14 changed files with 962 additions and 285 deletions

View File

@ -40,7 +40,7 @@
*/
require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/lib/ldap.lib.php");
require_once(DOL_DOCUMENT_ROOT."/lib/authldap.lib.php");
$langs->load("admin");
@ -66,10 +66,18 @@ if ($_GET["action"] == 'setvalue' && $user->admin)
{
print $db->error();
}
if (! dolibarr_set_const($db, 'LDAP_SERVER_HOST_SLAVE',$_POST["slave"]))
{
print $db->error();
}
if (! dolibarr_set_const($db, 'LDAP_SERVER_PORT',$_POST["port"]))
{
print $db->error();
}
if (! dolibarr_set_const($db, 'LDAP_SERVER_DN',$_POST["dn"]))
{
print $db->error();
}
if (! dolibarr_set_const($db, 'LDAP_ADMIN_DN',$_POST["admin"]))
{
print $db->error();
@ -191,6 +199,13 @@ print $langs->trans("LDAPServer").'</td><td>';
print '<input size="25" type="text" name="host" value="'.$conf->global->LDAP_SERVER_HOST.'">';
print '</td><td>'.$langs->trans("LDAPServerExample").'</td></tr>';
// Serveur
$var=!$var;
print '<tr '.$bc[$var].'><td>';
print $langs->trans("LDAPServerSlave").'</td><td>';
print '<input size="25" type="text" name="slave" value="'.$conf->global->LDAP_SERVER_HOST_SLAVE.'">';
print '</td><td>'.$langs->trans("LDAPServerExample").'</td></tr>';
// Port
$var=!$var;
print '<tr '.$bc[$var].'><td>'.$langs->trans("LDAPServerPort").'</td><td>';
@ -204,6 +219,12 @@ else
}
print '</td><td>'.$langs->trans("LDAPServerPortExample").'</td></tr>';
// DNserver
$var=!$var;
print '<tr '.$bc[$var].'><td>'.$langs->trans("DNServer").'</td><td>';
print '<input size="25" type="text" name="dn" value="'.$conf->global->LDAP_SERVER_DN.'">';
print '</td><td>'.$langs->trans("LDAPServerDnExample").'</td></tr>';
// DNAdmin
$var=!$var;
print '<tr '.$bc[$var].'><td>'.$langs->trans("DNAdmin").'</td><td>';
@ -215,7 +236,7 @@ $var=!$var;
print '<tr '.$bc[$var].'><td>'.$langs->trans("LDAPPassword").'</td><td>';
if ($conf->global->LDAP_ADMIN_PASS)
{
print '<input size="25" type="text" name="pass" value="'.$conf->global->LDAP_ADMIN_PASS.'">';// je le met en visible pour test
print '<input size="25" type="password" name="pass" value="'.$conf->global->LDAP_ADMIN_PASS.'">';// je le met en visible pour test
}
else
{
@ -274,7 +295,7 @@ if ($conf->global->LDAP_FILTER_CONNECTION)
}
else
{
print '<input size="25" type="text" name="filterconnection" value="(&(objectClass=user)(objectCategory=person))">';
print '<input size="25" type="text" name="filterconnection" value="&(objectClass=user)(objectCategory=person)">';
}
print '</td><td>'.$langs->trans("LDAPFilterConnectionExample").'</td></tr>';
@ -381,11 +402,11 @@ if (function_exists("ldap_connect"))
if ($conf->global->LDAP_SERVER_HOST && $conf->global->LDAP_ADMIN_DN && $conf->global->LDAP_ADMIN_PASS && $_GET["action"] == 'test')
{
$ldap = New Ldap();
$ldap = New AuthLdap();
// Test ldap_connect
// ce test n'est pas fiable car une ressource est constamment retournée
// il faut se fier au test ldap_bind
$ds = $ldap->dolibarr_ldap_connect();
$ds = $ldap->connect();
if ($ds)
{
print img_picto('','info');
@ -396,14 +417,14 @@ if (function_exists("ldap_connect"))
print img_picto('','alerte');
print $langs->trans("LDAPTestKO").'<br>';
print "<br>";
print $ldap->err;
print $ldap->ldapErrorCode." - ".$ldap->ldapErrorText;
print "<br>";
}
if ($ds)
{
// Test ldap_getversion
if (($ldap->dolibarr_ldap_getversion($ds) == 3))
if (($ldap->getVersion() == 3))
{
print img_picto('','info');
print $langs->trans("LDAPSetupForVersion3").'<br>';
@ -415,7 +436,7 @@ if (function_exists("ldap_connect"))
}
// Test ldap_bind
$bind = $ldap->dolibarr_ldap_bind($ds);
$bind = $ldap->bind();
if ($bind)
{
@ -426,14 +447,14 @@ if (function_exists("ldap_connect"))
{
print img_picto('','alerte');
print "Connexion au dn $dn raté : ";
print $ldap->err;
print $ldap->ldapErrorCode." - ".$ldap->ldapErrorText;
print "<br>";
}
// Test ldap_unbind
$unbind = $ldap->dolibarr_ldap_unbind($ds);
$unbind = $ldap->unbind();
if ($bind && $unbind)
if ($unbind)
{
print img_picto('','info');
print "Déconnection du dn $dn réussi<br>";
@ -443,6 +464,7 @@ if (function_exists("ldap_connect"))
print img_picto('','alerte');
print "Déconnection du dn $dn raté";
print "<br>";
print $ldap->ldapErrorCode." - ".$ldap->ldapErrorText;
}
}
}

View File

@ -275,6 +275,8 @@ class Conf
// Module export
$this->export->enabled=defined("MAIN_MODULE_EXPORT")?MAIN_MODULE_EXPORT:0;
$this->export->dir_ouput=DOL_DATA_ROOT."/export";
// Module ldap
$this->ldap->enabled=defined("MAIN_MODULE_LDAP")?MAIN_MODULE_LDAP:0;
/*

View File

@ -186,17 +186,14 @@ class Contact
dolibarr_syslog("Contact::update_ldap",LOG_DEBUG);
$this->fetch($this->id);
$ldap = New AuthLdap();
$ds = dolibarr_ldap_connect();
if ($ds)
{
$ldapbind = dolibarr_ldap_bind($ds);
if ($ldapbind)
{
if (LDAP_SERVER_TYPE == 'activedirectory') //enlever utf8 pour etre compatible Windows
{
if ($ldap->connect())
{
if (bind())
{
if (LDAP_SERVER_TYPE == 'activedirectory') //enlever utf8 pour etre compatible Windows
{
$info["objectclass"][0] = "top";
$info["objectclass"][1] = "person";
$info["objectclass"][2] = "organizationalPerson";
@ -207,33 +204,41 @@ class Contact
$info["sn"] = $this->name;
$info["givenName"] = $this->firstname;
if ($this->poste)
$info["title"] = $this->poste;
if ($this->poste) $info["title"] = $this->poste;
if ($this->socid > 0)
{
$soc = new Societe($this->db);
$soc->fetch($this->socid);
$info["o"] = $soc->nom;
$info["company"] = $soc->nom;
if ($soc->client == 1)
$info["businessCategory"] = "Clients";
elseif ($soc->client == 2)
$info["businessCategory"] = "Prospects";
if ($soc->fournisseur == 1)
$info["businessCategory"] = "Fournisseurs";
if ($soc->ville)
{
if ($soc->adresse)
$info["streetAddress"] = $soc->adresse;
if ($soc->cp)
$info["postalCode"] = $soc->cp;
$info["l"] = $soc->ville;
{
$soc = new Societe($this->db);
$soc->fetch($this->socid);
$info["o"] = $soc->nom;
$info["company"] = $soc->nom;
if ($soc->client == 1)
{
$info["businessCategory"] = "Clients";
}
elseif ($soc->client == 2)
{
$info["businessCategory"] = "Prospects";
}
if ($soc->fournisseur == 1)
{
$info["businessCategory"] = "Fournisseurs";
}
if ($soc->ville)
{
if ($soc->adresse)
{
$info["streetAddress"] = $soc->adresse;
}
if ($soc->cp)
{
$info["postalCode"] = $soc->cp;
}
$info["l"] = $soc->ville;
}
}
@ -370,7 +375,7 @@ class Contact
dolibarr_syslog("Contact::update_ldap bind failed",LOG_DEBUG);
}
dolibarr_ldap_unbind($ds);
$ldap->unbind();
}
else
@ -636,46 +641,42 @@ class Contact
{
if (defined('LDAP_CONTACT_ACTIVE') && LDAP_CONTACT_ACTIVE == 1)
{
$ldap = New AuthLdap();
$ds = dolibarr_ldap_connect();
if ($ds)
{
$ldapbind = dolibarr_ldap_bind($ds);
if ($ldapbind)
{
// delete from ldap directory
if (LDAP_SERVER_TYPE == 'activedirectory')
{
$userdn = $this->old_firstname." ".$this->old_name; //enlever utf8 pour etre compatible Windows
}
else
{
$userdn = utf8_encode($this->old_firstname." ".$this->old_name);
}
$dn = "cn=".$userdn.",".LDAP_CONTACT_DN;
$r = @ldap_delete($ds, $dn);
}
else
{
echo "LDAP bind failed...";
}
ldap_close($ds);
}
if ($ldap->connect())
{
if ($ldap->bind())
{
// delete from ldap directory
if (LDAP_SERVER_TYPE == 'activedirectory')
{
$userdn = $this->old_firstname." ".$this->old_name; //enlever utf8 pour etre compatible Windows
}
else
{
$userdn = utf8_encode($this->old_firstname." ".$this->old_name);
}
$dn = "cn=".$userdn.",".LDAP_CONTACT_DN;
$r = @ldap_delete($ds, $dn);
}
else
{
echo "LDAP bind failed...";
}
$ldap->close();
}
else
{
echo "Unable to connect to LDAP server";
}
{
echo "Unable to connect to LDAP server";
}
return $result;
}
}
}
}
/*
* \brief Charge les informations sur le contact, depuis la base

View File

@ -72,4 +72,5 @@ ErrorFailedToSaveFile=Error - Failed to save file
GuiLanguage=Interface language
InternalUser=Internal user
MyInformations=My informations
ExportDataset_user_1=Dolibarr's users and properties
ExportDataset_user_1=Dolibarr's users and properties
DomainUser=Domain user

View File

@ -73,3 +73,4 @@ GuiLanguage=Langage de l'interface
InternalUser=Utilisateur interne
MyInformations=Mes informations
ExportDataset_user_1=Utilisateurs Dolibarr et attributs
DomainUser=Utilisateur du domaine

608
htdocs/lib/authldap.lib.php Normal file
View File

@ -0,0 +1,608 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
* Copyright (C) 2005-2006 Regis Houssin <regis.houssin@cap-networks.com>
* Copyright (C) 2006 Laurent Destailleur <eldy@users.sourceforge.net>
*
* 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.
* or see http://www.gnu.org/
*
* $Id$
* $Source$
*/
/**
\file htdocs/lib/authldap.lib.php
\brief Librairie contenant les fonctions pour accèder au serveur ldap.
\author Rodolphe Quiedeville.
\author Benoit Mortier.
\author Regis Houssin.
\author Laurent Destailleur.
\version $Revision$
Ensemble des fonctions permettant d'accèder à un serveur LDAP.
*/
class AuthLdap {
/**
* Tableau des serveurs (IP addresses ou nom d'hôtes)
*/
var $server;
/**
* Base DN (e.g. "dc=foo,dc=com")
*/
var $dn;
/**
* type de serveur, actuellement OpenLdap et Active Directory
*/
var $serverType;
/**
* Version du protocole ldap
*/
var $domain;
/**
* Administrateur Ldap
* Active Directory ne supporte pas les connexions anonymes
*/
var $searchUser;
/**
* Mot de passe de l'administrateur
* Active Directory ne supporte pas les connexions anonymes
*/
var $searchPassword;
/**
* DN des utilisateurs
*/
var $people;
/**
* DN des groupes
*/
var $groups;
/**
* Code erreur retourné par le serveur Ldap
*/
var $ldapErrorCode;
/**
* Message texte de l'erreur
*/
var $ldapErrorText;
// 1.2 Private properties ----------------------------------------------------
/**
* The internal LDAP connection handle
*/
var $connection;
/**
* Result of any connections etc.
*/
var $result;
/**
* Constructor- creates a new instance of the authentication class
*
* @param string the ldap server to connect to
* @param string the base dn
* @param string the server type- current supports OpenLdap and ActiveDirectory
* @param string the domain to use when authenticating against Active Directory
* @param string the username to authenticate with when searching if anonymous binding is not supported
* @param string the password to authenticate with when searching if anonymous binding is not supported
*/
function AuthLdap () {
global $conf;
$this->server = array($conf->global->LDAP_SERVER_HOST, $conf->global->LDAP_SERVER_HOST_SLAVE);
$this->serverPort = $conf->global->LDAP_SERVER_PORT;
$this->ldapProtocolVersion = $conf->global->LDAP_SERVER_PROTOCOLVERSION;
$this->dn = $conf->global->LDAP_SERVER_DN;
$this->serverType = $conf->global->LDAP_SERVER_TYPE;
$this->domain = $sDomain;
$this->searchUser = $conf->global->LDAP_ADMIN_DN;
$this->searchPassword = $conf->global->LDAP_ADMIN_PASS;
$this->people = $conf->global->LDAP_USER_DN;
$this->groups = $conf->global->LDAP_GROUP_DN;
}
// 2.1 Connection handling methods -------------------------------------------
/**
* 2.1.1 : Connects to the server. Just creates a connection which is used
* in all later access to the LDAP server. If it can't connect and bind
* anonymously, it creates an error code of -1. Returns true if connected,
* false if failed. Takes an array of possible servers - if one doesn't work,
* it tries the next and so on.
*/
function connect() {
foreach ($this->server as $key => $host) {
if (ereg('^ldap',$host)) {
$this->connection = ldap_connect($host);
} else {
$this->connection = ldap_connect($host,$this->serverPort);
}
if ( $this->connection) {
$this->setVersion();
if ($this->serverType == "activedirectory") {
return true;
} else {
// Connected, now try binding anonymously
$this->result=@ldap_bind( $this->connection);
}
return true;
}
}
$this->ldapErrorCode = -1;
$this->ldapErrorText = "Unable to connect to any server";
return false;
}
/**
* 2.1.2 : Simply closes the connection set up earlier.
* Returns true if OK, false if there was an error.
*/
function close() {
if ( !@ldap_close($this->connection)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
return true;
}
}
/**
* 2.1.3 : Anonymously binds to the connection. After this is done,
* queries and searches can be done - but read-only.
*/
function bind() {
if ( !$this->result=@ldap_bind( $this->connection)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
return true;
}
}
/**
* \brief unbind du serveur ldap.
* \param ds
* \return bool
*/
function unbind() {
if (!$this->result=@ldap_unbind($this->connection)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
return true;
}
}
/**
* 2.1.4 : Binds as an authenticated user, which usually allows for write
* access. The FULL dn must be passed. For a directory manager, this is
* "cn=Directory Manager" under iPlanet. For a user, it will be something
* like "uid=jbloggs,ou=People,dc=foo,dc=com".
*/
function authBind( $bindDn,$pass) {
if ( !$this->result = @ldap_bind( $this->connection,$bindDn,$pass)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
return true;
}
}
/**
* \brief verification de la version du serveur ldap.
* \param ds
* \return version
*/
function getVersion() {
$version = 0;
$version = @ldap_get_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $version);
return $version;
}
/**
* \brief changement de la version du serveur ldap.
* \param ds
* \param version
* \return version
*/
function setVersion() {
$ldapsetversion = ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->ldapProtocolVersion);
return $ldapsetversion;
}
// 2.2 Password methods ------------------------------------------------------
/**
* 2.2.1 : Checks a username and password - does this by logging on to the
* server as a user - specified in the DN. There are several reasons why
* this login could fail - these are listed below.
*/
function checkPass( $uname,$pass) {
/* Construct the full DN, eg:-
** "uid=username, ou=People, dc=orgname,dc=com"
*/
if ($this->serverType == "activedirectory") {
$checkDn = "$uname@$this->domain";
} else {
$checkDn = $this->getUserIdentifier() . "=$uname, " . $this->setDn(true);
}
// Try and connect...
$this->result = @ldap_bind( $this->connection,$checkDn,$pass);
if ( $this->result) {
// Connected OK - login credentials are fine!
return true;
} else {
/* Login failed. Return false, together with the error code and text from
** the LDAP server. The common error codes and reasons are listed below :
** (for iPlanet, other servers may differ)
** 19 - Account locked out (too many invalid login attempts)
** 32 - User does not exist
** 49 - Wrong password
** 53 - Account inactive (manually locked out by administrator)
*/
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
}
}
/**
* 2.2.2 : Allows a password to be changed. Note that on most LDAP servers,
* a new ACL must be defined giving users the ability to modify their
* password attribute (userPassword). Otherwise this will fail.
*/
function changePass( $uname,$oldPass,$newPass) {
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
if ($this->serverType == "activedirectory") {
$checkDn = "$uname@$this->domain";
} else {
$checkDn = $this->getUserIdentifier() . "=$uname, " . $this->setDn(true);
}
$this->result = @ldap_bind( $this->connection,$checkDn,$oldPass);
if ( $this->result) {
// Connected OK - Now modify the password...
$info["userPassword"] = $newPass;
$this->result = @ldap_modify( $this->connection, $checkDn, $info);
if ( $this->result) {
// Change went OK
return true;
} else {
// Couldn't change password...
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
}
} else {
// Login failed - see checkPass method for common error codes
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
}
}
/**
* 2.2.3 : Returns days until the password will expire.
* We have to explicitly state this is what we want returned from the
* LDAP server - by default, it will only send back the "basic"
* attributes.
*/
function checkPassAge ( $uname) {
$results[0] = "passwordexpirationtime";
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
$checkDn = $this->setDn(true);
$this->result = @ldap_search( $this->connection,$checkDn,$this->getUserIdentifier()."=$uname",$results);
if ( !$info=@ldap_get_entries( $this->connection, $this->result)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
/* Now work out how many days remaining....
** Yes, it's very verbose code but I left it like this so it can easily
** be modified for your needs.
*/
$date = $info[0]["passwordexpirationtime"][0];
$year = substr( $date,0,4);
$month = substr( $date,4,2);
$day = substr( $date,6,2);
$hour = substr( $date,8,2);
$min = substr( $date,10,2);
$sec = substr( $date,12,2);
$timestamp = mktime( $hour,$min,$sec,$month,$day,$year);
$today = mktime();
$diff = $timestamp-$today;
return round( ( ( ( $diff/60)/60)/24));
}
}
// 2.3 Group methods ---------------------------------------------------------
/**
* 2.3.1 : Checks to see if a user is in a given group. If so, it returns
* true, and returns false if the user isn't in the group, or any other
* error occurs (eg:- no such user, no group by that name etc.)
*/
function checkGroup ( $uname,$group) {
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
$checkDn = $this->setDn(false);
// We need to search for the group in order to get it's entry.
$this->result = @ldap_search( $this->connection, $checkDn, "cn=" .$group);
$info = @ldap_get_entries( $this->connection, $this->result);
// Only one entry should be returned(no groups will have the same name)
$entry = ldap_first_entry( $this->connection,$this->result);
if ( !$entry) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false; // Couldn't find the group...
}
// Get all the member DNs
if ( !$values = @ldap_get_values( $this->connection, $entry, "uniqueMember")) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false; // No users in the group
}
foreach ( $values as $key => $value) {
/* Loop through all members - see if the uname is there...
** Also check for sub-groups - this allows us to define a group as
** having membership of another group.
** FIXME:- This is pretty ugly code and unoptimised. It takes ages
** to search if you have sub-groups.
*/
list( $cn,$ou) = explode( ",",$value);
list( $ou_l,$ou_r) = explode( "=",$ou);
if ( $this->groups==$ou_r) {
list( $cn_l,$cn_r) = explode( "=",$cn);
// OK, So we now check the sub-group...
if ( $this->checkGroup ( $uname,$cn_r)) {
return true;
}
}
if ( preg_match( "/$uname/i",$value)) {
return true;
}
}
}
// 2.4 Attribute methods -----------------------------------------------------
/**
* 2.4.1 : Returns an array containing a set of attribute values.
* For most searches, this will just be one row, but sometimes multiple
* results are returned (eg:- multiple email addresses)
*/
function getAttribute ( $uname,$attribute) {
global $conf;
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
//$checkDn = $this->setDn( true);
$checkDn = $this->people;
$results[0] = $attribute;
// We need to search for this user in order to get their entry.
$this->result = @ldap_search( $this->connection,$checkDn,$this->getUserIdentifier()."=$uname",$results);
$info = ldap_get_entries( $this->connection, $this->result);
// Only one entry should ever be returned (no user will have the same uid)
$entry = ldap_first_entry( $this->connection, $this->result);
if ( !$entry) {
$this->ldapErrorCode = -1;
$this->ldapErrorText = "Couldn't find user";
return false; // Couldn't find the user...
}
// Get all the member DNs
if ( !$values = @ldap_get_values( $this->connection, $entry, $attribute)) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false; // No matching attributes
}
// Return an array containing the attributes.
return $values;
}
/**
* 2.4.2 : Allows an attribute value to be set.
* This can only usually be done after an authenticated bind as a
* directory manager - otherwise, read/write access will not be granted.
*/
function setAttribute( $uname, $attribute, $value) {
// Construct a full DN...
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
$attrib_dn = $this->getUserIdentifier()."=$uname," . $this->setDn(true);
$info[$attribute] = $value;
// Change attribute
$this->result = ldap_modify( $this->connection, $attrib_dn, $info);
if ( $this->result) {
// Change went OK
return true;
} else {
// Couldn't change password...
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
}
}
// 2.5 User methods ----------------------------------------------------------
/**
* 2.5.1 : Returns an array containing a details of users, sorted by
* username. The search criteria is a standard LDAP query - * returns all
* users. The $attributeArray variable contains the required user detail field names
*/
function getUsers( $search, $attributeArray) {
global $conf;
// builds the appropriate dn, based on whether $this->people and/or $this->group is set
//$checkDn = $this->setDn( true);
$checkDn = $conf->global->LDAP_USER_DN;
// Perform the search and get the entry handles
// if the directory is AD, then bind first with the search user first
if ($this->serverType == "activedirectory") {
$this->authBind($this->searchUser, $this->searchPassword);
}
$filter = '('.$conf->global->LDAP_FILTER_CONNECTION.'('.$this->getUserIdentifier().'='.$search.'))';
$this->result = @ldap_search( $this->connection, $checkDn, $filter);
if (!$this->result)
{
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
}
$info = @ldap_get_entries( $this->connection, $this->result);
for( $i = 0; $i < $info["count"]; $i++)
{
// Get the username, and create an array indexed by it...
// Modify these as you see fit.
$uname = $info[$i][$this->getUserIdentifier()][0];
// add to the array for each attribute in my list
for ( $j = 0; $j < count( $attributeArray); $j++)
{
if (strtolower($attributeArray[$j]) == "dn")
{
$userslist["$uname"]["$attributeArray[$j]"] = $info[$i][strtolower($attributeArray[$j])];
}
else if (strtolower($attributeArray[$j]) == "objectsid")
{
$objectsid = $this->getObjectSid($uname);
$userslist["$uname"]["$attributeArray[$j]"] = $objectsid[0];
}
else
{
$userslist["$uname"]["$attributeArray[$j]"] = $info[$i][strtolower($attributeArray[$j])][0];
}
}
}
if ( !@asort( $userslist)) {
/* Sort into alphabetical order. If this fails, it's because there
** were no results returned (array is empty) - so just return false.
*/
$this->ldapErrorCode = -1;
$this->ldapErrorText = "No users found matching search criteria ".$search;
return false;
}
return $userslist;
}
/**
* Récupère le SID de l'utilisateur
* ldapuser. le login de l'utilisateur
*/
function getObjectSid($ldapUser)
{
global $conf;
$criteria = $this->getUserIdentifier()."=$ldapUser";
$justthese = array("objectsid");
$checkDn = $conf->global->LDAP_USER_DN;
$ldapSearchResult = ldap_search($this->connection, $checkDn, $criteria, $justthese);
$entry = ldap_first_entry($this->connection, $ldapSearchResult);
$ldapBinary = ldap_get_values_len ($this->connection, $entry, "objectsid");
return $ldapBinary;
}
// 2.6 helper methods
/**
* Sets and returns the appropriate dn, based on whether there
* are values in $this->people and $this->groups.
*
* @param boolean specifies whether to build a groups dn or a people dn
* @return string if true ou=$this->people,$this->dn, else ou=$this->groups,$this->dn
*/
function setDn($peopleOrGroups) {
if ($peopleOrGroups) {
if ( isset($this->people) && (strlen($this->people) > 0) ) {
$checkDn = "ou=" .$this->people. ", " .$this->dn;
}
} else {
if ( isset($this->groups) && (strlen($this->groups) > 0) ) {
$checkDn = "ou=" .$this->groups. ", " .$this->dn;
}
}
if ( !isset($checkDn) ) {
$checkDn = $this->dn;
}
return $checkDn;
}
/**
* Returns the correct user identifier to use, based on the ldap server type
*/
function getUserIdentifier() {
if ($this->serverType == "activedirectory") {
return "samaccountname";
} else {
return "uid";
}
}
/**
* \brief permet d'enlever les accents d'une chaine.
* \param str
* \return string
*/
function dolibarr_ldap_unacc($str)
{
$stu = ereg_replace("é","e",$str);
$stu = ereg_replace("è","e",$stu);
$stu = ereg_replace("ê","e",$stu);
$stu = ereg_replace("à","a",$stu);
$stu = ereg_replace("ç","c",$stu);
$stu = ereg_replace("ï","i",$stu);
$stu = ereg_replace("ä","a",$stu);
return $stu;
}
} // End of class
?>

View File

@ -1,163 +0,0 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
* Copyright (C) 2005 Regis Houssin <regis.houssin@cap-networks.com>
* Copyright (C) 2006 Laurent Destailleur <eldy@users.sourceforge.net>
*
* 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.
* or see http://www.gnu.org/
*
* $Id$
* $Source$
*/
/**
\file htdocs/lib/ldap.lib.php
\brief Librairie contenant les fonctions pour accèder au serveur ldap.
\author Rodolphe Quiedeville.
\author Benoit Mortier.
\version $Revision$
Ensemble des fonctions permettant d'accèder à un serveur LDAP.
*/
class Ldap
{
var $err; // erreur ldap
/**
* \brief Constructeur de la classe
*/
function Ldap()
{
$this->err = "";
}
/**
\brief Ouverture d'une connection vers le serveur LDAP
\return resource
*/
function dolibarr_ldap_connect()
{
global $conf;
if (ereg('^ldap',$conf->global->LDAP_SERVER_HOST))
{
// ex url: ldaps://ldap.example.com/
$ldapconnect = ldap_connect($conf->global->LDAP_SERVER_HOST);
}
else
{
// ex serveur: localhost
// ex port: 389
$ldapconnect = ldap_connect($conf->global->LDAP_SERVER_HOST,$conf->global->LDAP_SERVER_PORT);
}
if ($ldapconnect)
{
ldap_set_option($ldapconnect, LDAP_OPT_PROTOCOL_VERSION, $conf->global->LDAP_SERVER_PROTOCOLVERSION);
}
return $ldapconnect;
}
/**
\brief Se connecte au serveur LDAP avec user et mot de passe
\param ds
\return bool
*/
function dolibarr_ldap_bind($ds)
{
global $conf;
if (defined("LDAP_ADMIN_PASS") && $conf->global->LDAP_ADMIN_DN && $conf->global->LDAP_ADMIN_PASS)
{
$ldapbind = @ldap_bind($ds, $conf->global->LDAP_ADMIN_DN, $conf->global->LDAP_ADMIN_PASS);
}
if ($ldapbind)
{
return $ldapbind;
}
else
{
$this->err = ldap_error($ds);
}
}
/**
\brief unbind du serveur ldap.
\param ds
\return bool
*/
function dolibarr_ldap_unbind($ds)
{
$ldapunbind = @ldap_unbind($ds);
return $ldapunbind;
}
/**
\brief verification de la version du serveur ldap.
\param ds
\return version
*/
function dolibarr_ldap_getversion($ds)
{
global $conf;
$version = 0;
ldap_get_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version);
return $version;
}
/**
\brief changement de la version du serveur ldap.
\param ds
\param version
\return version
*/
function dolibarr_ldap_setversion($ds,$version)
{
global $conf;
$ldapsetversion = ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version);
return $ldapsetversion;
}
/**
\brief permet d'enlever les accents d'une chaine.
\param str
\return string
*/
function dolibarr_ldap_unacc($str)
{
$stu = ereg_replace("é","e",$str);
$stu = ereg_replace("è","e",$stu);
$stu = ereg_replace("ê","e",$stu);
$stu = ereg_replace("à","a",$stu);
$stu = ereg_replace("ç","c",$stu);
$stu = ereg_replace("ï","i",$stu);
$stu = ereg_replace("ä","a",$stu);
return $stu;
}
}
?>

View File

@ -49,6 +49,7 @@ class User
var $db;
var $id;
var $ldap_sid;
var $fullname;
var $nom;
var $prenom;
@ -102,7 +103,7 @@ class User
{
// Recupere utilisateur
$sql = "SELECT u.rowid, u.name, u.firstname, u.email, u.office_phone, u.office_fax, u.user_mobile, u.code, u.admin, u.login, u.pass, u.webcal_login, u.note,";
$sql.= " u.fk_societe, u.fk_socpeople, ";
$sql.= " u.fk_societe, u.fk_socpeople, u.ldap_sid,";
$sql.= " ".$this->db->pdate("u.datec")." as datec, ".$this->db->pdate("u.tms")." as datem,";
$sql.= " ".$this->db->pdate("u.datelastaccess")." as datel";
$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
@ -122,6 +123,7 @@ class User
if ($obj)
{
$this->id = $obj->rowid;
$this->ldap_sid = $obj->ldap_sid;
$this->nom = stripslashes($obj->name);
$this->prenom = stripslashes($obj->firstname);
@ -129,9 +131,9 @@ class User
$this->code = $obj->code;
$this->login = $obj->login;
$this->pass = $obj->pass;
$this->office_phone = $obj->office_phone;
$this->office_fax = $obj->office_fax;
$this->user_mobile = $obj->user_mobile;
$this->office_phone = $obj->office_phone;
$this->office_fax = $obj->office_fax;
$this->user_mobile = $obj->user_mobile;
$this->email = $obj->email;
$this->admin = $obj->admin;
$this->contact_id = $obj->fk_socpeople;
@ -574,7 +576,7 @@ class User
}
else
{
$sql = "INSERT INTO ".MAIN_DB_PREFIX."user (datec,login) VALUES(now(),'".addslashes($this->login)."')";
$sql = "INSERT INTO ".MAIN_DB_PREFIX."user (datec,login,ldap_sid) VALUES(now(),'".addslashes($this->login)."','".$this->ldap_sid."')";
$result=$this->db->query($sql);
if ($result)

View File

@ -32,6 +32,7 @@
require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/contact.class.php");
require_once(DOL_DOCUMENT_ROOT."/lib/authldap.lib.php");
// Defini si peux creer un utilisateur ou gerer groupe sur un utilisateur
@ -124,12 +125,13 @@ if ($_POST["action"] == 'add' && $canadduser)
$edituser->prenom = trim($_POST["prenom"]);
$edituser->login = trim($_POST["login"]);
$edituser->admin = trim($_POST["admin"]);
$edituser->office_phone = trim($_POST["office_phone"]);
$edituser->office_fax = trim($_POST["office_fax"]);
$edituser->user_mobile = trim($_POST["user_mobile"]);
$edituser->office_phone = trim($_POST["office_phone"]);
$edituser->office_fax = trim($_POST["office_fax"]);
$edituser->user_mobile = trim($_POST["user_mobile"]);
$edituser->email = trim($_POST["email"]);
$edituser->webcal_login = trim($_POST["webcal_login"]);
$edituser->note = trim($_POST["note"]);
$edituser->ldap_sid = trim($_POST["ldap_sid"]);
$db->begin();
@ -295,7 +297,7 @@ if ((($_POST["action"] == 'confirm_password' && $_POST["confirm"] == 'yes')
llxHeader('',$langs->trans("UserCard"));
if ($action == 'create')
if (($action == 'create') || ($action == 'adduserldap'))
{
/* ************************************************************************** */
/* */
@ -307,33 +309,154 @@ if ($action == 'create')
print "<br>";
if ($message) { print $message.'<br>'; }
/*
* ajout utilisateur ldap
*/
if ($conf->ldap->enabled)
{
if ($conf->global->LDAP_SERVER_HOST && $conf->global->LDAP_ADMIN_DN && $conf->global->LDAP_ADMIN_PASS)
{
$ldap = new AuthLdap();
if ($ldap->connect())
{
$justthese = array( "sn", "givenname", "samaccountname");
$ldapusers = $ldap->getUsers('*', $justthese);
if ($ldapusers)
{
$html = new Form($db);
foreach ($ldapusers as $key => $ldapuser)
{
if($ldapuser["sn"] != "")
$liste[$ldapuser["samaccountname"]] = utf8_decode($ldapuser["sn"])." ".utf8_decode($ldapuser["givenname"]);
}
print '<form name="add_user_ldap" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="adduserldap">';
print $html->select_array('users', $liste, '', 1);
print '<input type="submit" class="button" value="'.$langs->trans('Add').'">';
print '</form>';
print "<br>";
}
if ($action == 'adduserldap')
{
$selecteduser = $_POST['users'];
$justthese = array( "samaccountname",
"sn",
"givenname",
"mail",
"telephonenumber",
"facsimiletelephonenumber",
"mobile",
"objectsid");
$selectedUser = $ldap->getUsers($selecteduser, $justthese);
if ($selectedUser)
{
foreach ($selectedUser as $key => $attribute)
{
$ldap_nom = utf8_decode($attribute["sn"]?$attribute["sn"]:'');
$ldap_prenom = utf8_decode($attribute["givenname"]?$attribute["givenname"]:'');
$ldap_login = utf8_decode($attribute["samaccountname"]?$attribute["samaccountname"]:'');
$ldap_phone = utf8_decode($attribute["telephonenumber"]?$attribute["telephonenumber"]:'');
$ldap_fax = utf8_decode($attribute["facsimiletelephonenumber"]?$attribute["facsimiletelephonenumber"]:'');
$ldap_mobile = utf8_decode($attribute["mobile"]?$attribute["mobile"]:'');
$ldap_mail = utf8_decode($attribute["mail"]?$attribute["mail"]:'');
$ldap_SID = bin2hex($attribute["objectsid"]);
}
}
}
}
else
{
print $ldap->ldapErrorCode;
print $ldap->ldapErrorText;
}
if (!$ldap->close())
{
print $ldap->ldapErrorCode;
print $ldap->ldapErrorText;
}
}
}
print '<form action="fiche.php" method="post" name="createuser">';
print '<input type="hidden" name="action" value="add">';
if ($ldap_SID) print '<input type="hidden" name="ldap_sid" value="'.$ldap_SID.'">';
print '<table class="border" width="100%">';
print "<tr>".'<td valign="top">'.$langs->trans("Lastname").'</td>';
print '<td class="valeur"><input size="30" type="text" name="nom" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_nom)
{
print '<input type="hidden" name="nom" value="'.$ldap_nom.'">';
print $ldap_nom;
}
else
{
print '<input size="30" type="text" name="nom" value="">';
}
print '</td></tr>';
print '<tr><td valign="top" width="20%">'.$langs->trans("Firstname").'</td>';
print '<td class="valeur"><input size="30" type="text" name="prenom" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_prenom)
{
print '<input type="hidden" name="prenom" value="'.$ldap_prenom.'">';
print $ldap_prenom;
}
else
{
print '<input size="30" type="text" name="prenom" value="">';
}
print '</td></tr>';
print '<tr><td valign="top">'.$langs->trans("Login").'</td>';
print '<td class="valeur"><input size="20" maxsize="24" type="text" name="login" value=""></td></tr>';
$generated_password='';
if ($conf->global->USER_PASSWORD_GENERATED)
print '<td class="valeur">';
if ($ldap_login)
{
$nomclass="modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
$nomfichier=$nomclass.".class.php";
//print DOL_DOCUMENT_ROOT."/includes/modules/security/generate/".$nomclass;
require_once(DOL_DOCUMENT_ROOT."/includes/modules/security/generate/".$nomfichier);
$genhandler=new $nomclass($db,$conf,$lang,$user);
$generated_password=$genhandler->getNewGeneratedPassword();
print '<input type="hidden" name="login" value="'.$ldap_login.'">';
print $ldap_login;
}
print '<tr><td valign="top">'.$langs->trans("Password").'</td>';
print '<td class="valeur"><input size="30" maxsize="32" type="text" name="password" value="'.$generated_password.'"></td></tr>';
else
{
print '<input size="20" maxsize="24" type="text" name="login" value="">';
}
print '</td></tr>';
if (!$ldap_SID)
{
$generated_password='';
if ($conf->global->USER_PASSWORD_GENERATED)
{
$nomclass="modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
$nomfichier=$nomclass.".class.php";
//print DOL_DOCUMENT_ROOT."/includes/modules/security/generate/".$nomclass;
require_once(DOL_DOCUMENT_ROOT."/includes/modules/security/generate/".$nomfichier);
$genhandler=new $nomclass($db,$conf,$lang,$user);
$generated_password=$genhandler->getNewGeneratedPassword();
}
}
print '<tr><td valign="top">'.$langs->trans("Password").'</td>';
print '<td class="valeur">';
if ($ldap_SID)
{
print 'mot de passe du domaine';
}
else
{
print '<input size="30" maxsize="32" type="text" name="password" value="'.$generated_password.'">';
}
print '</td></tr>';
if ($user->admin)
{
@ -344,16 +467,56 @@ if ($action == 'create')
}
print '<tr><td valign="top">'.$langs->trans("Phone").'</td>';
print '<td class="valeur"><input size="20" type="text" name="office_phone" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_phone)
{
print '<input type="hidden" name="office_phone" value="'.$ldap_phone.'">';
print $ldap_phone;
}
else
{
print '<input size="20" type="text" name="office_phone" value="">';
}
print '</td></tr>';
print '<tr><td valign="top">'.$langs->trans("Fax").'</td>';
print '<td class="valeur"><input size="20" type="text" name="office_fax" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_fax)
{
print '<input type="hidden" name="office_fax" value="'.$ldap_fax.'">';
print $ldap_fax;
}
else
{
print '<input size="20" type="text" name="office_fax" value="">';
}
print '</td></tr>';
print '<tr><td valign="top">'.$langs->trans("Mobile").'</td>';
print '<td class="valeur"><input size="20" type="text" name="user_mobile" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_mobile)
{
print '<input type="hidden" name="user_mobile" value="'.$ldap_mobile.'">';
print $ldap_mobile;
}
else
{
print '<input size="20" type="text" name="user_mobile" value="">';
}
print '</td></tr>';
print '<tr><td valign="top">'.$langs->trans("EMail").'</td>';
print '<td class="valeur"><input size="40" type="text" name="email" value=""></td></tr>';
print '<td class="valeur">';
if ($ldap_mail)
{
print '<input type="hidden" name="email" value="'.$ldap_mail.'">';
print $ldap_mail;
}
else
{
print '<input size="40" type="text" name="email" value="">';
}
print '</td></tr>';
print '<tr><td valign="top">'.$langs->trans("Note").'</td><td>';
print "<textarea name=\"note\" rows=\"6\" cols=\"40\">";
@ -497,8 +660,15 @@ else
// Password
print '<tr><td width="25%" valign="top">'.$langs->trans("Password").'</td>';
print '<td width="50%" class="valeur">'.eregi_replace('.','*',$fuser->pass).'</td>';
print "</tr>\n";
if ($fuser->ldap_sid)
{
print '<td>Mot de passe du domaine</td>';
}
else
{
print '<td width="50%" class="valeur">'.eregi_replace('.','*',$fuser->pass);
}
print "</td></tr>\n";
// Administrateur
print '<tr><td width="25%" valign="top">'.$langs->trans("Administrator").'</td>';
@ -514,6 +684,10 @@ else
{
print $langs->trans("External");
}
else if ($fuser->ldap_sid)
{
print $langs->trans("DomainUser");
}
else
{
print $langs->trans("Internal");
@ -600,12 +774,12 @@ else
// Si on a un gestionnaire de generation de mot de passe actif
if ($conf->global->USER_PASSWORD_GENERATED != 'none')
{
if (($user->id != $_GET["id"] && $caneditpassword) && $fuser->login)
if (($user->id != $_GET["id"] && $caneditpassword) && $fuser->login && !$fuser->ldap_sid)
{
print '<a class="butAction" href="fiche.php?id='.$fuser->id.'&amp;action=password">'.$langs->trans("ReinitPassword").'</a>';
}
if (($user->id != $_GET["id"] && $caneditpassword) && $fuser->email && $fuser->login)
if (($user->id != $_GET["id"] && $caneditpassword) && $fuser->email && $fuser->login && !$fuser->ldap_sid)
{
print '<a class="butAction" href="fiche.php?id='.$fuser->id.'&amp;action=passwordsend">'.$langs->trans("SendNewPassword").'</a>';
}
@ -787,17 +961,20 @@ else
print '</td></tr>';
// Pass
if ($caneditpassword)
print '<tr><td valign="top">'.$langs->trans("Password").'</td>';
if ($fuser->ldap_sid)
{
print "<tr>".'<td valign="top">'.$langs->trans("Password").'</td>';
print '<td><input size="12" maxlength="32" type="password" class="flat" name="pass" value="'.$fuser->pass.'"></td></tr>';
print '<td>Mot de passe du domaine</td>';
}
else if ($caneditpassword)
{
print '<td><input size="12" maxlength="32" type="password" class="flat" name="pass" value="'.$fuser->pass.'"></td>';
}
else
{
print '<tr><td width="25%" valign="top">'.$langs->trans("Password").'</td>';
print '<td width="50%" class="valeur">'.eregi_replace('.','*',$fuser->pass).'</td>';
print "</tr>\n";
print '<td width="50%" class="valeur">'.eregi_replace('.','*',$fuser->pass);
}
print "</td></tr>\n";
// Administrateur
print "<tr>".'<td valign="top">'.$langs->trans("Administrator").'</td>';
@ -828,6 +1005,10 @@ else
{
print $langs->trans("External");
}
else if ($fuser->ldap_sid)
{
print $langs->trans("DomainUser");
}
else
{
print $langs->trans("Internal");

View File

@ -81,7 +81,7 @@ print '</td><td valign="top" width="70%" class="notopnoleftnoright">';
$max=10;
$sql = "SELECT u.rowid, u.name, u.firstname, u.admin, u.login, u.code, u.fk_societe, ".$db->pdate("u.datec")." as datec,";
$sql.= " s.nom";
$sql.= " u.ldap_sid, s.nom";
$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_societe=s.idp";
$sql.= " ORDER BY u.datec";
@ -111,6 +111,10 @@ if ($resql)
{
print '<a href="'.DOL_URL_ROOT.'/soc.php?socid='.$obj->fk_societe.'">'.img_object($langs->trans("ShowCompany"),"company").' '.$obj->nom.'</a>';
}
else if ($obj->ldap_sid)
{
print $langs->trans("DomainUser");
}
else print $langs->trans("InternalUser");
print '</td>';
print "<td width=\"80\" align=\"center\">".dolibarr_print_date($obj->datec)."</td>";

View File

@ -53,7 +53,7 @@ llxHeader();
print_titre($langs->trans("ListOfUsers"));
$sql = "SELECT u.rowid, u.name, u.firstname, u.admin, u.code, u.fk_societe, u.login, ".$db->pdate("u.datec")." as datec,";
$sql.= " s.nom";
$sql.= " u.ldap_sid, s.nom";
$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_societe = s.idp";
$sql.= " WHERE 1=1";
@ -115,6 +115,10 @@ if ($result)
{
print '<a href="'.DOL_URL_ROOT.'/soc.php?socid='.$obj->fk_societe.'">'.img_object($langs->trans("ShowCompany"),"company").' '.$obj->nom.'</a>';
}
else if ($obj->ldap_sid)
{
print $langs->trans("DomainUser");
}
else print $langs->trans("InternalUser");
print '</td>';
print '<td width="100" align="center">'.dolibarr_print_date($obj->datec,"%d %b %Y").'</td>';

View File

@ -518,6 +518,17 @@ insert into llx_c_pays (rowid,code,libelle) values (27, 'SA', 'Arabie Saoudite')
insert into llx_c_pays (rowid,code,libelle) values (28, 'MC', 'Monaco' );
insert into llx_c_pays (rowid,code,libelle) values (29, 'AU', 'Australie' );
insert into llx_c_pays (rowid,code,libelle) values (30, 'SG', 'Singapoure' );
insert into llx_c_pays (rowid,code,libelle) values (31, 'AF', 'Afghanistan' );
insert into llx_c_pays (rowid,code,libelle) values (32, 'AX', 'Aland Islands' );
insert into llx_c_pays (rowid,code,libelle) values (33, 'AL', 'Albanie' );
insert into llx_c_pays (rowid,code,libelle) values (34, 'AS', 'American Samoa' );
insert into llx_c_pays (rowid,code,libelle) values (35, 'AD', 'Andorre' );
insert into llx_c_pays (rowid,code,libelle) values (36, 'AO', 'Angola' );
insert into llx_c_pays (rowid,code,libelle) values (37, 'AI', 'Anguilla' );
insert into llx_c_pays (rowid,code,libelle) values (38, 'AQ', 'Antartique' );
insert into llx_c_pays (rowid,code,libelle) values (39, 'AG', 'Antigua et Barbuda');
insert into llx_c_pays (rowid,code,libelle) values (40, 'AM', 'Armenie' );
insert into llx_c_pays (rowid,code,libelle) values (41, 'AW', 'Aruba' );
--

View File

@ -310,4 +310,6 @@ insert into llx_const (name, value, type, visible, note) VALUES ('PROPALE_VALIDI
alter table llx_propal add column ref_client varchar(30) after ref;
alter table llx_societe_adresse_livraison drop column fk_departement;
alter table llx_societe_adresse_livraison drop column fk_departement;
alter table llx_user add column ldap_sid varchar(255)DEFAULT NULL;

View File

@ -43,6 +43,7 @@ create table llx_user
note text,
datelastaccess datetime,
egroupware_id integer,
ldap_sid varchar(255) DEFAULT NULL,
UNIQUE INDEX(login)
)type=innodb;