diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index b62009c2ba6..b5f22376c16 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -50,7 +50,7 @@ $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmatio $id = GETPOST('id', 'int'); $rowid = GETPOST('rowid', 'alpha'); -$search_label=GETPOST('search_label', 'alpha'); +$search_label=GETPOST('search_label', 'alphanohtml'); // Must allow value like 'Abc Def' or '(MyTemplateName)' $search_type_template=GETPOST('search_type_template', 'alpha'); $search_lang=GETPOST('search_lang', 'alpha'); $search_fk_user=GETPOST('search_fk_user', 'intcomma'); @@ -263,6 +263,7 @@ if (empty($reshook)) { //var_dump($i.' - '.$listfieldvalue[$i].' - '.$_POST[$listfieldvalue[$i]].' - '.$value); $keycode=$listfieldvalue[$i]; + if ($value == 'label') $_POST[$keycode] = dol_escape_htmltag($_POST[$keycode]); if ($value == 'lang') $keycode='langcode'; if ($value == 'entity') $_POST[$keycode] = $conf->entity; if ($i) $sql.=","; @@ -667,8 +668,6 @@ if ($resql) print ''; foreach ($fieldlist as $field => $value) { - // Determine le nom du champ par rapport aux noms possibles - // dans les dictionnaires de donnees $showfield=1; // By defaut $align="left"; $sortable=1; @@ -695,7 +694,7 @@ if ($resql) if ($fieldlist[$field]=='content') { $valuetoshow=$langs->trans("Content"); $showfield=0;} if ($fieldlist[$field]=='content_lines') { $valuetoshow=$langs->trans("ContentLines"); $showfield=0; } - // Affiche nom du champ + // Show fields if ($showfield) { if (! empty($tabhelp[$id][$value])) @@ -813,6 +812,10 @@ if ($resql) $showfield=1; $align="left"; $valuetoshow=$obj->{$fieldlist[$field]}; + if ($value == 'label' || $value == 'topic') + { + $valuetoshow = dol_escape_htmltag($valuetoshow); + } if ($value == 'type_template') { $valuetoshow = isset($elementList[$valuetoshow])?$elementList[$valuetoshow]:$valuetoshow; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 12926f9b360..3c138043d26 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -657,7 +657,7 @@ class ActionComm extends CommonObject $this->socid = $obj->fk_soc; // To have fetch_thirdparty method working $this->contactid = $obj->fk_contact; // To have fetch_contact method working - $this->fk_project = $obj->fk_project; // To have fetch_project method working + $this->fk_project = $obj->fk_project; // To have fetch_projet method working //$this->societe->id = $obj->fk_soc; // deprecated //$this->contact->id = $obj->fk_contact; // deprecated diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index d54d2dd02ff..6cd98f00e48 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -384,6 +384,10 @@ if (! $error && $massaction == 'confirm_presend') foreach ($looparray as $objectid => $objecttmp) // $objecttmp is a real object or an empty object if we choose to send one email per thirdparty instead of one per object { // Make substitution in email content + if (! empty($conf->projet->enabled) && method_exists($objecttmp, 'fetch_projet') && is_null($objecttmp->project)) + { + $objecttmp->fetch_projet(); + } $substitutionarray=getCommonSubstitutionArray($langs, 0, null, $objecttmp); $substitutionarray['__ID__'] = ($oneemailperrecipient ? join(', ', array_keys($listofqualifiedobj)) : $objecttmp->id); $substitutionarray['__REF__'] = ($oneemailperrecipient ? join(', ', $listofqualifiedref) : $objecttmp->ref); diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 836652ea819..de3a43d9ce6 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -113,8 +113,8 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO { $result=$object->fetch($id); - $sendtosocid=0; // Thirdparty on object - if (method_exists($object, "fetch_thirdparty") && ! in_array($object->element, array('societe','member','user','expensereport', 'contact'))) + $sendtosocid=0; // Id of related thirdparty + if (method_exists($object, "fetch_thirdparty") && ! in_array($object->element, array('societe', 'member', 'user', 'expensereport', 'contact'))) { $result=$object->fetch_thirdparty(); if ($object->element == 'user' && $result == 0) $result=1; // Even if not found, we consider ok @@ -124,7 +124,14 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO elseif ($object->element == 'member' || $object->element == 'user') { $thirdparty=$object; - if ($thirdparty->id > 0) $sendtosocid=$thirdparty->id; + if ($object->socid > 0) $sendtosocid=$object->socid; + } + elseif ($object->element == 'expensereport') + { + $tmpuser=new User($db); + $tmpuser->fetch($object->fk_user_author); + $thirdparty=$tmpuser; + if ($object->socid > 0) $sendtosocid=$object->socid; } elseif ($object->element == 'societe') { @@ -136,7 +143,7 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO $contact=$object; if ($contact->id > 0) $sendtosocid=$contact->fetch_thirdparty()->id; } - else dol_print_error('', 'Use actions_sendmails.in.php for an element/object that is not supported'); + else dol_print_error('', "Use actions_sendmails.in.php for an element/object '".$object->element."' that is not supported"); if (is_object($hookmanager)) { @@ -162,6 +169,7 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO if ($receiver == '-1') $receiver=array(); else $receiver=array($receiver); } + $tmparray=array(); if (trim($_POST['sendto'])) { @@ -173,22 +181,23 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO foreach($receiver as $key=>$val) { // Recipient was provided from combo list - if ($val == 'thirdparty') // Id of third party + if ($val == 'thirdparty') // Key selected means currentthird party (may be usd for current member or current user too) { - $tmparray[] = dol_string_nospecial($thirdparty->name, ' ', array(",")).' <'.$thirdparty->email.'>'; + $tmparray[] = dol_string_nospecial($thirdparty->getFullName($langs), ' ', array(",")).' <'.$thirdparty->email.'>'; } // Recipient was provided from combo list - elseif ($val == 'contact') // Id of contact + elseif ($val == 'contact') // Key selected means current contact { - $tmparray[] = dol_string_nospecial($contact->name, ' ', array(",")).' <'.$contact->email.'>'; + $tmparray[] = dol_string_nospecial($contact->getFullName($langs), ' ', array(",")).' <'.$contact->email.'>'; } - elseif ($val) // Id du contact + elseif ($val) // $val is the Id of a contact { $tmparray[] = $thirdparty->contact_get_property((int) $val, 'email'); $sendtoid[] = $val; } } } + if (!empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) { $receiveruser=$_POST['receiveruser']; @@ -222,16 +231,16 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO foreach($receivercc as $key=>$val) { // Recipient was provided from combo list - if ($val == 'thirdparty') // Id of third party + if ($val == 'thirdparty') // Key selected means currentthird party (may be usd for current member or current user too) { $tmparray[] = dol_string_nospecial($thirdparty->name, ' ', array(",")).' <'.$thirdparty->email.'>'; } // Recipient was provided from combo list - elseif ($val == 'contact') // Id of contact + elseif ($val == 'contact') // Key selected means current contact { $tmparray[] = dol_string_nospecial($contact->name, ' ', array(",")).' <'.$contact->email.'>'; } - elseif ($val) // Id du contact + elseif ($val) // $val is the Id of a contact { $tmparray[] = $thirdparty->contact_get_property((int) $val, 'email'); //$sendtoid[] = $val; TODO Add also id of contact in CC ? @@ -414,27 +423,6 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO $result=$mailfile->sendfile(); if ($result) { - // Two hooks are available into method $mailfile->sendfile, so dedicated code is no more required - /* - if (! empty($conf->dolimail->enabled)) - { - $mid = (GETPOST('mid','int') ? GETPOST('mid','int') : 0); // Original mail id is set ? - if ($mid) - { - // set imap flag answered if it is an answered mail - $dolimail=new DoliMail($db); - $dolimail->id = $mid; - $res=$dolimail->set_prop($user, 'answered',1); - } - if ($imap==1) - { - // write mail to IMAP Server - $movemail = $mailboxconfig->putMail($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$folder,$deliveryreceipt,$mailfile); - if ($movemail) setEventMessages($langs->trans("MailMovedToImapFolder",$folder), null, 'mesgs'); - else setEventMessages($langs->trans("MailMovedToImapFolder_Warning",$folder), null, 'warnings'); - } - }*/ - // Initialisation of datas of object to call trigger if (is_object($object)) { diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index fe00f803a6b..eca41a55301 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -88,11 +88,12 @@ class Translate if (empty($srclang) || $srclang == 'auto') { + // $_SERVER['HTTP_ACCEPT_LANGUAGE'] can be 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,it;q=0.6' but can contains also malicious content $langpref=empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])?'':$_SERVER['HTTP_ACCEPT_LANGUAGE']; - $langpref=preg_replace("/;([^,]*)/i", "", $langpref); + $langpref=preg_replace("/;([^,]*)/i", "", $langpref); // Remove the 'q=x.y,' part $langpref=str_replace("-", "_", $langpref); $langlist=preg_split("/[;,]/", $langpref); - $codetouse=$langlist[0]; + $codetouse=preg_replace('/[^_a-zA-Z]/', '', $langlist[0]); } else $codetouse=$srclang; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 1130f136354..d234195d8cd 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5897,11 +5897,13 @@ $substitutionarray=array_merge($substitutionarray, array( $substitutionarray['__REF_SUPPLIER__'] = '__REF_SUPPLIER__'; $substitutionarray['__EXTRAFIELD_XXX__'] = '__EXTRAFIELD_XXX__'; - $substitutionarray['__THIRDPARTY_ID__'] = '__THIRDPARTY_ID__'; - $substitutionarray['__THIRDPARTY_NAME__'] = '__THIRDPARTY_NAME__'; - $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = '__THIRDPARTY_NAME_ALIAS__'; - $substitutionarray['__THIRDPARTY_EMAIL__'] = '__THIRDPARTY_EMAIL__'; - + if (! empty($conf->societe->enabled)) + { + $substitutionarray['__THIRDPARTY_ID__'] = '__THIRDPARTY_ID__'; + $substitutionarray['__THIRDPARTY_NAME__'] = '__THIRDPARTY_NAME__'; + $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = '__THIRDPARTY_NAME_ALIAS__'; + $substitutionarray['__THIRDPARTY_EMAIL__'] = '__THIRDPARTY_EMAIL__'; + } if (! empty($conf->adherent->enabled)) { $substitutionarray['__MEMBER_ID__'] = '__MEMBER_ID__'; @@ -5909,15 +5911,19 @@ $substitutionarray=array_merge($substitutionarray, array( $substitutionarray['__MEMBER_FIRSTNAME__'] = '__MEMBER_FIRSTNAME__'; $substitutionarray['__MEMBER_LASTNAME__'] = '__MEMBER_LASTNAME__'; } - $substitutionarray['__PROJECT_ID__'] = '__PROJECT_ID__'; - $substitutionarray['__PROJECT_REF__'] = '__PROJECT_REF__'; - $substitutionarray['__PROJECT_NAME__'] = '__PROJECT_NAME__'; - - $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = 'Highest date planned for a service start'; - $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = 'Highest date and hour planned for service start'; - $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = 'Lowest data for planned expiration of service'; - $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = 'Lowest date and hour for planned expiration of service'; - + if (! empty($conf->projet->enabled)) + { + $substitutionarray['__PROJECT_ID__'] = '__PROJECT_ID__'; + $substitutionarray['__PROJECT_REF__'] = '__PROJECT_REF__'; + $substitutionarray['__PROJECT_NAME__'] = '__PROJECT_NAME__'; + } + if (! empty($conf->contrat->enabled)) + { + $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = 'Highest date planned for a service start'; + $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = 'Highest date and hour planned for service start'; + $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = 'Lowest data for planned expiration of service'; + $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = 'Lowest date and hour for planned expiration of service'; + } $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'UrlToPayOnlineIfApplicable'; $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = 'TextAndUrlToPayOnlineIfApplicable'; $substitutionarray['__SECUREKEYPAYMENT__'] = 'Security key (if key is not unique per record)'; @@ -5995,7 +6001,13 @@ $substitutionarray=array_merge($substitutionarray, array( $substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object->thirdparty)?$object->thirdparty->email:''); } - if (is_object($object->projet) && $object->projet->id > 0) + if (is_object($object->project) && $object->project->id > 0) + { + $substitutionarray['__PROJECT_ID__'] = (is_object($object->project)?$object->project->id:''); + $substitutionarray['__PROJECT_REF__'] = (is_object($object->project)?$object->project->ref:''); + $substitutionarray['__PROJECT_NAME__'] = (is_object($object->project)?$object->project->title:''); + } + if (is_object($object->projet) && $object->projet->id > 0) // Deprecated, for backward compatibility { $substitutionarray['__PROJECT_ID__'] = (is_object($object->projet)?$object->projet->id:''); $substitutionarray['__PROJECT_REF__'] = (is_object($object->projet)?$object->projet->ref:''); diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index ba792ad28ad..61217d91686 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -202,13 +202,13 @@ class modHoliday extends DolibarrModules $this->export_permission[$r]=array(array("holiday","read_all")); $this->export_fields_array[$r]=array( 'd.rowid'=>"LeaveId",'d.fk_type'=>'TypeOfLeaveId','t.code'=>'TypeOfLeaveCode','t.label'=>'TypeOfLeaveLabel','d.fk_user'=>'UserID', - 'u.lastname'=>'Lastname','u.firstname'=>'Firstname','u.login'=>"Login",'d.date_debut'=>'DateStart','d.date_fin'=>'DateEnd','d.halfday'=>'HalfDay', + 'u.lastname'=>'Lastname','u.firstname'=>'Firstname','u.login'=>"Login",'d.date_debut'=>'DateStart','d.date_fin'=>'DateEnd','d.halfday'=>'HalfDay','none.num_open_days'=>'NbUseDaysCP', 'd.date_valid'=>'DateApprove','d.fk_validator'=>"UserForApprovalID",'ua.lastname'=>"UserForApprovalLastname",'ua.firstname'=>"UserForApprovalFirstname", 'ua.login'=>"UserForApprovalLogin",'d.description'=>'Description','d.statut'=>'Status' ); $this->export_TypeFields_array[$r]=array( 'd.rowid'=>"Numeric",'t.code'=>'Text', 't.label'=>'Text','d.fk_user'=>'Numeric', - 'u.lastname'=>'Text','u.firstname'=>'Text','u.login'=>"Text",'d.date_debut'=>'Date','d.date_fin'=>'Date', + 'u.lastname'=>'Text','u.firstname'=>'Text','u.login'=>"Text",'d.date_debut'=>'Date','d.date_fin'=>'Date','none.num_open_days'=>'NumericCompute', 'd.date_valid'=>'Date','d.fk_validator'=>"Numeric",'ua.lastname'=>"Text",'ua.firstname'=>"Text", 'ua.login'=>"Text",'d.description'=>'Text','d.statut'=>'Numeric' ); @@ -216,6 +216,7 @@ class modHoliday extends DolibarrModules 'u.lastname'=>'user','u.firstname'=>'user','u.login'=>'user','ua.lastname'=>'user','ua.firstname'=>'user','ua.login'=>'user' ); $this->export_alias_array[$r]=array('d.rowid'=>"idholiday"); + $this->export_special_array[$r] = array('none.num_open_days'=>'getNumOpenDays'); $this->export_dependencies_array[$r]=array(); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $this->export_sql_start[$r]='SELECT DISTINCT '; diff --git a/htdocs/document.php b/htdocs/document.php index 8e86d6c3e6f..84fb0492554 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -161,6 +161,8 @@ if (! empty($conf->global->MAIN_DISABLE_FORCE_SAVEAS)) $attachment=false; $type = 'application/octet-stream'; if (GETPOST('type', 'alpha')) $type=GETPOST('type', 'alpha'); else $type=dol_mimetype($original_file); +// Security: Force to octet-stream if file is a dangerous file +if (preg_match('/\.noexe$/i', $original_file)) $type = 'application/octet-stream'; // Security: Delete string ../ into $original_file $original_file = str_replace("../", "/", $original_file); @@ -217,7 +219,7 @@ if (! $accessallowed) } // Security: -// On interdit les remontees de repertoire ainsi que les pipe dans les noms de fichiers. +// We refuse directory transversal change and pipes in file names if (preg_match('/\.\./', $fullpath_original_file) || preg_match('/[<>|]/', $fullpath_original_file)) { dol_syslog("Refused to deliver file ".$fullpath_original_file); @@ -229,6 +231,7 @@ if (preg_match('/\.\./', $fullpath_original_file) || preg_match('/[<>|]/', $full clearstatcache(); $filename = basename($fullpath_original_file); +$filename = preg_replace('/\.noexe$/i', '', $filename); // Output file on browser dol_syslog("document.php download $fullpath_original_file filename=$filename content-type=$type"); diff --git a/htdocs/exports/class/export.class.php b/htdocs/exports/class/export.class.php index 51a16f717b2..da184f27574 100644 --- a/htdocs/exports/class/export.class.php +++ b/htdocs/exports/class/export.class.php @@ -540,7 +540,7 @@ class Export public function build_file($user, $model, $datatoexport, $array_selected, $array_filterValue, $sqlquery = '') { // phpcs:enable - global $conf,$langs; + global $conf,$langs,$mysoc; $indice=0; asort($array_selected); @@ -634,6 +634,14 @@ class Export $alias=str_replace(array('.', '-','(',')'), '_', $key); if ($obj->$alias < 0) $obj->$alias='0'; } + // Operation GETNUMOPENDAYS (for Holiday module) + elseif ($this->array_export_special[$indice][$key]=='getNumOpenDays') + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + //$alias=$this->array_export_alias[$indice][$key]; + $alias=str_replace(array('.', '-','(',')'), '_', $key); + $obj->$alias=num_open_day(dol_stringtotime($obj->d_date_debut, 1), dol_stringtotime($obj->d_date_fin, 1), 0, 1, $obj->d_halfday, $mysoc->country_code); + } // Operation INVOICEREMAINTOPAY elseif ($this->array_export_special[$indice][$key]=='getRemainToPay') { diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 10233924d4a..febfda0a419 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -207,7 +207,7 @@ class ProductFournisseur extends Product /** * Modify the purchase price for a supplier * - * @param int $qty Min quantity for which price is valid + * @param float $qty Min quantity for which price is valid * @param float $buyprice Purchase price for the quantity min * @param User $user Object user user made changes * @param string $price_base_type HT or TTC @@ -230,7 +230,7 @@ class ProductFournisseur extends Product * @param string $desc_fourn Custom description for product_fourn_price * @param string $barcode Barcode * @param int $fk_barcode_type Barcode type - * @return int <0 if KO, >=0 if OK + * @return int <0 if KO, >=0 if OK */ public function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges = 0, $remise_percent = 0, $remise = 0, $newnpr = 0, $delivery_time_days = 0, $supplier_reputation = '', $localtaxes_array = array(), $newdefaultvatcode = '', $multicurrency_buyprice = 0, $multicurrency_price_base_type = 'HT', $multicurrency_tx = 1, $multicurrency_code = '', $desc_fourn = '', $barcode = '', $fk_barcode_type = '') { @@ -272,7 +272,7 @@ class ProductFournisseur extends Product $buyprice=price2num($buyprice, 'MU'); $charges=price2num($charges, 'MU'); - $qty=price2num($qty); + $qty=price2num($qty, 'MS'); $unitBuyPrice = price2num($buyprice/$qty, 'MU'); $error=0; diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index be441976f67..2f0b9be9954 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -1134,6 +1134,7 @@ else if ($action == 'edit' && $object->statut == Holiday::STATUS_DRAFT) $edit = true; print '
'."\n"; + print ''."\n"; print ''."\n"; print ''."\n"; } diff --git a/htdocs/langs/fr_NC/admin.lang b/htdocs/langs/fr_NC/admin.lang index d86b324fdc5..f7c25610e3f 100644 --- a/htdocs/langs/fr_NC/admin.lang +++ b/htdocs/langs/fr_NC/admin.lang @@ -1,4 +1,4 @@ # Dolibarr language file - Source file is en_US - admin -VATManagement=Gestion TSS -VATIsUsedDesc=Le taux de TSS proposé par défaut lors de la création de proposition commerciale, facture, commande, etc... répond à la règle standard suivante :
Si vendeur non assujetti à TSS, TSS par défaut=0. Fin de règle.
Si le (pays vendeur= pays acheteur) alors TSS par défaut=TSS du produit vendu. Fin de règle.
Si vendeur et acheteur dans Communauté européenne et bien vendu= moyen de transport neuf (auto, bateau, avion), TSS par défaut=0 (La TSS doit être payée par acheteur au centre d'impôts de son pays et non au vendeur). Fin de règle.
Si vendeur et acheteur dans Communauté européenne et acheteur= particulier alors TSS par défaut=TSS du produit vendu. Fin de règle.
Si vendeur et acheteur dans Communauté européenne et acheteur= entreprise alors TSS par défaut=0. Fin de règle.
Sinon TSS proposée par défaut=0. Fin de règle.
-VATIsNotUsedDesc=Le taux de TSS proposé par défaut est 0. C'est le cas d'associations, particuliers ou certaines petites sociétés. +VATManagement=Gestion TGC +VATIsUsedDesc=Le taux de TGC proposé par défaut lors de la création de proposition commerciale, facture, commande, etc... répond à la règle standard suivante :
Si vendeur non assujetti à TGC, TGC par défaut=0. Fin de règle.
Si le (pays vendeur= pays acheteur) alors TGC par défaut=TGC du produit vendu. Fin de règle.
Si vendeur et acheteur dans Communauté européenne et bien vendu= moyen de transport neuf (auto, bateau, avion), TGC par défaut=0 (La TGC doit être payée par acheteur au centre d'impôts de son pays et non au vendeur). Fin de règle.
Si vendeur et acheteur dans Communauté européenne et acheteur= particulier alors TGC par défaut=TGC du produit vendu. Fin de règle.
Si vendeur et acheteur dans Communauté européenne et acheteur= entreprise alors TGC par défaut=0. Fin de règle.
Sinon TGC proposée par défaut=0. Fin de règle.
+VATIsNotUsedDesc=Le taux de TGC proposé par défaut est 0. C'est le cas d'associations, particuliers ou certaines petites sociétés. diff --git a/htdocs/langs/fr_NC/companies.lang b/htdocs/langs/fr_NC/companies.lang index 9853f7e7e21..c3520226e42 100644 --- a/htdocs/langs/fr_NC/companies.lang +++ b/htdocs/langs/fr_NC/companies.lang @@ -1,3 +1,3 @@ # Dolibarr language file - Source file is en_US - companies -VATIsUsed=Assujetti à la TSS -VATIsNotUsed=Non assujetti à la TSS +VATIsUsed=Assujetti à la TGC +VATIsNotUsed=Non assujetti à la TGC diff --git a/htdocs/langs/fr_NC/compta.lang b/htdocs/langs/fr_NC/compta.lang index f22e834c4a5..2d7a5468f84 100644 --- a/htdocs/langs/fr_NC/compta.lang +++ b/htdocs/langs/fr_NC/compta.lang @@ -1,21 +1,21 @@ # Dolibarr language file - Source file is en_US - compta -VATToPay=TSS ventes -VATReceived=TSS collectée -VATToCollect=TSS achats -VATSummary=Balance de TSS -VATPaid=TSS payée -VATCollected=TSS récupérée -PaymentVat=Règlement TSS -VATPayment=Règlement TSS -VATPayments=Règlements TSS -ShowVatPayment=Affiche paiement TSS -RulesResultInOut=- Il inclut les règlements effectivement réalisés pour les factures, les charges et la TSS.
- Il se base sur la date de règlement de ces factures, charges et TSS. -VATReportByCustomersInInputOutputMode=Rapport par client des TSS collectées et payées (TSS sur encaissement) -VATReportByQuartersInInputOutputMode=Rapport par taux des TSS collectées et payées (TSS sur encaissement) -SeeVATReportInInputOutputMode=Voir le rapport %sTSS encaissement%s pour mode de calcul standard -SeeVATReportInDueDebtMode=Voir le rapport %sTSS sur débit%s pour mode de calcul avec option sur les débits -RulesVATInServices=- Pour les services, le rapport inclut les TSS des règlements effectivement reçus ou émis en se basant sur la date du règlement. -RulesVATInProducts=- Pour les biens matériels, il inclut les TSS des factures en se basant sur la date de facture. -RulesVATDueServices=- Pour les services, le rapport inclut les TSS des factures dues, payées ou non en se basant sur la date de facture. -RulesVATDueProducts=- Pour les biens matériels, il inclut les TSS des factures en se basant sur la date de facture. -CalculationRuleDesc=Pour calculer le total de TSS, il existe 2 modes:
Le mode 1 consiste à arrondir la TSS de chaque ligne et à sommer cet arrondi.
Le mode 2 consiste à sommer la tva de chaque ligne puis à l'arrondir.
Les résultats peuvent différer de quelques centimes. Le mode par défaut est le mode %s. +VATToPay=TGC ventes +VATReceived=TGC collectée +VATToCollect=TGC achats +VATSummary=Balance de TGC +VATPaid=TGC payée +VATCollected=TGC récupérée +PaymentVat=Règlement TGC +VATPayment=Règlement TGC +VATPayments=Règlements TGC +ShowVatPayment=Affiche paiement TGC +RulesResultInOut=- Il inclut les règlements effectivement réalisés pour les factures, les charges et la TGC.
- Il se base sur la date de règlement de ces factures, charges et TGC. +VATReportByCustomersInInputOutputMode=Rapport par client des TGC collectées et payées (TGC sur encaissement) +VATReportByQuartersInInputOutputMode=Rapport par taux des TGC collectées et payées (TGC sur encaissement) +SeeVATReportInInputOutputMode=Voir le rapport %sTGC encaissement%s pour mode de calcul standard +SeeVATReportInDueDebtMode=Voir le rapport %sTGC sur débit%s pour mode de calcul avec option sur les débits +RulesVATInServices=- Pour les services, le rapport inclut les TGC des règlements effectivement reçus ou émis en se basant sur la date du règlement. +RulesVATInProducts=- Pour les biens matériels, il inclut les TGC des factures en se basant sur la date de facture. +RulesVATDueServices=- Pour les services, le rapport inclut les TGC des factures dues, payées ou non en se basant sur la date de facture. +RulesVATDueProducts=- Pour les biens matériels, il inclut les TGC des factures en se basant sur la date de facture. +CalculationRuleDesc=Pour calculer le total de TGC, il existe 2 modes:
Le mode 1 consiste à arrondir la TGC de chaque ligne et à sommer cet arrondi.
Le mode 2 consiste à sommer la tva de chaque ligne puis à l'arrondir.
Les résultats peuvent différer de quelques centimes. Le mode par défaut est le mode %s. diff --git a/htdocs/langs/fr_NC/main.lang b/htdocs/langs/fr_NC/main.lang index 82c7a4ee746..c2d48114259 100644 --- a/htdocs/langs/fr_NC/main.lang +++ b/htdocs/langs/fr_NC/main.lang @@ -3,7 +3,7 @@ DIRECTION=ltr FONTFORPDF=helvetica FONTSIZEFORPDF=10 SeparatorDecimal=, -SeparatorThousand=None +SeparatorThousand=Space FormatDateShort=%d/%m/%Y FormatDateShortInput=%d/%m/%Y FormatDateShortJava=dd/MM/yyyy @@ -20,7 +20,7 @@ FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M ErrorNoVATRateDefinedForSellerCountry=Erreur, aucun taux de taxe défini pour le pays '%s'. -AmountVAT=Montant TSS -TotalVAT=Total TSS -VAT=TSS -VATRate=Taux TSS +AmountVAT=Montant TGC +TotalVAT=Total TGC +VAT=TGC +VATRate=Taux TGC diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 40b2352734d..5fd79e96c23 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -79,6 +79,8 @@ function testSqlAndScriptInject($val, $type) $inj += preg_match('/union.+select/i', $val); $inj += preg_match('/(\.\.%2f)+/i', $val); } + // For XSS Injection done by closing textarea to exucute content into a textarea field + $inj += preg_match('/<\/textarea/i', $val); // For XSS Injection done by adding javascript with script // This is all cases a browser consider text is javascript: // When it found ' 0 if OK + * @return int < 0 if KO, 0 if link already exists for this product, > 0 if OK */ public function add_fournisseur($user, $id_fourn, $ref_fourn, $quantity) { @@ -3498,6 +3498,9 @@ class Product extends CommonObject dol_syslog(get_class($this)."::add_fournisseur id_fourn = ".$id_fourn." ref_fourn=".$ref_fourn." quantity=".$quantity, LOG_DEBUG); + // Clean parameters + $quantity = price2num($quantity, 'MS'); + if ($ref_fourn) { $sql = "SELECT rowid, fk_product"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price"; @@ -3524,7 +3527,7 @@ class Product extends CommonObject if ($ref_fourn) { $sql.= " AND ref_fourn = '".$this->db->escape($ref_fourn)."'"; } else { $sql.= " AND (ref_fourn = '' OR ref_fourn IS NULL)"; } - $sql.= " AND quantity = '".$quantity."'"; + $sql.= " AND quantity = ".$quantity; $sql.= " AND fk_product = ".$this->id; $sql.= " AND entity IN (".getEntity('productsupplierprice').")"; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index cb56ff63cfc..42644f24098 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -154,7 +154,7 @@ if (empty($reshook)) if (empty($ref_fourn)) $ref_fourn=GETPOST("search_ref_fourn"); $ref_fourn_old=GETPOST("ref_fourn_old"); if (empty($ref_fourn_old)) $ref_fourn_old = $ref_fourn; - $quantity=GETPOST("qty"); + $quantity=price2num(GETPOST("qty", 'nohtml'), 'MS'); $remise_percent=price2num(GETPOST('remise_percent', 'alpha')); $npr = preg_match('/\*/', $_POST['tva_tx']) ? 1 : 0 ; $tva_tx = str_replace('*', '', GETPOST('tva_tx', 'alpha')); @@ -481,7 +481,7 @@ if ($id > 0 || $ref) print ''; print ''.$langs->trans("QtyMin").''; print ''; - $quantity = GETPOST('qty') ? GETPOST('qty') : "1"; + $quantity = GETPOSTISSET('qty') ? price2num(GETPOST('qty', 'nohtml'), 'MS') : "1"; if ($rowid) { print ''; diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 672f17ca81b..f23f71552c3 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -137,6 +137,7 @@ if ($action == 'valid' && $user->rights->facture->creer) $bankaccount=$conf->global->$accountname; } $now=dol_now(); + $res = 0; $invoice = new Facture($db); $invoice->fetch($placeid); @@ -179,41 +180,42 @@ if ($action == 'valid' && $user->rights->facture->creer) $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey); - $invoice->validate($user, '', $conf->global->$constantforkey); + $res = $invoice->validate($user, '', $conf->global->$constantforkey); $conf->global->STOCK_CALCULATE_ON_BILL = $savconst; } else { - $invoice->validate($user); + $res = $invoice->validate($user); } // Add the payment - $payment=new Paiement($db); - $payment->datepaye = $now; - $payment->fk_account = $bankaccount; - $payment->amounts[$invoice->id] = $amountofpayment; + if ($res > 0) { + $payment = new Paiement($db); + $payment->datepaye = $now; + $payment->fk_account = $bankaccount; + $payment->amounts[$invoice->id] = $amountofpayment; - // If user has not used change control, add total invoice payment - if ($amountofpayment == 0) $payment->amounts[$invoice->id] = $invoice->total_ttc; + // If user has not used change control, add total invoice payment + if ($amountofpayment == 0) $payment->amounts[$invoice->id] = $invoice->total_ttc; - $payment->paiementid=$paiementid; - $payment->num_payment=$invoice->ref; + $payment->paiementid=$paiementid; + $payment->num_payment=$invoice->ref; - $payment->create($user); - $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + $payment->create($user); + $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); - $remaintopay = $invoice->getRemainToPay(); - if ($remaintopay == 0) - { - dol_syslog("Invoice is paid, so we set it to pay"); - $result = $invoice->set_paid($user); - if ($result > 0) $invoice->paye = 1; - } - else - { - dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay); - } + $remaintopay = $invoice->getRemainToPay(); + if ($remaintopay == 0) { + dol_syslog("Invoice is paid, so we set it to pay"); + $result = $invoice->set_paid($user); + if ($result > 0) $invoice->paye = 1; + } else { + dol_syslog("Invoice is not paid, remain to pay = " . $remaintopay); + } + } else { + dol_htmloutput_errors($invoice->error, $invoice->errors, 1); + } } if ($action == 'history') diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index 83f4aefb5f5..9fd19b7378f 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -190,7 +190,7 @@ else print "var received=0;";
-
trans("Received"); ?>:
+
trans("Received"); ?>:
trans("Change"); ?>:
@@ -225,7 +225,7 @@ $numpad=$conf->global->TAKEPOS_NUMPAD; if ($paycode == 'CB') $paycode = 'card'; if ($paycode == 'CHQ') $paycode = 'cheque'; ?> - + @@ -238,7 +238,7 @@ $numpad=$conf->global->TAKEPOS_NUMPAD; if ($paycode == 'CB') $paycode = 'card'; if ($paycode == 'CHQ') $paycode = 'cheque'; ?> - + @@ -253,7 +253,7 @@ $button = array_pop($action_buttons); if ($paycode == 'CB') $paycode = 'card'; if ($paycode == 'CHQ') $paycode = 'cheque'; ?> - + - + lastname = GETPOST("lastname", 'alpha'); - $object->firstname = GETPOST("firstname", 'alpha'); - $object->login = GETPOST("login", 'alpha'); - $object->api_key = GETPOST("api_key", 'alpha'); - $object->gender = GETPOST("gender", 'alpha'); - $birth = dol_mktime(0, 0, 0, GETPOST('birthmonth'), GETPOST('birthday'), GETPOST('birthyear')); + $object->lastname = GETPOST("lastname", 'alphanohtml'); + $object->firstname = GETPOST("firstname", 'alphanohtml'); + $object->login = GETPOST("login", 'alphanohtml'); + $object->api_key = GETPOST("api_key", 'alphanohtml'); + $object->gender = GETPOST("gender", 'aZ09'); + $birth = dol_mktime(0, 0, 0, GETPOST('birthmonth', 'int'), GETPOST('birthday', 'int'), GETPOST('birthyear', 'int')); $object->birth = $birth; - $object->admin = GETPOST("admin", 'alpha'); + $object->admin = GETPOST("admin", 'int'); $object->address = GETPOST('address', 'alphanohtml'); $object->zip = GETPOST('zipcode', 'alphanohtml'); $object->town = GETPOST('town', 'alphanohtml'); @@ -217,8 +216,8 @@ if (empty($reshook)) { $object->facebook = GETPOST("facebook", 'alphanohtml'); $object->linkedin = GETPOST("linkedin", 'alphanohtml'); - $object->email = preg_replace('/\s+/', '', GETPOST("email", 'alpha')); - $object->job = GETPOST("job", 'alpha'); + $object->email = preg_replace('/\s+/', '', GETPOST("email", 'alphanohtml')); + $object->job = GETPOST("job", 'nohtml'); $object->signature = GETPOST("signature", 'none'); $object->accountancy_code = GETPOST("accountancy_code", 'alphanohtml'); $object->note = GETPOST("note", 'none'); @@ -233,10 +232,10 @@ if (empty($reshook)) { $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; $object->color = GETPOST("color", 'alphanohtml') != '' ? GETPOST("color", 'alphanohtml') : ''; - $dateemployment = dol_mktime(0, 0, 0, GETPOST('dateemploymentmonth'), GETPOST('dateemploymentday'), GETPOST('dateemploymentyear')); + $dateemployment = dol_mktime(0, 0, 0, GETPOST('dateemploymentmonth', 'int'), GETPOST('dateemploymentday', 'int'), GETPOST('dateemploymentyear', 'int')); $object->dateemployment = $dateemployment; - $dateemploymentend = dol_mktime(0, 0, 0, GETPOST('dateemploymentendmonth'), GETPOST('dateemploymentendday'), GETPOST('dateemploymentendyear')); + $dateemploymentend = dol_mktime(0, 0, 0, GETPOST('dateemploymentendmonth', 'int'), GETPOST('dateemploymentendday', 'int'), GETPOST('dateemploymentendyear', 'int')); $object->dateemploymentend = $dateemploymentend; $object->fk_warehouse = GETPOST('fk_warehouse', 'int'); @@ -348,15 +347,15 @@ if (empty($reshook)) { $db->begin(); - $object->lastname = GETPOST("lastname", 'alpha'); - $object->firstname = GETPOST("firstname", 'alpha'); - $object->login = GETPOST("login", 'alpha'); - $object->gender = GETPOST("gender", 'alpha'); - $birth = dol_mktime(0, 0, 0, GETPOST('birthmonth'), GETPOST('birthday'), GETPOST('birthyear')); + $object->lastname = GETPOST("lastname", 'alphanohtml'); + $object->firstname = GETPOST("firstname", 'alphanohtml'); + $object->login = GETPOST("login", 'alphanohtml'); + $object->gender = GETPOST("gender", 'aZ09'); + $birth = dol_mktime(0, 0, 0, GETPOST('birthmonth', 'int'), GETPOST('birthday', 'int'), GETPOST('birthyear', 'int')); $object->birth = $birth; $object->pass = GETPOST("password", 'none'); - $object->api_key = (GETPOST("api_key", 'alpha')) ? GETPOST("api_key", 'alpha') : $object->api_key; - if (! empty($user->admin)) $object->admin = GETPOST("admin"); // admin flag can only be set/unset by an admin user. A test is also done later when forging sql request + $object->api_key = (GETPOST("api_key", 'alphanohtml')) ? GETPOST("api_key", 'alphanohtml') : $object->api_key; + if (! empty($user->admin)) $object->admin = GETPOST("admin", "int"); // admin flag can only be set/unset by an admin user. A test is also done later when forging sql request $object->address = GETPOST('address', 'alphanohtml'); $object->zip = GETPOST('zipcode', 'alphanohtml'); $object->town = GETPOST('town', 'alphanohtml'); @@ -365,15 +364,17 @@ if (empty($reshook)) { $object->office_phone = GETPOST("office_phone", 'alphanohtml'); $object->office_fax = GETPOST("office_fax", 'alphanohtml'); $object->user_mobile = GETPOST("user_mobile", 'alphanohtml'); - $object->skype = GETPOST("skype", 'alpha'); - $object->twitter = GETPOST("twitter", 'alpha'); - $object->facebook = GETPOST("facebook", 'alpha'); - $object->linkedin = GETPOST("linkedin", 'alpha'); - $object->email = preg_replace('/\s+/', '', GETPOST("email", 'alpha')); - $object->job = GETPOST("job", 'alpha'); + + $object->skype = GETPOST("skype", 'alphanohtml'); + $object->twitter = GETPOST("twitter", 'alphanohtml'); + $object->facebook = GETPOST("facebook", 'alphanohtml'); + $object->linkedin = GETPOST("linkedin", 'alphanohtml'); + + $object->email = preg_replace('/\s+/', '', GETPOST("email", 'alphanohtml')); + $object->job = GETPOST("job", 'nohtml'); $object->signature = GETPOST("signature", 'none'); - $object->accountancy_code = GETPOST("accountancy_code", 'alpha'); - $object->openid = GETPOST("openid", 'alpha'); + $object->accountancy_code = GETPOST("accountancy_code", 'alphanohtml'); + $object->openid = GETPOST("openid", 'alphanohtml'); $object->fk_user = GETPOST("fk_user", 'int') > 0 ? GETPOST("fk_user", 'int') : 0; $object->employee = GETPOST('employee', 'int'); @@ -383,7 +384,7 @@ if (empty($reshook)) { $object->salaryextra = GETPOST("salaryextra", 'alphanohtml') != '' ? GETPOST("salaryextra", 'alphanohtml') : ''; $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; - $object->color = GETPOST("color", 'alpha') != '' ? GETPOST("color", 'alpha') : ''; + $object->color = GETPOST("color", 'alphanohtml') != '' ? GETPOST("color", 'alphanohtml') : ''; $dateemployment = dol_mktime(0, 0, 0, GETPOST('dateemploymentmonth', 'int'), GETPOST('dateemploymentday', 'int'), GETPOST('dateemploymentyear', 'int')); $object->dateemployment = $dateemployment; $dateemploymentend = dol_mktime(0, 0, 0, GETPOST('dateemploymentendmonth', 'int'), GETPOST('dateemploymentendday', 'int'), GETPOST('dateemploymentendyear', 'int')); @@ -1203,7 +1204,7 @@ if ($action == 'create' || $action == 'adduserldap') // Position/Job print ''.$langs->trans("PostOrFunction").''; print ''; - print ''; + print ''; print ''; // Default warehouse diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index b457c4c0fa7..68b93c6ec88 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -130,6 +130,24 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__."\n"; } + /** + * testSetLang + * + * @return string + */ + public function testSetLang() + { + global $conf; + $conf=$this->savconf; + + $tmplangs = new Translate('', $conf); + + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "' malicious text with quote"; + $tmplangs->setDefaultLang('auto'); + print __METHOD__.' $tmplangs->defaultlang='.$tmplangs->defaultlang."\n"; + $this->assertEquals($tmplangs->defaultlang, 'malicioustextwithquote_MALICIOUSTEXTWITHQUOTE'); + } + /** * testGETPOST *