diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php
index a1fc7c87d68..438c7cd5227 100644
--- a/htdocs/admin/dict.php
+++ b/htdocs/admin/dict.php
@@ -187,7 +187,7 @@ $tabsql[9] = "SELECT c.code_iso as code, c.label, c.unicode, c.active FROM ".MAI
$tabsql[10]= "SELECT t.rowid, t.code, t.taux, t.localtax1_type, t.localtax1, t.localtax2_type, t.localtax2, c.label as country, c.code as country_code, t.fk_pays as country_id, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid";
$tabsql[11]= "SELECT t.rowid as rowid, t.element, t.source, t.code, t.libelle, t.position, t.active FROM ".MAIN_DB_PREFIX."c_type_contact AS t";
$tabsql[12]= "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = " . getEntity($tabname[12]);
-$tabsql[13]= "SELECT c.id as rowid, c.code, c.libelle, c.type, c.active, c.accountancy_code, c.entity FROM ".MAIN_DB_PREFIX."c_paiement AS c WHERE c.entity = " . getEntity($tabname[13]);
+$tabsql[13]= "SELECT c.id as rowid, c.code, c.libelle, c.type, c.active, c.entity FROM ".MAIN_DB_PREFIX."c_paiement AS c WHERE c.entity = " . getEntity($tabname[13]);
$tabsql[14]= "SELECT e.rowid as rowid, e.code as code, e.libelle, e.price, e.organization, e.fk_pays as country_id, c.code as country_code, c.label as country, e.active FROM ".MAIN_DB_PREFIX."c_ecotaxe AS e, ".MAIN_DB_PREFIX."c_country as c WHERE e.fk_pays=c.rowid and c.active=1";
$tabsql[15]= "SELECT rowid as rowid, code, label as libelle, width, height, unit, active FROM ".MAIN_DB_PREFIX."c_paper_format";
$tabsql[16]= "SELECT code, label as libelle, sortorder, active FROM ".MAIN_DB_PREFIX."c_prospectlevel";
@@ -265,7 +265,7 @@ $tabfield[9] = "code,label,unicode";
$tabfield[10]= "country_id,country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfield[11]= "element,source,code,libelle,position";
$tabfield[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity";
-$tabfield[13]= "code,libelle,type,accountancy_code,entity";
+$tabfield[13]= "code,libelle,type,entity";
$tabfield[14]= "code,libelle,price,organization,country_id,country";
$tabfield[15]= "code,libelle,width,height,unit";
$tabfield[16]= "code,libelle,sortorder";
@@ -304,7 +304,7 @@ $tabfieldvalue[9] = "code,label,unicode";
$tabfieldvalue[10]= "country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfieldvalue[11]= "element,source,code,libelle,position";
$tabfieldvalue[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder";
-$tabfieldvalue[13]= "code,libelle,type,accountancy_code";
+$tabfieldvalue[13]= "code,libelle,type";
$tabfieldvalue[14]= "code,libelle,price,organization,country";
$tabfieldvalue[15]= "code,libelle,width,height,unit";
$tabfieldvalue[16]= "code,libelle,sortorder";
@@ -343,7 +343,7 @@ $tabfieldinsert[9] = "code_iso,label,unicode";
$tabfieldinsert[10]= "fk_pays,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfieldinsert[11]= "element,source,code,libelle,position";
$tabfieldinsert[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity";
-$tabfieldinsert[13]= "code,libelle,type,accountancy_code,entity";
+$tabfieldinsert[13]= "code,libelle,type,entity";
$tabfieldinsert[14]= "code,libelle,price,organization,fk_pays";
$tabfieldinsert[15]= "code,label,width,height,unit";
$tabfieldinsert[16]= "code,label,sortorder";
diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php
index 633f84b6582..08b384d7ac5 100644
--- a/htdocs/blockedlog/admin/blockedlog_list.php
+++ b/htdocs/blockedlog/admin/blockedlog_list.php
@@ -359,7 +359,8 @@ print '';
// User
print '
';
-print $form->select_dolusers($search_fk_user, 'search_fk_user', 1);
+print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300');
+
print ' | ';
// Actions code
diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php
index daa5ade05b5..255dc4888aa 100644
--- a/htdocs/categories/viewcat.php
+++ b/htdocs/categories/viewcat.php
@@ -353,7 +353,7 @@ if ($type == Categorie::TYPE_PRODUCT)
print "
";
print "\n";
- print '| '.$langs->trans("ProductsAndServices")." |
\n";
+ print '| '.$langs->trans("ProductsAndServices")." (".count($prods).") |
\n";
if (count($prods) > 0)
{
@@ -402,7 +402,7 @@ if ($type == Categorie::TYPE_SUPPLIER)
{
print "
";
print ''."\n";
- print '| '.$langs->trans("Suppliers")." |
\n";
+ print '| '.$langs->trans("Suppliers")." (".count($socs).") |
\n";
if (count($socs) > 0)
{
@@ -451,7 +451,7 @@ if($type == Categorie::TYPE_CUSTOMER)
{
print "
";
print ''."\n";
- print '| '.$langs->trans("Customers")." |
\n";
+ print '| '.$langs->trans("Customers")." (".count($socs).") |
\n";
if (count($socs) > 0)
{
@@ -507,7 +507,7 @@ if ($type == Categorie::TYPE_MEMBER)
{
print "
";
print "\n";
- print '| '.$langs->trans("Member")." |
\n";
+ print '| '.$langs->trans("Member")." (".count($prods).") |
\n";
if (count($prods) > 0)
{
@@ -558,7 +558,7 @@ if ($type == Categorie::TYPE_CONTACT)
{
print "
";
print ''."\n";
- print '| '.$langs->trans("Contact")." |
\n";
+ print '| '.$langs->trans("Contact")." (".count($contacts).") |
\n";
if (count($contacts) > 0)
{
@@ -613,7 +613,7 @@ if ($type == Categorie::TYPE_ACCOUNT)
{
print "
";
print "\n";
- print '| '.$langs->trans("Account")." |
\n";
+ print '| '.$langs->trans("Account")." (".count($accounts).") |
\n";
if (count($accounts) > 0)
{
@@ -666,7 +666,7 @@ if ($type == Categorie::TYPE_PROJECT)
{
print "
";
print "\n";
- print '| '.$langs->trans("Project")." |
\n";
+ print '| '.$langs->trans("Project")." (".count($projects).") |
\n";
if (count($projects) > 0)
{
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 88d4e550b03..9cbf52c1cc8 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -2188,7 +2188,7 @@ function dol_print_skype($skype,$cid=0,$socid=0,$addlink=0,$max=64)
*/
function dol_print_phone($phone,$countrycode='',$cid=0,$socid=0,$addlink='',$separ=" ",$withpicto='',$titlealt='',$adddivfloat=0)
{
- global $conf,$user,$langs,$mysoc;
+ global $conf, $user, $langs, $mysoc, $hookmanager;
// Clean phone parameter
$phone = preg_replace("/[\s.-]/","",trim($phone));
@@ -2278,23 +2278,33 @@ function dol_print_phone($phone,$countrycode='',$cid=0,$socid=0,$addlink='',$sep
$titlealt=($withpicto=='fax'?$langs->trans("Fax"):$langs->trans("Phone"));
}
$rep='';
- $picto = '';
- if($withpicto){
- if($withpicto=='fax'){
- $picto = 'phoning_fax';
- }elseif($withpicto=='phone'){
- $picto = 'phoning';
- }elseif($withpicto=='mobile'){
- $picto = 'phoning_mobile';
- }else{
- $picto = '';
+
+ if ($hookmanager) {
+ $parameters = array('countrycode' => $countrycode, 'cid' => $cid, 'socid' => $socid,'titlealt' => $titlealt, 'picto' => $withpicto);
+ $reshook = $hookmanager->executeHooks('printPhone', $parameters, $phone);
+ $rep.=$hookmanager->resPrint;
+ }
+ if (empty($reshook))
+ {
+ $picto = '';
+ if($withpicto){
+ if($withpicto=='fax'){
+ $picto = 'phoning_fax';
+ }elseif($withpicto=='phone'){
+ $picto = 'phoning';
+ }elseif($withpicto=='mobile'){
+ $picto = 'phoning_mobile';
+ }else{
+ $picto = '';
+ }
}
- }
- if ($adddivfloat) $rep.='';
- else $rep.='';
- $rep.=($withpicto?img_picto($titlealt, 'object_'.$picto.'.png').' ':'').$newphone;
- if ($adddivfloat) $rep.='
';
- else $rep.='';
+ if ($adddivfloat) $rep.='';
+ else $rep.='';
+ $rep.=($withpicto?img_picto($titlealt, 'object_'.$picto.'.png').' ':'').$newphone;
+ if ($adddivfloat) $rep.='
';
+ else $rep.='';
+ }
+
return $rep;
}
@@ -3357,18 +3367,19 @@ function img_searchclear($titlealt = 'default', $other = '')
* @param integer $infoonimgalt Info is shown only on alt of star picto, otherwise it is show on output after the star picto
* @param int $nodiv No div
* @param string $admin '1'=Info for admin users. '0'=Info for standard users (change only the look), 'xxx'=Other
+ * @param string $morecss More CSS
* @return string String with info text
*/
-function info_admin($text, $infoonimgalt = 0, $nodiv=0, $admin='1')
+function info_admin($text, $infoonimgalt = 0, $nodiv=0, $admin='1', $morecss='')
{
global $conf, $langs;
if ($infoonimgalt)
{
- return img_picto($text, 'info', 'class="hideonsmartphone"');
+ return img_picto($text, 'info', 'class="hideonsmartphone'.($morecss?' '.$morecss:'').'"');
}
- return ($nodiv?'':'').' '.$text.($nodiv?'':'
');
+ return ($nodiv?'':'').' '.$text.($nodiv?'':'
');
}
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 03612250b85..c55282dc3d0 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -82,6 +82,10 @@ function dol_hash($chain, $type='0')
{
global $conf;
+ // No need to add salt for password_hash
+ if ($type == '0' && ! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'password_hash' && function_exists('password_hash'))
+ return password_hash($chain, PASSWORD_DEFAULT);
+
// Salt value
if (! empty($conf->global->MAIN_SECURITY_SALT)) $chain=$conf->global->MAIN_SECURITY_SALT.$chain;
@@ -97,6 +101,32 @@ function dol_hash($chain, $type='0')
return md5($chain);
}
+/**
+ * Compute a hash and compare it to the given one
+ * For backward compatibility reasons, if the hash is not in the password_hash format, we will try to match against md5 and sha1md5
+ * If constant MAIN_SECURITY_HASH_ALGO is defined, we use this function as hashing function.
+ * If constant MAIN_SECURITY_SALT is defined, we use it as a salt.
+ *
+ * @param string $chain String to hash
+ * @param string $hash hash to compare
+ * @param string $type Type of hash ('0':auto, '1':sha1, '2':sha1+md5, '3':md5, '4':md5 for OpenLdap, '5':sha256). Use '3' here, if hash is not needed for security purpose, for security need, prefer '0'.
+ * @return bool True if the computed hash is the same as the given one
+ */
+function dol_verifyHash($chain, $hash, $type='0')
+{
+ global $conf;
+
+ if ($type == '0' && ! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'password_hash' && function_exists('password_verify')) {
+ if ($hash[0] == '$') return password_verify($chain, $hash);
+ else if(strlen($hash) == 32) return dol_verifyHash($chain, $hash, '3'); // md5
+ else if(strlen($hash) == 40) return dol_verifyHash($chain, $hash, '2'); // sha1md5
+
+ return false;
+ }
+
+ return dol_hash($chain, $type) == $hash;
+}
+
/**
* Check permissions of a user to show a page and an object. Check read permission.
@@ -607,4 +637,3 @@ function accessforbidden($message='',$printheader=1,$printfooter=1,$showonlymess
if ($printfooter && function_exists("llxFooter")) llxFooter();
exit(0);
}
-
diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php
index d8cf78747b8..25d5f2dc30c 100644
--- a/htdocs/core/login/functions_dolibarr.php
+++ b/htdocs/core/login/functions_dolibarr.php
@@ -84,7 +84,7 @@ function check_user_password_dolibarr($usertotest,$passwordtotest,$entitytotest=
// Check crypted password according to crypt algorithm
if ($cryptType == 'md5')
{
- if (dol_hash($passtyped) == $passcrypted)
+ if (dol_verifyHash($passtyped, $passcrypted))
{
$passok=true;
dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ok - ".$cryptType." of pass is ok");
@@ -152,5 +152,3 @@ function check_user_password_dolibarr($usertotest,$passwordtotest,$entitytotest=
return $login;
}
-
-
diff --git a/htdocs/index.php b/htdocs/index.php
index 867f305a680..b01e37927c4 100644
--- a/htdocs/index.php
+++ b/htdocs/index.php
@@ -656,7 +656,7 @@ if ($user->admin && empty($conf->global->MAIN_REMOVE_INSTALL_WARNING))
{
$langs->load("errors");
//if (! empty($message)) $message.='
';
- $message.=info_admin($langs->trans("WarningLockFileDoesNotExists",DOL_DATA_ROOT).' '.$langs->trans("WarningUntilDirRemoved",DOL_DOCUMENT_ROOT."/install"));
+ $message.=info_admin($langs->trans("WarningLockFileDoesNotExists",DOL_DATA_ROOT).' '.$langs->trans("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT."/install"), 0, 0, '1', 'clearboth');
}
// Conf files must be in read only mode
@@ -665,7 +665,7 @@ if ($user->admin && empty($conf->global->MAIN_REMOVE_INSTALL_WARNING))
$langs->load("errors");
//$langs->load("other");
//if (! empty($message)) $message.='
';
- $message.=info_admin($langs->transnoentities("WarningConfFileMustBeReadOnly").' '.$langs->trans("WarningUntilDirRemoved",DOL_DOCUMENT_ROOT."/install"));
+ $message.=info_admin($langs->transnoentities("WarningConfFileMustBeReadOnly").' '.$langs->trans("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT."/install"), 0, 0, '1', 'clearboth');
}
if ($message)
diff --git a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql
new file mode 100644
index 00000000000..e9a72ab9360
--- /dev/null
+++ b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql
@@ -0,0 +1,26 @@
+--
+-- Be carefull to requests order.
+-- This file must be loaded by calling /install/index.php page
+-- when current version is 7.0.0 or higher.
+--
+-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new;
+-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol;
+-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60);
+-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname;
+-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60);
+-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name;
+-- To drop an index: -- VMYSQL4.0 DROP INDEX nomindex on llx_table
+-- To drop an index: -- VPGSQL8.0 DROP INDEX nomindex
+-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y
+-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y
+-- To make pk to be auto increment (mysql): -- VMYSQL4.3 ALTER TABLE llx_c_shipment_mode CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT;
+-- To make pk to be auto increment (postgres): -- VPGSQL8.2 NOT POSSIBLE. MUST DELETE/CREATE TABLE
+-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL;
+-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL;
+-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL;
+-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL;
+-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL;
+-- Note: fields with type BLOB/TEXT can't have default value.
+
+-- For 8.0
+ALTER TABLE llx_societe ADD COLUMN fk_entrepot int DEFAULT 0;
diff --git a/htdocs/install/step5.php b/htdocs/install/step5.php
index 8a39faf526a..91c517f9644 100644
--- a/htdocs/install/step5.php
+++ b/htdocs/install/step5.php
@@ -181,7 +181,10 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i',$action))
// Define default setup for password encryption
dolibarr_set_const($db, "DATABASE_PWD_ENCRYPTED", "1", 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_SECURITY_SALT", dol_print_date(dol_now(), 'dayhourlog'), 'chaine', 0, '', 0); // All entities
- dolibarr_set_const($db, "MAIN_SECURITY_HASH_ALGO", 'sha1md5', 'chaine', 0, '', 0); // All entities
+ if (function_exists('password_hash'))
+ dolibarr_set_const($db, "MAIN_SECURITY_HASH_ALGO", 'password_hash', 'chaine', 0, '', 0); // All entities
+ else
+ dolibarr_set_const($db, "MAIN_SECURITY_HASH_ALGO", 'sha1md5', 'chaine', 0, '', 0); // All entities
}
}
diff --git a/htdocs/user/passwordforgotten.php b/htdocs/user/passwordforgotten.php
index 6d2661a2344..cde5c5199e0 100644
--- a/htdocs/user/passwordforgotten.php
+++ b/htdocs/user/passwordforgotten.php
@@ -78,7 +78,7 @@ if ($action == 'validatenewpassword' && $username && $passwordhash)
}
else
{
- if (dol_hash($edituser->pass_temp) == $passwordhash)
+ if (dol_verifyHash($edituser->pass_temp, $passwordhash))
{
$newpassword=$edituser->setPassword($user,$edituser->pass_temp,0);
dol_syslog("passwordforgotten.php new password for user->id=".$edituser->id." validated in database");
@@ -218,4 +218,3 @@ $reshook = $hookmanager->executeHooks('getPasswordForgottenPageExtraOptions',$pa
$moreloginextracontent = $hookmanager->resPrint;
include $template_dir.'passwordforgotten.tpl.php'; // To use native PHP
-