';
// TODO How record was recorded OrderMode (llx_c_input_method)
@@ -1895,7 +1896,7 @@ if ($action == 'create' && $usercancreate) {
$langs->load("projects");
print '
';
}
diff --git a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php
index 2b590e05fd9..515a004a3cd 100644
--- a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php
+++ b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php
@@ -249,9 +249,9 @@ if ($modecompta == 'CREANCES-DETTES') {
$sql .= " sum(f.total_ht) as amount, sum(f.total_ttc) as amount_ttc";
$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f, ".MAIN_DB_PREFIX."societe as s";
if ($selected_cat === -2) { // Without any category
- $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_societe as cs ON s.rowid = cs.fk_soc";
+ $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_fournisseur as cs ON s.rowid = cs.fk_soc";
} elseif ($selected_cat) { // Into a specific category
- $sql .= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_societe as cs";
+ $sql .= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_fournisseur as cs";
}
$sql .= " WHERE f.fk_statut in (1,2)";
$sql .= " AND f.type IN (0,2)";
@@ -276,9 +276,9 @@ if ($modecompta == 'CREANCES-DETTES') {
$sql .= ", ".MAIN_DB_PREFIX."paiementfourn as p";
$sql .= ", ".MAIN_DB_PREFIX."societe as s";
if ($selected_cat === -2) { // Without any category
- $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_societe as cs ON s.rowid = cs.fk_soc";
+ $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_fournisseur as cs ON s.rowid = cs.fk_soc";
} elseif ($selected_cat) { // Into a specific category
- $sql .= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_societe as cs";
+ $sql .= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_fournisseur as cs";
}
$sql .= " WHERE p.rowid = pf.fk_paiementfourn";
$sql .= " AND pf.fk_facturefourn = f.rowid";
diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example
index 1cc028ff137..5325523f8e5 100644
--- a/htdocs/conf/conf.php.example
+++ b/htdocs/conf/conf.php.example
@@ -302,7 +302,7 @@ $dolibarr_main_restrict_ip='';
// This might be required if you access Dolibarr behind a proxy that make bad URL rewriting, to avoid false alarms.
// In most cases, you should always keep this to 0.
// Default value: 0
-// Possible values: 0 or 1
+// Possible values: 0 or 1 (no strict CSRF test, only test on referer) or 2 (no CSRF test at all)
// Examples:
// $dolibarr_nocsrfcheck='0';
//
diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php
index a7a87e1ce6e..f6611669556 100644
--- a/htdocs/core/class/CMailFile.class.php
+++ b/htdocs/core/class/CMailFile.class.php
@@ -908,7 +908,7 @@ class CMailFile
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
- $storage = new DoliStorage($db, $conf);
+ $storage = new DoliStorage($db, $conf, $keyforprovider);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
$expire = false;
@@ -1030,7 +1030,7 @@ class CMailFile
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
- $storage = new DoliStorage($db, $conf);
+ $storage = new DoliStorage($db, $conf, $keyforprovider);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
diff --git a/htdocs/core/class/cgenericdic.class.php b/htdocs/core/class/cgenericdic.class.php
index ab1023b81f5..250fb3ec569 100644
--- a/htdocs/core/class/cgenericdic.class.php
+++ b/htdocs/core/class/cgenericdic.class.php
@@ -82,6 +82,8 @@ class CGenericDic
$fieldlabel = 'label';
if ($this->table_element == 'c_stcomm') {
$fieldlabel = 'libelle';
+ } elseif ($this->table_element == 'c_type_fees') {
+ $fieldrowid = 'id';
}
$error = 0;
@@ -162,6 +164,8 @@ class CGenericDic
if ($this->table_element == 'c_stcomm') {
$fieldrowid = 'id';
$fieldlabel = 'libelle';
+ } elseif ($this->table_element == 'c_type_fees') {
+ $fieldrowid = 'id';
}
$sql = "SELECT";
@@ -233,6 +237,8 @@ class CGenericDic
if ($this->table_element == 'c_stcomm') {
$fieldrowid = 'id';
$fieldlabel = 'libelle';
+ } elseif ($this->table_element == 'c_type_fees') {
+ $fieldrowid = 'id';
}
$sql = "SELECT";
@@ -303,6 +309,8 @@ class CGenericDic
if ($this->table_element == 'c_stcomm') {
$fieldrowid = 'id';
$fieldlabel = 'libelle';
+ } elseif ($this->table_element == 'c_type_fees') {
+ $fieldrowid = 'id';
}
// Clean parameters
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index e42748bc61d..b5bcbe3ef8f 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -849,7 +849,7 @@ abstract class CommonObject
}
if ($this->element == 'contact') {
$contactid = $this->id;
- $thirdpartyid = empty($object->fk_soc) ? 0 : $object->fk_soc;
+ $thirdpartyid = empty($this->fk_soc) ? 0 : $this->fk_soc;
}
if ($this->element == 'user') {
$contactid = $this->contact_id;
@@ -6084,6 +6084,8 @@ abstract class CommonObject
if (!empty($extrafields->attributes[$this->table_element]) && !empty($extrafields->attributes[$this->table_element]['computed'][$key])) {
//var_dump($conf->disable_compute);
if (empty($conf->disable_compute)) {
+ global $objectoffield; // We set a global variable to $objectoffield so
+ $objectoffield = $this; // we can use it inside computed formula
$this->array_options["options_".$key] = dol_eval($extrafields->attributes[$this->table_element]['computed'][$key], 1, 0, '');
}
}
diff --git a/htdocs/core/js/lib_notification.js.php b/htdocs/core/js/lib_notification.js.php
index aa9dd989c10..d7e1932ca27 100644
--- a/htdocs/core/js/lib_notification.js.php
+++ b/htdocs/core/js/lib_notification.js.php
@@ -99,12 +99,12 @@ function first_execution() {
function check_events() {
if (Notification.permission === "granted")
{
- var newToken = 'notrequired';
+ var currentToken = 'notrequired';
const allMeta = document.getElementsByTagName("meta");
for (let i = 0; i < allMeta.length; i++) {
- if (allMeta[i].getAttribute("name") == 'anti-csrf-token') {
- newToken = allMeta[i].getAttribute('content');
- console.log("newToken in page = "+newToken);
+ if (allMeta[i].getAttribute("name") == 'anti-csrf-currenttoken') {
+ currentToken = allMeta[i].getAttribute('content');
+ console.log("currentToken in page = "+currentToken);
}
}
time_js_next_test += time_auto_update;
@@ -113,7 +113,7 @@ function check_events() {
$.ajax("", {
type: "post", // Usually post or get
async: true,
- data: { time_js_next_test: time_js_next_test, forcechecknow: 1, token: newToken },
+ data: { time_js_next_test: time_js_next_test, forcechecknow: 1, token: currentToken },
dataType: "json",
success: function (result) {
//console.log(result);
@@ -181,7 +181,7 @@ function check_events() {
$.ajax(""+listofreminderids, {
type: "POST", // Usually post or get
async: true,
- data: { time_js_next_test: time_js_next_test, token: newToken }
+ data: { time_js_next_test: time_js_next_test, token: currentToken }
});
} else {
console.log("No reminder to do found, next search at "+time_js_next_test);
diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php
index 71bcc082961..b3ee5dc259a 100644
--- a/htdocs/core/lib/admin.lib.php
+++ b/htdocs/core/lib/admin.lib.php
@@ -2054,6 +2054,11 @@ function email_admin_prepare_head()
$head[$h][2] = 'templates';
$h++;
+ $head[$h][0] = DOL_URL_ROOT."/admin/mails_ingoing.php";
+ $head[$h][1] = $langs->trans("InGoingEmailSetup", $langs->transnoentitiesnoconv("EMailing"));
+ $head[$h][2] = 'common_ingoing';
+ $h++;
+
complete_head_from_modules($conf, $langs, null, $head, $h, 'email_admin', 'remove');
return $head;
diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php
index b1d53e452bb..05b8e98e8ed 100644
--- a/htdocs/core/lib/company.lib.php
+++ b/htdocs/core/lib/company.lib.php
@@ -1117,7 +1117,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserl
$extrafieldsobjectkey = $contactstatic->table_element;
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
- $sql = "SELECT t.rowid, t.entity, t.lastname, t.firstname, t.fk_pays as country_id, t.civility, t.poste, t.phone as phone_pro, t.phone_mobile, t.phone_perso, t.fax, t.email, t.socialnetworks, t.statut, t.photo,";
+ $sql = "SELECT t.rowid, t.entity, t.lastname, t.firstname, t.fk_pays as country_id, t.civility, t.poste, t.phone as phone_pro, t.phone_mobile, t.phone_perso, t.fax, t.email, t.socialnetworks, t.statut, t.photo, t.fk_soc,";
$sql .= " t.civility as civility_id, t.address, t.zip, t.town";
$sql .= ", t.note_private";
$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as t";
@@ -1272,6 +1272,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserl
$contactstatic->email = $obj->email;
$contactstatic->socialnetworks = $obj->socialnetworks;
$contactstatic->photo = $obj->photo;
+ $contactstatic->fk_soc = $obj->fk_soc;
$contactstatic->entity = $obj->entity;
$country_code = getCountry($obj->country_id, 2);
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 3150ea706cc..e94b9d5e4c0 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -4102,7 +4102,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
'paiment', 'paragraph', 'play', 'pdf', 'phone', 'phoning', 'phoning_mobile', 'phoning_fax', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'proposal', 'puce',
'stock', 'resize', 'service', 'stats', 'trip',
'security', 'setup', 'share-alt', 'sign-out', 'split', 'stripe', 'stripe-s', 'switch_off', 'switch_on', 'switch_on_red', 'tools', 'unlink', 'uparrow', 'user', 'user-tie', 'vcard', 'wrench',
- 'github', 'google', 'jabber', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp',
+ 'github', 'google', 'jabber', 'microsoft', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp',
'chevron-left', 'chevron-right', 'chevron-down', 'chevron-top', 'commercial', 'companies',
'generic', 'home', 'hrm', 'members', 'products', 'invoicing',
'partnership', 'payment', 'payment_vat', 'pencil-ruler', 'preview', 'project', 'projectpub', 'projecttask', 'question', 'refresh', 'region',
@@ -4123,7 +4123,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
if (in_array($pictowithouttext, array('card', 'bell', 'clock', 'establishment', 'generic', 'minus-square', 'object_generic', 'pdf', 'plus-square', 'timespent', 'note', 'off', 'on', 'object_bookmark', 'bookmark', 'vcard'))) {
$fa = 'far';
}
- if (in_array($pictowithouttext, array('black-tie', 'github', 'google', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'stripe', 'stripe-s', 'youtube', 'google-plus-g', 'whatsapp'))) {
+ if (in_array($pictowithouttext, array('black-tie', 'github', 'google', 'microsoft', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'stripe', 'stripe-s', 'youtube', 'google-plus-g', 'whatsapp'))) {
$fa = 'fab';
}
@@ -8917,10 +8917,12 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
// Only global variables can be changed by eval function and returned to caller
global $db, $langs, $user, $conf, $website, $websitepage;
global $action, $mainmenu, $leftmenu;
+ global $mysoc;
+ global $objectoffield;
+
+ // Old variables used
global $rights;
global $object;
- global $mysoc;
-
global $obj; // To get $obj used into list when dol_eval is used for computed fields and $obj is not yet $object
global $soc; // For backward compatibility
diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php
index f4aca8ef9a7..dfe6f78092c 100644
--- a/htdocs/core/lib/invoice.lib.php
+++ b/htdocs/core/lib/invoice.lib.php
@@ -281,8 +281,8 @@ function getNumberInvoicesPieChart($mode)
{
global $conf, $db, $langs, $user;
- if (($mode == 'customers' && isModEnabled('facture') && !empty($user->rights->facture->lire))
- || ($mode == 'suppliers' && (isModEnabled('fournisseur') || isModEnabled('supplier_invoice')) && !empty($user->rights->facture->lire))
+ if (($mode == 'customers' && isModEnabled('facture') && $user->hasRight('facture', 'lire'))
+ || ($mode == 'suppliers' && (isModEnabled('fournisseur') || isModEnabled('supplier_invoice')) && $user->hasRight('fournisseur', 'facture', 'lire'))
) {
include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php';
diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php
index 83359ef1c65..8a81d9a80e5 100644
--- a/htdocs/core/lib/oauth.lib.php
+++ b/htdocs/core/lib/oauth.lib.php
@@ -25,15 +25,17 @@
// Supported OAUTH (a provider is supported when a file xxx_oauthcallback.php is available into htdocs/core/modules/oauth)
$supportedoauth2array = array(
- 'OAUTH_GOOGLE_NAME'=>array('callbackfile' => 'google', 'picto' => 'google', 'urlforapp' => 'OAUTH_GOOGLE_DESC', 'name'=>'Google', 'urlforcredentials'=>'https://console.developers.google.com/', 'availablescopes'=> 'userinfo_email,userinfo_profile,openid,email,profile,cloud_print,admin_directory_user,gmail_full'),
+ 'OAUTH_GOOGLE_NAME'=>array('callbackfile' => 'google', 'picto' => 'google', 'urlforapp' => 'OAUTH_GOOGLE_DESC', 'name'=>'Google', 'urlforcredentials'=>'https://console.developers.google.com/', 'availablescopes'=> 'userinfo_email,userinfo_profile,openid,email,profile,cloud_print,admin_directory_user,gmail_full', 'returnurl'=>'/core/modules/oauth/google_oauthcallback.php'),
);
if (isModEnabled('stripe')) {
- $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = array('callbackfile' => 'stripetest', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeTest', 'urlforcredentials'=>'', 'availablescopes'=>'read_write');
- $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>'', 'availablescopes'=>'read_write');
+ $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = array('callbackfile' => 'stripetest', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeTest', 'urlforcredentials'=>'', 'availablescopes'=>'read_write', 'returnurl'=>'/core/modules/oauth/stripetest_oauthcallback.php');
+ $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>'', 'availablescopes'=>'read_write', 'returnurl'=>'/core/modules/oauth/stripelive_oauthcallback.php');
}
-$supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers', 'availablescopes'=>'user,public_repo');
+$supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers', 'availablescopes'=>'user,public_repo', 'returnurl'=>'/core/modules/oauth/github_oauthcallback.php');
+$supportedoauth2array['OAUTH_MICROSOFT_NAME'] = array('callbackfile' => 'microsoft', 'picto' => 'microsoft', 'urlforapp' => 'OAUTH_MICROSOFT_DESC', 'name'=>'Microsoft', 'urlforcredentials'=>'https://portal.azure.com/', 'availablescopes'=>'openid,offline_access,profile,email,User.Read,https://outlook.office365.com/IMAP.AccessAsUser.All,https://outlook.office365.com/SMTP.Send', 'returnurl'=>'/core/modules/oauth/microsoft_oauthcallback.php');
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
- $supportedoauth2array['OAUTH_OTHER_NAME'] = array('callbackfile' => 'generic', 'picto' => 'generic', 'urlforapp' => 'OAUTH_OTHER_DESC', 'name'=>'Other', 'urlforcredentials'=>'', 'availablescopes'=>'Standard');
+ $supportedoauth2array['OAUTH_OTHER_NAME'] = array('callbackfile' => 'generic', 'picto' => 'generic', 'urlforapp' => 'OAUTH_OTHER_DESC', 'name'=>'Other', 'urlforcredentials'=>'', 'availablescopes'=>'Standard', 'returnurl'=>'/core/modules/oauth/generic_oauthcallback.php');
+ // See https://learn.microsoft.com/fr-fr/azure/active-directory/develop/quickstart-register-app#register-an-application
}
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 51c3434a456..a097ba23e3e 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -119,6 +119,7 @@ function dolGetRandomBytes($length)
function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR")
{
global $dolibarr_main_instance_unique_id;
+ global $dolibarr_disable_dolcrypt_for_debug;
if ($chain === '' || is_null($chain)) {
return '';
@@ -136,7 +137,7 @@ function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR")
$newchain = $chain;
- if (function_exists('openssl_encrypt')) {
+ if (function_exists('openssl_encrypt') && empty($dolibarr_disable_dolcrypt_for_debug)) {
$ivlen = 16;
if (function_exists('openssl_cipher_iv_length')) {
$ivlen = openssl_cipher_iv_length($ciphering);
diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
index 0b8fa2d4621..548b5cf66f4 100644
--- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
+++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
@@ -336,15 +336,19 @@ class doc_generic_invoice_odt extends ModelePDFFactures
$object->fetchObjectLinked('', '', '', '');
//print_r($object->linkedObjects['propal']); exit;
- $propal_object = $object->linkedObjects['propal'][0];
+ if (isset($object->linkedObjects['propal'][0])) {
+ $propal_object = $object->linkedObjects['propal'][0];
+ } else {
+ $propal_object = null;
+ }
// Make substitution
$substitutionarray = array(
- '__FROM_NAME__' => $this->emetteur->name,
- '__FROM_EMAIL__' => $this->emetteur->email,
- '__TOTAL_TTC__' => $object->total_ttc,
- '__TOTAL_HT__' => $object->total_ht,
- '__TOTAL_VAT__' => $object->total_tva
+ '__FROM_NAME__' => $this->emetteur->name,
+ '__FROM_EMAIL__' => $this->emetteur->email,
+ '__TOTAL_TTC__' => $object->total_ttc,
+ '__TOTAL_HT__' => $object->total_ht,
+ '__TOTAL_VAT__' => $object->total_tva
);
complete_substitutions_array($substitutionarray, $langs, $object);
// Call the ODTSubstitution hook
@@ -435,8 +439,8 @@ class doc_generic_invoice_odt extends ModelePDFFactures
} else {
$odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
}
- } else // Text
- {
+ } else {
+ // Text
$odfHandler->setVars($key, $value, true, 'UTF-8');
}
} catch (OdfException $e) {
diff --git a/htdocs/core/modules/modOauth.class.php b/htdocs/core/modules/modOauth.class.php
index d93a715f1e7..e7c23d30455 100644
--- a/htdocs/core/modules/modOauth.class.php
+++ b/htdocs/core/modules/modOauth.class.php
@@ -51,7 +51,7 @@ class modOauth extends DolibarrModules
// Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module)
$this->name = preg_replace('/^mod/i', '', get_class($this));
// Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module)
- $this->description = "Enable OAuth authentication";
+ $this->description = "Enable OAuth2 authentication";
// Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version
$this->version = 'dolibarr';
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
diff --git a/htdocs/core/modules/oauth/generic_oauthcallback.php b/htdocs/core/modules/oauth/generic_oauthcallback.php
index 34422111d5d..a394c7f4986 100644
--- a/htdocs/core/modules/oauth/generic_oauthcallback.php
+++ b/htdocs/core/modules/oauth/generic_oauthcallback.php
@@ -66,7 +66,7 @@ $httpClient = new \OAuth\Common\Http\Client\CurlClient();
$serviceFactory->setHttpClient($httpClient);
// Dolibarr storage
-$storage = new DoliStorage($db, $conf);
+$storage = new DoliStorage($db, $conf, $keyforprovider);
// Setup the credentials for the requests
$keyforparamid = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_ID';
@@ -77,9 +77,11 @@ $credentials = new Credentials(
$currentUri->getAbsoluteUri()
);
+$state = GETPOST('state');
+
$requestedpermissionsarray = array();
-if (GETPOST('state')) {
- $requestedpermissionsarray = explode(',', GETPOST('state')); // Example: 'user'. 'state' parameter is standard to retrieve some parameters back
+if ($state) {
+ $requestedpermissionsarray = explode(',', $state); // Example: 'user'. 'state' parameter is standard to retrieve some parameters back
}
if ($action != 'delete' && empty($requestedpermissionsarray)) {
print 'Error, parameter state is not defined';
@@ -88,7 +90,8 @@ if ($action != 'delete' && empty($requestedpermissionsarray)) {
//var_dump($requestedpermissionsarray);exit;
// Instantiate the Api service using the credentials, http client and storage mechanism for the token
-$apiService = $serviceFactory->createService($genericstring, $credentials, $storage, $requestedpermissionsarray);
+// ucfirst(strtolower($genericstring)) must be the name of a class into OAuth/OAuth2/Services/Xxxx
+$apiService = $serviceFactory->createService(ucfirst(strtolower($genericstring)), $credentials, $storage, $requestedpermissionsarray);
/*
var_dump($genericstring.($keyforprovider ? '-'.$keyforprovider : ''));
@@ -128,35 +131,25 @@ if ($action == 'delete') {
exit();
}
-if (GETPOST('code')) { // We are coming from oauth provider page
+if (GETPOST('code') || GETPOST('error')) { // We are coming from oauth provider page
// We should have
//$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16))
- dol_syslog("We are coming from the oauth provider page");
- //llxHeader('',$langs->trans("OAuthSetup"));
-
- //$linkback=''.$langs->trans("BackToModuleList").'';
- //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
-
- //print dol_get_fiche_head();
- // retrieve the CSRF state parameter
- $state = GETPOSTISSET('state') ? GETPOST('state') : null;
- //print '
';
+ dol_syslog("We are coming from the oauth provider page code=".dol_trunc(GETPOST('code'), 5)." error=".GETPOST('error'));
// 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
+ //var_dump($apiService); // OAuth\OAuth2\Service\Xxx
- //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
- $token = $apiService->requestAccessToken(GETPOST('code'));
- // Github is a service that does not need state to 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.
+ if (GETPOST('error')) {
+ setEventMessages(GETPOST('error').' '.GETPOST('error_description'), null, 'errors');
+ } else {
+ //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ $token = $apiService->requestAccessToken(GETPOST('code'));
- setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
+ setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
+ }
$backtourl = $_SESSION["backtourlsavedbeforeoauthjump"];
unset($_SESSION["backtourlsavedbeforeoauthjump"]);
@@ -166,15 +159,17 @@ if (GETPOST('code')) { // We are coming from oauth provider page
} catch (Exception $e) {
print $e->getMessage();
}
-} else { // If entry on page with no parameter, we arrive here
+} else {
+ // If we enter this page without 'code' parameter, we arrive here. This is the case when we want to get the redirect
+ // to the OAuth provider login page.
$_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl;
$_SESSION["oauthkeyforproviderbeforeoauthjump"] = $keyforprovider;
$_SESSION['oauthstateanticsrf'] = $state;
// 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')));
+ if ($state) {
+ $url = $apiService->getAuthorizationUri(array('state' => $state));
} else {
$url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated
}
diff --git a/htdocs/core/modules/oauth/github_oauthcallback.php b/htdocs/core/modules/oauth/github_oauthcallback.php
index 24140718880..7656a1cda37 100644
--- a/htdocs/core/modules/oauth/github_oauthcallback.php
+++ b/htdocs/core/modules/oauth/github_oauthcallback.php
@@ -65,7 +65,7 @@ $httpClient = new \OAuth\Common\Http\Client\CurlClient();
$serviceFactory->setHttpClient($httpClient);
// Dolibarr storage
-$storage = new DoliStorage($db, $conf);
+$storage = new DoliStorage($db, $conf, $keyforprovider);
// Setup the credentials for the requests
$keyforparamid = 'OAUTH_GITHUB'.($keyforprovider ? '-'.$keyforprovider : '').'_ID';
@@ -115,30 +115,21 @@ if ($action == 'delete') {
exit();
}
-if (!empty($_GET['code'])) { // We are coming from oauth provider page
+if (GETPOST('code')) { // We are coming from oauth provider page
// We should have
//$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16))
- dol_syslog("We are coming from the oauth provider page");
- //llxHeader('',$langs->trans("OAuthSetup"));
-
- //$linkback=''.$langs->trans("BackToModuleList").'';
- //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
-
- //print dol_get_fiche_head();
- // retrieve the CSRF state parameter
- $state = isset($_GET['state']) ? $_GET['state'] : null;
- //print '
';
+ dol_syslog("We are coming from the oauth provider page code=".dol_trunc(GETPOST('code'), 5));
// 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 to be stored.
+ //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ $token = $apiService->requestAccessToken(GETPOST('code'));
+ // Github is a service that does not need state to be stored as second paramater of requestAccessToken
+
// 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.
diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php
index ed0caa1a4ff..bd59e513ddf 100644
--- a/htdocs/core/modules/oauth/google_oauthcallback.php
+++ b/htdocs/core/modules/oauth/google_oauthcallback.php
@@ -137,7 +137,7 @@ if ($action == 'delete') {
}
if (GETPOST('code')) { // We are coming from oauth provider page.
- dol_syslog("We are coming from the oauth provider page keyforprovider=".$keyforprovider);
+ dol_syslog("We are coming from the oauth provider page keyforprovider=".$keyforprovider." code=".dol_trunc(GETPOST('code'), 5));
// We must validate that the $state is the same than the one into $_SESSION['oauthstateanticsrf'], return error if not.
if (isset($_SESSION['oauthstateanticsrf']) && $state != $_SESSION['oauthstateanticsrf']) {
@@ -146,7 +146,6 @@ if (GETPOST('code')) { // We are coming from oauth provider page.
} else {
// This was a callback request from service, get the token
try {
- //var_dump($_GET['code']);
//var_dump($state);
//var_dump($apiService); // OAuth\OAuth2\Service\Google
@@ -193,7 +192,7 @@ if (GETPOST('code')) { // We are coming from oauth provider page.
}
}
} else {
- // If we enter this page without 'code' parameter, we arrive here. this is the case when we want to get the redirect
+ // If we enter this page without 'code' parameter, we arrive here. This is the case when we want to get the redirect
// to the OAuth provider login page.
$_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl;
$_SESSION["oauthkeyforproviderbeforeoauthjump"] = $keyforprovider;
@@ -218,6 +217,8 @@ if (GETPOST('code')) { // We are coming from oauth provider page.
//$url .= 'hd=xxx';
}
+ //var_dump($url);exit;
+
// we go on oauth provider authorization page
header('Location: '.$url);
exit();
diff --git a/htdocs/core/modules/oauth/microsoft_oauthcallback.php b/htdocs/core/modules/oauth/microsoft_oauthcallback.php
new file mode 100644
index 00000000000..bf057676cf3
--- /dev/null
+++ b/htdocs/core/modules/oauth/microsoft_oauthcallback.php
@@ -0,0 +1,214 @@
+
+ * Copyright (C) 2015 Frederic France
+ *
+ * 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 .
+ */
+
+/**
+ * \file htdocs/core/modules/oauth/microsoft_oauthcallback.php
+ * \ingroup oauth
+ * \brief Page to get oauth callback
+ */
+
+// Load Dolibarr environment
+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', 'aZ09');
+$backtourl = GETPOST('backtourl', 'alpha');
+$keyforprovider = GETPOST('keyforprovider', 'aZ09');
+if (empty($keyforprovider) && !empty($_SESSION["oauthkeyforproviderbeforeoauthjump"]) && (GETPOST('code') || $action == 'delete')) {
+ $keyforprovider = $_SESSION["oauthkeyforproviderbeforeoauthjump"];
+}
+$genericstring = 'MICROSOFT';
+
+
+/**
+ * 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/microsoft_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, $keyforprovider);
+
+// Setup the credentials for the requests
+$keyforparamid = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_ID';
+$keyforparamsecret = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_SECRET';
+$keyforparamtenant = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_TENANT';
+$credentials = new Credentials(
+ getDolGlobalString($keyforparamid),
+ getDolGlobalString($keyforparamsecret),
+ $currentUri->getAbsoluteUri()
+);
+
+$state = GETPOST('state');
+
+$requestedpermissionsarray = array();
+if ($state) {
+ $requestedpermissionsarray = explode(',', $state); // Example: 'user'. '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
+// ucfirst(strtolower($genericstring)) must be the name of a class into OAuth/OAuth2/Services/Xxxx
+// $requestedpermissionsarray contains list of scopes.
+// Conversion into URL is done by Reflection on constant with name SCOPE_scope_in_uppercase
+try {
+ $apiService = $serviceFactory->createService(ucfirst(strtolower($genericstring)), $credentials, $storage, $requestedpermissionsarray);
+} catch (Exception $e) {
+ print $e->getMessage();
+ exit;
+}
+/*
+var_dump($genericstring.($keyforprovider ? '-'.$keyforprovider : ''));
+var_dump($credentials);
+var_dump($storage);
+var_dump($requestedpermissionsarray);
+*/
+
+if (empty($apiService)) {
+ print 'Error, failed to create serviceFactory';
+ exit;
+}
+
+// access type needed to have oauth provider refreshing token
+//$apiService->setAccessType('offline');
+
+$langs->load("oauth");
+
+if (!getDolGlobalString($keyforparamid)) {
+ accessforbidden('Setup of service is not complete. Customer ID is missing');
+}
+if (!getDolGlobalString($keyforparamsecret)) {
+ accessforbidden('Setup of service is not complete. Secret key is missing');
+}
+
+
+/*
+ * Actions
+ */
+
+if ($action == 'delete') {
+ $storage->clearToken($genericstring);
+
+ setEventMessages($langs->trans('TokenDeleted'), null, 'mesgs');
+
+ header('Location: '.$backtourl);
+ exit();
+}
+
+//dol_syslog("GET=".join(',', $_GET));
+
+
+if (GETPOST('code') || GETPOST('error')) { // We are coming from oauth provider page
+ // We should have
+ //$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16))
+
+ dol_syslog("We are coming from the oauth provider page code=".dol_trunc(GETPOST('code'), 5)." error=".GETPOST('error'));
+
+ // This was a callback request from service, get the token
+ try {
+ //var_dump($state);
+ //var_dump($apiService); // OAuth\OAuth2\Service\Microsoft
+
+ if (GETPOST('error')) {
+ setEventMessages(GETPOST('error').' '.GETPOST('error_description'), null, 'errors');
+ } else {
+ //print GETPOST('code');exit;
+
+ //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ $token = $apiService->requestAccessToken(GETPOST('code'));
+ // Microsoft is a service that does not need state to be stored as second paramater of requestAccessToken
+
+ //print $token->getAccessToken().'
';
+ //print $token->getExtraParams()['id_token'].' ';
+ //print $token->getRefreshToken().' ';exit;
+
+ setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
+ }
+
+ $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"];
+ unset($_SESSION["backtourlsavedbeforeoauthjump"]);
+
+ header('Location: '.$backtourl);
+ exit();
+ } catch (Exception $e) {
+ print $e->getMessage();
+ }
+} else {
+ // If we enter this page without 'code' parameter, we arrive here. This is the case when we want to get the redirect
+ // to the OAuth provider login page.
+ $_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl;
+ $_SESSION["oauthkeyforproviderbeforeoauthjump"] = $keyforprovider;
+ $_SESSION['oauthstateanticsrf'] = $state;
+
+ //if (!preg_match('/^forlogin/', $state)) {
+ // $apiService->setApprouvalPrompt('auto');
+ //}
+
+ // 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 ($state) {
+ $url = $apiService->getAuthorizationUri(array('state' => $state));
+ } else {
+ $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated
+ }
+
+ // Show url to get authorization
+ //var_dump((string) $url);exit;
+ dol_syslog("Redirect to url=".$url);
+
+ // 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/stripelive_oauthcallback.php b/htdocs/core/modules/oauth/stripelive_oauthcallback.php
index ef35b6573cc..bc16b44461a 100644
--- a/htdocs/core/modules/oauth/stripelive_oauthcallback.php
+++ b/htdocs/core/modules/oauth/stripelive_oauthcallback.php
@@ -65,7 +65,7 @@ $httpClient = new \OAuth\Common\Http\Client\CurlClient();
$serviceFactory->setHttpClient($httpClient);
// Dolibarr storage
-$storage = new DoliStorage($db, $conf);
+$storage = new DoliStorage($db, $conf, $keyforprovider);
// Setup the credentials for the requests
$keyforparamid = 'OAUTH_STRIPE_LIVE'.($keyforprovider ? '-'.$keyforprovider : '').'_ID';
@@ -121,33 +121,20 @@ if ($action == 'delete') {
exit();
}
-if (!empty($_GET['code'])) { // We are coming from oauth provider page
+if (GETPOST('code')) { // We are coming from oauth provider page
// We should have
//$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16))
- dol_syslog("We are coming from the oauth provider page");
- //llxHeader('',$langs->trans("OAuthSetup"));
-
- //$linkback=''.$langs->trans("BackToModuleList").'';
- //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
-
- //print dol_get_fiche_head();
- // retrieve the CSRF state parameter
- $state = isset($_GET['state']) ? $_GET['state'] : null;
- //print '
';
+ dol_syslog("We are coming from the oauth provider page code=".dol_trunc(GETPOST('code'), 5));
// 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
+ //var_dump($apiService); // OAuth\OAuth2\Service\Stripe
- //$token = $apiService->requestAccessToken($_GET['code'], $state);
- $token = $apiService->requestAccessToken($_GET['code']);
- // Github is a service that does not need state to 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.
+ //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ $token = $apiService->requestAccessToken(GETPOST('code'));
+ // Stripe is a service that does not need state to be stored as second paramater of requestAccessToken
setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
diff --git a/htdocs/core/modules/oauth/stripetest_oauthcallback.php b/htdocs/core/modules/oauth/stripetest_oauthcallback.php
index a5d481dbef5..12d133da14c 100644
--- a/htdocs/core/modules/oauth/stripetest_oauthcallback.php
+++ b/htdocs/core/modules/oauth/stripetest_oauthcallback.php
@@ -65,7 +65,7 @@ $httpClient = new \OAuth\Common\Http\Client\CurlClient();
$serviceFactory->setHttpClient($httpClient);
// Dolibarr storage
-$storage = new DoliStorage($db, $conf);
+$storage = new DoliStorage($db, $conf, $keyforprovider);
// Setup the credentials for the requests
$keyforparamid = 'OAUTH_STRIPE_TEST'.($keyforprovider ? '-'.$keyforprovider : '').'_ID';
@@ -121,33 +121,20 @@ if ($action == 'delete') {
exit();
}
-if (!empty($_GET['code'])) { // We are coming from oauth provider page
+if (GETPOST('code')) { // We are coming from oauth provider page
// We should have
//$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16))
- dol_syslog("We are coming from the oauth provider page");
- //llxHeader('',$langs->trans("OAuthSetup"));
-
- //$linkback=''.$langs->trans("BackToModuleList").'';
- //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
-
- //print dol_get_fiche_head();
- // retrieve the CSRF state parameter
- $state = isset($_GET['state']) ? $_GET['state'] : null;
- //print '
';
+ dol_syslog("We are coming from the oauth provider page code=".dol_trunc(GETPOST('code'), 5));
// 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
+ //var_dump($apiService); // OAuth\OAuth2\Service\Stripe
- //$token = $apiService->requestAccessToken($_GET['code'], $state);
- $token = $apiService->requestAccessToken($_GET['code']);
- // Github is a service that does not need state to 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.
+ //$token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ $token = $apiService->requestAccessToken(GETPOST('code'));
+ // Stripe is a service that does not need state to be stored as second paramater of requestAccessToken
setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
diff --git a/htdocs/core/modules/printing/printgcp.modules.php b/htdocs/core/modules/printing/printgcp.modules.php
index c04d3ac9ca5..c1b6ba6c86e 100644
--- a/htdocs/core/modules/printing/printgcp.modules.php
+++ b/htdocs/core/modules/printing/printgcp.modules.php
@@ -116,10 +116,12 @@ class printing_printgcp extends PrintingDriver
'type'=>'info',
);
} else {
+ $keyforprovider = ''; // @FIXME
+
$this->google_id = getDolGlobalString('OAUTH_GOOGLE_ID');
$this->google_secret = getDolGlobalString('OAUTH_GOOGLE_SECRET');
// Token storage
- $storage = new DoliStorage($this->db, $this->conf);
+ $storage = new DoliStorage($this->db, $this->conf, $keyforprovider);
//$storage->clearToken($this->OAUTH_SERVICENAME_GOOGLE);
// Setup the credentials for the requests
$credentials = new Credentials(
@@ -254,8 +256,11 @@ class printing_printgcp extends PrintingDriver
public function getlistAvailablePrinters()
{
$ret = array();
+
+ $keyforprovider = ''; // @FIXME
+
// Token storage
- $storage = new DoliStorage($this->db, $this->conf);
+ $storage = new DoliStorage($this->db, $this->conf, $keyforprovider);
// Setup the credentials for the requests
$credentials = new Credentials(
$this->google_id,
@@ -392,8 +397,11 @@ class printing_printgcp extends PrintingDriver
'content' => base64_encode($contents), // encode file content as base64
'contentType' => $contenttype,
);
+
+ $keyforprovider = ''; // @FIXME
+
// Dolibarr Token storage
- $storage = new DoliStorage($this->db, $this->conf);
+ $storage = new DoliStorage($this->db, $this->conf, $keyforprovider);
// Setup the credentials for the requests
$credentials = new Credentials(
$this->google_id,
@@ -441,8 +449,11 @@ class printing_printgcp extends PrintingDriver
$error = 0;
$html = '';
+
+ $keyforprovider = ''; // @FIXME
+
// Token storage
- $storage = new DoliStorage($this->db, $this->conf);
+ $storage = new DoliStorage($this->db, $this->conf, $keyforprovider);
// Setup the credentials for the requests
$credentials = new Credentials(
$this->google_id,
diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php
index 2c23f6e0475..0168d8f86c6 100644
--- a/htdocs/emailcollector/class/emailcollector.class.php
+++ b/htdocs/emailcollector/class/emailcollector.class.php
@@ -1082,10 +1082,13 @@ class EmailCollector extends CommonObject
//$debugtext = "Host: ".$this->host." Port: ".$this->port." Login: ".$this->login." Password: ".$this->password." access type: ".$this->acces_type." oauth service: ".$this->oauth_service." Max email per collect: ".$this->maxemailpercollect;
//dol_syslog($debugtext);
- $storage = new DoliStorage($db, $conf);
+ $token = '';
+
+ $storage = new DoliStorage($db, $conf, $keyforprovider);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
+
$expire = true;
// Is token expired or will token expire in the next 30 seconds
// if (is_object($tokenobj)) {
@@ -1122,7 +1125,6 @@ class EmailCollector extends CommonObject
return -1;
}
-
$cm = new ClientManager();
$client = $cm->make([
'host' => $this->host,
diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php
index 08ecd37f995..80f167057df 100644
--- a/htdocs/filefunc.inc.php
+++ b/htdocs/filefunc.inc.php
@@ -206,7 +206,7 @@ include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
// when we post forms (we allow GET and HEAD to accept direct link from a particular page).
// Note about $_SERVER[HTTP_HOST/SERVER_NAME]: http://shiflett.org/blog/2006/mar/server-name-versus-http-host
// See also CSRF protections done into main.inc.php
-if (!defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck)) {
+if (!defined('NOCSRFCHECK') && isset($dolibarr_nocsrfcheck) && $dolibarr_nocsrfcheck == 1) { // If $dolibarr_nocsrfcheck is 0, there is a strict CSRF test with token in main
if (!empty($_SERVER['REQUEST_METHOD']) && !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')) && !empty($_SERVER['HTTP_HOST'])) {
$csrfattack = false;
if (empty($_SERVER['HTTP_REFERER'])) {
diff --git a/htdocs/includes/OAuth/Common/Http/Client/StreamClient.php b/htdocs/includes/OAuth/Common/Http/Client/StreamClient.php
index d81fee88202..9849afd4a32 100644
--- a/htdocs/includes/OAuth/Common/Http/Client/StreamClient.php
+++ b/htdocs/includes/OAuth/Common/Http/Client/StreamClient.php
@@ -57,6 +57,7 @@ class StreamClient extends AbstractClient
}
$extraHeaders['Content-length'] = 'Content-length: '.strlen($requestBody);
+ //var_dump($requestBody); var_dump($extraHeaders);var_dump($method);exit;
$context = $this->generateStreamContext($requestBody, $extraHeaders, $method);
$level = error_reporting(0);
diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
index 3e09e53fbe6..60af1f631c6 100644
--- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
+++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
@@ -57,6 +57,8 @@ class DoliStorage implements TokenStorageInterface
private $key;
//private $stateKey;
private $keyforprovider;
+ public $token;
+ private $tenant;
public $state;
public $date_creation;
@@ -73,6 +75,7 @@ class DoliStorage implements TokenStorageInterface
$this->db = $db;
$this->conf = $conf;
$this->keyforprovider = $keyforprovider;
+ $this->token = '';
$this->tokens = array();
$this->states = array();
//$this->key = $key;
@@ -96,7 +99,7 @@ class DoliStorage implements TokenStorageInterface
/**
* {@inheritDoc}
*/
- public function storeAccessToken($service, TokenInterface $token)
+ public function storeAccessToken($service, TokenInterface $tokenobj)
{
global $conf;
@@ -104,16 +107,25 @@ class DoliStorage implements TokenStorageInterface
//var_dump($token);
dol_syslog("storeAccessToken service=".$service);
- include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
- $serializedToken = dolEncrypt(serialize($token));
+ $servicepluskeyforprovider = $service;
+ if (!empty($this->keyforprovider)) {
+ // We clean the keyforprovider after the - to be sure it is not present
+ $servicepluskeyforprovider = preg_replace('/\-'.preg_quote($this->keyforprovider, '/').'$/', '', $servicepluskeyforprovider);
+ // Now we add the keyforprovider
+ $servicepluskeyforprovider .= '-'.$this->keyforprovider;
+ }
- $this->tokens[$service] = $token;
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
+ $serializedToken = serialize($tokenobj);
if (!is_array($this->tokens)) {
$this->tokens = array();
}
+
+ $this->tokens[$service] = $tokenobj;
+
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."oauth_token";
- $sql .= " WHERE service = '".$this->db->escape($service.($this->keyforprovider?'-'.$this->keyforprovider:''))."'";
+ $sql .= " WHERE service = '".$this->db->escape($servicepluskeyforprovider)."'";
$sql .= " AND entity IN (".getEntity('oauth_token').")";
$resql = $this->db->query($sql);
if (! $resql) {
@@ -123,16 +135,22 @@ class DoliStorage implements TokenStorageInterface
if ($obj) {
// update
$sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token";
- $sql.= " SET token = '".$this->db->escape($serializedToken)."'";
+ $sql.= " SET token = '".$this->db->escape(dolEncrypt($serializedToken))."'";
$sql.= " WHERE rowid = ".((int) $obj['rowid']);
$resql = $this->db->query($sql);
+ if (!$resql) {
+ dol_print_error($this->db);
+ }
} else {
// save
$sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, token, entity, datec)";
- $sql .= " VALUES ('".$this->db->escape($service.($this->keyforprovider?'-'.$this->keyforprovider:''))."', '".$this->db->escape($serializedToken)."', ".((int) $conf->entity).", ";
+ $sql .= " VALUES ('".$this->db->escape($servicepluskeyforprovider)."', '".$this->db->escape(dolEncrypt($serializedToken))."', ".((int) $conf->entity).", ";
$sql .= " '".$this->db->idate(dol_now())."'";
$sql .= ")";
$resql = $this->db->query($sql);
+ if (!$resql) {
+ dol_print_error($this->db);
+ }
}
//print $sql;
@@ -141,15 +159,26 @@ class DoliStorage implements TokenStorageInterface
}
/**
- * {@inheritDoc}
+ * Load token and other data from a $service
+ * Note: Token load are cumulated into array ->tokens when other properties are erased by last loaded token.
+ *
+ * @return void
*/
public function hasAccessToken($service)
{
// get from db
dol_syslog("hasAccessToken service=".$service);
+ $servicepluskeyforprovider = $service;
+ if (!empty($this->keyforprovider)) {
+ // We clean the keyforprovider after the - to be sure it is not present
+ $servicepluskeyforprovider = preg_replace('/\-'.preg_quote($this->keyforprovider, '/').'$/', '', $servicepluskeyforprovider);
+ // Now we add the keyforprovider
+ $servicepluskeyforprovider .= '-'.$this->keyforprovider;
+ }
+
$sql = "SELECT token, datec, tms, state FROM ".MAIN_DB_PREFIX."oauth_token";
- $sql .= " WHERE service = '".$this->db->escape($service.(empty($this->keyforprovider) ? '' : '-'.$this->keyforprovider))."'";
+ $sql .= " WHERE service = '".$this->db->escape($servicepluskeyforprovider)."'";
$sql .= " AND entity IN (".getEntity('oauth_token').")";
$resql = $this->db->query($sql);
if (! $resql) {
@@ -158,18 +187,20 @@ class DoliStorage implements TokenStorageInterface
$result = $this->db->fetch_array($resql);
if ($result) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
- $token = unserialize(dolDecrypt($result['token']));
+ $tokenobj = unserialize(dolDecrypt($result['token']));
+ $this->token = dolDecrypt($result['token']);
$this->date_creation = $this->db->jdate($result['datec']);
$this->date_modification = $this->db->jdate($result['tms']);
$this->state = $result['state'];
} else {
- $token = '';
+ $tokenobj = '';
+ $this->token = '';
$this->date_creation = null;
$this->date_modification = null;
$this->state = '';
}
- $this->tokens[$service] = $token;
+ $this->tokens[$service] = $tokenobj;
return is_array($this->tokens)
&& isset($this->tokens[$service])
@@ -325,4 +356,18 @@ class DoliStorage implements TokenStorageInterface
// allow chaining
return $this;
}
+
+ /**
+ * Return the token
+ *
+ * @return string String for the tenant used to create the token
+ */
+ public function getTenant()
+ {
+ // Set/Reset tenant now so it will be defined for.
+ // TODO We must store it into the table llx_oauth_token
+ $this->tenant = getDolGlobalString('OAUTH_MICROSOFT'.($this->keyforprovider ? '-'.$this->keyforprovider : '').'_TENANT');
+
+ return $this->tenant;
+ }
}
diff --git a/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php b/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
index 996506afbec..b6f89118d83 100644
--- a/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
+++ b/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
@@ -56,8 +56,8 @@ abstract class AbstractService extends BaseAbstractService implements ServiceInt
$this->stateParameterInAuthUrl = $stateParameterInAutUrl;
foreach ($scopes as $scope) {
- if (!$this->isValidScope($scope)) {
- throw new InvalidScopeException('Scope ' . $scope . ' is not valid for service ' . get_class($this));
+ if (!$this->isValidScope($scope)) {
+ throw new InvalidScopeException('Scope ' . $scope . ' is not valid for service ' . get_class($this));
}
}
@@ -223,6 +223,8 @@ abstract class AbstractService extends BaseAbstractService implements ServiceInt
$parameters,
$this->getExtraOAuthHeaders()
);
+ //print $responseBody;exit; // We must have a result "{"token_type":"Bearer","scope...
+
$token = $this->parseAccessTokenResponse($responseBody);
$this->storage->storeAccessToken($this->service(), $token);
diff --git a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php
index c815b22bd44..6c3b18b3c0f 100644
--- a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php
+++ b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php
@@ -12,30 +12,40 @@ use OAuth\Common\Http\Uri\UriInterface;
class Microsoft extends AbstractService
{
- const SCOPE_BASIC = 'wl.basic';
- const SCOPE_OFFLINE = 'wl.offline_access';
- const SCOPE_SIGNIN = 'wl.signin';
- const SCOPE_BIRTHDAY = 'wl.birthday';
- const SCOPE_CALENDARS = 'wl.calendars';
- const SCOPE_CALENDARS_UPDATE = 'wl.calendars_update';
- const SCOPE_CONTACTS_BIRTHDAY = 'wl.contacts_birthday';
- const SCOPE_CONTACTS_CREATE = 'wl.contacts_create';
- const SCOPE_CONTACTS_CALENDARS = 'wl.contacts_calendars';
- const SCOPE_CONTACTS_PHOTOS = 'wl.contacts_photos';
- const SCOPE_CONTACTS_SKYDRIVE = 'wl.contacts_skydrive';
- const SCOPE_EMAILS = 'wl.emails';
- const SCOPE_EVENTS_CREATE = 'wl.events_create';
- const SCOPE_MESSENGER = 'wl.messenger';
- const SCOPE_PHONE_NUMBERS = 'wl.phone_numbers';
- const SCOPE_PHOTOS = 'wl.photos';
- const SCOPE_POSTAL_ADDRESSES = 'wl.postal_addresses';
- const SCOPE_SHARE = 'wl.share';
- const SCOPE_SKYDRIVE = 'wl.skydrive';
- const SCOPE_SKYDRIVE_UPDATE = 'wl.skydrive_update';
- const SCOPE_WORK_PROFILE = 'wl.work_profile';
- const SCOPE_APPLICATIONS = 'wl.applications';
- const SCOPE_APPLICATIONS_CREATE = 'wl.applications_create';
- const SCOPE_IMAP = 'wl.imap';
+ const SCOPE_BASIC = 'basic';
+ const SCOPE_OFFLINE_ACCESS = 'offline_access';
+ const SCOPE_SIGNIN = 'signin';
+ const SCOPE_BIRTHDAY = 'birthday';
+ const SCOPE_CALENDARS = 'calendars';
+ const SCOPE_CALENDARS_UPDATE = 'calendars_update';
+ const SCOPE_CONTACTS_BIRTHDAY = 'contacts_birthday';
+ const SCOPE_CONTACTS_CREATE = 'contacts_create';
+ const SCOPE_CONTACTS_CALENDARS = 'contacts_calendars';
+ const SCOPE_CONTACTS_PHOTOS = 'contacts_photos';
+ const SCOPE_CONTACTS_SKYDRIVE = 'contacts_skydrive';
+ const SCOPE_EMAIL = 'email';
+ const SCOPE_EVENTS_CREATE = 'events_create';
+ const SCOPE_MESSENGER = 'messenger';
+ const SCOPE_OPENID = 'openid';
+ const SCOPE_PHONE_NUMBERS = 'phone_numbers';
+ const SCOPE_PHOTOS = 'photos';
+ const SCOPE_POSTAL_ADDRESSES = 'postal_addresses';
+ const SCOPE_PROFILE = 'profile';
+ const SCOPE_SHARE = 'share';
+ const SCOPE_SKYDRIVE = 'skydrive';
+ const SCOPE_SKYDRIVE_UPDATE = 'skydrive_update';
+ const SCOPE_WORK_PROFILE = 'work_profile';
+ const SCOPE_APPLICATIONS = 'applications';
+ const SCOPE_APPLICATIONS_CREATE = 'applications_create';
+ const SCOPE_IMAP = 'imap';
+ const SOCPE_IMAP_ACCESSASUSERALL = 'https://outlook.office365.com/IMAP.AccessAsUser.All';
+ const SOCPE_SMTPSEND = 'https://outlook.office365.com/SMTP.Send';
+ const SOCPE_USERREAD = 'User.Read';
+ const SOCPE_MAILREAD = 'Mail.Read';
+ const SOCPE_MAILSEND = 'Mail.Send';
+
+ protected $storage;
+
/**
* MS uses some magical not officialy supported scope to get even moar info like full emailaddresses.
@@ -48,7 +58,8 @@ class Microsoft extends AbstractService
*
* Considering this scope is not officially supported: use with care
*/
- const SCOPE_CONTACTS_EMAILS = 'wl.contacts_emails';
+ const SCOPE_CONTACTS_EMAILS = 'contacts_emails';
+
public function __construct(
CredentialsInterface $credentials,
@@ -59,6 +70,8 @@ class Microsoft extends AbstractService
) {
parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri);
+ $this->storage = $storage;
+
if (null === $baseApiUri) {
$this->baseApiUri = new Uri('https://apis.live.net/v5.0/');
}
@@ -69,7 +82,11 @@ class Microsoft extends AbstractService
*/
public function getAuthorizationEndpoint()
{
- return new Uri('https://login.live.com/oauth20_authorize.srf');
+ $tenant = $this->storage->getTenant();
+
+ //return new Uri('https://login.live.com/oauth20_authorize.srf');
+ //return new Uri('https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize');
+ return new Uri('https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/authorize');
}
/**
@@ -77,7 +94,11 @@ class Microsoft extends AbstractService
*/
public function getAccessTokenEndpoint()
{
- return new Uri('https://login.live.com/oauth20_token.srf');
+ $tenant = $this->storage->getTenant();
+
+ //return new Uri('https://login.live.com/oauth20_token.srf');
+ //return new Uri('https://login.microsoftonline.com/organizations/oauth2/v2.0/token');
+ return new Uri('https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/token');
}
/**
@@ -100,6 +121,7 @@ class Microsoft extends AbstractService
} elseif (isset($data['error'])) {
throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"');
}
+ //print $data['access_token'];exit;
$token = new StdOAuth2Token();
$token->setAccessToken($data['access_token']);
diff --git a/htdocs/includes/webklex/php-imap/src/Client.php b/htdocs/includes/webklex/php-imap/src/Client.php
index 15944e4c646..85c537f16fa 100755
--- a/htdocs/includes/webklex/php-imap/src/Client.php
+++ b/htdocs/includes/webklex/php-imap/src/Client.php
@@ -353,6 +353,7 @@ class Client {
} catch (Exceptions\RuntimeException $e) {
throw new ConnectionFailedException("connection setup failed - run exception", 0, $e);
}
+
$this->authenticate();
return $this;
diff --git a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php
index ef01d46ec9b..6087ac55b75 100644
--- a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php
+++ b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php
@@ -190,7 +190,7 @@ abstract class Protocol implements ProtocolInterface {
STREAM_CLIENT_CONNECT,
stream_context_create($this->defaultSocketOptions($transport))
);
- stream_set_timeout($stream, $timeout);
+ //stream_set_timeout($stream, $timeout); // Hang id $strem empty and already done line 199
if (!$stream) {
throw new ConnectionFailedException($errstr, $errno);
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 28d2c7593fc..f20065556bf 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -451,7 +451,7 @@ ExtrafieldCheckBox=Checkboxes
ExtrafieldCheckBoxFromList=Checkboxes from table
ExtrafieldLink=Link to an object
ComputedFormula=Computed field
-ComputedFormulaDesc=You can enter here a formula using other properties of object or any PHP coding to get a dynamic computed value. You can use any PHP compatible formulas including the "?" condition operator, and following global object: $db, $conf, $langs, $mysoc, $user, $object. WARNING: Only some properties of $object may be available. If you need a properties not loaded, just fetch yourself the object into your formula like in the second example. Using a computed field means you can't enter yourself any value from interface. Also, if there is a syntax error, the formula may return nothing.
Example to reload object (($reloadedobj = new Societe($db)) && ($reloadedobj->fetchNoCompute($obj->id ? $obj->id: ($obj->rowid ? $obj->rowid: $object->id)) > 0)) ? $reloadedobj->array_options['options_extrafieldkey'] * $reloadedobj->capital / 5: '-1'
Other example of formula to force load of object and its parent object: (($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref: 'Parent project not found'
+ComputedFormulaDesc=You can enter here a formula using other properties of object or any PHP coding to get a dynamic computed value. You can use any PHP compatible formulas including the "?" condition operator, and following global object: $db, $conf, $langs, $mysoc, $user, $objectoffield. WARNING: If you need properties of an object not loaded, just fetch yourself the object into your formula like in the second example. Using a computed field means you can't enter yourself any value from interface. Also, if there is a syntax error, the formula may return nothing.
Example to reload object (($reloadedobj = new Societe($db)) && ($reloadedobj->fetchNoCompute($objectoffield->id) > 0 ? $reloadedobj->array_options['options_extrafieldkey'] * $reloadedobj->capital / 5: '-1')
Other example of formula to force load of object and its parent object: (($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($objectoffield->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref: 'Parent project not found'
Computedpersistent=Store computed field
ComputedpersistentDesc=Computed extra fields will be stored in the database, however, the value will only be recalculated when the object of this field is changed. If the computed field depends on other objects or global data this value might be wrong!!
ExtrafieldParamHelpPassword=Leaving this field blank means this value will be stored without encryption (field must be only hidden with star on screen). Set 'auto' to use the default encryption rule to save password into database (then value read will be the hash only, no way to retrieve original value)
@@ -700,6 +700,8 @@ Module62000Name=Incoterms
Module62000Desc=Add features to manage Incoterms
Module63000Name=Resources
Module63000Desc=Manage resources (printers, cars, rooms, ...) for allocating to events
+Module66000Name=Enable OAuth2 authentication
+Module66000Desc=Provide a tool to generate and manage OAuth2 tokens. The token can then be used by some other modules.
Module94160Name=Receptions
Permission11=Read customer invoices
Permission12=Create/modify customer invoices
@@ -2348,3 +2350,5 @@ AllowExternalDownload=Allow external download (without login, using a shared lin
DeadlineDayVATSubmission=Deadline day for vat submission on the next month
MaxNumberOfAttachementOnForms=Max number of joinded files in a form
IfDefinedUseAValueBeetween=If defined, use a value between %s and %s
+EMailsInGoingDesc=Incoming emails are managed by the module %s. You must enable and configure it if you need to support ingoing emails.
+MAIN_IMAP_USE_PHPIMAP=Use the PHP-IMAP library for IMAP instead of native PHP IMAP. This also allows the use of an OAuth2 connection for IMAP (module OAuth must also be activated).
diff --git a/htdocs/langs/en_US/oauth.lang b/htdocs/langs/en_US/oauth.lang
index 01bb08e38bd..9d4791a9f63 100644
--- a/htdocs/langs/en_US/oauth.lang
+++ b/htdocs/langs/en_US/oauth.lang
@@ -31,8 +31,9 @@ OAUTH_GITHUB_SECRET=OAuth GitHub Secret
OAUTH_URL_FOR_CREDENTIAL=Go to this page to create or get your OAuth ID and Secret
OAUTH_STRIPE_TEST_NAME=OAuth Stripe Test
OAUTH_STRIPE_LIVE_NAME=OAuth Stripe Live
-OAUTH_ID=OAuth ID
+OAUTH_ID=OAuth Client ID
OAUTH_SECRET=OAuth secret
+OAUTH_TENANT=OAuth tenant
OAuthProviderAdded=OAuth provider added
AOAuthEntryForThisProviderAndLabelAlreadyHasAKey=An OAuth entry for this provider and label already exists
URLOfServiceForAuthorization=URL provided by OAuth service for authentication
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index b01db102bff..1dd9eb35c04 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -501,7 +501,7 @@ if ((!empty($conf->global->MAIN_VERSION_LAST_UPGRADE) && ($conf->global->MAIN_VE
// Creation of a token against CSRF vulnerabilities
if (!defined('NOTOKENRENEWAL') && !defined('NOSESSION')) {
- // No token renewal on .css.php, .js.php and .json.php
+ // No token renewal on .css.php, .js.php and .json.php (even if the NOTOKENRENEWAL was not provided)
if (!preg_match('/\.(css|js|json)\.php$/', $_SERVER["PHP_SELF"])) {
// Rolling token at each call ($_SESSION['token'] contains token of previous page)
if (isset($_SESSION['newtoken'])) {
@@ -1561,7 +1561,8 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr
print ''."\n"; // Do not index
print ''."\n"; // Scale for mobile device
print ''."\n";
- print ''."\n";
+ print ''."\n";
+ print ''."\n";
if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) {
print ''."\n";
}
diff --git a/htdocs/printing/admin/printing.php b/htdocs/printing/admin/printing.php
index fb8426abc1b..ed856024d63 100644
--- a/htdocs/printing/admin/printing.php
+++ b/htdocs/printing/admin/printing.php
@@ -201,13 +201,15 @@ if ($mode == 'setup' && $user->admin) {
$i++;
if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS') {
+ $keyforprovider = ''; // @BUG This must be set
+
// Token
print '