diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 1c76d0408da..fa8cd088604 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1074,7 +1074,7 @@ class AccountancyExport print $racine_subledger_account.$separator; // deprecated CPTG & CPTA use instead // MONT - print price(abs($line->montant), 0, '', 1, 2).$separator; + print price(abs($line->montant), 0, '', 1, 2, 2).$separator; // CODC print $line->sens.$separator; // CPTG diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index f57e4408a6f..f0c24ab1b8a 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -68,9 +68,11 @@ class Paiement extends CommonObject */ public $montant; - public $amount; // Total amount of payment - public $amounts = array(); // Array of amounts - public $multicurrency_amounts = array(); // Array of amounts + public $amount; // Total amount of payment (in the main currency) + public $multicurrency_amount; // Total amount of payment (in the currency of the bank account) + public $amounts = array(); // array: invoice ID => amount for that invoice (in the main currency)> + public $multicurrency_amounts = array(); // array: invoice ID => amount for that invoice (in the invoice's currency)> + public $author; public $paiementid; // Type of payment. Id saved into fields fk_paiement on llx_paiement public $paiementcode; // Code of payment. @@ -159,7 +161,7 @@ class Paiement extends CommonObject */ public function fetch($id, $ref = '', $fk_bank = '') { - $sql = 'SELECT p.rowid, p.ref, p.datep as dp, p.amount, p.statut, p.ext_payment_id, p.ext_payment_site, p.fk_bank,'; + $sql = 'SELECT p.rowid, p.ref, p.datep as dp, p.amount, p.statut, p.ext_payment_id, p.ext_payment_site, p.fk_bank, p.multicurrency_amount,'; $sql .= ' c.code as type_code, c.libelle as type_label,'; $sql .= ' p.num_paiement as num_payment, p.note,'; $sql .= ' b.fk_account'; @@ -179,6 +181,7 @@ class Paiement extends CommonObject if ($this->db->num_rows($resql)) { $obj = $this->db->fetch_object($resql); + $this->id = $obj->rowid; $this->ref = $obj->ref ? $obj->ref : $obj->rowid; $this->date = $this->db->jdate($obj->dp); @@ -187,6 +190,7 @@ class Paiement extends CommonObject $this->num_payment = $obj->num_payment; $this->montant = $obj->amount; // deprecated $this->amount = $obj->amount; + $this->multicurrency_amount = $obj->multicurrency_amount; $this->note = $obj->note; $this->type_label = $obj->type_label; $this->type_code = $obj->type_code; diff --git a/htdocs/core/actions_linkedfiles.inc.php b/htdocs/core/actions_linkedfiles.inc.php index 20630c487f7..7884fc09e67 100644 --- a/htdocs/core/actions_linkedfiles.inc.php +++ b/htdocs/core/actions_linkedfiles.inc.php @@ -206,8 +206,10 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') if (empty($reshook)) { - if (!file_exists($destpath)) - { + if (preg_match('/^\./', $filenameto)) { + $langs->load("errors"); // lang must be loaded because we can't rely on loading during output, we need var substitution to be done now. + setEventMessages($langs->trans("ErrorFilenameCantStartWithDot", $filenameto), null, 'errors'); + } elseif (!file_exists($destpath)) { $result = dol_move($srcpath, $destpath); if ($result) { @@ -231,11 +233,11 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') setEventMessages($langs->trans("FileRenamed"), null); } else { - $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now. + $langs->load("errors"); // lang must be loaded because we can't rely on loading during output, we need var substitution to be done now. setEventMessages($langs->trans("ErrorFailToRenameFile", $filenamefrom, $filenameto), null, 'errors'); } } else { - $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now. + $langs->load("errors"); // lang must be loaded because we can't rely on loading during output, we need var substitution to be done now. setEventMessages($langs->trans("ErrorDestinationAlreadyExists", $filenameto), null, 'errors'); } } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 74798a37e85..39fcb84996e 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -320,11 +320,13 @@ function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir) // Complete filearray with properties found into $filearrayindatabase foreach ($filearray as $key => $val) { + $tmpfilename = preg_replace('/\.noexe$/', '', $filearray[$key]['name']); + $found = 0; // Search if it exists into $filearrayindatabase foreach ($filearrayindatabase as $key2 => $val2) { - if ($filearrayindatabase[$key2]['name'] == $filearray[$key]['name']) + if ($filearrayindatabase[$key2]['name'] == $tmpfilename) { $filearray[$key]['position_name'] = ($filearrayindatabase[$key2]['position'] ? $filearrayindatabase[$key2]['position'] : '0').'_'.$filearrayindatabase[$key2]['name']; $filearray[$key]['position'] = $filearrayindatabase[$key2]['position']; @@ -345,7 +347,7 @@ function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir) $filearray[$key]['acl'] = ''; $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filearray[$key]['fullname']); - if (!preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filetorenameafter)) // If not a tmp file + if (!preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filename)) // If not a tmp file { dol_syslog("list_of_documents We found a file called '".$filearray[$key]['name']."' not indexed into database. We add it"); include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; @@ -1513,6 +1515,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesess if (!empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error'] { dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG); + if (dol_mkdir($upload_dir) >= 0) { $TFile = $_FILES[$varfiles]; @@ -1539,6 +1542,13 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesess $destfile = preg_replace('/__file__/', $TFile['name'][$i], $savingdocmask); } + $filenameto = basename($destfile); + if (preg_match('/^\./', $filenameto)) { + $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now. + setEventMessages($langs->trans("ErrorFilenameCantStartWithDot", $filenameto), null, 'errors'); + break; + } + // dol_sanitizeFileName the file name and lowercase extension $info = pathinfo($destfull); $destfull = $info['dirname'].'/'.dol_sanitizeFileName($info['filename'].($info['extension'] != '' ? ('.'.strtolower($info['extension'])) : '')); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 2187d6dc655..cd95fe40e5d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8600,15 +8600,16 @@ function fetchObjectByElement($element_id, $element_type, $element_ref = '') /** * Return if a file can contains executable content * - * @param string $filename File NamedRange + * @param string $filename File name to test * @return boolean True if yes, False if no */ function isAFileWithExecutableContent($filename) { - if (preg_match('/\.(htm|html|js|php|php\d+|phtml|pl|py|cgi|ksh|sh|bash|bat|cmd|wpk|exe|dmg)$/i', $filename)) + if (preg_match('/\.(htm|html|js|phar|php|php\d+|phtml|pht|pl|py|cgi|ksh|sh|shtml|bash|bat|cmd|wpk|exe|dmg)$/i', $filename)) { return true; } + return false; } diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 5da86289ca0..3c1d143ae55 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -279,9 +279,12 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f if (!$readok) accessforbidden(); //print "Read access is ok"; - // Check write permission from module (we need to know write permission to create but also to delete drafts record) + // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files) $createok = 1; $nbko = 0; - if (GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update' || ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete')) + $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update'); + $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'); + + if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) { foreach ($featuresarray as $feature) { @@ -336,7 +339,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f // If a or and at least one ok if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok = 1; - if ((GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update') && !$createok) accessforbidden(); + if ($wemustcheckpermissionforcreate && !$createok) accessforbidden(); //print "Write access is ok"; } diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 624311c74f0..b65c4fd956b 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -298,6 +298,14 @@ class modFournisseur extends DolibarrModules 'p.ref'=>'ProductRef', 'p.label'=>'ProductLabel', 'p.accountancy_code_buy'=>'ProductAccountancyBuyCode', 'project.rowid'=>'ProjectId', 'project.ref'=>'ProjectRef', 'project.title'=>'ProjectLabel' ); + if (! empty($conf->multicurrency->enabled)) + { + $this->export_fields_array[$r]['f.multicurrency_code'] = 'Currency'; + $this->export_fields_array[$r]['f.multicurrency_tx'] = 'CurrencyRate'; + $this->export_fields_array[$r]['f.multicurrency_total_ht'] = 'MulticurrencyAmountHT'; + $this->export_fields_array[$r]['f.multicurrency_total_tva'] = 'MulticurrencyAmountVAT'; + $this->export_fields_array[$r]['f.multicurrency_total_ttc'] = 'MulticurrencyAmountTTC'; + } //$this->export_TypeFields_array[$r]=array( // 's.rowid'=>"List:societe:CompanyName",'s.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','c.code'=>'Text','s.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text', // 's.ape'=>'Text','s.idprof4'=>'Text','s.tva_intra'=>'Text','f.ref'=>"Text",'f.datec'=>"Date",'f.datef'=>"Date",'f.total_ht'=>"Numeric",'f.total_ttc'=>"Numeric",'f.total_tva'=>"Numeric", @@ -425,6 +433,14 @@ class modFournisseur extends DolibarrModules 'f.fk_statut'=>'InvoiceStatus', 'f.note_public'=>"InvoiceNote", 'p.rowid'=>'PaymentId', 'pf.amount'=>'AmountPayment', 'p.datep'=>'DatePayment', 'p.num_paiement'=>'PaymentNumber', 'p.fk_bank'=>'IdTransaction', 'project.rowid'=>'ProjectId', 'project.ref'=>'ProjectRef', 'project.title'=>'ProjectLabel' ); + if (! empty($conf->multicurrency->enabled)) + { + $this->export_fields_array[$r]['f.multicurrency_code'] = 'Currency'; + $this->export_fields_array[$r]['f.multicurrency_tx'] = 'CurrencyRate'; + $this->export_fields_array[$r]['f.multicurrency_total_ht'] = 'MulticurrencyAmountHT'; + $this->export_fields_array[$r]['f.multicurrency_total_tva'] = 'MulticurrencyAmountVAT'; + $this->export_fields_array[$r]['f.multicurrency_total_ttc'] = 'MulticurrencyAmountTTC'; + } //$this->export_TypeFields_array[$r]=array( // 's.rowid'=>"List:societe:CompanyName",'s.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','c.code'=>'Text','s.phone'=>'Text', // 's.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.tva_intra'=>'Text','f.ref'=>"Text",'f.datec'=>"Date",'f.datef'=>"Date", @@ -511,6 +527,14 @@ class modFournisseur extends DolibarrModules 'fd.total_tva'=>"LineTotalVAT", 'fd.product_type'=>'TypeOfLineServiceOrProduct', 'fd.ref'=>'RefSupplier', 'fd.fk_product'=>'ProductId', 'p.ref'=>'ProductRef', 'p.label'=>'ProductLabel', 'project.rowid'=>'ProjectId', 'project.ref'=>'ProjectRef', 'project.title'=>'ProjectLabel' ); + if (! empty($conf->multicurrency->enabled)) + { + $this->export_fields_array[$r]['f.multicurrency_code'] = 'Currency'; + $this->export_fields_array[$r]['f.multicurrency_tx'] = 'CurrencyRate'; + $this->export_fields_array[$r]['f.multicurrency_total_ht'] = 'MulticurrencyAmountHT'; + $this->export_fields_array[$r]['f.multicurrency_total_tva'] = 'MulticurrencyAmountVAT'; + $this->export_fields_array[$r]['f.multicurrency_total_ttc'] = 'MulticurrencyAmountTTC'; + } if (empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)) { unset($this->export_fields_array['f.date_approve2']); diff --git a/htdocs/fourn/class/paiementfourn.class.php b/htdocs/fourn/class/paiementfourn.class.php index ddfc3b1f8a4..e6795593721 100644 --- a/htdocs/fourn/class/paiementfourn.class.php +++ b/htdocs/fourn/class/paiementfourn.class.php @@ -91,12 +91,12 @@ class PaiementFourn extends Paiement { $error = 0; - $sql = 'SELECT p.rowid, p.ref, p.entity, p.datep as dp, p.amount, p.statut, p.fk_bank,'; + $sql = 'SELECT p.rowid, p.ref, p.entity, p.datep as dp, p.amount, p.statut, p.fk_bank, p.multicurrency_amount,'; $sql .= ' c.code as paiement_code, c.libelle as paiement_type,'; $sql .= ' p.num_paiement as num_payment, p.note, b.fk_account'; $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid '; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid'; $sql .= ' WHERE p.entity IN ('.getEntity('facture_fourn').')'; if ($id > 0) $sql .= ' AND p.rowid = '.$id; @@ -113,6 +113,7 @@ class PaiementFourn extends Paiement if ($num > 0) { $obj = $this->db->fetch_object($resql); + $this->id = $obj->rowid; $this->ref = $obj->ref; $this->entity = $obj->entity; @@ -125,11 +126,13 @@ class PaiementFourn extends Paiement $this->bank_line = $obj->fk_bank; $this->montant = $obj->amount; // deprecated $this->amount = $obj->amount; + $this->multicurrency_amount = $obj->multicurrency_amount; $this->note = $obj->note; $this->note_private = $obj->note; $this->type_code = $obj->paiement_code; $this->type_label = $obj->paiement_type; $this->statut = $obj->statut; + $error = 1; } else { $error = -2; // TODO Use 0 instead diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 6dbb616f2fc..449f4986592 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -183,6 +183,7 @@ ErrorBadDefinitionOfMenuArrayInModuleDescriptor=Bad Definition Of Menu Array In ErrorSavingChanges=An error has occurred when saving the changes ErrorWarehouseRequiredIntoShipmentLine=Warehouse is required on the line to ship ErrorFileMustHaveFormat=File must have format %s +ErrorFilenameCantStartWithDot=Filename can't start with a '.' ErrorSupplierCountryIsNotDefined=Country for this vendor is not defined. Correct this first. ErrorsThirdpartyMerge=Failed to merge the two records. Request canceled. ErrorStockIsNotEnoughToAddProductOnOrder=Stock is not enough for product %s to add it into a new order.