diff --git a/ChangeLog b/ChangeLog index 584b7c1ee0c..b8a3fea2ce9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,7 +21,7 @@ Following changes may create regressions for some external modules, but were nec * The hook "moreFamily" must return payment into var "totalpayment" and no more "paiement" (english replace french). * Removed deprecated method actioncomm->add(), use create() instead * If you have developed your own emailing target selector and used parent::add_to_target(...), you must now use parent::addToTargets(...) - +* Removed function dol_micro_time. Use native PHP microtime instead. ***** ChangeLog for 10.0.2 compared to 10.0.1 ***** diff --git a/htdocs/admin/ldap_groups.php b/htdocs/admin/ldap_groups.php index 450fec88ad0..8ae918ce180 100644 --- a/htdocs/admin/ldap_groups.php +++ b/htdocs/admin/ldap_groups.php @@ -58,6 +58,7 @@ if ($action == 'setvalue' && $user->admin) //if (! dolibarr_set_const($db, 'LDAP_GROUP_FIELD_NAME',$_POST["fieldname"],'chaine',0,'',$conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_GROUP_FIELD_DESCRIPTION', GETPOST("fielddescription"), 'chaine', 0, '', $conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_GROUP_FIELD_GROUPMEMBERS', GETPOST("fieldgroupmembers"), 'chaine', 0, '', $conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_GROUP_FIELD_GROUPID', GETPOST("fieldgroupid"), 'chaine', 0, '', $conf->entity)) $error++; // This one must be after the others $valkey=''; @@ -170,6 +171,13 @@ print ''.$langs->trans("LDAPFieldGroupMembersExample").''; print 'global->LDAP_KEY_GROUPS && $conf->global->LDAP_KEY_GROUPS==$conf->global->LDAP_GROUP_FIELD_GROUPMEMBERS)?' checked':'').">"; print ''; +// Group id +print ''.$langs->trans("LDAPFieldGroupid").''; +print ''; +print ''.$langs->trans("LDAPFieldGroupidExample").''; +print ' '; +print ''; + print ''; print info_admin($langs->trans("LDAPDescValues")); diff --git a/htdocs/admin/ldap_users.php b/htdocs/admin/ldap_users.php index 4148d81f438..394451c9472 100644 --- a/htdocs/admin/ldap_users.php +++ b/htdocs/admin/ldap_users.php @@ -5,6 +5,7 @@ * Copyright (C) 2005 Regis Houssin * Copyright (C) 2006-2011 Laurent Destailleur * Copyright (C) 2011-2016 Juanjo Menent + * Copyright (C) 2019 Abbes Bahfir * * 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 @@ -73,6 +74,10 @@ if ($action == 'setvalue' && $user->admin) if (! dolibarr_set_const($db, 'LDAP_FIELD_DESCRIPTION', GETPOST("fielddescription"), 'chaine', 0, '', $conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_FIELD_SID', GETPOST("fieldsid"), 'chaine', 0, '', $conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_FIELD_TITLE', GETPOST("fieldtitle"), 'chaine', 0, '', $conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_FIELD_GROUPID', GETPOST("fieldgroupid"), 'chaine', 0, '', $conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_FIELD_USERID', GETPOST("fielduserid"), 'chaine', 0, '', $conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_FIELD_HOMEDIRECTORY', GETPOST("fieldhomedirectory"), 'chaine', 0, '', $conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_FIELD_HOMEDIRECTORYPREFIX', GETPOST("fieldhomedirectoryprefix"), 'chaine', 0, '', $conf->entity)) $error++; // This one must be after the others $valkey=''; @@ -301,6 +306,34 @@ print ''.$langs->trans("LDAPFieldSidExample").''; print 'global->LDAP_KEY_USERS && $conf->global->LDAP_KEY_USERS==$conf->global->LDAP_FIELD_SID)?' checked':'').">"; print ''; +// Group id +print ''.$langs->trans("LDAPFieldGroupid").''; +print ''; +print ''.$langs->trans("LDAPFieldGroupidExample").''; +print ' '; +print ''; + +// Userid +print ''.$langs->trans("LDAPFieldUserid").''; +print ''; +print ''.$langs->trans("LDAPFieldUseridExample").''; +print ' '; +print ''; + +// Home Directory +print ''.$langs->trans("LDAPFieldHomedirectory").''; +print ''; +print ''.$langs->trans("LDAPFieldHomedirectoryExample").''; +print ' '; +print ''; + +// Home Directory Prefix +print ''.$langs->trans("LDAPFieldHomedirectoryprefix").''; +print ''; +print ''; +print ' '; +print ''; + print ''; print info_admin($langs->trans("LDAPDescValues")); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d8a4d40d20f..738786a6b91 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4909,13 +4909,12 @@ abstract class CommonObject if (! is_array($optionsArray)) { // If $extrafields is not a known object, we initialize it. Best practice is to have $extrafields defined into card.php or list.php page. - // TODO Use of existing $extrafield is not yet ready (must mutualize code that use extrafields in form first) - // global $extrafields; - //if (! is_object($extrafields)) - //{ + global $extrafields; + if (! isset($extrafields) || ! is_object($extrafields)) + { require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $extrafields = new ExtraFields($this->db); - //} + } // Load array of extrafields for elementype = $this->table_element if (empty($extrafields->attributes[$this->table_element]['loaded'])) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 1d1a6122288..267949e2149 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -609,7 +609,7 @@ class Ldap } if ($result <= 0) { - $this->error = ldap_errno($this->connection)." ".ldap_error($this->connection)." ".$this->error; + $this->error = ldap_error($this->connection).' (Code '.ldap_errno($this->connection).") ".$this->error; dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR); //print_r($info); return -1; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9bb4c239663..d0b724bbf8e 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5779,20 +5779,6 @@ function dol_nboflines_bis($text, $maxlinesize = 0, $charset = 'UTF-8') return $nblines; } -/** - * Same function than microtime in PHP 5 but compatible with PHP4 - * - * @return float Time (millisecondes) with microsecondes in decimal part - * @deprecated Dolibarr does not support PHP4, you should use native function - * @see microtime() - */ -function dol_microtime_float() -{ - dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING); - - return microtime(true); -} - /** * Return if a text is a html content * diff --git a/htdocs/core/triggers/interface_50_modIFTTT_IFTTT.class.php b/htdocs/core/triggers/interface_50_modIFTTT_IFTTT.class.php deleted file mode 100644 index c7ce8f121fc..00000000000 --- a/htdocs/core/triggers/interface_50_modIFTTT_IFTTT.class.php +++ /dev/null @@ -1,147 +0,0 @@ - - * 2016 Christophe Battarel - * - * 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/triggers/interface_50_modIFTTT_IFTTT.class.php - * \ingroup core - * \brief File of trigger for IFTTT module - */ -require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; - - -/** - * Class of triggers for IFTTT module - */ -class InterfaceIFTTT extends DolibarrTriggers -{ - /** - * @var DoliDB Database handler. - */ - public $db; - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - $this->db = $db; - - $this->name = preg_replace('/^Interface/i', '', get_class($this)); - $this->family = "ifttt"; - $this->description = "Triggers of the module IFTTT"; - $this->version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' or version - $this->picto = 'ifttt'; - } - - /** - * Return name of trigger file - * - * @return string Name of trigger file - */ - public function getName() - { - return $this->name; - } - - /** - * Return description of trigger file - * - * @return string Description of trigger file - */ - public function getDesc() - { - return $this->description; - } - - /** - * Return version of trigger file - * - * @return string Version of trigger file - */ - public function getVersion() - { - global $langs; - $langs->load("admin"); - - if ($this->version == 'development') { - return $langs->trans("Development"); - } elseif ($this->version == 'experimental') { - return $langs->trans("Experimental"); - } elseif ($this->version == 'dolibarr') { - return DOL_VERSION; - } elseif ($this->version) { - return $this->version; - } else { - return $langs->trans("Unknown"); - } - } - - /** - * Function called when a Dolibarrr business event is done. - * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers - * - * @param string $action Event action code - * @param Object $object Object - * @param User $user Object user - * @param Translate $langs Object langs - * @param conf $conf Object conf - * @return int <0 if KO, 0 if no triggered ran, >0 if OK - */ - public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) - { - $ok = 0; - - if (empty($conf->ifttt->enabled)) return 0; // Module not active, we do nothing - - switch ($action) { - case 'THIRDPARTY_CREATED': - dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); - - include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; - - // See https://platform.ifttt.com/docs/api_reference#realtime-api - - $arrayofdata=array(); - $arrayofdata['user_id']=$conf->global->IFTTT_USER_ID; - $arrayofdata['trigger_identity']=$conf->global->IFTTT_TRIGGER_IDENTITY; - $arrayofdata['name']='testabcdef'; - $arrayofdata['email']='testemailabcdef'; - - $url = 'https://realtime.ifttt.com/v1/notifications'; - - $addheaders=array( - 'IFTTT-Service-Key'=>'123', - 'Accept'=>'application/json', - 'Accept-Charset'=>'utf-8', - 'Accept-Encoding'=>'gzip, deflate', - 'Content-Type'=>'application/json', - 'X-Request-ID'=>getRandomPassword(true, null) - ); - - $result = getURLContent($url, 'POSTALREADYFORMATED', '', 1, $addheaders); - - $ok = 1; - break; - } - - return $ok; - } -} diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index c035adbcd60..a4ae8c15542 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -152,7 +152,7 @@ if (empty($dolibarr_strict_mode)) $dolibarr_strict_mode=0; // For debug in php s // See also option $conf->global->MAIN_SECURITY_CSRF_WITH_TOKEN for a stronger CSRF protection. if (! defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck)) { - if (! empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'GET' && ! empty($_SERVER['HTTP_HOST'])) + if (! empty($_SERVER['REQUEST_METHOD']) && ! in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')) && ! empty($_SERVER['HTTP_HOST'])) { $csrfattack=false; if (empty($_SERVER['HTTP_REFERER'])) $csrfattack=true; // An evil browser was used @@ -165,8 +165,8 @@ if (! defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck)) if ($csrfattack) { //print 'NOCSRFCHECK='.defined('NOCSRFCHECK').' REQUEST_METHOD='.$_SERVER['REQUEST_METHOD'].' HTTP_HOST='.$_SERVER['HTTP_HOST'].' HTTP_REFERER='.$_SERVER['HTTP_REFERER']; - print "Access refused by CSRF protection in main.inc.php. Referer of form is outside server that serve the POST.\n"; - print "If you access your server behind a proxy using url rewriting, you might check that all HTTP header is propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file).\n"; + print "Access refused by CSRF protection in main.inc.php. Referer of form (".$_SERVER['HTTP_REFERER'].") is outside the server that serve this page (with method = ".$_SERVER['REQUEST_METHOD'].").\n"; + print "If you access your server behind a proxy using url rewriting, you might check that all HTTP headers are propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file to remove this security check).\n"; die; } } diff --git a/htdocs/includes/ckeditor/ckeditor/contents.css b/htdocs/includes/ckeditor/ckeditor/contents.css index 7bd09d5552a..933afb9c6f3 100644 --- a/htdocs/includes/ckeditor/ckeditor/contents.css +++ b/htdocs/includes/ckeditor/ckeditor/contents.css @@ -16,7 +16,7 @@ body /* Remove the background color to make it transparent. */ background-color: #fff; - margin: 20px; + margin: 5px; } .cke_editable diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 5fac7433680..08c1069e457 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1459,6 +1459,13 @@ LDAPFieldSidExample=Example: objectsid LDAPFieldEndLastSubscription=Date of subscription end LDAPFieldTitle=Job position LDAPFieldTitleExample=Example: title +LDAPFieldGroupid=Group id +LDAPFieldGroupidExample=Exemple : gidnumber +LDAPFieldUserid=User id +LDAPFieldUseridExample=Exemple : uidnumber +LDAPFieldHomedirectory=Home directory prefix +LDAPFieldHomedirectoryExample=Exemple : homedirectory +LDAPFieldHomedirectoryprefix=Home directory prefix LDAPSetupNotComplete=LDAP setup not complete (go on others tabs) LDAPNoUserOrPasswordProvidedAccessIsReadOnly=No administrator or password provided. LDAP access will be anonymous and in read only mode. LDAPDescContact=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr contacts. diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 3197cc12bca..8e985a793b3 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -150,7 +150,7 @@ OrderCreated=Your orders have been created OrderFail=An error happened during your orders creation CreateOrders=Create orders ToBillSeveralOrderSelectCustomer=To create an invoice for several orders, click first onto customer, then choose "%s". -OptionToSetOrderBilledNotEnabled=Option (from module Workflow) to set order to 'Billed' automatically when invoice is validated is off, so you will have to set status of order to 'Billed' manually. +OptionToSetOrderBilledNotEnabled=Option from module Workflow, to set order to 'Billed' automatically when invoice is validated, is not enabled, so you will have to set the status of orders to 'Billed' manually after the invoice has been generated. IfValidateInvoiceIsNoOrderStayUnbilled=If invoice validation is 'No', the order will remain to status 'Unbilled' until the invoice is validated. CloseReceivedSupplierOrdersAutomatically=Close order to status "%s" automatically if all products are received. SetShippingMode=Set shipping mode diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 20cdc9175d6..ff684f01cb9 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -1458,6 +1458,13 @@ LDAPFieldSidExample=Exemple : objectsid LDAPFieldEndLastSubscription=Date de fin de validité adhésion LDAPFieldTitle=Poste/fonction LDAPFieldTitleExample=Exemple: title +LDAPFieldGroupid=Groupe id +LDAPFieldGroupidExample=Exemple : gidnumber +LDAPFieldUserid=User id +LDAPFieldUseridExample=Exemple : uidnumber +LDAPFieldHomedirectory=Répertoire d'accueil +LDAPFieldHomedirectoryExample=Exemple : homedirectory +LDAPFieldHomedirectoryprefix=Préfixe du répertoire d'accueil LDAPSetupNotComplete=Configuration LDAP incomplète (à compléter sur les autres onglets) LDAPNoUserOrPasswordProvidedAccessIsReadOnly=Administrateur ou mot de passe non renseigné. Les accès LDAP seront donc anonymes et en lecture seule. LDAPDescContact=Cette page permet de définir le nom des attributs de l'arbre LDAP pour chaque information des contacts Dolibarr. diff --git a/htdocs/product/list.php b/htdocs/product/list.php index e7e8f1e4999..d8d9686ae4a 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -57,7 +57,8 @@ $search_label=GETPOST("search_label", 'alpha'); $search_type = GETPOST("search_type", 'int'); $search_sale = GETPOST("search_sale", 'int'); $search_vatrate=GETPOST("search_vatrate", 'alpha'); -$search_categ = GETPOST("search_categ", 'int'); +$searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0); +$searchCategoryProductList = GETPOST('search_category_product_list', 'array'); $search_tosell = GETPOST("search_tosell", 'int'); $search_tobuy = GETPOST("search_tobuy", 'int'); $fourn_id = GETPOST("fourn_id", 'int'); @@ -231,7 +232,8 @@ if (empty($reshook)) $search_ref=""; $search_label=""; $search_barcode=""; - $search_categ=0; + $searchCategoryProductOperator = 0; + $searchCategoryProductList = array(); $search_tosell=""; $search_tobuy=""; $search_vatrate=""; @@ -301,7 +303,7 @@ $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); // $sql.=$hookmanager->resPrint; $sql.= ' FROM '.MAIN_DB_PREFIX.'product as p'; if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_extrafields as ef on (p.rowid = ef.fk_object)"; -if (! empty($search_categ) || ! empty($catid)) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ +if (!empty($searchCategoryProductList) || !empty($catid)) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; // multilang if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang = '".$langs->getDefaultLang() ."'"; @@ -333,8 +335,30 @@ if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); if (dol_strlen($canvas) > 0) $sql.= " AND p.canvas = '".$db->escape($canvas)."'"; if ($catid > 0) $sql.= " AND cp.fk_categorie = ".$catid; if ($catid == -2) $sql.= " AND cp.fk_categorie IS NULL"; -if ($search_categ > 0) $sql.= " AND cp.fk_categorie = ".$db->escape($search_categ); -if ($search_categ == -2) $sql.= " AND cp.fk_categorie IS NULL"; +$searchCategoryProductSqlList = array(); +if ($searchCategoryProductOperator == 1) { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL"; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "cp.fk_categorie = " . $db->escape($searchCategoryProduct); + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (" . implode(' OR ', $searchCategoryProductSqlList) . ")"; + } +} else { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL"; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "p.rowid IN (SELECT fk_product FROM " . MAIN_DB_PREFIX . "categorie_product WHERE fk_categorie = " . $searchCategoryProduct . ")"; + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (" . implode(' AND ', $searchCategoryProductSqlList) . ")"; + } +} if ($fourn_id > 0) $sql.= " AND pfp.fk_soc = ".$fourn_id; if ($search_tobatch != '' && $search_tobatch >= 0) $sql.= " AND p.tobatch = ".$db->escape($search_tobatch); if ($search_accountancy_code_sell) $sql.= natural_search('p.accountancy_code_sell', $search_accountancy_code_sell); @@ -421,7 +445,10 @@ if ($resql) if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit); if ($sall) $param.="&sall=".urlencode($sall); - if ($search_categ > 0) $param.="&search_categ=".urlencode($search_categ); + if ($searchCategoryProductOperator == 1) $param .= "&search_category_product_operator=" . urlencode($searchCategoryProductOperator); + foreach ($searchCategoryProductList as $searchCategoryProduct) { + $param .= "&search_category_product_list[]=" . urlencode($searchCategoryProduct); + } if ($search_ref) $param="&search_ref=".urlencode($search_ref); if ($search_ref_supplier) $param="&search_ref_supplier=".urlencode($search_ref_supplier); if ($search_barcode) $param.=($search_barcode?"&search_barcode=".urlencode($search_barcode):""); @@ -430,7 +457,7 @@ if ($resql) if ($search_tobuy != '') $param.="&search_tobuy=".urlencode($search_tobuy); if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); if ($fourn_id > 0) $param.=($fourn_id?"&fourn_id=".$fourn_id:""); - if ($seach_categ) $param.=($search_categ?"&search_categ=".urlencode($search_categ):""); + //if ($seach_categ) $param.=($search_categ?"&search_categ=".urlencode($search_categ):""); if ($show_childproducts) $param.=($show_childproducts?"&search_show_childproducts=".urlencode($show_childproducts):""); if ($type != '') $param.='&type='.urlencode($type); if ($search_type != '') $param.='&search_type='.urlencode($search_type); @@ -465,7 +492,7 @@ if ($resql) $label='NewProduct'; if($type == Product::TYPE_SERVICE) $label='NewService'; $newcardbutton.= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type='.$type); - } + } print '
'; if ($optioncss != '') print ''; @@ -507,8 +534,11 @@ if ($resql) { $moreforfilter.='
'; $moreforfilter.=$langs->trans('Categories'). ': '; - $moreforfilter.=$htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1); - $moreforfilter.='
'; + $categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1); + $categoriesProductArr[-2] = '- ' . $langs->trans('NotCategorized') . ' -'; + $moreforfilter.=Form::multiselectarray('search_category_product_list', $categoriesProductArr, $searchCategoryProductList, 0, 0, 'minwidth300'); + $moreforfilter.=' ' . $langs->trans('or'); + $moreforfilter.=''; } //Show/hide child products. Hidden by default diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index f29ce739b30..26cb0e7b828 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -254,6 +254,9 @@ if ($resql) else dol_print_error($db); +$companystatic=new Societe($db); // We need a clean new object for next loop because current one has some properties set. + + // Open project per thirdparty print '
'; print ''; diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 4b6364ea3be..f2c0fb75ca5 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1834,7 +1834,7 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment print '
'; - print ''."\n"; + print ''."\n"; print ''."\n"; print ''."\n"; @@ -1909,7 +1909,7 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment
'; - print ''; + print ''; print ''; print ' @@ -1943,7 +1943,6 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment { print ''; print ''."\n"; - $urllogofull = 'http://home.destailleur.fr:805/dolibarr_dev/htdocs/viewimage.php?modulepart=mycompany&entity=1&file=logos%2Fthumbs%2Ffbm+logo_small.png'; print ''."\n"; // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code. @@ -2122,13 +2121,13 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment payment_method_data: { billing_details: { name: cardholderName.value - thirdparty) && ! empty($object->thirdparty->email))) { ?>, email: 'thirdparty->email); ?>' - thirdparty) && ! empty($object->thirdparty->phone)) { ?>, phone: 'thirdparty->phone; ?>' + thirdparty) && ! empty($object->thirdparty->email))) { ?>, email: 'thirdparty->email); ?>' + thirdparty) && ! empty($object->thirdparty->phone)) { ?>, phone: 'thirdparty->phone); ?>'thirdparty)) { ?>, address: { - city: 'thirdparty->town; ?>', - country: 'thirdparty->country_code; ?>', - line1: 'thirdparty->address; ?>', - postal_code: 'thirdparty->zip; ?>'} + city: 'thirdparty->town); ?>', + country: 'thirdparty->country_code); ?>', + line1: 'thirdparty->address)); ?>', + postal_code: 'thirdparty->zip); ?>'} } }, save_payment_method: /* true when a customer was provided when creating payment intent. true ask to save the card */ diff --git a/htdocs/public/test/test_csrf.php b/htdocs/public/test/test_csrf.php new file mode 100644 index 00000000000..8c242cade64 --- /dev/null +++ b/htdocs/public/test/test_csrf.php @@ -0,0 +1,22 @@ + + +This is a form to test a CSRF.
+
+Open this form into a Virtual server A.
+Change url to send request to into file to send request to virtual server B.
+ +
+
'; +?> + + + + + + + \ No newline at end of file diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 3731cfe07fa..90d90b388ac 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -600,7 +600,7 @@ if (empty($reshook)) $db->rollback(); } } - + if ($action == 'setkey_account_supplier') { $error = 0; @@ -819,7 +819,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print '
'; print '
'; - print '
'; + print '
'; if ($object->client) { @@ -872,7 +872,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ''; } } - + if ($object->fournisseur) { print ''; print ''; print ''; - + if (is_array($balance->available) && count($balance->available)) { foreach ($balance->available as $cpt) @@ -1322,7 +1322,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ''; } } - + if (is_array($balance->pending) && count($balance->pending)) { foreach ($balance->pending as $cpt) @@ -1598,7 +1598,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' // Edit BAN if ($socid && $action == 'edit' && $user->rights->societe->creer) { - dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), -1, 'company'); $linkback = ''.$langs->trans("BackToList").''; @@ -1705,7 +1705,7 @@ if ($socid && $action == 'edit' && $user->rights->societe->creer) // Edit Card if ($socid && $action == 'editcard' && $user->rights->societe->creer) { - dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), -1, 'company'); $linkback = ''.$langs->trans("BackToList").''; @@ -1753,7 +1753,7 @@ if ($socid && $action == 'editcard' && $user->rights->societe->creer) // Create BAN if ($socid && $action == 'create' && $user->rights->societe->creer) { - dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), -1, 'company'); $linkback = ''.$langs->trans("BackToList").''; @@ -1854,7 +1854,7 @@ if ($socid && $action == 'create' && $user->rights->societe->creer) // Create Card if ($socid && $action == 'createcard' && $user->rights->societe->creer) { - dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), -1, 'company'); $linkback = ''.$langs->trans("BackToList").''; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 9defab81a73..9c0bc9ebae3 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -293,7 +293,7 @@ class Stripe extends CommonObject } /** - * Get the Stripe payment intent. Create it with confirm=false + * Get the Stripe payment intent. Create it with confirmnow=false * Warning. If a payment was tried and failed, a payment intent was created. * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed. * Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay), @@ -312,7 +312,7 @@ class Stripe extends CommonObject * @param int $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt * @param int $mode automatic=automatic confirmation/payment when conditions are ok, manual=need to call confirm() on intent * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) - * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found + * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found and failed to create */ public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) { @@ -503,6 +503,149 @@ class Stripe extends CommonObject } } + + /** + * Get the Stripe payment intent. Create it with confirmnow=false + * Warning. If a payment was tried and failed, a payment intent was created. + * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed. + * Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay), + * that's why i comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used) + * Note: This is used when option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the public/payment/newpayment.php page + * but not when using the STRIPE_USE_NEW_CHECKOUT. + * + * @param string $description Description + * @param Societe $object Object to pay with Stripe + * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() + * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect + * @param int $status Status (0=test, 1=live) + * @param int $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt + * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) + * @return \Stripe\SetupIntent|null Stripe SetupIntent or null if not found and failed to create + */ + public function getSetupIntent($description, $object, $customer, $key, $status, $usethirdpartyemailforreceiptemail = 0, $confirmnow = false) + { + global $conf; + + dol_syslog("getSetupIntent", LOG_INFO, 1); + + $error = 0; + + if (empty($status)) $service = 'StripeTest'; + else $service = 'StripeLive'; + + $setupintent = null; + + if (empty($setupintent)) + { + $ipaddress=getUserRemoteIP(); + $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress); + if (is_object($object)) + { + $metadata['dol_type'] = $object->element; + $metadata['dol_id'] = $object->id; + if (is_object($object->thirdparty) && $object->thirdparty->id > 0) $metadata['dol_thirdparty_id'] = $object->thirdparty->id; + } + + $dataforintent = array( + "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent + "payment_method_types" => array("card"), + "description" => $description, + "usage" => "off_session", + "metadata" => $metadata + ); + if (! is_null($customer)) $dataforintent["customer"]=$customer; + // payment_method = + // payment_method_types = array('card') + //var_dump($dataforintent); + + if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) + { + $dataforintent["receipt_email"] = $object->thirdparty->email; + } + + try { + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + + // Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent. + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description")); + $setupintent = \Stripe\SetupIntent::create($dataforintent, array()); + } else { + //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); + $setupintent = \Stripe\SetupIntent::create($dataforintent, array("stripe_account" => $key)); + } + //var_dump($setupintent->id); + + // Store the setup intent + /*if (is_object($object)) + { + $setupintentalreadyexists = 0; + // Check that payment intent $setupintent->id is not already recorded. + $sql = "SELECT pi.rowid"; + $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; + $sql.= " WHERE pi.entity IN (".getEntity('societe').")"; + $sql.= " AND pi.ext_payment_site = '" . $service . "'"; + $sql.= " AND pi.ext_payment_id = '".$this->db->escape($setupintent->id)."'"; + + dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_facture_demande", LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num) + { + $obj = $this->db->fetch_object($resql); + if ($obj) $setupintentalreadyexists++; + } + } + else dol_print_error($this->db); + + // If not, we create it. + if (! $setupintentalreadyexists) + { + $now=dol_now(); + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_facture_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)"; + $sql .= " VALUES ('".$this->db->idate($now)."', '0', '".$this->db->escape($setupintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', " . $conf->entity . ", '" . $service . "')"; + $resql = $this->db->query($sql); + if (! $resql) + { + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$setupintent->id." into database."); + } + } + } + else + { + $_SESSION["stripe_setup_intent"] = $setupintent; + }*/ + } + catch(Exception $e) + { + /*var_dump($dataforintent); + var_dump($description); + var_dump($key); + var_dump($setupintent); + var_dump($e->getMessage());*/ + $error++; + $this->error = $e->getMessage(); + } + } + + dol_syslog("getSetupIntent return error=".$error, LOG_INFO, -1); + + if (! $error) + { + return $setupintent; + } + else + { + return null; + } + } + + /** * Get the Stripe card of a company payment mode (with option to create it on Stripe if not linked yet) * @@ -609,6 +752,7 @@ class Stripe extends CommonObject /** * Create charge with public/payment/newpayment.php, stripe/card.php, cronjobs or REST API + * This is using old Stripe API charge. * * @param int $amount Amount to pay * @param string $currency EUR, GPB... diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 86b4fa82c12..cbb69df74f9 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5789,10 +5789,13 @@ div.tabsElem a.tab { } .titlefield { - width: auto !important; /* We want to ignor the 30%, try to use more if you can */ + width: auto !important; /* We want to ignore the 30%, try to use more if you can */ } - .tableforfield>tr>td:first-child { - max-width: 100px; /* but no more than 100px */ + .tableforfield>tr>td:first-child, .tableforfield>tbody>tr>td:first-child, div.tableforfield div.tagtr>div.tagtd:first-of-type { + /* max-width: 100px; */ /* but no more than 100px */ + } + .tableforfield>tr>td:nth-child(2), .tableforfield>tbody>tr>td:nth-child(2), div.tableforfield div.tagtr>div.tagtd:nth-child(2) { + word-break: break-word; } .badge { line-height: 1.2em; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 205ed21bdcf..ebf6b1df23d 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1137,11 +1137,17 @@ select.selectarrowonleft option { } } .linkobject { cursor: pointer; } + +table.tableforfield tr>td:first-of-type, div.tableforfield div.tagtr>div.tagtd:first-of-type { + color: #666; +} + .hideonprint { display: none; } + /* ============================================================================== */ /* Styles for dragging lines */ /* ============================================================================== */ @@ -5716,8 +5722,11 @@ border-top-right-radius: 6px; .titlefield { width: auto !important; /* We want to ignor the 30%, try to use more if you can */ } - .tableforfield>tr>td:first-child, div.tableforfield div.tagtr>div.tagtd:first-of-type { - max-width: 100px; /* but no more than 100px */ + .tableforfield>tr>td:first-child, .tableforfield>tbody>tr>td:first-child, div.tableforfield div.tagtr>div.tagtd:first-of-type { + /* max-width: 100px; */ /* but no more than 100px */ + } + .tableforfield>tr>td:nth-child(2), .tableforfield>tbody>tr>td:nth-child(2), div.tableforfield div.tagtr>div.tagtd:nth-child(2) { + word-break: break-word; } } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index cfb79cfc06f..a5096617d98 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -13,6 +13,7 @@ * Copyright (C) 2018 charlene Benke * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2019 Frédéric France + * Copyright (C) 2019 Abbes Bahfir * * 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 @@ -35,6 +36,7 @@ */ require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT .'/user/class/usergroup.class.php'; /** * Class to manage Dolibarr users @@ -2712,8 +2714,22 @@ class User extends CommonObject if ($this->phone_mobile) $info["phpgwCellTelephoneNumber"] = $this->phone_mobile; } - return $info; - } + if (!empty($conf->global->LDAP_FIELD_USERID))$info[$conf->global->LDAP_FIELD_USERID] = $this->id; + if(!empty($info[$conf->global->LDAP_FIELD_GROUPID])){ + $usergroup = new UserGroup($this->db); + $groupslist = $usergroup->listGroupsForUser($this->id); + $info[$conf->global->LDAP_FIELD_GROUPID] = '1'; + if(!empty($groupslist)){ + foreach ($groupslist as $groupforuser) { + $info[$conf->global->LDAP_FIELD_GROUPID] = $groupforuser->id;//Select first group in list + break; + } + } + } + if (!empty($this->firstname) && !empty($conf->global->LDAP_FIELD_HOMEDIRECTORY) && !empty($conf->global->LDAP_FIELD_HOMEDIRECTORYPREFIX)) $info[$conf->global->LDAP_FIELD_HOMEDIRECTORY]="{$conf->global->LDAP_FIELD_HOMEDIRECTORYPREFIX}/$this->firstname"; + + return $info; + } /** diff --git a/htdocs/user/class/usergroup.class.php b/htdocs/user/class/usergroup.class.php index d51d82c8d13..a89126b122f 100644 --- a/htdocs/user/class/usergroup.class.php +++ b/htdocs/user/class/usergroup.class.php @@ -6,6 +6,7 @@ * Copyright (C) 2014 Juanjo Menent * Copyright (C) 2014 Alexis Algoud * Copyright (C) 2018 Nicolas ZABOURI + * Copyright (C) 2019 Abbes Bahfir * * 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 @@ -978,7 +979,10 @@ class UserGroup extends CommonObject $valueofldapfield[] = $muser->_load_ldap_dn($info2); } $info[$conf->global->LDAP_GROUP_FIELD_GROUPMEMBERS] = (!empty($valueofldapfield)?$valueofldapfield:''); - } + } + if(!empty($info[$conf->global->LDAP_GROUP_FIELD_GROUPID])){ + $info[$conf->global->LDAP_GROUP_FIELD_GROUPID]=$this->id; + } return $info; }
'; @@ -891,12 +891,12 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' if ($conf->facture->enabled && $user->rights->facture->lire) $elementTypeArray['invoice']=$langs->transnoentitiesnoconv('Invoices'); if ($conf->contrat->enabled && $user->rights->contrat->lire) $elementTypeArray['contract']=$langs->transnoentitiesnoconv('Contracts'); } - + if (! empty($conf->stripe->enabled) && ! empty($conf->stripeconnect->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2) { $permissiontowrite = $user->rights->societe->creer; $stripesupplieracc = $stripe->getStripeAccount($service, $object->id); // Get Stripe OAuth connect account (no network access here) - + // Stripe customer key 'cu_....' stored into llx_societe_account print '
'; print $form->editfieldkey("StripeConnectAccount", 'key_account_supplier', $stripesupplieracc, $object, $permissiontowrite, 'string', '', 0, 2, 'socid'); @@ -905,7 +905,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' if (! empty($conf->stripe->enabled) && $stripesupplieracc && $action != 'editkey_account_supplier') { $connect=''; - + $url='https://dashboard.stripe.com/test/connect/accounts/'.$stripesupplieracc; if ($servicestatus) { @@ -1299,7 +1299,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ""; print '
'; } - + // List of Stripe payment modes if (! empty($conf->stripe->enabled) && ! empty($conf->stripeconnect->enabled) && $object->fournisseur && ! empty($stripesupplieracc)) { @@ -1311,7 +1311,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print '
'.$langs->trans('Amount').''.$langs->trans('Currency').'
'.$langs->trans("Available").''.price($amount, 0, '', 1, - 1, - 1, strtoupper($cpt->currency)).' '.$langs->trans("Currency".strtoupper($cpt->currency)).'