diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php
index d4b5407c9123400c6b3dea3b2079e0a74cc0686b..ba2643a04b87170fc36ec530f5d6564adc0ff710 100644
--- a/htdocs/accountancy/admin/accountmodel.php
+++ b/htdocs/accountancy/admin/accountmodel.php
@@ -888,18 +888,18 @@ if ($id)
             {
                 if ($value == 'country')
                 {
-                    print '<td>';
+                    print '<td class="liste_titre">';
                     print $form->select_country($search_country_id, 'search_country_id', '', 28, 'maxwidth200 maxwidthonsmartphone');
                     print '</td>';
                 }
                 else
                 {
-                    print '<td></td>';
+                    print '<td class="liste_titre"></td>';
                 }
             }
         }
         if ($id == 4) print '<td></td>';
-        print '<td></td>';
+        print '<td class="liste_titre"></td>';
     	print '<td class="liste_titre" colspan="2" align="right">';
     	$searchpitco=$form->showFilterAndCheckAddButtons(0);
     	print $searchpitco;
diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php
index 6308c2d3edc52ecd160af94215196d22339cbe27..ca6a3657774736cd748fc35a76b41d07bf93bcb0 100644
--- a/htdocs/accountancy/bookkeeping/listbyaccount.php
+++ b/htdocs/accountancy/bookkeeping/listbyaccount.php
@@ -235,9 +235,8 @@ print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60"
 print "</tr>\n";
 
 print '<tr class="liste_titre">';
-print '<form action="' . $_SERVER["PHP_SELF"] . '" method="GET">';
-print '<td>' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . '</td>';
-print '<td></td>';
+print '<td class="liste_titre">' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . '</td>';
+print '<td class="liste_titre"></td>';
 print '<td class="liste_titre" align="center">';
 print $langs->trans('From') . ': ';
 print $form->select_date($search_date_start, 'date_start', 0, 0, 1);
@@ -247,10 +246,10 @@ print $form->select_date($search_date_end, 'date_end', 0, 0, 1);
 print '</td>';
 print '<td class="liste_titre"><input type="text" size="7" class="flat" name="search_mvt_label" value="' . $search_mvt_label . '"/></td>';
 print '<td class="liste_titre"><input type="text" size="7" class="flat" name="search_label_account" value="' . $search_label_account . '"/></td>';
-print '<td>&nbsp;</td>';
-print '<td>&nbsp;</td>';
-print '<td  align="right"><input type="text" name="search_ledger_code" size="3" value="' . $search_ledger_code . '"></td>';
-print '<td align="right" colspan="2" class="liste_titre">';
+print '<td class="liste_titre">&nbsp;</td>';
+print '<td class="liste_titre">&nbsp;</td>';
+print '<td class="liste_titre" align="right"><input type="text" name="search_ledger_code" size="3" value="' . $search_ledger_code . '"></td>';
+print '<td class="liste_titre" align="right" colspan="2">';
 $searchpitco=$form->showFilterAndCheckAddButtons(0);
 print $searchpitco;
 print '</td>';
diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php
index ef5c512179a290f2386f70a51abbd6524f8e9d75..dddc7c896c02003bb6077cec8b85a25143ea3aa4 100644
--- a/htdocs/accountancy/customer/index.php
+++ b/htdocs/accountancy/customer/index.php
@@ -29,6 +29,7 @@
 require '../../main.inc.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
+require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
 
 // Langs
 $langs->load("compta");
@@ -179,7 +180,14 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 1) print '<a class="butActionDelete" hr
 $sql = "SELECT count(*) FROM " . MAIN_DB_PREFIX . "facturedet as fd";
 $sql .= " , " . MAIN_DB_PREFIX . "facture as f";
 $sql .= " WHERE fd.fk_code_ventilation = 0";
-$sql .= " AND f.rowid = fd.fk_facture AND f.fk_statut = 1;";
+$sql .= " AND f.rowid = fd.fk_facture";
+$sql .= " AND f.fk_statut > 0";
+if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+} else {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+}
+$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";    // We don't share object for accountancy
 
 dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG);
 $result = $db->query($sql);
@@ -222,6 +230,11 @@ $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'
 $sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
 $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
 $sql .= " AND aa.account_number IS NULL";
+if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+} else {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+}
 $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label";
 
 dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG);
@@ -273,6 +286,11 @@ $sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid
 $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
 $sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
 $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
+if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+} else {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+}
 $sql .= " AND aa.account_number IS NOT NULL";
 $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label";
 
@@ -301,97 +319,105 @@ print "</table>\n";
 
 
 
-
-
-print '<br>';
-print '<br>';
-
-
-print_fiche_titre($langs->trans("OtherInfo"), '', '');
-
-
-print "<br>\n";
-print '<table class="noborder" width="100%">';
-print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("TotalVente") . '</td>';
-for($i = 1; $i <= 12; $i ++) {
-	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
-}
-print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
-
-$sql = "SELECT '" . $langs->trans("TotalVente") . "' AS total,";
-for($i = 1; $i <= 12; $i ++) {
-	$sql .= "  SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
-}
-$sql .= "  SUM(fd.total_ht) as total";
-$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd";
-$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture";
-$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
-$sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
-$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy
-
-dol_syslog('htdocs/accountancy/customer/index.php');
-$resql = $db->query($sql);
-if ($resql) {
-	$i = 0;
-	$num = $db->num_rows($resql);
-
-	while ($row = $db->fetch_row($resql)) {
-		print '<tr><td>' . $row[0] . '</td>';
-		for($i = 1; $i <= 12; $i ++) {
-			print '<td align="right">' . price($row[$i]) . '</td>';
-		}
-		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
-		print '</tr>';
-		$i ++;
-	}
-	$db->free($resql);
-} else {
-	print $db->lasterror(); // Show last sql error
+if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ?
+{
+    print '<br>';
+    print '<br>';
+    
+    print_fiche_titre($langs->trans("OtherInfo"), '', '');
+    
+    print "<br>\n";
+    print '<table class="noborder" width="100%">';
+    print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("TotalVente") . '</td>';
+    for($i = 1; $i <= 12; $i ++) {
+    	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+    }
+    print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+    
+    $sql = "SELECT '" . $langs->trans("TotalVente") . "' AS total,";
+    for($i = 1; $i <= 12; $i ++) {
+    	$sql .= "  SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+    }
+    $sql .= "  SUM(fd.total_ht) as total";
+    $sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd";
+    $sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture";
+    $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+    $sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+    $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy
+    if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+        $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+    } else {
+        $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+    }
+    
+    dol_syslog('htdocs/accountancy/customer/index.php');
+    $resql = $db->query($sql);
+    if ($resql) {
+    	$i = 0;
+    	$num = $db->num_rows($resql);
+    
+    	while ($row = $db->fetch_row($resql)) {
+    		print '<tr><td>' . $row[0] . '</td>';
+    		for($i = 1; $i <= 12; $i ++) {
+    			print '<td align="right">' . price($row[$i]) . '</td>';
+    		}
+    		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
+    		print '</tr>';
+    		$i ++;
+    	}
+    	$db->free($resql);
+    } else {
+    	print $db->lasterror(); // Show last sql error
+    }
+    print "</table>\n";
+    
+    if (! empty($conf->margin->enabled)) {
+    	print "<br>\n";
+    	print '<table class="noborder" width="100%">';
+    	print '<tr class="liste_titre"><td width="400">' . $langs->trans("TotalMarge") . '</td>';
+    	for($i = 1; $i <= 12; $i ++) {
+    		print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+    	}
+    	print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+    
+    	$sql = "SELECT '" . $langs->trans("Vide") . "' AS marge,";
+    	for($i = 1; $i <= 12; $i ++) {
+    		$sql .= "  SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, '(fd.total_ht-(fd.qty * fd.buy_price_ht))', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+    	}
+    	$sql .= "  SUM((fd.total_ht-(fd.qty * fd.buy_price_ht))) as total";
+    	$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd";
+    	$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture";
+    	$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+    	$sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+    	$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
+    	if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+    	    $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+    	} else {
+    	    $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+    	}
+    	 
+    	dol_syslog('htdocs/accountancy/customer/index.php:: $sql=' . $sql);
+    	$resql = $db->query($sql);
+    	if ($resql) {
+    		$num = $db->num_rows($resql);
+    
+    		while ($row = $db->fetch_row($resql)) {
+    
+    			print '<tr><td>' . $row[0] . '</td>';
+    			for($i = 1; $i <= 12; $i ++) {
+    				print '<td align="right">' . price(price2num($row[$i])) . '</td>';
+    			}
+    			print '<td align="right"><b>' . price(price2num($row[13])) . '</b></td>';
+    			print '</tr>';
+    		}
+    		$db->free($resql);
+    	} else {
+    		print $db->lasterror(); // Show last sql error
+    	}
+    	print "</table>\n";
+    }
 }
-print "</table>\n";
-
-if (! empty($conf->margin->enabled)) {
-	print "<br>\n";
-	print '<table class="noborder" width="100%">';
-	print '<tr class="liste_titre"><td width="400">' . $langs->trans("TotalMarge") . '</td>';
-	for($i = 1; $i <= 12; $i ++) {
-		print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
-	}
-	print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
 
-	$sql = "SELECT '" . $langs->trans("Vide") . "' AS marge,";
-	for($i = 1; $i <= 12; $i ++) {
-		$sql .= "  SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, '(fd.total_ht-(fd.qty * fd.buy_price_ht))', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
-	}
-	$sql .= "  SUM((fd.total_ht-(fd.qty * fd.buy_price_ht))) as total";
-	$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd";
-	$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture";
-	$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
-	$sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
-	$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
-
-	dol_syslog('htdocs/accountancy/customer/index.php:: $sql=' . $sql);
-	$resql = $db->query($sql);
-	if ($resql) {
-		$num = $db->num_rows($resql);
-
-		while ($row = $db->fetch_row($resql)) {
-
-			print '<tr><td>' . $row[0] . '</td>';
-			for($i = 1; $i <= 12; $i ++) {
-				print '<td align="right">' . price(price2num($row[$i])) . '</td>';
-			}
-			print '<td align="right"><b>' . price(price2num($row[13])) . '</b></td>';
-			print '</tr>';
-		}
-		$db->free($resql);
-	} else {
-		print $db->lasterror(); // Show last sql error
-	}
-	print "</table>\n";
-}
-print "</table>\n";
-print '</td></tr></table>';
 
 llxFooter();
 $db->close();
diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php
index 7f214ffdf3c22b9131130a8b164092c3de2e12f7..dbb342991046d0f5f6fc6780655e60c8e7c5b83b 100644
--- a/htdocs/accountancy/customer/list.php
+++ b/htdocs/accountancy/customer/list.php
@@ -210,6 +210,11 @@ if (strlen(trim($search_account))) {
 if (strlen(trim($search_vat))) {
     $sql .= natural_search("l.tva_tx",$search_vat,1);
 }
+if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
+} else {
+	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
+}
 $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";    // We don't share object for accountancy
 
 $sql .= $db->order($sortfield, $sortorder);
diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php
index b4c5da80af4deab515d63dbfce44c7266b2581c3..b4d7c0bbb7ac7b3948f9e3269fe97f786b471c58 100644
--- a/htdocs/accountancy/expensereport/index.php
+++ b/htdocs/accountancy/expensereport/index.php
@@ -290,55 +290,55 @@ print "</table>\n";
 
 
 
-print '<br>';
-print '<br>';
-
-
-print_fiche_titre($langs->trans("OtherInfo"), '', '');
-
-
-
-print "<br>\n";
-print '<table class="noborder" width="100%">';
-print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';
-for($i = 1; $i <= 12; $i ++) {
-	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
-}
-print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
-
-$sql = "SELECT '" . $langs->trans("TotalExpenseReport") . "' AS label,";
-for($i = 1; $i <= 12; $i ++) {
-	$sql .= " SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
-}
-$sql .= " ROUND(SUM(erd.total_ht),2) as total";
-$sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd";
-$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expensereport as er ON er.rowid = erd.fk_expensereport";
-$sql .= " WHERE er.date_debut >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
-$sql .= " AND er.date_debut <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
-$sql .= " AND er.fk_statut > 0 ";
-$sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";     // We don't share object for accountancy
-
-dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql);
-$resql = $db->query($sql);
-if ($resql) {
-	$num = $db->num_rows($resql);
-
-	while ( $row = $db->fetch_row($resql)) {
-
-
-		print '<tr><td>' . $row[0] . '</td>';
-			for($i = 1; $i <= 12; $i ++) {
-			print '<td align="right">' . price($row[$i]) . '</td>';
-		}
-		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
-		print '</tr>';
-	}
-
-	$db->free($resql);
-} else {
-	print $db->lasterror(); // Show last sql error
+if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ?
+{
+    print '<br>';
+    print '<br>';
+    
+    print_fiche_titre($langs->trans("OtherInfo"), '', '');
+    
+    print "<br>\n";
+    print '<table class="noborder" width="100%">';
+    print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';
+    for($i = 1; $i <= 12; $i ++) {
+    	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+    }
+    print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+    
+    $sql = "SELECT '" . $langs->trans("TotalExpenseReport") . "' AS label,";
+    for($i = 1; $i <= 12; $i ++) {
+    	$sql .= " SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+    }
+    $sql .= " ROUND(SUM(erd.total_ht),2) as total";
+    $sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd";
+    $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expensereport as er ON er.rowid = erd.fk_expensereport";
+    $sql .= " WHERE er.date_debut >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+    $sql .= " AND er.date_debut <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+    $sql .= " AND er.fk_statut > 0 ";
+    $sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";     // We don't share object for accountancy
+    
+    dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql);
+    $resql = $db->query($sql);
+    if ($resql) {
+    	$num = $db->num_rows($resql);
+    
+    	while ( $row = $db->fetch_row($resql)) {
+    
+    
+    		print '<tr><td>' . $row[0] . '</td>';
+    			for($i = 1; $i <= 12; $i ++) {
+    			print '<td align="right">' . price($row[$i]) . '</td>';
+    		}
+    		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
+    		print '</tr>';
+    	}
+    
+    	$db->free($resql);
+    } else {
+    	print $db->lasterror(); // Show last sql error
+    }
+    print "</table>\n";
 }
-print "</table>\n";
 
 llxFooter();
 $db->close();
diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php
index ef7d470bb070fcea3754f1b2c102856204ceda8d..a747342a50897883b6b50b73b6aed990d8a1dfe8 100644
--- a/htdocs/accountancy/supplier/index.php
+++ b/htdocs/accountancy/supplier/index.php
@@ -289,58 +289,56 @@ print "</table>\n";
 
 
 
-
-print '<br>';
-print '<br>';
-
-
-print_fiche_titre($langs->trans("OtherInfo"), '', '');
-
-
-
-
-
-print "<br>\n";
-print '<table class="noborder" width="100%">';
-print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';
-for($i = 1; $i <= 12; $i ++) {
-	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
-}
-print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
-
-$sql = "SELECT '" . $langs->trans("CAHTF") . "' AS label,";
-for($i = 1; $i <= 12; $i ++) {
-	$sql .= "  SUM(" . $db->ifsql('MONTH(ff.datef)=' . $i, 'ffd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ?
+{
+    print '<br>';
+    print '<br>';
+    
+    print_fiche_titre($langs->trans("OtherInfo"), '', '');
+    
+    print "<br>\n";
+    print '<table class="noborder" width="100%">';
+    print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';
+    for($i = 1; $i <= 12; $i ++) {
+    	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+    }
+    print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+    
+    $sql = "SELECT '" . $langs->trans("CAHTF") . "' AS label,";
+    for($i = 1; $i <= 12; $i ++) {
+    	$sql .= "  SUM(" . $db->ifsql('MONTH(ff.datef)=' . $i, 'ffd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+    }
+    $sql .= "  ROUND(SUM(ffd.total_ht),2) as total";
+    $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as ffd";
+    $sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn";
+    $sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+    $sql .= "  AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+    $sql .= "  AND ff.fk_statut > 0 ";
+    $sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")";     // We don't share object for accountancy
+    
+    dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql);
+    $resql = $db->query($sql);
+    if ($resql) {
+    	$num = $db->num_rows($resql);
+    
+    	while ( $row = $db->fetch_row($resql)) {
+    
+    
+    		print '<tr><td>' . $row[0] . '</td>';
+    			for($i = 1; $i <= 12; $i ++) {
+    			print '<td align="right">' . price($row[$i]) . '</td>';
+    		}
+    		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
+    		print '</tr>';
+    	}
+    
+    	$db->free($resql);
+    } else {
+    	print $db->lasterror(); // Show last sql error
+    }
+    print "</table>\n";
 }
-$sql .= "  ROUND(SUM(ffd.total_ht),2) as total";
-$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as ffd";
-$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn";
-$sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
-$sql .= "  AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
-$sql .= "  AND ff.fk_statut > 0 ";
-$sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")";     // We don't share object for accountancy
-
-dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql);
-$resql = $db->query($sql);
-if ($resql) {
-	$num = $db->num_rows($resql);
-
-	while ( $row = $db->fetch_row($resql)) {
 
 
-		print '<tr><td>' . $row[0] . '</td>';
-			for($i = 1; $i <= 12; $i ++) {
-			print '<td align="right">' . price($row[$i]) . '</td>';
-		}
-		print '<td align="right"><b>' . price($row[13]) . '</b></td>';
-		print '</tr>';
-	}
-
-	$db->free($resql);
-} else {
-	print $db->lasterror(); // Show last sql error
-}
-print "</table>\n";
-
 llxFooter();
 $db->close();
diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php
index b41ae78d4c70db7660373b20b083f0de328c2ff1..2433575e553beca44e21530b0b917a34b609bc55 100644
--- a/htdocs/admin/oauthlogintokens.php
+++ b/htdocs/admin/oauthlogintokens.php
@@ -104,6 +104,11 @@ if ($action == 'setvalue' && $user->admin)
  * View
  */
 
+// Define $urlwithroot
+$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
+//$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
+
 $form = new Form($db);
 
 llxHeader('',$langs->trans("PrintingSetup"));
@@ -127,70 +132,179 @@ if ($mode == 'setup' && $user->admin)
         if (in_array($key[0], array_keys($supportedoauth2array))) $supported=1;
         if (! $supported) continue;     // show only supported
         
+        
+        $OAUTH_SERVICENAME='Unknown';
+        if ($key[0] == 'OAUTH_GITHUB_NAME')
+        {
+            $OAUTH_SERVICENAME='GitHub';
+            $urltorenew=$urlwithroot.'/core/modules/oauth/github_oauthcallback.php?state=user,public_repo&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+            $urltodelete=$urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+            $urltocheckperms='https://github.com/settings/applications/';
+        }
+        if ($key[0] == 'OAUTH_GOOGLE_NAME')
+        {
+            $OAUTH_SERVICENAME='Google';
+            $urltorenew=$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?state=userinfo_email,userinfo_profile,cloud_print&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+            $urltodelete=$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+            $urltocheckperms='https://security.google.com/settings/security/permissions';
+        }
+        
+        // Show value of token
+        $tokenobj=null;
+        // Token
+        require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
+        require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
+        // Dolibarr storage
+        $storage = new DoliStorage($db, $conf);
+        try
+        {
+            $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
+        }
+        catch(Exception $e)
+        {
+            // Return an error if token not found
+        }
+        
+        // Set other properties
+        $refreshtoken=false;
+        $expiredat='';
+        
+        $expire = false;
+        // Is token expired or will token expire in the next 30 seconds
+        if (is_object($tokenobj)) {
+            $expire = ($tokenobj->getEndOfLife() !== $tokenobj::EOL_NEVER_EXPIRES && $tokenobj->getEndOfLife() !== $tokenobj::EOL_UNKNOWN && time() > ($tokenobj->getEndOfLife() - 30));
+        }
+        
+        if ($key[1] != '' && $key[2] != '') {
+            if (is_object($tokenobj)) {
+                $refreshtoken = $tokenobj->getRefreshToken();
+                
+                $endoflife = $tokenobj->getEndOfLife();
+                if ($endoflife == $tokenobj::EOL_NEVER_EXPIRES)
+                {
+                    $expiredat = $langs->trans("Never");
+                }
+                elseif ($endoflife == $tokenobj::EOL_UNKNOWN)
+                {
+                    $expiredat = $langs->trans("Unknown");
+                }
+                else
+                {
+                    $expiredat=dol_print_date($endoflife, "dayhour");
+                }
+            }
+        }
+
+        $submit_enabled=0;
+        
         print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?mode=setup&amp;driver='.$driver.'" autocomplete="off">';
         print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
         print '<input type="hidden" name="action" value="setconst">';
     
         
         print '<table class="noborder" width="100%">'."\n";
-        $var=true;
+        
+        $var=false;
         print '<tr class="liste_titre">';
-        print '<th>'.$langs->trans("Parameters").'</th>';
-        print '<th>'.$langs->trans("Value").'</th>';
-        print '<th>&nbsp;</th>';
+        print '<th class="titlefieldcreate">'.$langs->trans($key[0]).'</th>';
+        print '<th></th>';
+        print '<th></th>';
         print "</tr>\n";
-        $submit_enabled=0;
-    
+        
+        print '<tr '.$bc[$var].'>';
+        print '<td'.($key['required']?' class="required"':'').'>';
+        //var_dump($key);
+        print $langs->trans("OAuthIDSecret").'</td>';
+        print '<td>';
+        print $langs->trans("SeePreviousTab");
+        print '</td>';
+        print '<td>';
+        print '</td>';
+        print '</tr>'."\n";
+        
+        $var = ! $var;
         print '<tr '.$bc[$var].'>';
-        print '<td'.($key['required']?' class=required':'').'>'.$langs->trans($key['varname']).'</td>';
-        print '<td>'.$langs->trans($key['info']).'</td>';
+        print '<td'.($key['required']?' class="required"':'').'>';
+        //var_dump($key);
+        print $langs->trans("IsTokenGenerated");
+        print '</td>';
+        print '<td>';
+        if (is_object($tokenobj)) print $langs->trans("HasAccessToken");
+        else print $langs->trans("NoAccessToken");
+        print '</td>';
         print '<td>';
-        if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS')
+        // Links to delete/checks token
+        if (is_object($tokenobj))
         {
-            // Delete remote tokens
-            if (! empty($key['delete'])) print '<a class="button" href="'.$key['delete'].'">'.$langs->trans('DeleteAccess').'</a><br><br>';
-            // Request remote token
-            print '<a class="button" href="'.$key['renew'].'">'.$langs->trans('RequestAccess').'</a><br><br>';
-            // Check remote access
-            print $langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME_GOOGLE).': <a href="https://security.google.com/settings/security/permissions" target="_google">https://security.google.com/settings/security/permissions</a>';
+            //test on $storage->hasAccessToken($OAUTH_SERVICENAME) ?
+            print '<a class="button" href="'.$urltodelete.'">'.$langs->trans('DeleteAccess').'</a><br><br>';
+        }
+        // Request remote token
+        print '<a class="button" href="'.$urltorenew.'">'.$langs->trans('RequestAccess').'</a><br><br>';
+        // Check remote access
+        if ($urltocheckperms)
+        {
+            print $langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': <a href="'.$urltocheckperms.'" target="_'.strtolower($OAUTH_SERVICENAME).'">'.$urltocheckperms.'</a>';
         }
         print '</td>';
-        print '</tr>'."\n";
+        print '</tr>';
         
-        // Show value of token
-        if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS')
+        $var = ! $var;
+        print '<tr '.$bc[$var].'>';
+        print '<td'.($key['required']?' class="required"':'').'>';
+        //var_dump($key);
+        print $langs->trans("Token").'</td>';
+        print '<td colspan="2">';
+        if (is_object($tokenobj))
+        {
+            //var_dump($tokenobj);
+            print $tokenobj->getAccessToken().'<br>';
+            //print 'Refresh: '.$tokenobj->getRefreshToken().'<br>';
+            //print 'EndOfLife: '.$tokenobj->getEndOfLife().'<br>';
+            //var_dump($tokenobj->getExtraParams());
+            /*print '<br>Extra: <br><textarea class="quatrevingtpercent">';
+            print ''.join(',',$tokenobj->getExtraParams());
+            print '</textarea>';*/
+        }        
+        print '</td>';
+        print '</tr>'."\n";
+
+        if (is_object($tokenobj))
         {
-            // Token
+            // Token refresh
+            $var = ! $var;
             print '<tr '.$bc[$var].'>';
-            print '<td>'.$langs->trans("Token").'</td>';
-            print '<td>';
-            // Dolibarr storage
-            $storage = new DoliStorage($db, $conf);
-            try
-            {
-                $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME_GOOGLE);
-            }
-            catch(Exception $e)
-            {
-                // Return an error if token not found
-            }
-            if (is_object($tokenobj))
-            {
-                //var_dump($tokenobj);
-                print $tokenobj->getAccessToken().'<br>';
-                //print 'Refresh: '.$tokenobj->getRefreshToken().'<br>';
-                //print 'EndOfLife: '.$tokenobj->getEndOfLife().'<br>';
-                //var_dump($tokenobj->getExtraParams());
-                /*print '<br>Extra: <br><textarea class="quatrevingtpercent">';
-                print ''.join(',',$tokenobj->getExtraParams());
-                print '</textarea>';*/
-            }
+            print '<td'.($key['required']?' class="required"':'').'>';
+            //var_dump($key);
+            print $langs->trans("TOKEN_REFRESH").'</td>';
+            print '<td colspan="2">';
+            print yn($refreshtoken);
+            print '</td>';
+            print '</tr>';
+    
+            // Token expired
+            $var = ! $var;
+            print '<tr '.$bc[$var].'>';
+            print '<td'.($key['required']?' class="required"':'').'>';
+            //var_dump($key);
+            print $langs->trans("TOKEN_EXPIRED").'</td>';
+            print '<td colspan="2">';
+            print yn($expire);
             print '</td>';
-            print '<td>';
+            print '</tr>';
+            
+            // Token expired at
+            $var = ! $var;
+            print '<tr '.$bc[$var].'>';
+            print '<td'.($key['required']?' class="required"':'').'>';
+            //var_dump($key);
+            print $langs->trans("TOKEN_EXPIRE_AT").'</td>';
+            print '<td colspan="2">';
+            print $expiredat;
             print '</td>';
-            print '</tr>'."\n";
+            print '</tr>';        
         }
-    
+        
         print '</table>';
 
         if (! empty($driver))
@@ -199,7 +313,8 @@ if ($mode == 'setup' && $user->admin)
                 print '<div class="center"><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Modify")).'"></div>';
             }
         }
-    
+
+        
         print '</form>';
     }
     
diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php
index 1340b5ae3c1dc72e78f2d7e20aed2d24315ede57..c0ff5d75819a9dcee897bf460f24f24106c426ec 100644
--- a/htdocs/admin/system/filecheck.php
+++ b/htdocs/admin/system/filecheck.php
@@ -82,8 +82,8 @@ $xmlremote = GETPOST('xmlremote')?GETPOST('xmlremote'):'https://www.dolibarr.org
 
 // Test if remote test is ok
 $enableremotecheck = True;
-if (preg_match('/beta|alpha/i', DOL_VERSION)) $enableremotecheck=False;
-
+if (preg_match('/beta|alpha|rc/i', DOL_VERSION) || ! empty($conf->global->MAIN_ALLOW_INTEGRITY_CHECK_ON_UNSTABLE)) $enableremotecheck=False;
+$enableremotecheck = true;
 
 print '<form name="check" action="'.$_SERVER["PHP_SELF"].'">';
 print $langs->trans("MakeIntegrityAnalysisFrom").':<br>';
@@ -101,7 +101,8 @@ else
 print '<!-- for a remote target=remote&xmlremote=... -->'."\n";
 if ($enableremotecheck)
 {
-    print '<input type="radio" name="target" value="remote"'.(GETPOST('target') == 'remote' ? 'checked="checked"':'').'> '.$langs->trans("RemoteSignature").' = '.$xmlremote.'<br>';
+    print '<input type="radio" name="target" value="remote"'.(GETPOST('target') == 'remote' ? 'checked="checked"':'').'> '.$langs->trans("RemoteSignature").' = ';
+    print '<input name="xmlremote" class="flat quatrevingtpercent" value="'.$xmlremote.'"><br>';
 }
 else
 {
@@ -156,19 +157,25 @@ if ($xml)
         $file_list = array();
         $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat);		// Fill array $file_list
     
+        print_fiche_titre($langs->trans("FilesMissing"));
+        
         print '<table class="noborder">';
         print '<tr class="liste_titre">';
-        print '<td>' . $langs->trans("FilesMissing") . '</td>';
+        print '<td>#</td>';
+        print '<td>' . $langs->trans("Filename") . '</td>';
         print '<td align="center">' . $langs->trans("ExpectedChecksum") . '</td>';
         print '</tr>'."\n";
         $var = true;
         $tmpfilelist = dol_sort_array($file_list['missing'], 'filename');
         if (is_array($tmpfilelist) && count($tmpfilelist))
         {
+            $i = 0;
 	        foreach ($tmpfilelist as $file)
 	        {
+	            $i++;
 	            $var = !$var;
 	            print '<tr ' . $bc[$var] . '>';
+	            print '<td>'.$i.'</td>' . "\n";
 	            print '<td>'.$file['filename'].'</td>' . "\n";
 	            print '<td align="center">'.$file['expectedmd5'].'</td>' . "\n";
 	            print "</tr>\n";
@@ -176,15 +183,18 @@ if ($xml)
         }
         else 
         {
-            print '<tr ' . $bc[false] . '><td colspan="2" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
+            print '<tr ' . $bc[false] . '><td colspan="3" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
         }            
         print '</table>';
 
         print '<br>';
 
+        print_fiche_titre($langs->trans("FilesUpdated"));
+        
         print '<table class="noborder">';
         print '<tr class="liste_titre">';
-        print '<td>' . $langs->trans("FilesUpdated") . '</td>';
+        print '<td>#</td>';
+        print '<td>' . $langs->trans("Filename") . '</td>';
         print '<td align="center">' . $langs->trans("ExpectedChecksum") . '</td>';
         print '<td align="center">' . $langs->trans("CurrentChecksum") . '</td>';
         print '<td align="right">' . $langs->trans("Size") . '</td>';
@@ -194,10 +204,13 @@ if ($xml)
         $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename');
         if (is_array($tmpfilelist2) && count($tmpfilelist2))
         {
+            $i = 0;
 	        foreach ($tmpfilelist2 as $file)
 	        {
+	            $i++;
 	            $var = !$var;
 	            print '<tr ' . $bc[$var] . '>';
+	            print '<td>'.$i.'</td>' . "\n";
 	            print '<td>'.$file['filename'].'</td>' . "\n";
 	            print '<td align="center">'.$file['expectedmd5'].'</td>' . "\n";
 	            print '<td align="center">'.$file['md5'].'</td>' . "\n";
@@ -241,14 +254,12 @@ if ($xml)
     //var_dump($checksumconcat);
     $checksumget = md5(join(',',$checksumconcat));
     $checksumtoget = $xml->dolibarr_htdocs_dir_checksum;
-    if ($checksumtoget)
-    {
-        print '<br>';
-        print '<strong>'.$langs->trans("GlobalChecksum").'</strong><br>';
-        print $langs->trans("ExpectedChecksum").' = '.$checksumtoget.'<br>';
-        print $langs->trans("CurrentChecksum").' = '.$checksumget;
-    }
-    
+
+    print '<br>';
+
+    print_fiche_titre($langs->trans("GlobalChecksum")).'<br>';
+    print $langs->trans("ExpectedChecksum").' = '. ($checksumtoget ? $checksumtoget : $langs->trans("Unknown")) .'<br>';
+    print $langs->trans("CurrentChecksum").' = '.$checksumget;
 }
 
 
diff --git a/htdocs/admin/tools/update.php b/htdocs/admin/tools/update.php
index e306862b67a7f658f9accb5903d26b30ab8f8ff8..5cebb1dac4e2e1f42b1ed825f9c1bd877e4ab4b5 100644
--- a/htdocs/admin/tools/update.php
+++ b/htdocs/admin/tools/update.php
@@ -39,7 +39,7 @@ if (GETPOST('msg','alpha')) {
 }
 
 
-$urldolibarr='http://www.dolibarr.org/downloads/';
+$urldolibarr='https://www.dolibarr.org/downloads/';
 $urldolibarrmodules='https://www.dolistore.com/';
 $urldolibarrthemes='https://www.dolistore.com/';
 $dolibarrroot=preg_replace('/([\\/]+)$/i','',DOL_DOCUMENT_ROOT);
diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php
index 6f47ef6e62b0226478b46f739fc9410d83eae90c..0149b581fa2277c24a3cf0c6936afdc2868dce88 100644
--- a/htdocs/core/lib/oauth.lib.php
+++ b/htdocs/core/lib/oauth.lib.php
@@ -26,9 +26,13 @@
 // Supported OAUTH (a provider is supported when a file xxx_oauthcallback.php is available into htdocs/core/modules/oauth)
 $supportedoauth2array=array(
     'OAUTH_GOOGLE_NAME'=>'google',
-    'OAUTH_GITHUB_NAME'=>'github'
 );
 
+if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
+{
+    $supportedoauth2array['OAUTH_GITHUB_NAME']='github';
+}
+$supportedoauth2array['OAUTH_GITHUB_NAME']='github';
 // API access parameters OAUTH
 $list = array (
     array(
@@ -264,7 +268,7 @@ function oauthadmin_prepare_head()
     $h++;
     
     $head[$h][0] = dol_buildpath('/admin/oauthlogintokens.php', 1);
-    $head[$h][1] = $langs->trans("ManualTokenGeneration");
+    $head[$h][1] = $langs->trans("TokenManager");
     $head[$h][2] = 'tokengeneration';
     $h++;
     
diff --git a/htdocs/core/modules/oauth/github_oauthcallback.php b/htdocs/core/modules/oauth/github_oauthcallback.php
new file mode 100644
index 0000000000000000000000000000000000000000..83c3da66a473e1d6a4e7809b9e4d14273286fc2a
--- /dev/null
+++ b/htdocs/core/modules/oauth/github_oauthcallback.php
@@ -0,0 +1,171 @@
+<?php
+/*
+ * Copyright (C) 2015       Frederic France      <frederic.france@free.fr>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *      \file       htdocs/core/modules/oauth/github_oauthcallback.php
+ *      \ingroup    oauth
+ *      \brief      Page to get oauth callback
+ */
+
+require '../../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
+use OAuth\Common\Storage\DoliStorage;
+use OAuth\Common\Consumer\Credentials;
+use OAuth\OAuth2\Service\GitHub;
+
+// Define $urlwithroot
+$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
+//$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
+
+
+
+$action = GETPOST('action', 'alpha');
+$backtourl = GETPOST('backtourl', 'alpha');
+
+
+/**
+ * Create a new instance of the URI class with the current URI, stripping the query string
+ */
+$uriFactory = new \OAuth\Common\Http\Uri\UriFactory();
+//$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
+//$currentUri->setQuery('');
+$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/github_oauthcallback.php');
+
+
+/**
+ * Load the credential for the service
+ */
+
+/** @var $serviceFactory \OAuth\ServiceFactory An OAuth service factory. */
+$serviceFactory = new \OAuth\ServiceFactory();
+$httpClient = new \OAuth\Common\Http\Client\CurlClient();
+// TODO Set options for proxy and timeout
+// $params=array('CURLXXX'=>value, ...)
+//$httpClient->setCurlParameters($params);
+$serviceFactory->setHttpClient($httpClient);
+
+// Dolibarr storage
+$storage = new DoliStorage($db, $conf);
+
+// Setup the credentials for the requests
+$credentials = new Credentials(
+    $conf->global->OAUTH_GITHUB_ID,
+    $conf->global->OAUTH_GITHUB_SECRET,
+    $currentUri->getAbsoluteUri()
+);
+
+$requestedpermissionsarray=array();
+if (GETPOST('state')) $requestedpermissionsarray=explode(',', GETPOST('state'));       // Example: 'userinfo_email,userinfo_profile,cloud_print'. 'state' parameter is standard to retrieve some parameters back
+if ($action != 'delete' && empty($requestedpermissionsarray))
+{
+    print 'Error, parameter state is not defined';
+    exit;
+}
+//var_dump($requestedpermissionsarray);exit;
+
+// Instantiate the Api service using the credentials, http client and storage mechanism for the token
+/** @var $apiService Service */
+$apiService = $serviceFactory->createService('GitHub', $credentials, $storage, $requestedpermissionsarray);
+
+// access type needed to have oauth provider refreshing token
+//$apiService->setAccessType('offline');
+
+$langs->load("oauth");
+
+
+/*
+ * Actions
+ */
+
+
+if ($action == 'delete') 
+{
+    $storage->clearToken('GitHub');
+    
+    setEventMessages($langs->trans('TokenDeleted'), null, 'mesgs');
+    
+    header('Location: ' . $backtourl);
+    exit();
+} 
+
+if (! empty($_GET['code']))     // We are coming from oauth provider page
+{
+    //llxHeader('',$langs->trans("OAuthSetup"));
+
+    //$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+    //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
+
+    //dol_fiche_head();
+    // retrieve the CSRF state parameter
+    $state = isset($_GET['state']) ? $_GET['state'] : null;
+    //print '<table>';
+
+    // This was a callback request from service, get the token
+    try {
+        //var_dump($_GET['code']);
+        //var_dump($state);
+        //var_dump($apiService);      // OAuth\OAuth2\Service\GitHub
+        
+        //$token = $apiService->requestAccessToken($_GET['code'], $state);
+        $token = $apiService->requestAccessToken($_GET['code']);                
+        // Github is a service that does not need state yo be stored.
+        // Into constructor of GitHub, the call
+        // parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri)
+        // has not the ending parameter to true like the Google class constructor.
+
+        setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs');   // Stored into object managed by class DoliStorage so into table oauth_token
+    } catch (Exception $e) {
+        print $e->getMessage();
+    }
+
+    $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"];
+    unset($_SESSION["backtourlsavedbeforeoauthjump"]);
+    
+    header('Location: ' . $backtourl);
+    exit();
+}
+else // If entry on page with no parameter, we arrive here
+{
+    $_SESSION["backtourlsavedbeforeoauthjump"]=$backtourl;
+    
+    // This may create record into oauth_state before the header redirect.
+    // Creation of record with state in this tables depend on the Provider used (see its constructor).
+    if (GETPOST('state'))
+    {
+        $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state')));
+    }
+    else
+    {
+        $url = $apiService->getAuthorizationUri();      // Parameter state will be randomly generated
+    }
+    
+    // we go on oauth provider authorization page
+    header('Location: ' . $url);
+    exit();
+}
+
+
+/*
+ * View
+ */
+
+// No view at all, just actions
+
+$db->close();
+
diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php
index 3068a29098c6343bd9dfba1961827cc368512bb1..c69493ed9a554dc5988a53361387c0797846d741 100644
--- a/htdocs/core/modules/oauth/google_oauthcallback.php
+++ b/htdocs/core/modules/oauth/google_oauthcallback.php
@@ -17,7 +17,7 @@
  */
 
 /**
- *      \file       htdocs/core/modules/oauth/getoauthcallback.php
+ *      \file       htdocs/core/modules/oauth/google_oauthcallback.php
  *      \ingroup    oauth
  *      \brief      Page to get oauth callback
  */
@@ -83,7 +83,7 @@ if ($action != 'delete' && empty($requestedpermissionsarray))
 /** @var $apiService Service */
 $apiService = $serviceFactory->createService('Google', $credentials, $storage, $requestedpermissionsarray);
 
-// access type needed for google refresh token
+// access type needed to have oauth provider refreshing token
 $apiService->setAccessType('offline');
 
 $langs->load("oauth");
@@ -104,7 +104,7 @@ if ($action == 'delete')
     exit();
 } 
 
-if (! empty($_GET['code']))     // We are coming from Google oauth page
+if (! empty($_GET['code']))     // We are coming from oauth provider page
 {
     //llxHeader('',$langs->trans("OAuthSetup"));
 
@@ -121,6 +121,7 @@ if (! empty($_GET['code']))     // We are coming from Google oauth page
         //var_dump($_GET['code']);
         //var_dump($state);
         //var_dump($apiService);      // OAuth\OAuth2\Service\Google
+        
         $token = $apiService->requestAccessToken($_GET['code'], $state);
         
         setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs');   // Stored into object managed by class DoliStorage so into table oauth_token
@@ -138,6 +139,8 @@ else // If entry on page with no parameter, we arrive here
 {
     $_SESSION["backtourlsavedbeforeoauthjump"]=$backtourl;
     
+    // This may create record into oauth_state before the header redirect.
+    // Creation of record with state in this tables depend on the Provider used (see its constructor).
     if (GETPOST('state'))
     {
         $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state')));
@@ -146,7 +149,8 @@ else // If entry on page with no parameter, we arrive here
     {
         $url = $apiService->getAuthorizationUri();      // Parameter state will be randomly generated
     }
-    // we go on google authorization page
+    
+    // we go on oauth provider authorization page
     header('Location: ' . $url);
     exit();
 }
diff --git a/htdocs/core/modules/printing/printgcp.modules.php b/htdocs/core/modules/printing/printgcp.modules.php
index 3d086466c872d746d7733fe15fcc9886d3fecb10..baa5106ae93b81f7c2791d88fce7391fd55b6bc0 100644
--- a/htdocs/core/modules/printing/printgcp.modules.php
+++ b/htdocs/core/modules/printing/printgcp.modules.php
@@ -66,6 +66,7 @@ class printing_printgcp extends PrintingDriver
         $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
         $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
         //$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
+
         $this->db = $db;
         
         if (!$conf->oauth->enabled) {
@@ -117,10 +118,28 @@ class printing_printgcp extends PrintingDriver
                 $this->conf[] = array('varname'=>'PRINTGCP_INFO', 'info'=>'GoogleAuthConfigured', 'type'=>'info');
                 $this->conf[] = array('varname'=>'PRINTGCP_TOKEN_ACCESS', 'info'=>$access, 'type'=>'info', 'renew'=>$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?state=userinfo_email,userinfo_profile,cloud_print&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'), 'delete'=>($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)?$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'):''));
                 if ($token_ok) {
+                    $expiredat='';
+                    
                     $refreshtoken = $token->getRefreshToken();
+                    
+                    $endoflife=$token->getEndOfLife();
+
+                    if ($endoflife == $token::EOL_NEVER_EXPIRES)
+                    {
+                        $expiredat = $langs->trans("Never");
+                    }
+                    elseif ($endoflife == $token::EOL_UNKNOWN)
+                    {
+                        $expiredat = $langs->trans("Unknown");
+                    }
+                    else
+                    {
+                        $expiredat=dol_print_date($endoflife, "dayhour");
+                    }
+                    
                     $this->conf[] = array('varname'=>'TOKEN_REFRESH',   'info'=>((! empty($refreshtoken))?'Yes':'No'), 'type'=>'info');
                     $this->conf[] = array('varname'=>'TOKEN_EXPIRED',   'info'=>($expire?'Yes':'No'), 'type'=>'info');
-                    $this->conf[] = array('varname'=>'TOKEN_EXPIRE_AT', 'info'=>(dol_print_date($token->getEndOfLife(), "dayhour")), 'type'=>'info');
+                    $this->conf[] = array('varname'=>'TOKEN_EXPIRE_AT', 'info'=>($expiredat), 'type'=>'info');
                 }
                 /*
                 if ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)) {
diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php
index 5e79b71ee34e9d0c28bad54b7760a7dd61d36442..ae1118b4ce7292c2fe70b85818b6fb1497c9dc8d 100644
--- a/htdocs/core/tpl/login.tpl.php
+++ b/htdocs/core/tpl/login.tpl.php
@@ -102,9 +102,9 @@ $(document).ready(function () {
 <!-- Password -->
 <tr>
 <td class="nowrap center valignmiddle">
-<?php if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { ?><label for="password" hidden><?php echo $langs->trans("Password"); ?></label><?php } ?>
+<?php if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { ?><label for="password" class="hidden"><?php echo $langs->trans("Password"); ?></label><?php } ?>
 <span class="span-icon-password">
-<input id="password" placeholder="<?php echo $langs->trans("Password"); ?>" name="password" class="flat input-icon-password" type="password" size="20" value="<?php echo dol_escape_htmltag($password); ?>" tabindex="2" autocomplete="off" />
+<input id="password" placeholder="<?php echo $langs->trans("Password"); ?>" name="password" class="flat input-icon-password" type="password" size="20" value="<?php echo dol_escape_htmltag($password); ?>" tabindex="2" autocomplete="<?php echo empty($conf->global->MAIN_LOGIN_ENABLE_PASSWORD_AUTOCOMPLETE)?'off':'on'; ?>" />
 </span>
 </td></tr>
 <?php
diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
index 7e82bb63cb28e071e0a4e67daac0db9568d20c81..463afe194dba5aea890b3544a94b3b9c03e70b37 100644
--- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
+++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
@@ -97,7 +97,7 @@ class DoliStorage implements TokenStorageInterface
             $this->tokens = array();
         }
         $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."oauth_token";
-        $sql.= " WHERE service='".$service."' AND entity=1";
+        $sql.= " WHERE service='".$this->db->escape($service)."' AND entity=1";
         $resql = $this->db->query($sql);
         if (! $resql)
         {
@@ -113,7 +113,7 @@ class DoliStorage implements TokenStorageInterface
         } else {
             // save
             $sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, token, entity)";
-            $sql.= " VALUES ('".$service."', '".$this->db->escape($serializedToken)."', 1)";
+            $sql.= " VALUES ('".$this->db->escape($service)."', '".$this->db->escape($serializedToken)."', 1)";
             $resql = $this->db->query($sql);
         }
         //print $sql;
@@ -130,7 +130,7 @@ class DoliStorage implements TokenStorageInterface
         // get from db
         dol_syslog("hasAccessToken service=".$service);
         $sql = "SELECT token FROM ".MAIN_DB_PREFIX."oauth_token";
-        $sql.= " WHERE service='".$service."'";
+        $sql.= " WHERE service='".$this->db->escape($service)."'";
         $resql = $this->db->query($sql);
         if (! $resql)
         {
@@ -159,7 +159,7 @@ class DoliStorage implements TokenStorageInterface
         //    unset($tokens[$service]);
 
             $sql = "DELETE FROM ".MAIN_DB_PREFIX."oauth_token";
-            $sql.= " WHERE service='".$service."'";
+            $sql.= " WHERE service='".$this->db->escape($service)."'";
             $resql = $this->db->query($sql);
         //}
 
@@ -189,7 +189,7 @@ class DoliStorage implements TokenStorageInterface
 
         }
 
-        throw new AuthorizationStateNotFoundException('State not found in conf, are you sure you stored it?');
+        throw new AuthorizationStateNotFoundException('State not found in db, are you sure you stored it?');
     }
 
     /**
@@ -207,7 +207,7 @@ class DoliStorage implements TokenStorageInterface
         $this->states[$service] = $state;
 
         $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."oauth_state";
-        $sql.= " WHERE service='".$service."' AND entity=1";
+        $sql.= " WHERE service='".$this->db->escape($service)."' AND entity=1";
         $resql = $this->db->query($sql);
         if (! $resql)
         {
@@ -223,7 +223,7 @@ class DoliStorage implements TokenStorageInterface
         } else {
             // save
             $sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_state (service, state, entity)";
-            $sql.= " VALUES ('".$service."', '".$state."', 1)";
+            $sql.= " VALUES ('".$this->db->escape($service)."', '".$this->db->escape($state)."', 1)";
             $resql = $this->db->query($sql);
         }
 
@@ -236,9 +236,10 @@ class DoliStorage implements TokenStorageInterface
      */
     public function hasAuthorizationState($service)
     {
-        // get from db
+        // get state from db
+        dol_syslog("get state from db");
         $sql = "SELECT state FROM ".MAIN_DB_PREFIX."oauth_state";
-        $sql.= " WHERE service='".$service."'";
+        $sql.= " WHERE service='".$this->db->escape($service)."'";
         $resql = $this->db->query($sql);
         $result = $this->db->fetch_array($resql);
         $states[$service] = $result[state];
diff --git a/htdocs/install/default.css b/htdocs/install/default.css
index dfde26cdedb42635789961f02b8fd1de8bdb2ec0..257f2d99af81248f1780e772c8c2ba8e607c6af6 100644
--- a/htdocs/install/default.css
+++ b/htdocs/install/default.css
@@ -343,8 +343,8 @@ ul {
 
 
 .button {
-    background: #eee;
-    /*border: 1px solid #C0C0C0;*/
+    background: #fcfcfc;
+    border: 1px solid #d0d0d0;
     padding: 0.3em 0.7em;
     margin: 0 0.5em;
     -moz-border-radius:0 5px 0 5px;
diff --git a/htdocs/install/repair.php b/htdocs/install/repair.php
index 13aa7401ee81f0d302020bfbc52a5393a5f45038..cdaa0b22b7ff16afeddcf5856bd4e74cdc9e7356 100644
--- a/htdocs/install/repair.php
+++ b/htdocs/install/repair.php
@@ -251,10 +251,34 @@ if ($ok)
 	            if (! in_array($code,array_keys($arrayoffieldsfound)))
 	            {
 	                print 'Found field '.$code.' declared into '.MAIN_DB_PREFIX.'extrafields table but not found into desc of table '.$tableextra." -> ";
-	                $type=$extrafields->attribute_type[$code]; $value=$extrafields->attribute_size[$code]; $attribute=''; $default=''; $extra=''; $null='null';
+	                $type=$extrafields->attribute_type[$code]; $length=$extrafields->attribute_size[$code]; $attribute=''; $default=''; $extra=''; $null='null';
+	                
+           			if ($type=='boolean') {
+        				$typedb='int';
+        				$lengthdb='1';
+        			} elseif($type=='price') {
+        				$typedb='double';
+        				$lengthdb='24,8';
+        			} elseif($type=='phone') {
+        				$typedb='varchar';
+        				$lengthdb='20';
+        			}elseif($type=='mail') {
+        				$typedb='varchar';
+        				$lengthdb='128';
+        			} elseif (($type=='select') || ($type=='sellist') || ($type=='radio') ||($type=='checkbox') ||($type=='chkbxlst')){
+        				$typedb='text';
+        				$lengthdb='';
+        			} elseif ($type=='link') {
+        				$typedb='int';
+        				$lengthdb='11';
+        			} else {
+        				$typedb=$type;
+        				$lengthdb=$length;
+        			}
+	                
 	                $field_desc=array(
-	                	'type'=>$type,
-	                	'value'=>$value,
+	                	'type'=>$typedb,
+	                	'value'=>$lengthdb,
 	                	'attribute'=>$attribute,
 	                	'default'=>$default,
 	                	'extra'=>$extra,
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 4f029afd8d81f219bbe50f5cd72475994ee9b9aa..77796bb5b0224130a56cfdd971329d0a0b081c00 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -279,7 +279,7 @@ ModuleFamilyInterface=Interfaces with external systems
 MenuHandlers=Menu handlers
 MenuAdmin=Menu editor
 DoNotUseInProduction=Do not use in production
-ThisIsProcessToFollow=This is setup to process:
+ThisIsProcessToFollow=This is steps to process:
 ThisIsAlternativeProcessToFollow=This is an alternative setup to process:
 StepNb=Step %s
 FindPackageFromWebSite=Find a package that provides feature you want (for example on official web site %s).
@@ -1575,7 +1575,7 @@ BackupDumpWizard=Wizard to build database backup dump file
 SomethingMakeInstallFromWebNotPossible=Installation of external module is not possible from the web interface for the following reason:
 SomethingMakeInstallFromWebNotPossible2=For this reason, process to upgrade described here is only manual steps a privileged user can do. 
 InstallModuleFromWebHasBeenDisabledByFile=Install of external module from application has been disabled by your administrator. You must ask him to remove the file <strong>%s</strong> to allow this feature.
-ConfFileMuseContainCustom=Installing an external module from application save the module files into directory <strong>%s</strong>. To have this directory processed by Dolibarr, you must setup your <strong>conf/conf.php</strong> to have option<br><strong>$dolibarr_main_url_root_alt='/custom';</strong><br><strong>$dolibarr_main_document_root_alt='%s/custom';</strong> 
+ConfFileMuseContainCustom=Installing an external module from application need to save the module files into directory <strong>%s</strong>. To have this directory processed by Dolibarr, you must setup your <strong>conf/conf.php</strong> to have option<br><strong>$dolibarr_main_url_root_alt='/custom';</strong><br><strong>$dolibarr_main_document_root_alt='%s/custom';</strong> 
 HighlightLinesOnMouseHover=Highlight table lines when mouse move passes over
 HighlightLinesColor=Highlight color of the line when the mouse passes over (keep empty for no highlight)
 TextTitleColor=Color of page title
@@ -1618,8 +1618,8 @@ ByDefaultInList=Show by default on list view
 YouUseLastStableVersion=You use the last stable version
 TitleExampleForMajorRelease=Example of message you can use to announce this major release (feel free to use it on your web sites)
 TitleExampleForMaintenanceRelease=Example of message you can use to announce this maintenance release (feel free to use it on your web sites)
-ExampleOfNewsMessageForMajorRelease=Dolibarr ERP & CRM %s is available. Version %s is a major release with a lot of new features for both users and developers. You can download it from the download area of http://www.dolibarr.org portal (subdirectory Stable versions). You can read <a href="https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog">ChangeLog</a> for complete list of changes.
-ExampleOfNewsMessageForMaintenanceRelease=Dolibarr ERP & CRM %s is available. Version %s is a maintenance version, so it contains only fixes of bugs. We recommend everybody using an older version to upgrade to this one. As any maintenance release, no new features, nor data structure change is present into this version. You can download it from the download area of http://www.dolibarr.org portal (subdirectory Stable versions). You can read <a href="https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog">ChangeLog</a> for complete list of changes.
+ExampleOfNewsMessageForMajorRelease=Dolibarr ERP & CRM %s is available. Version %s is a major release with a lot of new features for both users and developers. You can download it from the download area of https://www.dolibarr.org portal (subdirectory Stable versions). You can read <a href="https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog">ChangeLog</a> for complete list of changes.
+ExampleOfNewsMessageForMaintenanceRelease=Dolibarr ERP & CRM %s is available. Version %s is a maintenance version, so it contains only fixes of bugs. We recommend everybody using an older version to upgrade to this one. As any maintenance release, no new features, nor data structure change is present into this version. You can download it from the download area of https://www.dolibarr.org portal (subdirectory Stable versions). You can read <a href="https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog">ChangeLog</a> for complete list of changes.
 MultiPriceRuleDesc=When option "Several level of prices per product/service" is on, you can define different prices (one per price level) for each product. To save you time, you can enter here rule to have price for each level autocalculated according to price of first level, so you will have to enter only price for first level on each product. This page is here to save you time and can be usefull only if your prices for each leve are relative to first level. You can ignore this page in most cases.
 ModelModulesProduct=Templates for product documents
 ToGenerateCodeDefineAutomaticRuleFirst=To be able to generate automatically codes, you must first define a manager to auto define barcode number.
diff --git a/htdocs/langs/en_US/oauth.lang b/htdocs/langs/en_US/oauth.lang
index f4df2dc3dda082c3eb55a1cea692275cd931329d..cafca379f6f1dc58b19c8d9a33f2e2405572cf9c 100644
--- a/htdocs/langs/en_US/oauth.lang
+++ b/htdocs/langs/en_US/oauth.lang
@@ -2,15 +2,20 @@
 ConfigOAuth=Oauth Configuration
 OAuthServices=OAuth services
 ManualTokenGeneration=Manual token generation
+TokenManager=Token manager
+IsTokenGenerated=Is token generated ?
 NoAccessToken=No access token saved into local database
 HasAccessToken=A token was generated and saved into local database
-NewTokenStored=Token received ans saved
-ToCheckDeleteTokenOnProvider=To check/delete authorization saved by %s OAuth provider
+NewTokenStored=Token received and saved
+ToCheckDeleteTokenOnProvider=Click here to check/delete authorization saved by %s OAuth provider
 TokenDeleted=Token deleted
 RequestAccess=Click here to request/renew access and receive a new token to save
 DeleteAccess=Click here to delete token
 UseTheFollowingUrlAsRedirectURI=Use the following URL as the Redirect URI when creating your credential on your OAuth provider:
 ListOfSupportedOauthProviders=Enter here credential provided by your OAuth2 provider. Only supported OAuth2 providers are visible here. This setup may be used by other modules that need OAuth2 authentication.
+OAuthSetupForLogin=Page to generate an OAuth token
+SeePreviousTab=See previous tab
+OAuthIDSecret=OAuth ID and Secret
 TOKEN_REFRESH=Token Refresh Present
 TOKEN_EXPIRED=Token expired
 TOKEN_EXPIRE_AT=Token expire at
diff --git a/htdocs/langs/en_US/printing.lang b/htdocs/langs/en_US/printing.lang
index d6cf49bd525f4f256a636f9cb22c8358f04ff465..a357409289ad27fc6e81728dfeef9d8efd148dbd 100644
--- a/htdocs/langs/en_US/printing.lang
+++ b/htdocs/langs/en_US/printing.lang
@@ -46,6 +46,6 @@ IPP_Media=Printer media
 IPP_Supported=Type of media
 DirectPrintingJobsDesc=This page lists printing jobs found for available printers.
 GoogleAuthNotConfigured=Google OAuth setup not done. Enable module OAuth and set a Google ID/Secret.
-GoogleAuthConfigured=Google OAuth credentials found into setup of module OAuth.
+GoogleAuthConfigured=Google OAuth credentials were found into setup of module OAuth.
 PrintingDriverDescprintgcp=Configuration variables for printing driver Google Cloud Print.
 PrintTestDescprintgcp=List of Printers for Google Cloud Print.
diff --git a/htdocs/printing/admin/printing.php b/htdocs/printing/admin/printing.php
index 8e9a9d20b9a811eab87202a62d88e893fa129654..8d9609459ed2323200f2daff61692a89d9cfbee0 100644
--- a/htdocs/printing/admin/printing.php
+++ b/htdocs/printing/admin/printing.php
@@ -161,9 +161,19 @@ if ($mode == 'setup' && $user->admin)
                     break;
                 case "info":    // Google Api setup or Google OAuth Token
                     print '<tr '.$bc[$var].'>';
-                    print '<td'.($key['required']?' class=required':'').'>'.$langs->trans($key['varname']).'</td>';
+                    print '<td'.($key['required']?' class=required':'').'>';
+                    if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS')
+                    {
+                        print $langs->trans("IsTokenGenerated");
+                    }
+                    else
+                    {
+                        print $langs->trans($key['varname']);
+                    }
+                    print '</td>';
                     print '<td>'.$langs->trans($key['info']).'</td>';
                     print '<td>';
+                    //var_dump($key);
                     if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS')
                     {
                         // Delete remote tokens
@@ -187,7 +197,8 @@ if ($mode == 'setup' && $user->admin)
                 // Token
                 print '<tr '.$bc[$var].'>';
                 print '<td>'.$langs->trans("Token").'</td>';
-                print '<td>';
+                print '<td colspan="2">';
+                $tokenobj=null;
                 // Dolibarr storage
                 $storage = new DoliStorage($db, $conf);
                 try
@@ -210,8 +221,6 @@ if ($mode == 'setup' && $user->admin)
                     print '</textarea>';*/
                 }
                 print '</td>';
-                print '<td>';
-                print '</td>';
                 print '</tr>'."\n";
             }
         }
diff --git a/htdocs/projet/tasks/contact.php b/htdocs/projet/tasks/contact.php
index dcb9f7426a8ef587fcc9a40e252f73dd338442d2..096f44cc2f2507986778a5ce4d700aa36d2a1653 100644
--- a/htdocs/projet/tasks/contact.php
+++ b/htdocs/projet/tasks/contact.php
@@ -208,7 +208,7 @@ if ($id > 0 || ! empty($ref))
             // Define a complementary filter for search of next/prev ref.
             if (! $user->rights->projet->all->lire)
             {
-                $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
+                $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0);
                 $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
             }
             
diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php
index 7c62fb651f18b35b9027a0036210bce49440ad5a..e51c0fb28cc62e8c1057995692765fe0f7a533e7 100644
--- a/htdocs/projet/tasks/document.php
+++ b/htdocs/projet/tasks/document.php
@@ -151,7 +151,7 @@ if ($object->id > 0)
         // Define a complementary filter for search of next/prev ref.
         if (! $user->rights->projet->all->lire)
         {
-            $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
+            $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0);
             $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
         }
         
diff --git a/htdocs/projet/tasks/note.php b/htdocs/projet/tasks/note.php
index f443facaabf72d8535f51303aef4420633577a3d..9ee9c160ad0f8f7e1db1cfdae85c96ede9ec13ab 100644
--- a/htdocs/projet/tasks/note.php
+++ b/htdocs/projet/tasks/note.php
@@ -130,7 +130,7 @@ if ($object->id > 0)
 		// Define a complementary filter for search of next/prev ref.
 		if (! $user->rights->projet->all->lire)
 		{
-		    $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
+		    $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0);
 		    $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
 		}
 		
diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php
index cbee3683f7322f9237548f6efaf7ab6db5b01b38..2e5c17acc5967f1937324fe387dc407fa035f126 100644
--- a/htdocs/projet/tasks/task.php
+++ b/htdocs/projet/tasks/task.php
@@ -242,7 +242,7 @@ if ($id > 0 || ! empty($ref))
             // Define a complementary filter for search of next/prev ref.
             if (! $user->rights->projet->all->lire)
             {
-                $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
+                $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0);
                 $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
             }
             
diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php
index 5a9a670456697607d8686ae7d73e918116f5a1ec..d0b9475bfc1dbd674d196028af1f97b992c47ef4 100644
--- a/htdocs/projet/tasks/time.php
+++ b/htdocs/projet/tasks/time.php
@@ -318,7 +318,7 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0)
             // Define a complementary filter for search of next/prev ref.
             if (! $user->rights->projet->all->lire)
             {
-                $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
+                $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0);
                 $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
             }
             
diff --git a/htdocs/support/index.php b/htdocs/support/index.php
index 947ae72e70cc5f5988fdf2f46cfb1fb63081636d..a895cf5cb1e183e731c91ef2c5159304b6c6a813 100644
--- a/htdocs/support/index.php
+++ b/htdocs/support/index.php
@@ -86,13 +86,13 @@ print '<td align="center" valign="top">';
 
 print '<table class="nocellnopadd">';
 print '<tr><td align="center">';
-$urlwiki='http://wiki.dolibarr.org';
-if (preg_match('/fr/i',$langs->defaultlang)) $urlwiki='http://wiki.dolibarr.org/index.php/Accueil';
-if (preg_match('/es/i',$langs->defaultlang)) $urlwiki='http://wiki.dolibarr.org/index.php/Portada';
+$urlwiki='https://wiki.dolibarr.org';
+if (preg_match('/fr/i',$langs->defaultlang)) $urlwiki='https://wiki.dolibarr.org/index.php/Accueil';
+if (preg_match('/es/i',$langs->defaultlang)) $urlwiki='https://wiki.dolibarr.org/index.php/Portada';
 print '<br>'.$langs->trans("ForDocumentationSeeWiki",$urlwiki,$urlwiki);
 print '<br>';
-$urlforum='http://www.dolibarr.org/forum/';
-$urlforumlocal='http://www.dolibarr.org/forum/';
+$urlforum='https://www.dolibarr.org/forum/';
+$urlforumlocal='https://www.dolibarr.org/forum/';
 if (preg_match('/fr/i',$langs->defaultlang)) $urlforumlocal='http://www.dolibarr.fr/forum/';
 if (preg_match('/es/i',$langs->defaultlang)) $urlforumlocal='http://www.dolibarr.es/index.php/foro/';
 if (preg_match('/it/i',$langs->defaultlang)) $urlforumlocal='http://www.dolibarr.it/forum/';
@@ -194,8 +194,7 @@ print '</td></tr></table>';
 
 print '</td>';
 print '</tr><tr>';
-//$urlwiki='http://wiki.dolibarr.org/index.php/List of Dolibarr partners and providers';
-$urlwiki='http://partners.dolibarr.org';
+$urlwiki='https://partners.dolibarr.org';
 print '<td align="center" valign="top">';
 print '<table class="nocellnopadd">';
 print '<tr><td align="center">';
@@ -229,8 +228,7 @@ print '</td></tr></table>';
 
 print '</td>';
 print '</tr><tr>';
-//$urlwiki='http://wiki.dolibarr.org/index.php/List of Dolibarr partners and providers';
-$urlwiki='http://partners.dolibarr.org';
+$urlwiki='https://partners.dolibarr.org';
 print '<td align="center" valign="top">';
 print '<table class="nocellnopadd">';
 print '<tr><td align="center">';
diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php
index 0e278019df6bc62ecc25cee952b2de7bdeda5db5..d72d303aa324b5e18e4cae7f9428245434bb8b6e 100644
--- a/htdocs/theme/eldy/style.css.php
+++ b/htdocs/theme/eldy/style.css.php
@@ -261,7 +261,8 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla
 }
 
 input:focus, textarea:focus, button:focus, select:focus {
-    box-shadow: 0 0 4px #8091BF;
+    /* box-shadow: 0 0 4px #8091BF; */
+    border-bottom: 1px solid #8091BF !important;
 }
 textarea.cke_source:focus
 {
@@ -337,9 +338,9 @@ input[type=checkbox] { background-color: transparent; border: none; box-shadow:
 input[type=radio]    { background-color: transparent; border: none; box-shadow: none; }
 input[type=image]    { background-color: transparent; border: none; box-shadow: none; }
 input:-webkit-autofill {
-	background-color: #FBFFEA !important;
+	background-color: #FDFFF0 !important;
 	background-image:none !important;
-	-webkit-box-shadow: 0 0 0 50px #FBFFEA inset;
+	-webkit-box-shadow: 0 0 0 50px #FDFFF0 inset;
 }
 ::-webkit-input-placeholder { color:#ccc; }
 :-moz-placeholder { color:#bbb; } 			/* firefox 18- */
@@ -790,6 +791,7 @@ td.showDragHandle {
 .side-nav {
 	display: table-cell;
 	border-right: 1px solid #d0d0d0;
+	box-shadow: 3px 0 6px -2px #eee;
 }
 div.blockvmenulogo
 {
@@ -1375,6 +1377,7 @@ foreach($mainmenuusedarray as $val)
 .bodylogin
 {
 	background: #f0f0f0;
+	/* background: linear-gradient(to left top, rgb(255,255,255), rgb(240,240,240)) fixed; */
 }
 .login_vertical_align {
 	padding: 10px;
@@ -1406,12 +1409,29 @@ form#login {
 	-moz-box-shadow: 0 2px 23px 2px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(60,60,60,0.15);
 	-webkit-box-shadow: 0 2px 23px 2px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(60,60,60,0.15);
 	box-shadow: 0 2px 23px 2px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(60,60,60,0.15);
+	
 	/*-moz-box-shadow: 3px 2px 20px #CCC;
     -webkit-box-shadow: 3px 2px 20px #CCC;
     box-shadow: 3px 2px 20px #CCC;*/
 
 	border-radius: 5px;
-	border:solid 1px rgba(80,80,80,.4);
+	/*border-top:solid 1px rgba(180,180,180,.4);
+	border-left:solid 1px rgba(180,180,180,.4);
+	border-right:solid 1px rgba(180,180,180,.4);
+	border-bottom:solid 1px rgba(180,180,180,.4);*/
+}
+.login_table input#username, .login_table input#password, .login_table input#securitycode {
+	border: none;
+	border-bottom: solid 1px rgba(180,180,180,.4);
+	padding: 5px;
+	margin-left: 18px;
+	margin-top: 5px;
+}
+.login_table input#username:focus, .login_table input#password:focus, .login_table input#securitycode:focus {
+	outline: none !important;
+	/* box-shadow: none;
+	-webkit-box-shadow: 0 0 0 50px #FFF inset;
+	box-shadow: 0 0 0 50px #FFF inset;*/
 }
 .login_main_message {
 	text-align: center;
@@ -1448,8 +1468,8 @@ table.login_table_securitycode tr td {
 	border: 1px solid #DDDDDD;
 }
 #img_logo, .img_logo {
-	max-width: 200px;
-	max-height: 100px;
+	max-width: 170px;
+	max-height: 90px;
 }
 
 div.login_block {
@@ -1523,18 +1543,18 @@ img.loginphoto {
     height: 16px;
 }
 .span-icon-user {
-	/* background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/object_user.png',1); ?>); */
+	background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/object_user.png',1); ?>);
 	background-repeat: no-repeat;
 }
 .span-icon-password {
-	/* background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/lock.png',1); ?>); */
+	background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/lock.png',1); ?>);
 	background-repeat: no-repeat;
 }
-
+/*
 .span-icon-user input, .span-icon-password input {
 	/* margin-left: 18px; */
 	margin-left: 0px;
-}
+}*/
 
 /* ============================================================================== */
 /* Menu gauche                                                                    */
@@ -3050,7 +3070,7 @@ div.info {
   -moz-border-radius: 4px;
   -webkit-border-radius: 4px;
   border-radius: 4px;
-  background: #E0EAE4;
+  background: #EaE4Ea;
   text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
 }
 
diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php
index f45b0355880486872cd0ab3ceaba4537bd80e891..409a902648e79ba42cca764215f255b453c69f0a 100644
--- a/htdocs/theme/md/style.css.php
+++ b/htdocs/theme/md/style.css.php
@@ -261,7 +261,8 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla
 }
 
 input:focus, textarea:focus, button:focus, select:focus {
-    box-shadow: 0 0 4px #8091BF;
+    /* box-shadow: 0 0 4px #8091BF; */
+    border-bottom: 1px solid #8091BF !important;
 }
 textarea.cke_source:focus
 {
@@ -805,6 +806,7 @@ td.showDragHandle {
 <?php } else { ?>
 	background: #FFF;
 	border-right: 1px solid rgba(0,0,0,0.2);
+	box-shadow: 3px 0 6px -2px #eee;
 	bottom: 0;
 	color: #333;
 	display: block;
@@ -1453,6 +1455,19 @@ form#login {
 
 	border-top:solid 1px f8f8f8;
 }
+.login_table input#username, .login_table input#password, .login_table input#securitycode{
+	border: none;
+	border-bottom: solid 1px rgba(180,180,180,.4);
+	padding: 5px;
+	margin-left: 18px;
+	margin-top: 5px;
+}
+.login_table input#username:focus, .login_table input#password:focus, .login_table input#securitycode:focus {
+	outline: none !important;
+	/* box-shadow: none;
+	-webkit-box-shadow: 0 0 0 50px #FFF inset;
+	box-shadow: 0 0 0 50px #FFF inset;*/
+}
 .login_main_message {
 	text-align: center;
 	max-width: 560px;
@@ -1488,8 +1503,8 @@ table.login_table_securitycode tr td {
 	border: 1px solid #f4f4f4;
 }
 #img_logo, .img-logo {
-	max-width: 200px;
-	max-height: 100px;
+	max-width: 170px;
+	max-height: 90px;
 }
 
 div.login_block {
@@ -1567,7 +1582,8 @@ img.loginphoto {
 }
 
 .span-icon-user {
-	background: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/object_user.png',1); ?>) no-repeat scroll 7px 7px;
+	background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/object_user.png',1); ?>);
+	background-repeat: no-repeat;
 }
 .span-icon-password {
 	background-image: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/lock.png',1); ?>);
@@ -2976,7 +2992,7 @@ div.info {
   -moz-border-radius: 4px;
   -webkit-border-radius: 4px;
   border-radius: 4px;
-  background: #E0EAE4;
+  background: #EaE4Ea;
   text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
 }