From 7c01e984f87a03f1cc1130494a56020c509b6557 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Mon, 22 Apr 2013 10:05:32 +0200 Subject: [PATCH 01/29] Fix : column missing in migration for price by qty --- htdocs/install/mysql/migration/3.2.0-3.3.0.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql index eaf395a6204..0ba2270dd88 100755 --- a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql +++ b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql @@ -848,6 +848,7 @@ ALTER TABLE llx_product_price_by_qty ADD CONSTRAINT fk_product_price_by_qty_fk_p ALTER TABLE llx_product_price_by_qty ADD remise_percent DOUBLE NOT NULL DEFAULT '0' AFTER price_ttc; ALTER TABLE llx_product_price_by_qty ADD remise DOUBLE NOT NULL DEFAULT '0' AFTER remise_percent; +ALTER TABLE llx_product_price_by_qty ADD unitprice DOUBLE (24,8) NOT NULL DEFAULT '0' AFTER qty_min; -- Change index name to be compliant with SQL standard, index name must be unique in database schema ALTER TABLE llx_c_actioncomm DROP INDEX code; From 882da5d7d7f1e9a8d9f1a1a7dd1328842d61937e Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Mon, 22 Apr 2013 11:54:30 +0200 Subject: [PATCH 02/29] Fix : price by quantity, bad column name --- htdocs/install/mysql/migration/3.2.0-3.3.0.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql index 0ba2270dd88..f7054bc4184 100755 --- a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql +++ b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql @@ -849,6 +849,7 @@ ALTER TABLE llx_product_price_by_qty ADD CONSTRAINT fk_product_price_by_qty_fk_p ALTER TABLE llx_product_price_by_qty ADD remise_percent DOUBLE NOT NULL DEFAULT '0' AFTER price_ttc; ALTER TABLE llx_product_price_by_qty ADD remise DOUBLE NOT NULL DEFAULT '0' AFTER remise_percent; ALTER TABLE llx_product_price_by_qty ADD unitprice DOUBLE (24,8) NOT NULL DEFAULT '0' AFTER qty_min; +ALTER TABLE llx_product_price_by_qty CHANGE qty_min quantity DOUBLE NULL DEFAULT NULL; -- Change index name to be compliant with SQL standard, index name must be unique in database schema ALTER TABLE llx_c_actioncomm DROP INDEX code; From 6adaf2fa8fde1788ff9392605e795b5732234364 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 13:02:10 +0200 Subject: [PATCH 03/29] Fix: Pb when using virtual products inside virtual products --- htdocs/product/class/product.class.php | 153 +++++++++++-------------- 1 file changed, 65 insertions(+), 88 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 49f1d495cde..22c6aa0e6c1 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1799,8 +1799,16 @@ class Product extends CommonObject */ function add_sousproduit($id_pere, $id_fils,$qty) { - $sql = 'DELETE from '.MAIN_DB_PREFIX.'product_association'; - $sql .= ' WHERE fk_product_pere = "'.$id_pere.'" AND fk_product_fils = "'.$id_fils.'"'; + // Clean parameters + if (! is_numeric($id_pere)) $id_pere=0; + if (! is_numeric($id_fils)) $id_fils=0; + + $result=$this->del_sousproduit($id_pere, $id_fils); + if ($result < 0) return $result; + + // Check not already father of id_pere (to avoid father -> child -> father links) + $sql = 'SELECT fk_product_pere from '.MAIN_DB_PREFIX.'product_association'; + $sql .= ' WHERE fk_product_pere = '.$id_fils.' AND fk_product_fils = '.$id_pere; if (! $this->db->query($sql)) { dol_print_error($this->db); @@ -1808,37 +1816,27 @@ class Product extends CommonObject } else { - $sql = 'SELECT fk_product_pere from '.MAIN_DB_PREFIX.'product_association'; - $sql .= ' WHERE fk_product_pere = "'.$id_fils.'" AND fk_product_fils = "'.$id_pere.'"'; - if (! $this->db->query($sql)) + $result = $this->db->query($sql); + if ($result) { - dol_print_error($this->db); - return -1; - } - else - { - $result = $this->db->query($sql); - if ($result) + $num = $this->db->num_rows($result); + if($num > 0) { - $num = $this->db->num_rows($result); - if($num > 0) + $this->error="isFatherOfThis"; + return -1; + } + else + { + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_association(fk_product_pere,fk_product_fils,qty)'; + $sql .= ' VALUES ('.$id_pere.', '.$id_fils.', '.$qty.')'; + if (! $this->db->query($sql)) { - $this->error="isFatherOfThis"; + dol_print_error($this->db); return -1; } else { - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_association(fk_product_pere,fk_product_fils,qty)'; - $sql .= ' VALUES ("'.$id_pere.'","'.$id_fils.'","'.$qty.'")'; - if (! $this->db->query($sql)) - { - dol_print_error($this->db); - return -1; - } - else - { - return 1; - } + return 1; } } } @@ -1850,14 +1848,18 @@ class Product extends CommonObject * * @param int $fk_parent Id du produit auquel ne sera plus lie le produit lie * @param int $fk_child Id du produit a ne plus lie - * @return int < 0 si erreur, > 0 si ok + * @return int < 0 if KO, > 0 if OK */ function del_sousproduit($fk_parent, $fk_child) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_association"; - $sql.= " WHERE fk_product_pere = '".$fk_parent."'"; - $sql.= " AND fk_product_fils = '".$fk_child."'"; + if (! is_numeric($fk_parent)) $fk_parent=0; + if (! is_numeric($fk_child)) $fk_child=0; + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_association"; + $sql.= " WHERE fk_product_pere = ".$fk_parent; + $sql.= " AND fk_product_fils = ".$fk_child; + + dol_syslog(get_class($this).'::del_sousproduit sql='.$sql); if (! $this->db->query($sql)) { dol_print_error($this->db); @@ -2122,7 +2124,7 @@ class Product extends CommonObject * Define value of this->res * * @param array $prod Products array - * @param string $compl_path Directory path + * @param string $compl_path Directory path of parents to add before * @param int $multiply Because each sublevel must be multiplicated by parent nb * @param int $level Init level * @return void @@ -2132,65 +2134,36 @@ class Product extends CommonObject global $conf,$langs; $product = new Product($this->db); - foreach($prod as $nom_pere => $desc_pere) + //var_dump($prod); + foreach($prod as $id_product => $desc_pere) // nom_pere is 0 or id of sub_product { if (is_array($desc_pere)) // If this parent desc is an array, this is an array of childs { $id=(! empty($desc_pere[0]) ? $desc_pere[0] :''); $nb=(! empty($desc_pere[1]) ? $desc_pere[1] :''); $type=(! empty($desc_pere[2]) ? $desc_pere[2] :''); + $label=(! empty($desc_pere[3]) ? $desc_pere[3] :''); + if ($multiply < 1) $multiply=1; - if ($multiply) - { - //print "XXX ".$desc_pere[1]." multiply=".$multiply; - $img=""; - $this->fetch($id); - $this->load_stock(); - if ($this->stock_warehouse[1]->real < $this->seuil_stock_alerte) - { - $img=img_warning($langs->trans("StockTooLow")); - } - $this->res[]= array( -/* "      -> - ".$compl_path.stripslashes($nom_pere)." - (".$desc_pere[1].") ".($desc_pere[1]*$multiply)."   - ".$this->stock_entrepot[1]." ".$img."", - $desc_pere[0], // Id product -*/ 'id'=>$id, // Id product - 'nb'=>$nb, // Nb of units that compose parent product - 'nb_total'=>$nb*$multiply, // Nb of units for all nb of product - 'stock'=>$this->stock_warehouse[1]->real, // Stock - 'stock_alert'=>$this->seuil_stock_alerte, // Stock alert - 'fullpath' => $compl_path.$nom_pere, // Label - 'type'=>$type // Nb of units that compose parent product - ); - } - else - { - $this->fetch($desc_pere[0]); - $this->load_stock(); - $this->res[]= array( -/* $compl_path.$nom_pere." (".$desc_pere[1].")", - $desc_pere[0], // Id product -*/ 'id'=>$id, // Id product + //print "XXX We add id=".$id." - label=".$label." - nb=".$nb." - multiply=".$multiply." fullpath=".$compl_path.$label."\n"; + $this->fetch($id); + $this->load_stock(); + $this->res[]= array( + 'id'=>$id, // Id product 'nb'=>$nb, // Nb of units that compose parent product - 'nb_total'=>$nb, // Nb of units for all nb of product - 'stock'=>$this->stock_warehouse[1]->real, // Stock + 'nb_total'=>$nb*$multiply, // Nb of units for all nb of product + 'stock'=>$this->stock_warehouse[1]->real, // Stock 'stock_alert'=>$this->seuil_stock_alerte, // Stock alert - 'fullpath' => $compl_path.$nom_pere, // Label - 'type'=>$type // Nb of units that compose parent product - ); - } - } - else if($nom_pere != "0" && $nom_pere != "1") - { - $this->res[]= array($compl_path.$nom_pere,$desc_pere); + 'fullpath' => $compl_path.$label, // Label + 'type'=>$type // Nb of units that compose parent product + ); } // Recursive call if child is an array - if (is_array($desc_pere[0])) + if (is_array($desc_pere['childs'])) { - $this ->fetch_prod_arbo($desc_pere[0], $nom_pere." -> ", $desc_pere[1]*$multiply, $level+1); + //print 'YYY We go down for '.$desc_pere[3]." -> \n"; + $this ->fetch_prod_arbo($desc_pere['childs'], $compl_path.$desc_pere[3]." -> ", $desc_pere[1]*$multiply, $level+1); } } } @@ -2227,11 +2200,12 @@ class Product extends CommonObject $this->res = array(); if (isset($this->sousprods) && is_array($this->sousprods)) { - foreach($this->sousprods as $nom_pere => $desc_pere) + foreach($this->sousprods as $prod_name => $desc_product) { - if (is_array($desc_pere)) $this->fetch_prod_arbo($desc_pere,"",$multiply); + if (is_array($desc_product)) $this->fetch_prod_arbo($desc_product,"",$multiply); } } + //var_dump($this->res); return $this->res; } @@ -2292,7 +2266,7 @@ class Product extends CommonObject /** - * Return all parent products fo current product + * Return all direct parent products fo current product * * @return array prod */ @@ -2323,31 +2297,34 @@ class Product extends CommonObject } /** - * Return childs of prodcut with if fk_parent + * Return childs of product $id * - * @param int $fk_parent Id of product to search childs of + * @param int $id Id of product to search childs of * @return array Prod */ - function getChildsArbo($fk_parent) + function getChildsArbo($id) { $sql = "SELECT p.rowid, p.label as label, pa.qty as qty, pa.fk_product_fils as id, p.fk_product_type"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ", ".MAIN_DB_PREFIX."product_association as pa"; $sql.= " WHERE p.rowid = pa.fk_product_fils"; - $sql.= " AND pa.fk_product_pere = ".$fk_parent; + $sql.= " AND pa.fk_product_pere = ".$id; + $sql.= " AND pa.fk_product_fils != ".$id; // This should not happens, it is to avoid infinite loop if it happens + dol_syslog(get_class($this).'::getChildsArbo sql='.$sql); $res = $this->db->query($sql); if ($res) { $prods = array(); while ($rec = $this->db->fetch_array($res)) { + $prods[$rec['rowid']]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type'],3=>$this->db->escape($rec['label'])); //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type']); - $prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']); + //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']); $listofchilds=$this->getChildsArbo($rec['id']); foreach($listofchilds as $keyChild => $valueChild) { - $prods[$this->db->escape($rec['label'])][$keyChild] = $valueChild; + $prods[$rec['rowid']]['childs'][$keyChild] = $valueChild; } } @@ -2369,14 +2346,14 @@ class Product extends CommonObject function get_sousproduits_arbo() { $parent = $this->getParent(); - foreach($parent as $key => $value) + foreach($parent as $key => $value) // key=label, value[0]=id { foreach($this->getChildsArbo($value[0]) as $keyChild => $valueChild) { $parent[$key][$keyChild] = $valueChild; } } - foreach($parent as $key => $value) + foreach($parent as $key => $value) // key=label, value is array of childs { $this->sousprods[$key] = $value; } From 60382f4b2cfc47eaf043cc1ebb0856c4de0e29e0 Mon Sep 17 00:00:00 2001 From: jfefe Date: Mon, 22 Apr 2013 13:18:40 +0200 Subject: [PATCH 04/29] New webservice to retrieve a document (work on invoice, propal, order and generic) --- htdocs/webservices/server_other.php | 212 +++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/htdocs/webservices/server_other.php b/htdocs/webservices/server_other.php index 64bc426d144..3578796838b 100644 --- a/htdocs/webservices/server_other.php +++ b/htdocs/webservices/server_other.php @@ -27,7 +27,7 @@ require_once '../master.inc.php'; require_once NUSOAP_PATH.'/nusoap.php'; // Include SOAP require_once DOL_DOCUMENT_ROOT.'/core/lib/ws.lib.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; - +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; @@ -82,6 +82,21 @@ $server->wsdl->addComplexType( ) ); +// Define WSDL Return object for document +$server->wsdl->addComplexType( + 'document', + 'complexType', + 'struct', + 'all', + '', + array( + 'filename' => array('name'=>'filename','type'=>'xsd:string'), + 'mimetype' => array('name'=>'mimetype','type'=>'xsd:string'), + 'content' => array('name'=>'content','type'=>'xsd:string'), + 'length' => array('name'=>'length','type'=>'xsd:string') + ) +); + // Define other specific objects // None @@ -107,6 +122,20 @@ $server->register( 'WS to get Versions' ); +// Register WSDL +$server->register( + 'getDocument', + // Entry values + array('authentication'=>'tns:authentication', 'modulepart'=>'xsd:string', 'file'=>'xsd:string' ), + // Exit values + array('result'=>'tns:result','document'=>'tns:document'), + $ns, + $ns.'#getDocument', + $styledoc, + $styleuse, + 'WS to get document' +); + // Full methods code @@ -144,6 +173,187 @@ function getVersions($authentication) } +/* + * Method to get a document by webservice +* \param authentication array +* \param modulepart array Properties of document +* +*/ +function getDocument($authentication, $modulepart, $file) +{ + global $db,$conf,$langs,$mysoc; + + dol_syslog("Function: getDocument login=".$authentication['login'].' - modulepart='.$modulepart.' - file='.$file); + + if ($authentication['entity']) $conf->entity=$authentication['entity']; + + $objectresp=array(); + $errorcode='';$errorlabel=''; + $error=0; + + // Properties of doc + $original_file = $file; + $type=dol_mimetype($original_file); + $relativefilepath = $ref . "/"; + $relativepath = $relativefilepath . $ref.'.pdf'; + + $accessallowed=0; + + $fuser=check_authentication($authentication,$error,$errorcode,$errorlabel); + + if ($fuser->societe_id) $socid=$fuser->societe_id; + + // Check parameters + if (! $error && ( ! $file || ! $modulepart ) ) + { + $error++; + $errorcode='BAD_PARAMETERS'; $errorlabel="Parameter file and modulepart must be both provided."; + } + + if (! $error) + { + $fuser->getrights(); + + // Suppression de la chaine de caractere ../ dans $original_file + $original_file = str_replace("../","/", $original_file); + + // find the subdirectory name as the reference + $refname=basename(dirname($original_file)."/"); + + // Wrapping for invoices + if ($modulepart == 'facture') + { + if ($fuser->rights->facture->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file = $conf->facture->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$refname."' AND entity=".$conf->entity; + } + // Wrapping pour les propales + else if ($modulepart == 'propal') + { + if ($fuser->rights->propal->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file = $conf->propal->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les commandes + else if ($modulepart == 'commande') + { + if ($fuser->rights->commande->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->commande->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$refname."' AND entity=".$conf->entity; + } + // Wrapping pour generic module + else + { + if ($fuser->rights->$modulepart->read || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->$modulepart->dir_output.'/'.$original_file; + // TODO + //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."registration WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Basic protection (against external users only) + if ($fuser->societe_id > 0) + { + if ($sqlprotectagainstexternals) + { + $resql = $db->query($sqlprotectagainstexternals); + if ($resql) + { + $num=$db->num_rows($resql); + $i=0; + while ($i < $num) + { + $obj = $db->fetch_object($resql); + if ($fuser->societe_id != $obj->fk_soc) + { + $accessallowed=0; + break; + } + $i++; + } + } + } + } + + // Security: + // Limite acces si droits non corrects + if (! $accessallowed) + { + $errorcode='NOT_PERMITTED'; + $errorlabel='Access not allowed'; + $error++; + } + + // Security: + // On interdit les remontees de repertoire ainsi que les pipe dans + // les noms de fichiers. + if (preg_match('/\.\./',$original_file) || preg_match('/[<>|]/',$original_file)) + { + dol_syslog("Refused to deliver file ".$original_file); + $errorcode='REFUSED'; + $errorlabel=''; + $error++; + } + + clearstatcache(); + + if(!$error) + { + if(file_exists($original_file)) + { + dol_syslog("Function: getDocument $original_file $filename content-type=$type"); + + $file=$fileparams['fullname']; + $filename = basename($file); + + $f = fopen($original_file,'r'); + $content_file = fread($f,filesize($original_file)); + + $objectret = array( + 'filename' => basename($original_file), + 'mimetype' => dol_mimetype($original_file), + 'content' => base64_encode($content_file), + 'length' => filesize($original_file) + ); + + // Create return object + $objectresp = array( + 'result'=>array('result_code'=>'OK', 'result_label'=>''), + 'document'=>$objectret + ); + } + else + { + dol_syslog("File doesn't exist ".$original_file); + $errorcode='NOT_FOUND'; + $errorlabel=''; + $error++; + } + } + } + + if ($error) + { + $objectresp = array( + 'result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel) + ); + } + + return $objectresp; +} + // Return the results. $server->service($HTTP_RAW_POST_DATA); From b9dab6d059d6f3abcd8557ef313171a92b0b964b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 13:57:24 +0200 Subject: [PATCH 05/29] Fix: Korting --- htdocs/langs/nl_NL/bills.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/nl_NL/bills.lang b/htdocs/langs/nl_NL/bills.lang index bc238882ecc..17880cd10af 100644 --- a/htdocs/langs/nl_NL/bills.lang +++ b/htdocs/langs/nl_NL/bills.lang @@ -223,9 +223,9 @@ ExportDataset_invoice_1 = Afnemersfacturen en factuurregels ExportDataset_invoice_2 = Afnemersfacturen en -betalingen ProformaBill = Proforma factuur: Reduction = Vermindering -ReductionShort = Minder +ReductionShort = Korting Reductions = Verminderingen -ReductionsShort = Minder +ReductionsShort = Korting Discount = Korting Discounts = Kortingen ShowDiscount = Toon korting From 88fe3e86f241a5694329f3395d54121a71135ebf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 14:01:47 +0200 Subject: [PATCH 06/29] Missing translation --- htdocs/langs/fr_FR/admin.lang | 4 ++-- htdocs/langs/fr_FR/externalsite.lang | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 51966eebcf2..2bff0050348 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -45,8 +45,8 @@ ErrorModuleRequireDolibarrVersion= Erreur, ce module requiert une version %s ou ErrorDecimalLargerThanAreForbidden= Erreur, les précisions supérieures à %s ne sont pas supportées. DictionnarySetup= Dictionnaires Dictionnary= Dictionnaires -ErrorReservedTypeSystemSystemAuto= -ErrorCodeCantContainZero= +ErrorReservedTypeSystemSystemAuto=Erreur, La valeur 'system' et 'systemauto' est réservée. +ErrorCodeCantContainZero=Erruer, le code ne peut contenir la valeur 0 DisableJavascript= Désactiver les fonctions Javascript et Ajax ConfirmAjax= Utiliser les popups de confirmation Ajax UseSearchToSelectCompany= Utiliser un champ avec autocomplétion pour choisir un tiers (plutôt qu'une liste déroulante).

Notez que si vous avez un nombre important de produits ou services (> 100 000), vous pouvez améliorer les performances en définissant la constante SOCIETE_DONOTSEARCH_ANYWHERE à 1 dans Configuration->Divers. La recherche sera alors limitée au début de la chaine. diff --git a/htdocs/langs/fr_FR/externalsite.lang b/htdocs/langs/fr_FR/externalsite.lang index 36c8686a3c3..e41bab65bbd 100644 --- a/htdocs/langs/fr_FR/externalsite.lang +++ b/htdocs/langs/fr_FR/externalsite.lang @@ -2,4 +2,4 @@ CHARSET=UTF-8 ExternalSiteSetup=Configuration du lien vers le site externe ExternalSiteURL=URL du site externe -ExternalSiteModuleNotComplete= \ No newline at end of file +ExternalSiteModuleNotComplete=La configuration du module "Lien externe" est incomplète. \ No newline at end of file From 63a5aee80e06d7fde214e8af7b8958192fd52779 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 12:35:31 +0200 Subject: [PATCH 07/29] Fix: broken features for fileupload --- htdocs/comm/action/document.php | 2 +- htdocs/core/class/fileupload.class.php | 28 +++++++++++++++++++++++++- htdocs/projet/class/task.class.php | 1 + htdocs/projet/tasks/document.php | 8 ++++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php index 9fcbca3e743..042f330b199 100755 --- a/htdocs/comm/action/document.php +++ b/htdocs/comm/action/document.php @@ -263,7 +263,7 @@ if ($objectid > 0) // Affiche formulaire upload $formfile=new FormFile($db); - $formfile->form_attach_new_file(DOL_URL_ROOT.'/comm/action/document.php?id='.$act->id,'',0,0,($user->rights->agenda->myactions->create||$user->rights->agenda->allactions->create)); + $formfile->form_attach_new_file(DOL_URL_ROOT.'/comm/action/document.php?id='.$act->id,'',0,0,($user->rights->agenda->myactions->create||$user->rights->agenda->allactions->create),50,$act); // List of document diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php index c5e83017940..a86073e6969 100644 --- a/htdocs/core/class/fileupload.class.php +++ b/htdocs/core/class/fileupload.class.php @@ -56,6 +56,8 @@ class FileUpload $filename = $regs[2]; } + $parentForeignKey = ''; + // For compatibility if ($element == 'propal') { $pathname = 'comm/propal'; @@ -69,6 +71,14 @@ class FileUpload $element = $pathname = 'projet'; $dir_output=$conf->$element->dir_output; } + elseif ($element == 'project_task') { + $pathname = 'projet'; $filename='task'; + $dir_output=$conf->projet->dir_output; + $parentForeignKey = 'fk_project'; + $parentClass = 'Project'; + $parentElement = 'projet'; + $parentObject = 'project'; + } elseif ($element == 'fichinter') { $element='ficheinter'; $dir_output=$conf->$element->dir_output; @@ -80,6 +90,10 @@ class FileUpload elseif ($element == 'invoice_supplier') { $pathname = 'fourn'; $filename='fournisseur.facture'; $dir_output=$conf->fournisseur->facture->dir_output; + } + elseif ($element == 'action') { + $pathname = 'comm/action'; $filename='actioncomm'; + $dir_output=$conf->agenda->dir_output; } else { $dir_output=$conf->$element->dir_output; } @@ -97,11 +111,23 @@ class FileUpload $object = new $classname($db); $object->fetch($fk_element); - $object->fetch_thirdparty(); + if (!empty($parentForeignKey)) { + dol_include_once('/'.$parentElement.'/class/'.$parentObject.'.class.php'); + $parent = new $parentClass($db); + $parent->fetch($object->$parentForeignKey); + if (!empty($parent->socid)) { + $parent->fetch_thirdparty(); + } + $object->$parentObject = dol_clone($parent); + } else { + $object->fetch_thirdparty(); + } $object_ref = dol_sanitizeFileName($object->ref); if ($element == 'invoice_supplier') { $object_ref = get_exdir($object->id, 2) . $object_ref; + } else if ($element == 'project_task') { + $object_ref = $object->project->ref . '/' . $object_ref; } $this->options = array( diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index f28e5d27e6d..12571aad64a 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -171,6 +171,7 @@ class Task extends CommonObject $sql.= " t.label,"; $sql.= " t.description,"; $sql.= " t.duration_effective,"; + $sql.= " t.datec,"; $sql.= " t.dateo,"; $sql.= " t.datee,"; $sql.= " t.fk_user_creat,"; diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php index 5d42a44d54b..90adc2925c2 100644 --- a/htdocs/projet/tasks/document.php +++ b/htdocs/projet/tasks/document.php @@ -93,7 +93,11 @@ if ($id > 0 || ! empty($ref)) { $projectstatic->fetch($object->fk_project); - if (! empty($projectstatic->socid)) $projectstatic->societe->fetch($projectstatic->socid); + if (! empty($projectstatic->socid)) { + $projectstatic->fetch_thirdparty(); + } + + $object->project = dol_clone($projectstatic); $upload_dir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($projectstatic->ref).'/'.dol_sanitizeFileName($object->ref); } @@ -114,7 +118,7 @@ if ($action=='delete') { $langs->load("other"); $file = $upload_dir . '/' . GETPOST('urlfile'); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). - $ret=dol_delete_file($file); + $ret=dol_delete_file($file,0,0,0,$object); if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id); From 5ccb4108d4d8bdbd9645d47406a6496be73a8deb Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 14:47:37 +0200 Subject: [PATCH 08/29] Fix: merge problem --- htdocs/comm/action/document.php | 323 ++++++++++++++++---------------- 1 file changed, 162 insertions(+), 161 deletions(-) diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php index 042f330b199..6a576c580ca 100755 --- a/htdocs/comm/action/document.php +++ b/htdocs/comm/action/document.php @@ -51,6 +51,19 @@ if ($user->societe_id > 0) $socid = $user->societe_id; } +$act = new ActionComm($db); + +if ($objectid > 0) +{ + $ret = $act->fetch($objectid); + if ($ret > 0) { + $company=new Societe($db); + $company->fetch($act->societe->id); + $act->societe=$company; // For backward compatibility + $act->thirdparty=$company; + } +} + // Get parameters $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); @@ -79,7 +92,7 @@ if ($action == 'delete') { $upload_dir = $conf->agenda->dir_output.'/'.dol_sanitizeFileName($objectid); $file = $upload_dir . '/' . $_GET['urlfile']; // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). - $ret=dol_delete_file($file); + $ret=dol_delete_file($file,0,0,0,$act); if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); $action=''; @@ -96,184 +109,172 @@ $help_url='EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; llxHeader('',$langs->trans("Agenda"),$help_url); -if ($objectid > 0) +if ($act->id > 0) { - $act = new ActionComm($db); - if ($act->fetch($objectid)) + $upload_dir = $conf->agenda->dir_output.'/'.dol_sanitizeFileName($objectid); + + $author=new User($db); + $author->fetch($act->author->id); + $act->author=$author; + + if ($act->contact->id) $act->fetch_contact($act->contact->id); + + $head=actions_prepare_head($act); + dol_fiche_head($head, 'documents', $langs->trans("Action"),0,'action'); + + // Affichage fiche action en mode visu + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + + // Type + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - $upload_dir = $conf->agenda->dir_output.'/'.dol_sanitizeFileName($objectid); + print ''; + } - $company=new Societe($db); - $company->fetch($act->societe->id); - $act->societe=$company; + // Title + print ''; - $author=new User($db); - $author->fetch($act->author->id); - $act->author=$author; + // Full day event + print ''; - if ($act->contact->id) $act->fetch_contact($act->contact->id); + // Date start + print ''; + print ''; + print ''; - $head=actions_prepare_head($act); - dol_fiche_head($head, 'documents', $langs->trans("Action"),0,'action'); + // Date end + print ''; - // Affichage fiche action en mode visu - print '
'.$langs->trans("Ref").''; + print $form->showrefnav($act, 'id', $linkback, ($user->societe_id?0:1), 'id', 'ref', ''); + print '
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Title").''.$act->label.'
'.$langs->trans("EventOnFullDay").''.yn($act->fulldayevent).'
'.$langs->trans("DateActionStart").''; + if (! $act->fulldayevent) print dol_print_date($act->datep,'dayhour'); + else print dol_print_date($act->datep,'day'); + if ($act->percentage == 0 && $act->datep && $act->datep < ($now - $delay_warning)) print img_warning($langs->trans("Late")); + print ''."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendar').' '; + print '
'."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendarweek').' '; + print '
'."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendarday').' '; + print '
'."\n"; + print '
'.$langs->trans("DateActionEnd").''; + if (! $act->fulldayevent) print dol_print_date($act->datef,'dayhour'); + else print dol_print_date($act->datef,'day'); + if ($act->percentage > 0 && $act->percentage < 100 && $act->datef && $act->datef < ($now- $delay_warning)) print img_warning($langs->trans("Late")); + print '
'; + // Status + print ''; - $linkback = ''.$langs->trans("BackToList").''; + // Location + print ''; - // Ref - print ''; - // Type - if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + print '
'.$langs->trans("Status").' / '.$langs->trans("Percentage").''; + print $act->getLibStatut(4); + print '
'.$langs->trans("Location").''.$act->location.'
'.$langs->trans("Ref").''; - print $form->showrefnav($act, 'id', $linkback, ($user->societe_id?0:1), 'id', 'ref', ''); - print '


'; + + + // Third party - Contact + print ''; + print "
".dol_print_phone($act->societe->tel); } - - // Title - print ''; - - // Full day event - print ''; - - // Date start - print ''; - print ''; - print ''; - - // Date end - print ''; - - // Status - print ''; - - // Location - print ''; - - - print '
'.$langs->trans("ActionOnCompany").''.($act->societe->id?$act->societe->getNomUrl(1):$langs->trans("None")); + if ($act->societe->id && $act->type_code == 'AC_TEL') + { + if ($act->societe->fetch($act->societe->id)) { - print '
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Title").''.$act->label.'
'.$langs->trans("EventOnFullDay").''.yn($act->fulldayevent).'
'.$langs->trans("DateActionStart").''; - if (! $act->fulldayevent) print dol_print_date($act->datep,'dayhour'); - else print dol_print_date($act->datep,'day'); - if ($act->percentage == 0 && $act->datep && $act->datep < ($now - $delay_warning)) print img_warning($langs->trans("Late")); - print ''."\n"; - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print img_picto($langs->trans("ViewCal"),'object_calendar').' '; - print '
'."\n"; - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print img_picto($langs->trans("ViewCal"),'object_calendarweek').' '; - print '
'."\n"; - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print img_picto($langs->trans("ViewCal"),'object_calendarday').' '; - print '
'."\n"; - print '
'.$langs->trans("DateActionEnd").''; - if (! $act->fulldayevent) print dol_print_date($act->datef,'dayhour'); - else print dol_print_date($act->datef,'day'); - if ($act->percentage > 0 && $act->percentage < 100 && $act->datef && $act->datef < ($now- $delay_warning)) print img_warning($langs->trans("Late")); - print '
'.$langs->trans("Status").' / '.$langs->trans("Percentage").''; - print $act->getLibStatut(4); - print '
'.$langs->trans("Location").''.$act->location.'


'; - - - // Third party - Contact - print ''; - print ''; - print ''; - - // Project - if (! empty($conf->projet->enabled)) - { - print ''; - } - - // Priority - print ''; - - - print '
'.$langs->trans("ActionOnCompany").''.($act->societe->id?$act->societe->getNomUrl(1):$langs->trans("None")); - if ($act->societe->id && $act->type_code == 'AC_TEL') - { - if ($act->societe->fetch($act->societe->id)) - { - print "
".dol_print_phone($act->societe->tel); - } - } - print '
'.$langs->trans("Contact").''; - if ($act->contact->id > 0) - { - print $act->contact->getNomUrl(1); - if ($act->contact->id && $act->type_code == 'AC_TEL') - { - if ($act->contact->fetch($act->contact->id)) - { - print "
".dol_print_phone($act->contact->phone_pro); - } - } - } - else - { - print $langs->trans("None"); - } - - print '
'.$langs->trans("Project").''; - if ($act->fk_project) - { - $project=new Project($db); - $project->fetch($act->fk_project); - print $project->getNomUrl(1); - } - print '
'.$langs->trans("Priority").''; - print ($act->priority?$act->priority:''); - print '


'; - - // Construit liste des fichiers - $filearray=dol_dir_list($upload_dir,"files",0,'','\.meta$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); - $totalsize=0; - foreach($filearray as $key => $file) + } + print ''; + print ''; + print ''; - print ''; - print '
'.$langs->trans("Contact").''; + if ($act->contact->id > 0) + { + print $act->contact->getNomUrl(1); + if ($act->contact->id && $act->type_code == 'AC_TEL') { - $totalsize+=$file['size']; + if ($act->contact->fetch($act->contact->id)) + { + print "
".dol_print_phone($act->contact->phone_pro); + } } - - - print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; - - print ''; - - - // Affiche formulaire upload - $formfile=new FormFile($db); - $formfile->form_attach_new_file(DOL_URL_ROOT.'/comm/action/document.php?id='.$act->id,'',0,0,($user->rights->agenda->myactions->create||$user->rights->agenda->allactions->create),50,$act); - - - // List of document - $param='&id='.$act->id; - $formfile->list_of_documents($filearray,$act,'actions',$param,0,'',$user->rights->agenda->myactions->create); } else { - dol_print_error($db); + print $langs->trans("None"); } + + print ''; + + // Project + if (! empty($conf->projet->enabled)) + { + print ''.$langs->trans("Project").''; + if ($act->fk_project) + { + $project=new Project($db); + $project->fetch($act->fk_project); + print $project->getNomUrl(1); + } + print ''; + } + + // Priority + print ''.$langs->trans("Priority").''; + print ($act->priority?$act->priority:''); + print ''; + + + print '

'; + + // Construit liste des fichiers + $filearray=dol_dir_list($upload_dir,"files",0,'','\.meta$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); + $totalsize=0; + foreach($filearray as $key => $file) + { + $totalsize+=$file['size']; + } + + + print ''; + print ''; + print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; + + print ''; + + + // Affiche formulaire upload + $formfile=new FormFile($db); + $formfile->form_attach_new_file(DOL_URL_ROOT.'/comm/action/document.php?id='.$act->id,'',0,0,($user->rights->agenda->myactions->create||$user->rights->agenda->allactions->create),50,$act); + + + // List of document + $param='&id='.$act->id; + $formfile->list_of_documents($filearray,$act,'actions',$param,0,'',$user->rights->agenda->myactions->create); } else { From b5e66cc4920958159a3491c37da4e144624f0ff6 Mon Sep 17 00:00:00 2001 From: jfefe Date: Mon, 22 Apr 2013 15:00:29 +0200 Subject: [PATCH 09/29] Mutualize code for security check when accessing a document by document.php and bywebservice --- htdocs/core/lib/files.lib.php | 358 ++++++++++++++++++++++++++++ htdocs/document.php | 341 +------------------------- htdocs/webservices/server_other.php | 47 +--- 3 files changed, 366 insertions(+), 380 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 02d3cc16a76..9aea97696ec 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1228,4 +1228,362 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('\.meta$ return $tmparray[0]; } +/** + * Security check when accessing to a document (used in document.php and webservices) + * @param string $modulepart module of document + * @param string $original_file relative path with filename + * @return mixed Array with access information : accessallowed & sqlprotectagainstexternals + */ +function dol_check_secure_access_document($modulepart,&$original_file) +{ + global $user, $conf; + + $accessallowed=0; + $sqlprotectagainstexternals=''; + $ret=array(); + + if ($modulepart) + { + // On fait une verification des droits et on definit le repertoire concerne + + // Wrapping for third parties + if ($modulepart == 'company' || $modulepart == 'societe') + { + if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->societe->multidir_output[$entity].'/'.$original_file; + $sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$refname."' AND entity IN (".getEntity('societe', 1).")"; + } + + // Wrapping for invoices + else if ($modulepart == 'facture' || $modulepart == 'invoice') + { + if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->facture->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + else if ($modulepart == 'unpaid') + { + if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->facture->dir_output.'/unpaid/temp/'.$original_file; + } + + // Wrapping pour les fiches intervention + else if ($modulepart == 'ficheinter') + { + if ($user->rights->ficheinter->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->ficheinter->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les deplacements et notes de frais + else if ($modulepart == 'deplacement') + { + if ($user->rights->deplacement->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->deplacement->dir_output.'/'.$original_file; + //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les prelevements + else if ($modulepart == 'prelevement') + { + if ($user->rights->prelevement->bons->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->prelevement->dir_output.'/'.$original_file; + } + + // Wrapping pour les propales + else if ($modulepart == 'propal') + { + if ($user->rights->propale->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + + $original_file=$conf->propal->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les commandes + else if ($modulepart == 'commande' || $modulepart == 'order') + { + if ($user->rights->commande->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->commande->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les projets + else if ($modulepart == 'project') + { + if ($user->rights->projet->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->projet->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les commandes fournisseurs + else if ($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') + { + if ($user->rights->fournisseur->commande->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les factures fournisseurs + else if ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') + { + if ($user->rights->fournisseur->facture->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$refname."' AND entity=".$conf->entity; + } + + // Wrapping pour les rapport de paiements + else if ($modulepart == 'facture_paiement') + { + if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + if ($user->societe_id > 0) $original_file=$conf->facture->dir_output.'/payments/private/'.$user->id.'/'.$original_file; + else $original_file=$conf->facture->dir_output.'/payments/'.$original_file; + } + + // Wrapping pour les exports de compta + else if ($modulepart == 'export_compta') + { + if ($user->rights->compta->ventilation->creer || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->compta->dir_output.'/'.$original_file; + } + + // Wrapping pour les expedition + else if ($modulepart == 'expedition') + { + if ($user->rights->expedition->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->expedition->dir_output."/sending/".$original_file; + } + + // Wrapping pour les bons de livraison + else if ($modulepart == 'livraison') + { + if ($user->rights->expedition->livraison->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->expedition->dir_output."/receipt/".$original_file; + } + + // Wrapping pour les actions + else if ($modulepart == 'actions') + { + if ($user->rights->agenda->myactions->read || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->agenda->dir_output.'/'.$original_file; + } + + // Wrapping pour les actions + else if ($modulepart == 'actionsreport') + { + if ($user->rights->agenda->allactions->read || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file = $conf->agenda->dir_temp."/".$original_file; + } + + // Wrapping pour les produits et services + else if ($modulepart == 'produit' || $modulepart == 'service') + { + if (($user->rights->produit->lire || $user->rights->service->lire) || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + if (! empty($conf->product->enabled)) $original_file=$conf->product->multidir_output[$entity].'/'.$original_file; + elseif (! empty($conf->service->enabled)) $original_file=$conf->service->multidir_output[$entity].'/'.$original_file; + } + + // Wrapping pour les contrats + else if ($modulepart == 'contract') + { + if ($user->rights->contrat->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->contrat->dir_output.'/'.$original_file; + } + + // Wrapping pour les dons + else if ($modulepart == 'donation') + { + if ($user->rights->don->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->don->dir_output.'/'.$original_file; + } + + // Wrapping pour les remises de cheques + else if ($modulepart == 'remisecheque') + { + if ($user->rights->banque->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + + $original_file=$conf->banque->dir_output.'/bordereau/'.get_exdir(basename($original_file,".pdf"),2,1).$original_file; + } + + // Wrapping for export module + else if ($modulepart == 'export') + { + // Aucun test necessaire car on force le rep de download sur + // le rep export qui est propre a l'utilisateur + $accessallowed=1; + $original_file=$conf->export->dir_temp.'/'.$user->id.'/'.$original_file; + } + + // Wrapping for import module + else if ($modulepart == 'import') + { + // Aucun test necessaire car on force le rep de download sur + // le rep export qui est propre a l'utilisateur + $accessallowed=1; + $original_file=$conf->import->dir_temp.'/'.$original_file; + } + + // Wrapping pour l'editeur wysiwyg + else if ($modulepart == 'editor') + { + // Aucun test necessaire car on force le rep de download sur + // le rep export qui est propre a l'utilisateur + $accessallowed=1; + $original_file=$conf->fckeditor->dir_output.'/'.$original_file; + } + + // Wrapping pour les backups + else if ($modulepart == 'systemtools') + { + if ($user->admin) + { + $accessallowed=1; + } + $original_file=$conf->admin->dir_output.'/'.$original_file; + } + + // Wrapping for upload file test + else if ($modulepart == 'admin_temp') + { + if ($user->admin) + $accessallowed=1; + $original_file=$conf->admin->dir_temp.'/'.$original_file; + } + + // Wrapping pour BitTorrent + else if ($modulepart == 'bittorrent') + { + $accessallowed=1; + $dir='files'; + if ($type == 'application/x-bittorrent') $dir='torrents'; + $original_file=$conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file; + } + + // Wrapping pour Foundation module + else if ($modulepart == 'member') + { + if ($user->rights->adherent->lire || preg_match('/^specimen/i',$original_file)) + { + $accessallowed=1; + } + $original_file=$conf->adherent->dir_output.'/'.$original_file; + } + + // Wrapping for Scanner + else if ($modulepart == 'scanner_user_temp') + { + $accessallowed=1; + $original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file; + } + + // Generic wrapping + else + { + // For dir temp + $dir_temp=false; + if (preg_match('/\_temp$/i', $modulepart)) { + $modulepart = str_replace('_temp', '', $modulepart); + $dir_temp=true; + } + // Define $accessallowed + if (($user->rights->$modulepart->lire) || ($user->rights->$modulepart->read) || ($user->rights->$modulepart->download)) $accessallowed=1; // No subpermission, we have checked on main permission + elseif (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a specimen + elseif ($user->admin) $accessallowed=1; // If user is admin + + // For modules who wants to manage different levels of permissions for documents + $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS'; + if (! empty($conf->global->$subPermCategoryConstName)) + { + $subPermCategory = $conf->global->$subPermCategoryConstName; + if (! empty($subPermCategory) && (($user->rights->$modulepart->$subPermCategory->lire) || ($user->rights->$modulepart->$subPermCategory->read) || ($user->rights->$modulepart->$subPermCategory->download))) + { + $accessallowed=1; + } + } + + // Define $original_file + $dir = $conf->$modulepart->dir_output; + if ($dir_temp) $dir = $conf->$modulepart->dir_temp; + $original_file = $dir.'/'.$original_file; + + // Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query. + $sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS'; + if (! empty($conf->global->$sqlProtectConstName)) // If module want to define its own $sqlprotectagainstexternals + { + // Example: mymodule__SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS = "SELECT fk_soc FROM ".MAIN_DB_PREFIX.$modulepart." WHERE ref='".$refname."' AND entity=".$conf->entity; + eval('$sqlprotectagainstexternals = "'.$conf->global->$sqlProtectConstName.'";'); + } + } + + $ret = array( + 'accessallowed' => $accessallowed, + 'sqlprotectagainstexternals'=>$sqlprotectagainstexternals + ); + + } + return $ret; +} ?> diff --git a/htdocs/document.php b/htdocs/document.php index 2a04ba28a74..7e7132db901 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -96,344 +96,9 @@ $refname=basename(dirname($original_file)."/"); // Security check $accessallowed=0; -$sqlprotectagainstexternals=''; -if ($modulepart) -{ - // On fait une verification des droits et on definit le repertoire concerne - - // Wrapping for third parties - if ($modulepart == 'company' || $modulepart == 'societe') - { - if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->societe->multidir_output[$entity].'/'.$original_file; - $sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$refname."' AND entity IN (".getEntity('societe', 1).")"; - } - - // Wrapping for invoices - else if ($modulepart == 'facture' || $modulepart == 'invoice') - { - if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->facture->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - else if ($modulepart == 'unpaid') - { - if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->facture->dir_output.'/unpaid/temp/'.$original_file; - } - - // Wrapping pour les fiches intervention - else if ($modulepart == 'ficheinter') - { - if ($user->rights->ficheinter->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->ficheinter->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les deplacements et notes de frais - else if ($modulepart == 'deplacement') - { - if ($user->rights->deplacement->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->deplacement->dir_output.'/'.$original_file; - //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les prelevements - else if ($modulepart == 'prelevement') - { - if ($user->rights->prelevement->bons->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->prelevement->dir_output.'/'.$original_file; - } - - // Wrapping pour les propales - else if ($modulepart == 'propal') - { - if ($user->rights->propale->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - - $original_file=$conf->propal->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les commandes - else if ($modulepart == 'commande' || $modulepart == 'order') - { - if ($user->rights->commande->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->commande->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les projets - else if ($modulepart == 'project') - { - if ($user->rights->projet->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->projet->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les commandes fournisseurs - else if ($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') - { - if ($user->rights->fournisseur->commande->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les factures fournisseurs - else if ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') - { - if ($user->rights->fournisseur->facture->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les rapport de paiements - else if ($modulepart == 'facture_paiement') - { - if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - if ($user->societe_id > 0) $original_file=$conf->facture->dir_output.'/payments/private/'.$user->id.'/'.$original_file; - else $original_file=$conf->facture->dir_output.'/payments/'.$original_file; - } - - // Wrapping pour les exports de compta - else if ($modulepart == 'export_compta') - { - if ($user->rights->compta->ventilation->creer || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->compta->dir_output.'/'.$original_file; - } - - // Wrapping pour les expedition - else if ($modulepart == 'expedition') - { - if ($user->rights->expedition->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->expedition->dir_output."/sending/".$original_file; - } - - // Wrapping pour les bons de livraison - else if ($modulepart == 'livraison') - { - if ($user->rights->expedition->livraison->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->expedition->dir_output."/receipt/".$original_file; - } - - // Wrapping pour les actions - else if ($modulepart == 'actions') - { - if ($user->rights->agenda->myactions->read || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->agenda->dir_output.'/'.$original_file; - } - - // Wrapping pour les actions - else if ($modulepart == 'actionsreport') - { - if ($user->rights->agenda->allactions->read || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file = $conf->agenda->dir_temp."/".$original_file; - } - - // Wrapping pour les produits et services - else if ($modulepart == 'produit' || $modulepart == 'service') - { - if (($user->rights->produit->lire || $user->rights->service->lire) || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - if (! empty($conf->product->enabled)) $original_file=$conf->product->multidir_output[$entity].'/'.$original_file; - elseif (! empty($conf->service->enabled)) $original_file=$conf->service->multidir_output[$entity].'/'.$original_file; - } - - // Wrapping pour les contrats - else if ($modulepart == 'contract') - { - if ($user->rights->contrat->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->contrat->dir_output.'/'.$original_file; - } - - // Wrapping pour les dons - else if ($modulepart == 'donation') - { - if ($user->rights->don->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->don->dir_output.'/'.$original_file; - } - - // Wrapping pour les remises de cheques - else if ($modulepart == 'remisecheque') - { - if ($user->rights->banque->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - - $original_file=$conf->banque->dir_output.'/bordereau/'.get_exdir(basename($original_file,".pdf"),2,1).$original_file; - } - - // Wrapping for export module - else if ($modulepart == 'export') - { - // Aucun test necessaire car on force le rep de download sur - // le rep export qui est propre a l'utilisateur - $accessallowed=1; - $original_file=$conf->export->dir_temp.'/'.$user->id.'/'.$original_file; - } - - // Wrapping for import module - else if ($modulepart == 'import') - { - // Aucun test necessaire car on force le rep de download sur - // le rep export qui est propre a l'utilisateur - $accessallowed=1; - $original_file=$conf->import->dir_temp.'/'.$original_file; - } - - // Wrapping pour l'editeur wysiwyg - else if ($modulepart == 'editor') - { - // Aucun test necessaire car on force le rep de download sur - // le rep export qui est propre a l'utilisateur - $accessallowed=1; - $original_file=$conf->fckeditor->dir_output.'/'.$original_file; - } - - // Wrapping pour les backups - else if ($modulepart == 'systemtools') - { - if ($user->admin) - { - $accessallowed=1; - } - $original_file=$conf->admin->dir_output.'/'.$original_file; - } - - // Wrapping for upload file test - else if ($modulepart == 'admin_temp') - { - if ($user->admin) - $accessallowed=1; - $original_file=$conf->admin->dir_temp.'/'.$original_file; - } - - // Wrapping pour BitTorrent - else if ($modulepart == 'bittorrent') - { - $accessallowed=1; - $dir='files'; - if ($type == 'application/x-bittorrent') $dir='torrents'; - $original_file=$conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file; - } - - // Wrapping pour Foundation module - else if ($modulepart == 'member') - { - if ($user->rights->adherent->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->adherent->dir_output.'/'.$original_file; - } - - // Wrapping for Scanner - else if ($modulepart == 'scanner_user_temp') - { - $accessallowed=1; - $original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file; - } - - // Generic wrapping - else - { - // For dir temp - $dir_temp=false; - if (preg_match('/\_temp$/i', $modulepart)) { - $modulepart = str_replace('_temp', '', $modulepart); - $dir_temp=true; - } - // Define $accessallowed - if (($user->rights->$modulepart->lire) || ($user->rights->$modulepart->read) || ($user->rights->$modulepart->download)) $accessallowed=1; // No subpermission, we have checked on main permission - elseif (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a specimen - elseif ($user->admin) $accessallowed=1; // If user is admin - - // For modules who wants to manage different levels of permissions for documents - $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS'; - if (! empty($conf->global->$subPermCategoryConstName)) - { - $subPermCategory = $conf->global->$subPermCategoryConstName; - if (! empty($subPermCategory) && (($user->rights->$modulepart->$subPermCategory->lire) || ($user->rights->$modulepart->$subPermCategory->read) || ($user->rights->$modulepart->$subPermCategory->download))) - { - $accessallowed=1; - } - } - - // Define $original_file - $dir = $conf->$modulepart->dir_output; - if ($dir_temp) $dir = $conf->$modulepart->dir_temp; - $original_file = $dir.'/'.$original_file; - - // Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query. - $sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS'; - if (! empty($conf->global->$sqlProtectConstName)) // If module want to define its own $sqlprotectagainstexternals - { - // Example: mymodule__SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS = "SELECT fk_soc FROM ".MAIN_DB_PREFIX.$modulepart." WHERE ref='".$refname."' AND entity=".$conf->entity; - eval('$sqlprotectagainstexternals = "'.$conf->global->$sqlProtectConstName.'";'); - } - } -} - +$check_access = dol_check_secure_access_document($modulepart,$original_file); +$accessallowed=$check_access['accessallowed']; +$sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals']; // Basic protection (against external users only) if ($user->societe_id > 0) diff --git a/htdocs/webservices/server_other.php b/htdocs/webservices/server_other.php index 3578796838b..23c22807002 100644 --- a/htdocs/webservices/server_other.php +++ b/htdocs/webservices/server_other.php @@ -220,48 +220,11 @@ function getDocument($authentication, $modulepart, $file) // find the subdirectory name as the reference $refname=basename(dirname($original_file)."/"); - // Wrapping for invoices - if ($modulepart == 'facture') - { - if ($fuser->rights->facture->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file = $conf->facture->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$refname."' AND entity=".$conf->entity; - } - // Wrapping pour les propales - else if ($modulepart == 'propal') - { - if ($fuser->rights->propal->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file = $conf->propal->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$refname."' AND entity=".$conf->entity; - } - - // Wrapping pour les commandes - else if ($modulepart == 'commande') - { - if ($fuser->rights->commande->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->commande->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$refname."' AND entity=".$conf->entity; - } - // Wrapping pour generic module - else - { - if ($fuser->rights->$modulepart->read || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->$modulepart->dir_output.'/'.$original_file; - // TODO - //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."registration WHERE ref='".$refname."' AND entity=".$conf->entity; - } + // Security check + $accessallowed=0; + $check_access = dol_check_secure_access_document($modulepart,$original_file); + $accessallowed=$check_access['accessallowed']; + $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals']; // Basic protection (against external users only) if ($fuser->societe_id > 0) From ccf809b14aca83272451863534d767dc80291df1 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 15:09:19 +0200 Subject: [PATCH 10/29] Fix: broken features --- htdocs/compta/sociales/class/chargesociales.class.php | 2 +- htdocs/compta/sociales/document.php | 4 ++-- htdocs/core/class/fileupload.class.php | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index 6fbd0a23143..f62b2fcc594 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; */ class ChargeSociales extends CommonObject { - public $element='rowid'; + public $element='chargesociales'; public $table='chargesociales'; public $table_element='chargesociales'; diff --git a/htdocs/compta/sociales/document.php b/htdocs/compta/sociales/document.php index dcb082b41d7..452de21285a 100644 --- a/htdocs/compta/sociales/document.php +++ b/htdocs/compta/sociales/document.php @@ -79,7 +79,7 @@ if (GETPOST("sendit") && ! empty($conf->global->MAIN_UPLOAD_DOC)) if ($action == 'delete') { $file = $upload_dir . '/' . GETPOST("urlfile"); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). - $ret=dol_delete_file($file); + $ret=dol_delete_file($file,0,0,0,$object); if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); } @@ -172,7 +172,7 @@ if ($object->id) // Affiche formulaire upload $formfile=new FormFile($db); - $formfile->form_attach_new_file(DOL_URL_ROOT.'/compta/sociales/document.php?id='.$object->id,'',0,0,$user->rights->tax->charges->creer); + $formfile->form_attach_new_file(DOL_URL_ROOT.'/compta/sociales/document.php?id='.$object->id,'',0,0,$user->rights->tax->charges->creer,50,$object); // List of document diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php index a86073e6969..6bb5b9209d1 100644 --- a/htdocs/core/class/fileupload.class.php +++ b/htdocs/core/class/fileupload.class.php @@ -94,6 +94,10 @@ class FileUpload elseif ($element == 'action') { $pathname = 'comm/action'; $filename='actioncomm'; $dir_output=$conf->agenda->dir_output; + } + elseif ($element == 'chargesociales') { + $pathname = 'compta/sociales'; $filename='chargesociales'; + $dir_output=$conf->tax->dir_output; } else { $dir_output=$conf->$element->dir_output; } From 7217d91f132b76b14ccaf5541e07e23755fd13ee Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 15:26:14 +0200 Subject: [PATCH 11/29] Fix: missing commit --- htdocs/core/class/fileupload.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php index 6bb5b9209d1..910ad55e0a0 100644 --- a/htdocs/core/class/fileupload.class.php +++ b/htdocs/core/class/fileupload.class.php @@ -91,6 +91,9 @@ class FileUpload $pathname = 'fourn'; $filename='fournisseur.facture'; $dir_output=$conf->fournisseur->facture->dir_output; } + elseif ($element == 'product') { + $dir_output = $conf->product->multidir_output[$conf->entity]; + } elseif ($element == 'action') { $pathname = 'comm/action'; $filename='actioncomm'; $dir_output=$conf->agenda->dir_output; From de5a57a3c8c56823be209b806586b2349cc9919f Mon Sep 17 00:00:00 2001 From: simnandez Date: Mon, 22 Apr 2013 16:23:59 +0200 Subject: [PATCH 12/29] Fix: Uniformize creation in orders --- htdocs/core/menus/standard/eldy.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index f4d7f3581db..ed73b895280 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -658,7 +658,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu { $langs->load("orders"); $newmenu->add("/commande/index.php?leftmenu=orders", $langs->trans("CustomersOrders"), 0, $user->rights->commande->lire, '', $mainmenu, 'orders'); - $newmenu->add("/societe/societe.php?leftmenu=orders", $langs->trans("NewOrder"), 1, $user->rights->commande->creer); + $newmenu->add("/commande/fiche.php?action=create", $langs->trans("NewOrder"), 1, $user->rights->commande->creer); $newmenu->add("/commande/liste.php?leftmenu=orders", $langs->trans("List"), 1, $user->rights->commande->lire); if (empty($leftmenu) || $leftmenu=="orders") $newmenu->add("/commande/liste.php?leftmenu=orders&viewstatut=0", $langs->trans("StatusOrderDraftShort"), 2, $user->rights->commande->lire); if (empty($leftmenu) || $leftmenu=="orders") $newmenu->add("/commande/liste.php?leftmenu=orders&viewstatut=1", $langs->trans("StatusOrderValidated"), 2, $user->rights->commande->lire); From f8ddd69ccbb84db596f31b7a08b46fd2bd6f3d17 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 16:42:44 +0200 Subject: [PATCH 13/29] FIXME regresion if code with not in numeric base --- htdocs/admin/dict.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 5a4db149b87..779a7da96f5 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -448,11 +448,12 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $ok=0; $msg.= $langs->transnoentities('ErrorCodeCantContainZero').'
'; } - if (!is_numeric($_POST['code'])) + // FIXME regresion if code with not in numeric base + /*if (!is_numeric($_POST['code'])) { $ok = 0; $msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'
'; - } + }*/ } if (isset($_POST["pays"]) && $_POST["pays"]=='0') { $ok=0; From 7f6a87ab3585a8aeb8af30a836e4cad11eb776b3 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 22 Apr 2013 16:42:44 +0200 Subject: [PATCH 14/29] FIXME regresion if code with not in numeric base --- htdocs/admin/dict.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 41178e36012..ef64ad34527 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -456,11 +456,12 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $ok=0; $msg.= $langs->transnoentities('ErrorCodeCantContainZero').'
'; } - if (!is_numeric($_POST['code'])) + // FIXME regresion if code with not in numeric base + /*if (!is_numeric($_POST['code'])) { $ok = 0; $msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'
'; - } + }*/ } if (isset($_POST["country"]) && $_POST["country"]=='0') { $ok=0; From 5d74f228d8ce9baba3f93460c1462cf13307d8b5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 19:59:41 +0200 Subject: [PATCH 15/29] Removed version into trigger page (version on trigger is useless since trigger depend on module. Only version of module is required). --- htdocs/admin/triggers.php | 22 ++++++++++++- htdocs/core/tpl/triggers.tpl.php | 53 -------------------------------- 2 files changed, 21 insertions(+), 54 deletions(-) delete mode 100644 htdocs/core/tpl/triggers.tpl.php diff --git a/htdocs/admin/triggers.php b/htdocs/admin/triggers.php index 7710b8e0490..3d9ebbd1d29 100644 --- a/htdocs/admin/triggers.php +++ b/htdocs/admin/triggers.php @@ -52,7 +52,27 @@ $template_dir = DOL_DOCUMENT_ROOT.'/core/tpl/'; $interfaces = new Interfaces($db); $triggers = $interfaces->getTriggersList(0,'priority'); -include $template_dir.'triggers.tpl.php'; +print ' + + + + + +'; + +$var=True; +foreach ($triggers as $trigger) +{ + $var=!$var; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; +} + +print '
'.$langs->trans("File").''.$langs->trans("Active").' 
'.$trigger['picto'].''.$trigger['file'].''.$trigger['status'].''.$form->textwithpicto('', $trigger['info']).'
'; llxFooter(); diff --git a/htdocs/core/tpl/triggers.tpl.php b/htdocs/core/tpl/triggers.tpl.php deleted file mode 100644 index ad933e43cd9..00000000000 --- a/htdocs/core/tpl/triggers.tpl.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * 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 . - * - */ -?> - - - - - - - - - - - - - -> - - - - - - - - - - - -
trans("File"); ?>trans("Version"); ?>trans("Active"); ?> 
textwithpicto('', $trigger['info']); ?>
- - \ No newline at end of file From 4e939f558a650bdf331a2b6f2306edb2f8aaf2f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 20:41:38 +0200 Subject: [PATCH 16/29] Restore font weight --- htdocs/theme/eldy/style.css.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index bcfb9a051bd..de15a44705f 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -1369,7 +1369,7 @@ a.tab#active { a.tab:link, a.tab:visited, a.tab:hover, a.tab#active { color: #; - font-weight: normal !important; + /* font-weight: normal !important; */ } a.tabimage { From 494e9dbe184452c2792f9dba516868d423093bcb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 20:45:47 +0200 Subject: [PATCH 17/29] Removed warning --- htdocs/core/modules/modBanque.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modBanque.class.php b/htdocs/core/modules/modBanque.class.php index 832d96a194b..aeec5a30fef 100644 --- a/htdocs/core/modules/modBanque.class.php +++ b/htdocs/core/modules/modBanque.class.php @@ -159,7 +159,7 @@ class modBanque extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON bu.url_id = s.rowid'; $this->export_sql_end[$r] .=' WHERE ba.rowid = b.fk_account'; $this->export_sql_end[$r] .=' AND ba.entity = '.$conf->entity; - $this->export_sql_order[$r] .=' ORDER BY b.datev, b.num_releve'; + $this->export_sql_order[$r] =' ORDER BY b.datev, b.num_releve'; } From c8b2ce3d8ec9f4271e380257bd1728c4ddac4d93 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 22 Apr 2013 20:46:53 +0200 Subject: [PATCH 18/29] Removed warning --- htdocs/core/modules/modBanque.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modBanque.class.php b/htdocs/core/modules/modBanque.class.php index 1bae9f61129..4b9f5f060b3 100644 --- a/htdocs/core/modules/modBanque.class.php +++ b/htdocs/core/modules/modBanque.class.php @@ -159,7 +159,7 @@ class modBanque extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON bu.url_id = s.rowid'; $this->export_sql_end[$r] .=' WHERE ba.rowid = b.fk_account'; $this->export_sql_end[$r] .=' AND ba.entity = '.$conf->entity; - $this->export_sql_order[$r] .=' ORDER BY b.datev, b.num_releve'; + $this->export_sql_order[$r] =' ORDER BY b.datev, b.num_releve'; } From ff3b2933a817df4255b3448cbe8ed84ad46871cd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 10:42:10 +0200 Subject: [PATCH 19/29] Fix: Removed bad test --- test/phpunit/DateLibTest.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/phpunit/DateLibTest.php b/test/phpunit/DateLibTest.php index 15da662b92e..1b35809e0af 100644 --- a/test/phpunit/DateLibTest.php +++ b/test/phpunit/DateLibTest.php @@ -304,19 +304,5 @@ class DateLibTest extends PHPUnit_Framework_TestCase return $result; } - /** - * testDolGetFirstDay - * - * @return void - */ - public function testDolGetFirstDay() - { - global $conf,$user,$langs,$db; - $conf=$this->savconf; - $user=$this->savuser; - $langs=$this->savlangs; - $db=$this->savdb; - - } } ?> \ No newline at end of file From 78a0c7ace2ee1e83fafb0e50d5563458fcff8dea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:00:02 +0200 Subject: [PATCH 20/29] Fix: log must use the mask defined into setup --- htdocs/core/modules/syslog/mod_syslog_file.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/syslog/mod_syslog_file.php b/htdocs/core/modules/syslog/mod_syslog_file.php index f5315f064ae..e6bbefb7295 100644 --- a/htdocs/core/modules/syslog/mod_syslog_file.php +++ b/htdocs/core/modules/syslog/mod_syslog_file.php @@ -96,7 +96,7 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface /** * Return the parsed logfile path * - * @param string $suffixinfilename When output is a file, append this suffix into default log filename. + * @param string $suffixinfilename When output is a file, append this suffix into default log filename. * @return string */ private function getFilename($suffixinfilename='') @@ -109,11 +109,13 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface * Export the message * * @param array $content Array containing the info about the message - * @param string $suffixinfilename When output is a file, append this suffix into default log filename. + * @param string $suffixinfilename When output is a file, append this suffix into default log filename. * @return void */ public function export($content, $suffixinfilename='') { + global $conf; + $logfile = $this->getFilename($suffixinfilename); if (defined("SYSLOG_FILE_NO_ERROR")) $filefd = @fopen($logfile, 'a+'); @@ -145,6 +147,7 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface fwrite($filefd, $message."\n"); fclose($filefd); + @chmod($logfile, octdec($conf->global->MAIN_UMASK)); } } -} \ No newline at end of file +} From 39d3d1a34e7cc87b6b0532f83e1551471d4494b8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:00:31 +0200 Subject: [PATCH 21/29] Enhance script to send email to sale representatives --- htdocs/langs/en_US/admin.lang | 2 +- htdocs/langs/fr_FR/admin.lang | 2 +- .../email_unpaid_invoices_to_representatives.php | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 290707219bb..13cd8e505f8 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -298,7 +298,7 @@ DoTestServerAvailability=Test server connectivity DoTestSend=Test sending DoTestSendHTML=Test sending HTML ErrorCantUseRazInStartedYearIfNoYearMonthInMask=Error, can't use option @ if sequence {yy}{mm} or {yyyy}{mm} is not in mask. -UMask=UMask parameter for new files on Unix/Linux/BSD file system. +UMask=UMask parameter for new files on Unix/Linux/BSD/Mac file system. UMaskExplanation=This parameter allow you to define permissions set by default on files created by Dolibarr on server (during upload for example).
It must be the octal value (for example, 0666 means read and write for everyone).
This parameter is useless on a Windows server. SeeWikiForAllTeam=Take a look at the wiki page for full list of all actors and their organisation UseACacheDelay= Delay for caching export response in seconds (0 or empty for no cache) diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index cc2ee5b2a4e..5e9d958858e 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -293,7 +293,7 @@ DoTestServerAvailability= Tester disponibilité serveur DoTestSend= Tester envoi DoTestSendHTML= Tester envoi HTML ErrorCantUseRazInStartedYearIfNoYearMonthInMask= Erreur, ne peut utiliser l'option @ si la séquence {yy}{mm} ou {yyyy}{mm} n'est pas dans le masque. -UMask= Paramètre UMask des nouveaux fichiers sous Unix/Linux/BSD. +UMask= Paramètre UMask des nouveaux fichiers sous Unix/Linux/BSD/Mac. UMaskExplanation= Ce paramètre permet de définir les droits des fichiers créés sur le serveur par Dolibarr (lors d'upload par exemple).
Ce doit être la valeur octale (par exemple 0666 signifie lecture/écriture pour tous).
Ce paramètre n'a aucun effet sur un serveur Windows. SeeWikiForAllTeam= Voir le wiki pour le détail de tous les acteurs et leur organisation UseACacheDelay= Délai de mise en cache de l'export en secondes (0 ou vide pour aucun cache) diff --git a/scripts/invoices/email_unpaid_invoices_to_representatives.php b/scripts/invoices/email_unpaid_invoices_to_representatives.php index e62403366fb..abeb8296493 100755 --- a/scripts/invoices/email_unpaid_invoices_to_representatives.php +++ b/scripts/invoices/email_unpaid_invoices_to_representatives.php @@ -50,6 +50,7 @@ $mode=$argv[1]; require($path."../../htdocs/master.inc.php"); require_once (DOL_DOCUMENT_ROOT."/core/class/CMailFile.class.php"); +$langs->load('main'); /* @@ -62,7 +63,7 @@ $duration_value=$argv[2]; $error = 0; print $script_file." launched with mode ".$mode.($duration_value?" delay=".$duration_value:"")."\n"; -$sql = "SELECT f.facnumber, f.total_ttc, s.nom as name, u.rowid as uid, u.lastname, u.firstname, u.email, u.lang"; +$sql = "SELECT f.facnumber, f.total_ttc, f.date_lim_reglement as due_date, s.nom as name, u.rowid as uid, u.lastname, u.firstname, u.email, u.lang"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " , ".MAIN_DB_PREFIX."societe as s"; $sql .= " , ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -110,7 +111,7 @@ if ($resql) if (dol_strlen($oldemail)) { $message .= $langs->trans("Invoice")." ".$obj->facnumber." : ".price($obj->total_ttc)." : ".$obj->name."\n"; - print "Invoice ".$obj->facnumber.", price ".price2num($obj->total_ttc).", linked to company ".$obj->name." with sale representative ".dolGetFirstLastname($obj->firstname, $obj->lastname)." qualified.\n"; + print "Unpaid invoice ".$obj->facnumber.", price ".price2num($obj->total_ttc).", due date ".dol_print_date($db->jdate($obj->due_date),'day')." (linked to company ".$obj->name.", sale representative ".dolGetFirstLastname($obj->firstname, $obj->lastname).", email ".$obj->email.") qualified.\n"; dol_syslog("email_unpaid_invoices_to_representatives.php: ".$obj->email); } @@ -129,7 +130,7 @@ if ($resql) } else { - print "No unpaid invoices to companies linked to a particular commercial dolibarr user\n"; + print "No unpaid invoices (for companies linked to a particular commercial dolibarr user) found\n"; } } else @@ -213,6 +214,8 @@ function envoi_mail($mode,$oldemail,$message,$total,$userlang) } else { + print "No email sent (test mode)\n"; + dol_syslog("No email sent (test mode)"); $mail->dump_mail(); $result=1; } From 3f1f065d4ecb212bc5b4825dc059ffdbac474aee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:02:56 +0200 Subject: [PATCH 22/29] Fix: log must use the mask defined into setup Conflicts: htdocs/core/modules/syslog/mod_syslog_file.php --- htdocs/core/modules/syslog/mod_syslog_file.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/syslog/mod_syslog_file.php b/htdocs/core/modules/syslog/mod_syslog_file.php index b0e1bd550b4..4d482f017cf 100644 --- a/htdocs/core/modules/syslog/mod_syslog_file.php +++ b/htdocs/core/modules/syslog/mod_syslog_file.php @@ -96,7 +96,12 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface /** * Return the parsed logfile path * +<<<<<<< OURS * @return string +======= + * @param string $suffixinfilename When output is a file, append this suffix into default log filename. + * @return string +>>>>>>> THEIRS */ private function getFilename() { @@ -111,6 +116,8 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface */ public function export($content) { + global $conf; + $logfile = $this->getFilename(); if (defined("SYSLOG_FILE_NO_ERROR")) $filefd = @fopen($logfile, 'a+'); @@ -142,6 +149,7 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface fwrite($filefd, $message."\n"); fclose($filefd); + @chmod($logfile, octdec($conf->global->MAIN_UMASK)); } } -} \ No newline at end of file +} From dbc2eddcbacbb4721ff61d0fba3160dac3da8c4d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:09:21 +0200 Subject: [PATCH 23/29] Prepare for 3.3.2 --- build/debian/changelog | 4 ++-- build/doxygen/dolibarr-doxygen.doxyfile | 2 +- build/exe/doliwamp/doliwamp.iss | 6 +++--- build/makepack-dolibarr.pl | 2 +- build/makepack-howto.txt | 2 +- build/perl/virtualmin/dolibarr.pl | 2 +- build/rpm/dolibarr_fedora.spec | 2 +- build/rpm/dolibarr_generic.spec | 2 +- build/rpm/dolibarr_mandriva.spec | 2 +- build/rpm/dolibarr_opensuse.spec | 2 +- htdocs/filefunc.inc.php | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/debian/changelog b/build/debian/changelog index 4382b1ae605..b9302cfc624 100644 --- a/build/debian/changelog +++ b/build/debian/changelog @@ -1,9 +1,9 @@ -dolibarr (3.3.1+nmu1) unstable; urgency=low +dolibarr (3.3.2+nmu1) unstable; urgency=low * Non-maintainer upload. * New upstream release. closes: bug#634783 - -- Dolibarr team Sat, 2 Mar 2013 12:00:00 +0100 + -- Dolibarr team Mon, 22 Apr 2013 12:00:00 +0100 # For a changelog file dedicated to end users, see /usr/share/doc/dolibarr/ChangeLog.gz \ No newline at end of file diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 690b5daf1a2..294541450fb 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = dolibarr # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 3.3.0 +PROJECT_NUMBER = 3.3.2 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/build/exe/doliwamp/doliwamp.iss b/build/exe/doliwamp/doliwamp.iss index dc202fdd371..4f9b0fabea6 100644 --- a/build/exe/doliwamp/doliwamp.iss +++ b/build/exe/doliwamp/doliwamp.iss @@ -17,9 +17,9 @@ ; ----- Change this ----- AppName=DoliWamp ; DoliWamp-x.x.x or DoliWamp-x.x.x-alpha or DoliWamp-x.x.x-beta or DoliWamp-x.x.x-rc or DoliWamp-x.x.x -AppVerName=DoliWamp-3.3.1 +AppVerName=DoliWamp-3.3.2 ; DoliWamp-x.x x or DoliWamp-x.x.x-alpha or DoliWamp-x.x.x-beta or DoliWamp-x.x.x-rc or DoliWamp-x.x.x -OutputBaseFilename=DoliWamp-3.3.1 +OutputBaseFilename=DoliWamp-3.3.2 ; Define full path from wich all relative path are defined ; You must modify this to put here your dolibarr root directory ;SourceDir=C:\Documents and Settings\ldestailleur\git\dolibarr_old @@ -33,7 +33,7 @@ AppPublisherURL=http://www.nltechno.com AppSupportURL=http://www.dolibarr.org AppUpdatesURL=http://www.dolibarr.org AppComments=DoliWamp includes Dolibarr, Apache, PHP and Mysql softwares. -AppCopyright=Copyright (C) 2008-2012 Laurent Destailleur, NLTechno +AppCopyright=Copyright (C) 2008-2013 Laurent Destailleur, NLTechno DefaultDirName=c:\dolibarr DefaultGroupName=Dolibarr ;LicenseFile=COPYING diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index c2e8a0eda1a..f8fcdd762c4 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -10,7 +10,7 @@ use Cwd; $PROJECT="dolibarr"; $MAJOR="3"; $MINOR="3"; -$BUILD="1"; # Mettre x pour release, x-dev pour dev, x-beta pour beta, x-rc pour release candidate +$BUILD="2"; # Mettre x pour release, x-dev pour dev, x-beta pour beta, x-rc pour release candidate $RPMSUBVERSION="auto"; # auto use value found into BUILD @LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages diff --git a/build/makepack-howto.txt b/build/makepack-howto.txt index fad028cfbf6..4847b0102ef 100644 --- a/build/makepack-howto.txt +++ b/build/makepack-howto.txt @@ -32,7 +32,7 @@ This files describe steps made by Dolibarr packaging team to make a complete release of Dolibarr, step by step. - Check all files are commited. -- Update version/info in /ChangeLog and /filefunc.inc.php +- Update version/info in ChangeLog - Update version number with x.x.x in htdocs/filefunc.inc.php - Update version number with x.x.x in build/makepack-dolibarr.pl - Update version number with x.x.x in build/debian/changelog diff --git a/build/perl/virtualmin/dolibarr.pl b/build/perl/virtualmin/dolibarr.pl index 1bc5f350954..0ede11d9968 100644 --- a/build/perl/virtualmin/dolibarr.pl +++ b/build/perl/virtualmin/dolibarr.pl @@ -30,7 +30,7 @@ return "Regis Houssin"; # script_dolibarr_versions() sub script_dolibarr_versions { -return ( "3.3.0", "3.2.1", "3.1.1" ); +return ( "3.3.2", "3.3.1", "3.3.0", "3.2.1", "3.1.1" ); } sub script_dolibarr_category diff --git a/build/rpm/dolibarr_fedora.spec b/build/rpm/dolibarr_fedora.spec index e2e1299a9df..41dff2735ff 100755 --- a/build/rpm/dolibarr_fedora.spec +++ b/build/rpm/dolibarr_fedora.spec @@ -333,5 +333,5 @@ fi %changelog -* Sun Feb 17 2013 Laurent Destailleur 3.3.1-0.3 +* Mon Apr 22 2013 Laurent Destailleur 3.3.2-0.3 - Initial version (#723326) diff --git a/build/rpm/dolibarr_generic.spec b/build/rpm/dolibarr_generic.spec index dbd2a26686a..9fe677e6f42 100755 --- a/build/rpm/dolibarr_generic.spec +++ b/build/rpm/dolibarr_generic.spec @@ -522,5 +522,5 @@ fi %changelog -* Sun Feb 17 2013 Laurent Destailleur 3.3.1-0.3 +* Mon Apr 22 2013 Laurent Destailleur 3.3.2-0.3 - Initial version (#723326) diff --git a/build/rpm/dolibarr_mandriva.spec b/build/rpm/dolibarr_mandriva.spec index 4701ff2651e..f31988aed20 100755 --- a/build/rpm/dolibarr_mandriva.spec +++ b/build/rpm/dolibarr_mandriva.spec @@ -322,5 +322,5 @@ fi %changelog -* Sun Feb 17 2013 Laurent Destailleur 3.3.1-0.3 +* Mon Apr 22 2013 Laurent Destailleur 3.3.2-0.3 - Initial version (#723326) diff --git a/build/rpm/dolibarr_opensuse.spec b/build/rpm/dolibarr_opensuse.spec index c5bde7c5427..3c59a8a075c 100755 --- a/build/rpm/dolibarr_opensuse.spec +++ b/build/rpm/dolibarr_opensuse.spec @@ -333,5 +333,5 @@ fi %changelog -* Sun Feb 17 2013 Laurent Destailleur 3.3.1-0.3 +* Mon Apr 22 2013 Laurent Destailleur 3.3.2-0.3 - Initial version (#723326) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index a8dba530b21..dd3b9981fce 100755 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -29,7 +29,7 @@ * \brief File that include conf.php file and commons lib like functions.lib.php */ -if (! defined('DOL_VERSION')) define('DOL_VERSION','3.3.1'); +if (! defined('DOL_VERSION')) define('DOL_VERSION','3.3.2'); if (! defined('EURO')) define('EURO',chr(128)); // Define syslog constants From 8f502b8cfc2dec020ce7d33c0e01398bc9512b66 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:39:55 +0200 Subject: [PATCH 24/29] Prepare 3.3.2 --- build/debian/README.howto | 2 +- build/debian/po/fr.po | 12 ++++++------ build/debian/po/templates.pot | 15 ++++++++------- build/debian/rules | 3 +++ build/makepack-dolibarr.pl | 2 ++ 5 files changed, 20 insertions(+), 14 deletions(-) mode change 100755 => 100644 build/debian/po/templates.pot diff --git a/build/debian/README.howto b/build/debian/README.howto index 9c3dbc9ad07..b281c20b13b 100644 --- a/build/debian/README.howto +++ b/build/debian/README.howto @@ -13,7 +13,7 @@ with format .DEB (for Debian, Ubuntu, ...). # This is standard command to work on Debian packaging: # -# gpg --gen-key Generate a GPG key +# gpg --gen-key Generate a GPG key (-> pubring.gpg + secring.gpg) # # debconf-updatepo To run into po dir to regenate templates.pot # podebconf-report-po --from email@email.com To send email to ask translations diff --git a/build/debian/po/fr.po b/build/debian/po/fr.po index a96cd360299..d23da598297 100755 --- a/build/debian/po/fr.po +++ b/build/debian/po/fr.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-08-01 18:17+0200\n" +"Report-Msgid-Bugs-To: dolibarr@packages.debian.org\n" +"POT-Creation-Date: 2013-04-23 12:16+0200\n" "PO-Revision-Date: 2011-07-29 22:45+0100\n" "Last-Translator: Laurent Destailleur \n" "Language-Team: Laurent Destailleur \n" @@ -27,13 +27,13 @@ msgstr "" #. Type: multiselect #. Description -#: ../templates:1001 +#: ../dolibarr.templates:1001 msgid "Web server to reconfigure automatically:" msgstr "Seveur web à reconfigurer automatiquement:" #. Type: multiselect #. Description -#: ../templates:1001 +#: ../dolibarr.templates:1001 msgid "" "Please choose the web server that should be automatically configured to run " "dolibarr." @@ -44,14 +44,14 @@ msgstr "" # #. Type: boolean #. Description -#: ../templates:2001 +#: ../dolibarr.templates:2001 msgid "Delete database and uploaded files ?" msgstr "Effacer la base de donnée et les fichiers uploadés ?" # #. Type: boolean #. Description -#: ../templates:2001 +#: ../dolibarr.templates:2001 msgid "" "Answer if you want to removed the Dolibarr MySQL database and all other " "datas (datas related to this question are the Dolibarr DBMS account, all " diff --git a/build/debian/po/templates.pot b/build/debian/po/templates.pot old mode 100755 new mode 100644 index 8813bd2d45b..90b57278e04 --- a/build/debian/po/templates.pot +++ b/build/debian/po/templates.pot @@ -3,11 +3,12 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # +#, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-08-01 18:17+0200\n" +"Project-Id-Version: dolibarr\n" +"Report-Msgid-Bugs-To: dolibarr@packages.debian.org\n" +"POT-Creation-Date: 2013-04-23 12:16+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,13 +19,13 @@ msgstr "" #. Type: multiselect #. Description -#: ../templates:1001 +#: ../dolibarr.templates:1001 msgid "Web server to reconfigure automatically:" msgstr "" #. Type: multiselect #. Description -#: ../templates:1001 +#: ../dolibarr.templates:1001 msgid "" "Please choose the web server that should be automatically configured to run " "dolibarr." @@ -32,13 +33,13 @@ msgstr "" #. Type: boolean #. Description -#: ../templates:2001 +#: ../dolibarr.templates:2001 msgid "Delete database and uploaded files ?" msgstr "" #. Type: boolean #. Description -#: ../templates:2001 +#: ../dolibarr.templates:2001 msgid "" "Answer if you want to removed the Dolibarr MySQL database and all other " "datas (datas related to this question are the Dolibarr DBMS account, all " diff --git a/build/debian/rules b/build/debian/rules index 6b75c68b85d..e36aa8f0545 100755 --- a/build/debian/rules +++ b/build/debian/rules @@ -112,6 +112,9 @@ clean: rm -fr htdocs/includes/tcpdf/fonts/freefont-20100919 rm -fr htdocs/includes/tcpdf/fonts/utils + # clean from files to avoid warning of missing dependencies + rm -fr htdocs/includes/jquery/plugins/jqueryFileTree/connectors/jqueryFileTree.py + # Licence files are included into copyright file. rm -fr htdocs/includes/phpexcel/license.txt rm -f htdocs/includes/tcpdf/LICENSE.TXT diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index f8fcdd762c4..ee44ac8a493 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -656,6 +656,8 @@ if ($nboftargetok) { $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/dev/skeletons/skeleton_webservice_server.php`; $cmd="find $BUILDROOT/$PROJECT.tmp/scripts -name '*.php' -type f -exec chmod 755 {} \\; "; $ret=`$cmd`; + $cmd="find $BUILDROOT/$PROJECT.tmp/scripts -name '*.sh' -type f -exec chmod 755 {} \\; "; + $ret=`$cmd`; print "Rename directory $BUILDROOT/$PROJECT.tmp into $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build\n"; From 624a039eaf08f23b6292995b58497d36ecacbad1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 12:58:58 +0200 Subject: [PATCH 25/29] Update debian doc --- build/debian/README.howto | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build/debian/README.howto b/build/debian/README.howto index b281c20b13b..797e653bc27 100644 --- a/build/debian/README.howto +++ b/build/debian/README.howto @@ -43,10 +43,11 @@ To submit a package to Debian: See page http://www.debian.org/devel/wnpp/#l1 for example of ITP requests contents. - Wait until you received bug number. -For first ITP submission of Dolibarr, bug id was 634783. + For first ITP submission of Dolibarr, bug id was 634783. -- Check bug is into database by searching with id on http://www.debian.org/Bugs/ - +- Check bug is into database by searching with id on + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634783 + - Add a line for upstream into file changelog with bug number - Call for a mentor on ML debian-mentors to upload packages From 57ab4fb7983ea517d551bb899781cb1185fe42df Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 13:38:00 +0200 Subject: [PATCH 26/29] Fix doc --- build/launchpad/README | 79 +++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/build/launchpad/README b/build/launchpad/README index 2a1e7d138ca..37c1c51f96a 100644 --- a/build/launchpad/README +++ b/build/launchpad/README @@ -28,6 +28,8 @@ a package onto LaunchPad - Edit file ~/.bashrc to add DEBFULLNAME="" DEBEMAIL="" +- Create a Bazaar directory + mkdir bzr If you want to build/test package locally: - Create a file ~/.pbuilderrc with content @@ -36,24 +38,43 @@ If you want to build/test package locally: sudo pbuilder create [--distribution sid|squeeze] -# Push/declare sources to Launchpad +# Push/declare Dolibarr sources to Launchpad #---------------------------------- - -- Create a Bazaar directory - mkdir bzr -- Create a series - Call it 'dev' or 'stable' - For stable: Add file with *: http://www.dolibarr.org/files/stable/package_debian-ubuntu/dolibarr_3.2.*.tar.gz - For dev: Configure Series branch - Link to series +- From Launchpad project (https://launchpad.net/dolibarr), register a series: + Call it 'trunk' or 'beta' or 'stable' + Use branch (dev): + ~eldy/dolibarr/develop + ~eldy/dolibarr/beta + ~eldy/dolibarr/stable + or + Use URL pattern (beta or stable): + http://www.dolibarr.org/files/lastbuild/package_debian-ubuntu/dolibarr_x.z.*.tar.gz + http://www.dolibarr.org/files/stable/package_debian-ubuntu/dolibarr_x.y.*.tar.gz + +- For Dev, you can also add link serie to GIT HEAD. +- For beta and stable, you can init from command line + cd bzr/dolibarr-[beta|stable] bzr init bzr add bzr commit -m "Init" - bzr push lp:~yourlogin/dolibarr/stable + bzr push lp:~yourlogin/dolibarr/[beta|stable] -# Init repository of sources into launchpad (when repository for sources does not exist) +- List of series are visible here: https://launchpad.net/dolibarr/+series + +# To update Dolibarr into launchpad (when repository for sources already exists) #---------------------------------- + cd bzr + bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] + bzr status + -- Update files here -- + bzr commit -m "Description of change" + bzr push lp:~yourlogin/+junk/debian-[dev|beta|stable] -- Create debian directory and upload it onto bzr branch ~yourlogin/+junk/debian-[dev|stable] + + +# Init debian dir repository into launchpad (when repository for sources does not exist) +#---------------------------------- +- Create debian directory and upload it onto bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] cd bzr mkdir debian cd debian @@ -61,24 +82,28 @@ If you want to build/test package locally: bzr init bzr add bzr commit -m "Init control files" - bzr push lp:~yourlogin/+junk/debian-[dev|stable] (put here any branch name) - or download it from launchpad bazaar: + bzr push lp:~yourlogin/+junk/debian-[dev|beta|stable] (put here any branch name) +- or download it from launchpad bazaar: cd bzr - bzr branch lp:~yourlogin/+junk/debian-[dev|stable] -- To update this debian directory, edit files into the bzr dir and run - bzr status - bzr commit -m "Description of change" - bzr push lp:~yourlogin/+junk/debian-[dev|stable] + bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] -# Get repository of sources from launchpad (when repository for sources already exists) +# Get debian dir repository from launchpad (when repository for sources already exists) #---------------------------------- cd bzr - bzr branch lp:~yourlogin/+junk/debian-[dev|stable] + bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] + +# To update debian dir into launchpad (when repository for sources already exists) +#---------------------------------- + cd bzr + bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] + bzr status + -- Update files here -- + bzr commit -m "Description of change" + bzr push lp:~yourlogin/+junk/debian-[dev|beta|stable] # Define a recipe into launchpad (a rule to build packages into a PPA) #---------------------------------- - - Create a file dolibarr.recipe with content cd bzr vi dolibarr.recipe @@ -101,11 +126,11 @@ If you want to build/test package locally: # To get/download package from PPA: #---------------------------------- -Add signing key of the Launchpad repository: +- Add signing key of the Launchpad repository: > gpg --keyserver keyserver.ubuntu.com --recv-key A38BF8FD > sudo apt-key add ~/.gnupg/pubring.gpg -Add Dolibarr Launchpad repository to your system setup by adding the two lines to /etc/apt/sources.list +- Add Dolibarr Launchpad repository to your system setup by adding the two lines to /etc/apt/sources.list For the development snapshot version: deb http://ppa.launchpad.net/yourlogin/dolibarr-dev/ubuntu precise main deb-src http://ppa.launchpad.net/yourlogin/dolibarr-dev/ubuntu precise main @@ -113,12 +138,10 @@ For the stable version: deb http://ppa.launchpad.net/yourlogin/dolibarr-stable/ubuntu precise main deb-src http://ppa.launchpad.net/yourlogin/dolibarr-stable/ubuntu precise main -Update your package cache: +- Update your package cache: > apt-get update -Install Dolibarr: +- Install Dolibarr: > apt-get install dolibarr - - - + From 365a5e18e859148e532b57c21ab503628b7637de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 13:56:59 +0200 Subject: [PATCH 27/29] Prepare 3.3.2 --- build/launchpad/README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build/launchpad/README b/build/launchpad/README index 37c1c51f96a..dbf2dbdb4f1 100644 --- a/build/launchpad/README +++ b/build/launchpad/README @@ -64,12 +64,12 @@ If you want to build/test package locally: # To update Dolibarr into launchpad (when repository for sources already exists) #---------------------------------- cd bzr - bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] + bzr branch lp:~yourlogin/dolibarr/[dev|beta|stable] + cd dolibarr-[dev|beta|stable] bzr status -- Update files here -- bzr commit -m "Description of change" - bzr push lp:~yourlogin/+junk/debian-[dev|beta|stable] - + bzr push # Init debian dir repository into launchpad (when repository for sources does not exist) @@ -96,6 +96,7 @@ If you want to build/test package locally: #---------------------------------- cd bzr bzr branch lp:~yourlogin/+junk/debian-[dev|beta|stable] + cd debian-[dev|beta|stable] bzr status -- Update files here -- bzr commit -m "Description of change" From 203d4e3ca8907f3471fc79bac63e25c7fb143f1c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 14:17:04 +0200 Subject: [PATCH 28/29] Prepare database for parameters into boxes --- htdocs/install/mysql/migration/3.3.0-3.4.0.sql | 3 +++ htdocs/install/mysql/tables/llx_boxes.key.sql | 2 +- htdocs/install/mysql/tables/llx_boxes.sql | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql index 957dadf2845..acebc660662 100755 --- a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql +++ b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql @@ -347,3 +347,6 @@ ALTER TABLE llx_opensurvey_sondage ADD INDEX idx_date_fin (date_fin); ALTER TABLE llx_opensurvey_user_studs ADD INDEX idx_id_users (id_users); ALTER TABLE llx_opensurvey_user_studs ADD INDEX idx_nom (nom); ALTER TABLE llx_opensurvey_user_studs ADD INDEX idx_id_sondage (id_sondage); + +ALTER TABLE llx_boxes ADD COLUMN params varchar(255); + diff --git a/htdocs/install/mysql/tables/llx_boxes.key.sql b/htdocs/install/mysql/tables/llx_boxes.key.sql index d628257b5ce..52e06daf2af 100644 --- a/htdocs/install/mysql/tables/llx_boxes.key.sql +++ b/htdocs/install/mysql/tables/llx_boxes.key.sql @@ -21,7 +21,7 @@ ALTER TABLE llx_boxes ADD UNIQUE INDEX uk_boxes (entity, box_id, position, fk_user); -- Supprime orphelins pour permettre montee de la cle --- V4 DELETE llx_boxes FROM llx_boxes LEFT JOIN llx_boxes_def ON llx_boxes.box_id = llx_boxes_def.rowid WHERE llx_boxes_def.rowid IS NULL; +-- MYSQL V4 DELETE llx_boxes FROM llx_boxes LEFT JOIN llx_boxes_def ON llx_boxes.box_id = llx_boxes_def.rowid WHERE llx_boxes_def.rowid IS NULL; -- POSTGRESQL V8 DELETE FROM llx_boxes USING llx_boxes_def WHERE llx_boxes.box_id NOT IN (SELECT llx_boxes_def.rowid FROM llx_boxes_def); ALTER TABLE llx_boxes ADD INDEX idx_boxes_boxid (box_id); diff --git a/htdocs/install/mysql/tables/llx_boxes.sql b/htdocs/install/mysql/tables/llx_boxes.sql index a594e153afb..383e1bbcce4 100644 --- a/htdocs/install/mysql/tables/llx_boxes.sql +++ b/htdocs/install/mysql/tables/llx_boxes.sql @@ -19,7 +19,7 @@ -- =========================================================================== -- --- position : 0=index.php +-- position : 0=Home page index.php -- box_order : Box sort order -- @@ -31,6 +31,6 @@ create table llx_boxes position smallint NOT NULL, box_order varchar(3) NOT NULL, fk_user integer default 0 NOT NULL, - maxline integer NULL - + maxline integer NULL, + params varchar(255) )ENGINE=innodb; From 854b9df96de947c83a5689a02c19e4e940712eee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Apr 2013 16:18:26 +0200 Subject: [PATCH 29/29] Qual: Clean code of box management --- dev/skeletons/modMyModule.class.php | 10 +- htdocs/admin/boxes.php | 13 +- htdocs/core/ajax/box.php | 1 - htdocs/core/boxes/box_activity.php | 20 ++- htdocs/core/boxes/box_comptes.php | 15 +- htdocs/core/boxes/box_external_rss.php | 7 +- .../boxes/box_graph_invoices_permonth.php | 147 ++++++++++++++++++ htdocs/core/boxes/box_members.php | 13 +- htdocs/core/boxes/modules_boxes.php | 6 +- htdocs/core/class/html.formother.class.php | 14 +- htdocs/core/class/infobox.class.php | 31 ++-- htdocs/core/modules/DolibarrModules.class.php | 33 ++-- htdocs/core/modules/modFacture.class.php | 8 +- 13 files changed, 250 insertions(+), 68 deletions(-) create mode 100644 htdocs/core/boxes/box_graph_invoices_permonth.php diff --git a/dev/skeletons/modMyModule.class.php b/dev/skeletons/modMyModule.class.php index 5711b61c4ac..4bb936ba339 100644 --- a/dev/skeletons/modMyModule.class.php +++ b/dev/skeletons/modMyModule.class.php @@ -133,7 +133,7 @@ class modMyModule extends DolibarrModules $this->tabs = array(); // Dictionnaries - if (! isset($conf->mymodule->enabled)) + if (! isset($conf->mymodule->enabled)) { $conf->mymodule=new stdClass(); $conf->mymodule->enabled=0; @@ -158,14 +158,8 @@ class modMyModule extends DolibarrModules // Boxes // Add here list of php file(s) stored in core/boxes that contains class to show a box. $this->boxes = array(); // List of boxes - $r=0; // Example: - /* - $this->boxes[$r][1] = "myboxa.php"; - $r++; - $this->boxes[$r][1] = "myboxb.php"; - $r++; - */ + //$this->boxes=array(array(0=>array('file'=>'myboxa.php','note'=>'','enabledbydefaulton'=>'Home'),1=>array('file'=>'myboxb.php','note'=>''),2=>array('file'=>'myboxc.php','note'=>''));); // Permissions $this->rights = array(); // Permission array used by this module diff --git a/htdocs/admin/boxes.php b/htdocs/admin/boxes.php index 6fb5e458945..0b19d96040c 100644 --- a/htdocs/admin/boxes.php +++ b/htdocs/admin/boxes.php @@ -36,9 +36,8 @@ $rowid = GETPOST('rowid','int'); $action = GETPOST('action','alpha'); $errmesg=''; -// Definition des positions possibles pour les boites -$pos_array = array(0); // Positions possibles pour une boite (0,1,2,...) -$pos_name = array(0=>$langs->trans("Home")); // Nom des positions 0=Homepage, 1=... +// Define possible position of boxes +$pos_name = getStaticMember('InfoBox','listOfPages'); $boxes = array(); @@ -360,7 +359,7 @@ foreach($boxtoadd as $box) // Pour chaque position possible, on affiche un lien d'activation si boite non deja active pour cette position print ''; - print $form->selectarray("pos",$pos_name); + print $form->selectarray("pos",$pos_name,0,0,0,0,'',1); print ''; print ''; print ' '; @@ -406,7 +405,9 @@ foreach($boxactivated as $key => $box) print "\n".''."\n"; print ''; - print ''.img_object("",$logo).' '.$langs->transnoentitiesnoconv($box->boxlabel).''; + print ''.img_object("",$logo).' '.$langs->transnoentitiesnoconv($box->boxlabel); + //if (! empty($box->graph)) print ' ('.$langs->trans("Graph").')'; + print ''; print ''; if ($box->note == '(WarningUsingThisBoxSlowDown)') { @@ -415,7 +416,7 @@ foreach($boxactivated as $key => $box) } else print ($box->note?$box->note:' '); print ''; - print '' . (isset($pos_name[$box->position])?$pos_name[$box->position]:'') . ''; + print '' . (empty($pos_name[$box->position])?'':$langs->trans($pos_name[$box->position])) . ''; $hasnext=($key < (count($boxactivated)-1)); $hasprevious=($key != 0); print ''.($key+1).''; diff --git a/htdocs/core/ajax/box.php b/htdocs/core/ajax/box.php index 324339f5b25..50305655dcd 100644 --- a/htdocs/core/ajax/box.php +++ b/htdocs/core/ajax/box.php @@ -68,7 +68,6 @@ if ($boxorder && $zone != '' && $userid > 0) // boxorder value is the target order: "A:idboxA1,idboxA2,A-B:idboxB1,idboxB2,B" dol_syslog("AjaxBox boxorder=".$boxorder." zone=".$zone." userid=".$userid, LOG_DEBUG); - //$infobox=new InfoBox($db); $result=InfoBox::saveboxorder($db,$zone,$boxorder,$userid); } diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php index 87e555958e8..ad0da9451e9 100644 --- a/htdocs/core/boxes/box_activity.php +++ b/htdocs/core/boxes/box_activity.php @@ -41,9 +41,23 @@ class box_activity extends ModeleBoxes var $info_box_head = array(); var $info_box_contents = array(); - // FIXME: Use a cache to save data because this slow down too much main home page. This box slow down too seriously software. - // FIXME: Removed number_format (not compatible with all languages) - // FIXME: Pb into some status + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + function __construct($db,$param) + { + global $conf; + + $this->db=$db; + // FIXME: Use a cache to save data because this slow down too much main home page. This box slow down too seriously software. + // FIXME: Removed number_format (not compatible with all languages) + // FIXME: Pb into some status + $this->enabled=$conf->global->MAIN_FEATURES_LEVEL; // Not enabled by default due to bugs (see previous FIXME) + } /** * Charge les donnees en memoire pour affichage ulterieur diff --git a/htdocs/core/boxes/box_comptes.php b/htdocs/core/boxes/box_comptes.php index 5fc8d2add91..2df5f0dd002 100644 --- a/htdocs/core/boxes/box_comptes.php +++ b/htdocs/core/boxes/box_comptes.php @@ -39,22 +39,23 @@ class box_comptes extends ModeleBoxes var $db; var $param; var $enabled = 1; - + var $info_box_head = array(); var $info_box_contents = array(); - + /** - * Constructor + * Constructor * - * @param DoliDB $db Database handler + * @param DoliDB $db Database handler + * @param string $param More parameters */ - function __construct($db) + function __construct($db,$param='') { global $conf, $user; - + $this->db = $db; - + // disable module for such cases $listofmodulesforexternal=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL); if (! in_array('banque',$listofmodulesforexternal) && ! empty($user->societe_id)) $this->enabled=0; // disabled for external users diff --git a/htdocs/core/boxes/box_external_rss.php b/htdocs/core/boxes/box_external_rss.php index faf8f872ecc..09b56cff52e 100644 --- a/htdocs/core/boxes/box_external_rss.php +++ b/htdocs/core/boxes/box_external_rss.php @@ -39,11 +39,12 @@ class box_external_rss extends ModeleBoxes var $depends = array("externalrss"); var $db; - var $param; + var $paramdef; // Params of box definition (not user params) var $info_box_head = array(); var $info_box_contents = array(); + /** * Constructor * @@ -53,7 +54,7 @@ class box_external_rss extends ModeleBoxes function __construct($db,$param) { $this->db=$db; - $this->param=$param; + $this->paramdef=$param; } /** @@ -71,7 +72,7 @@ class box_external_rss extends ModeleBoxes $this->max=$max; // On recupere numero de param de la boite - preg_match('/^([0-9]+) /',$this->param,$reg); + preg_match('/^([0-9]+) /',$this->paramdef,$reg); $site=$reg[1]; // Create dir nor required diff --git a/htdocs/core/boxes/box_graph_invoices_permonth.php b/htdocs/core/boxes/box_graph_invoices_permonth.php new file mode 100644 index 00000000000..c0e6ce00447 --- /dev/null +++ b/htdocs/core/boxes/box_graph_invoices_permonth.php @@ -0,0 +1,147 @@ + + * + * 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/boxes/box_invoice_permonth.php + * \ingroup factures + * \brief Box to show graph of invoices per month + */ +include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; + + +/** + * Class to manage the box to show last invoices + */ +class box_graph_invoices_permonth extends ModeleBoxes +{ + var $boxcode="invoicespermonth"; + var $boximg="object_bill"; + var $boxlabel="BoxInvoicesPerMonth"; + var $depends = array("facture"); + + var $db; + + var $info_box_head = array(); + var $info_box_contents = array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + function __construct($db,$param) + { + global $conf; + + $this->db=$db; + $this->enabled=$conf->global->MAIN_FEATURES_LEVEL; + } + + /** + * Load data into info_box_contents array to show array later. + * + * @param int $max Maximum number of records to load + * @return void + */ + function loadBox($max=5) + { + global $conf, $user, $langs, $db; + + $this->max=$max; + + include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $facturestatic=new Facture($db); + + $text = $langs->trans("BoxInvoicesPerMonth",$max); + $this->info_box_head = array( + 'text' => $text, + 'limit'=> dol_strlen($text) + ); + + if ($user->rights->facture->lire) + { + $sql = "SELECT f.rowid as facid, f.facnumber, f.type, f.amount, f.datef as df"; + $sql.= ", f.paye, f.fk_statut, f.datec, f.tms"; + $sql.= ", s.nom, s.rowid as socid"; + $sql.= ", f.date_lim_reglement as datelimite"; + $sql.= " FROM (".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= ")"; + $sql.= " WHERE f.fk_soc = s.rowid"; + $sql.= " AND f.entity = ".$conf->entity; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; + $sql.= " ORDER BY f.tms DESC"; + $sql.= $db->plimit($max, 0); + + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + $now=dol_now(); + + $i = 0; + $l_due_date = $langs->trans('Late').' ('.strtolower($langs->trans('DateEcheance')).': %s)'; + + while ($i < $num) + { + $objp = $db->fetch_object($result); + $datelimite=$db->jdate($objp->datelimite); + $datec=$db->jdate($objp->datec); + + $picto='bill'; + if ($objp->type == 1) $picto.='r'; + if ($objp->type == 2) $picto.='a'; + $late = ''; + if ($objp->paye == 0 && ($objp->fk_statut != 2 && $objp->fk_statut != 3) && $datelimite < ($now - $conf->facture->client->warning_delay)) { $late = img_warning(sprintf($l_due_date,dol_print_date($datelimite,'day')));} + + $i++; + } + + $this->info_box_contents[0][0] = array('td' => 'align="center"','text2'=>'xxxxxxx'); + } + else + { + $this->info_box_contents[0][0] = array( 'td' => 'align="left"', + 'maxlength'=>500, + 'text' => ($db->error().' sql='.$sql)); + } + + } + else { + $this->info_box_contents[0][0] = array('td' => 'align="left"', + 'text' => $langs->trans("ReadPermissionNotAllowed")); + } + } + + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @return void + */ + function showBox($head = null, $contents = null) + { + parent::showBox($this->info_box_head, $this->info_box_contents); + } + +} + +?> diff --git a/htdocs/core/boxes/box_members.php b/htdocs/core/boxes/box_members.php index 91d3cd918b9..fdb6db8c7f5 100755 --- a/htdocs/core/boxes/box_members.php +++ b/htdocs/core/boxes/box_members.php @@ -39,25 +39,26 @@ class box_members extends ModeleBoxes var $db; var $param; var $enabled = 1; - + var $info_box_head = array(); var $info_box_contents = array(); /** - * Constructor + * Constructor * - * @param DoliDB $db Database handler + * @param DoliDB $db Database handler + * @param string $param More parameters */ - function __construct($db) + function __construct($db,$param='') { global $conf, $user; $this->db = $db; - + // disable module for such cases $listofmodulesforexternal=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL); - if (! in_array('banque',$listofmodulesforexternal) && ! empty($user->societe_id)) $this->enabled=0; // disabled for external users + if (! in_array('adherent',$listofmodulesforexternal) && ! empty($user->societe_id)) $this->enabled=0; // disabled for external users } /** diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index c681395f5af..c930fece2e5 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -40,6 +40,7 @@ class ModeleBoxes // Can't be abtract as it is instanciated to build "empty" var $box_order; var $fk_user; var $sourcefile; + var $class; var $box_id; var $note; @@ -47,9 +48,10 @@ class ModeleBoxes // Can't be abtract as it is instanciated to build "empty" /** * Constructor * - * @param DoliDB $db Database handler + * @param DoliDB $db Database handler + * @param string $param More parameters */ - function __construct($db) + function __construct($db,$param='') { $this->db=$db; } diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index a0d63e42b4a..73427b71455 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -886,7 +886,9 @@ class FormOther foreach($boxactivated as $box) { if (! empty($boxidactivatedforuser[$box->id])) continue; // Already visible for user - $arrayboxtoactivatelabel[$box->id]=$langs->transnoentitiesnoconv($box->boxlabel); // We keep only boxes not shown for user, to show into combo list + $label=$langs->transnoentitiesnoconv($box->boxlabel); + if (preg_match('/graph/',$box->class)) $label.=' ('.$langs->trans("Graph").')'; + $arrayboxtoactivatelabel[$box->id]=$label; // We keep only boxes not shown for user, to show into combo list } $form=new Form($db); @@ -897,7 +899,7 @@ class FormOther if (! empty($conf->use_javascript_ajax)) { print ''."\n"; } diff --git a/htdocs/core/class/infobox.class.php b/htdocs/core/class/infobox.class.php index 1a4cd9d4244..07ca9026482 100644 --- a/htdocs/core/class/infobox.class.php +++ b/htdocs/core/class/infobox.class.php @@ -27,6 +27,9 @@ */ class InfoBox { + static $listOfPages = array(0=>'Home'); // Nom des positions 0=Home, 1=... + + /** * Return array of boxes qualified for area and user * @@ -57,17 +60,16 @@ class InfoBox $sql.= " ORDER BY b.box_order"; } else - { + { $sql = "SELECT d.rowid as box_id, d.file, d.note, d.tms"; $sql.= " FROM ".MAIN_DB_PREFIX."boxes_def as d"; - if (! empty($conf->multicompany->enabled) && ! empty($conf->multicompany->transverse_mode)) { - + if (! empty($conf->multicompany->enabled) && ! empty($conf->multicompany->transverse_mode)) + { $sql.= " WHERE entity IN (1,".$conf->entity.")"; // TODO add method for define another master entity - - } else { - + } + else + { $sql.= " WHERE entity = ".$conf->entity; - } } @@ -95,18 +97,24 @@ class InfoBox $relsourcefile = "/core/boxes/".$boxname.".php"; } + // TODO PERF Do not make "dol_include_once" here, nor "new" later. This means, we must store a 'depends' field to store modules list, then + // the "enabled" condition for modules forbidden for external users and the depends condition can be done. + // Goal is to avoid making a new instance for each boxes returned by select. + dol_include_once($relsourcefile); if (class_exists($boxname)) { - $box=new $boxname($db,$obj->note); + $box=new $boxname($db,$obj->note); // Constructor may set properties like box->enabled. obj->note is note into box def, not user params. + //$box=new stdClass(); // box properties $box->rowid = (empty($obj->rowid) ? '' : $obj->rowid); $box->id = (empty($obj->box_id) ? '' : $obj->box_id); - $box->position = (empty($obj->position) ? '' : $obj->position); + $box->position = ($obj->position == '' ? '' : $obj->position); // '0' must staty '0' $box->box_order = (empty($obj->box_order) ? '' : $obj->box_order); $box->fk_user = (empty($obj->fk_user) ? 0 : $obj->fk_user); - $box->sourcefile=$relsourcefile; + $box->sourcefile= $relsourcefile; + $box->class = $boxname; if ($mode == 'activated' && ! is_object($user)) // List of activated box was not yet personalized into database { if (is_numeric($box->box_order)) @@ -119,6 +127,8 @@ class InfoBox $box->box_id = (empty($obj->box_id) ? '' : $obj->box_id); $box->note = (empty($obj->note) ? '' : $obj->note); + // Filter on box->enabled (fused for example by box_comptes) and box->depends + //$enabled=1; $enabled=$box->enabled; if (isset($box->depends) && count($box->depends) > 0) { @@ -131,6 +141,7 @@ class InfoBox //print 'xx module='.$module.' enabled='.$enabled; if ($enabled) $boxes[]=$box; + else unset($box); } } $j++; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 1885662a512..3134ae4162a 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -502,7 +502,9 @@ abstract class DolibarrModules */ function insert_boxes() { - global $conf; + require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; + + global $conf; $err=0; @@ -510,9 +512,12 @@ abstract class DolibarrModules { foreach ($this->boxes as $key => $value) { - //$titre = $this->boxes[$key][0]; - $file = isset($this->boxes[$key][1])?$this->boxes[$key][1]:''; - $note = isset($this->boxes[$key][2])?$this->boxes[$key][2]:''; + $file = isset($this->boxes[$key]['file'])?$this->boxes[$key]['file']:''; + $note = isset($this->boxes[$key]['note'])?$this->boxes[$key]['note']:''; + $enabledbydefaulton = isset($this->boxes[$key]['enabledbydefaulton'])?$this->boxes[$key]['enabledbydefaulton']:'Home'; + + if (empty($file)) $file = isset($this->boxes[$key][1])?$this->boxes[$key][1]:''; // For backward compatibility + if (empty($note)) $note = isset($this->boxes[$key][2])?$this->boxes[$key][2]:''; // For backward compatibility $sql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."boxes_def"; $sql.= " WHERE file = '".$this->db->escape($file)."'"; @@ -544,12 +549,19 @@ abstract class DolibarrModules { $lastid=$this->db->last_insert_id(MAIN_DB_PREFIX."boxes_def","rowid"); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes (box_id,position,box_order,fk_user,entity)"; - $sql.= " VALUES (".$lastid.", 0, '0', 0, ".$conf->entity.")"; + $pos_name = getStaticMember('InfoBox','listOfPages'); + foreach ($pos_name as $key2 => $val2) + { + //print 'key2='.$key2.'-val2='.$val2."
\n"; + if ($enabledbydefaulton && $val2 != $enabledbydefaulton) continue; // Not enabled by default onto this page. - dol_syslog(get_class($this)."::insert_boxes sql=".$sql); - $resql=$this->db->query($sql); - if (! $resql) $err++; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes (box_id,position,box_order,fk_user,entity)"; + $sql.= " VALUES (".$lastid.", ".$key2.", '0', 0, ".$conf->entity.")"; + + dol_syslog(get_class($this)."::insert_boxes onto page ".$key2."=".$val2." sql=".$sql); + $resql=$this->db->query($sql); + if (! $resql) $err++; + } } if (! $err) @@ -563,9 +575,10 @@ abstract class DolibarrModules $this->db->rollback(); } } + // else box already registered into database } else - { + { $this->error=$this->db->lasterror(); dol_syslog(get_class($this)."::insert_boxes ".$this->error, LOG_ERR); $err++; diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index 4d18c3d8757..6b243b4d22e 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -97,12 +97,8 @@ class modFacture extends DolibarrModules $r++; // Boxes - $this->boxes = array(); - $r=0; - $this->boxes[$r][1] = "box_factures_imp.php"; - $r++; - $this->boxes[$r][1] = "box_factures.php"; - $r++; + //$this->boxes = array(0=>array(1=>'box_factures_imp.php'),1=>array(1=>'box_factures.php')); + $this->boxes = array(0=>array('file'=>'box_factures_imp.php','enabledbydefaulton'=>'Home'),1=>array('file'=>'box_factures.php','enabledbydefaulton'=>'Home'),2=>array('file'=>'box_graph_invoices_permonth.php','enabledbydefaulton'=>'Home')); // Permissions $this->rights = array();