Skip to content
Snippets Groups Projects
Select Git revision
  • 73fda2cb86d81235bac37808efaf3599ea7e2aed
  • 3.9 default
  • develop
  • 6.0
  • 5.0
  • 4.0
  • scrutinizer-patch-4
  • scrutinizer-patch-3
  • scrutinizer-patch-2
  • scrutinizer-patch-1
  • 3.7
  • 3.8
  • 3.6
  • 3.9_backported
  • 3.8_backported
  • 3.7_backported
  • 3.5
  • 3.6_backported
  • 3.5_backported
  • 3.4
  • 3.3_backported
  • 6.0.4
  • 6.0.3
  • 5.0.7
  • 6.0.2
  • 6.0.1
  • 5.0.6
  • 6.0.0
  • 5.0.5
  • 6.0.0-rc
  • 5.0.4
  • 6.0.0-beta
  • 5.0.3
  • 4.0.6
  • 5.0.2
  • 5.0.1
  • 4.0.5
  • 5.0.0
  • 4.0.4
  • 5.0.0-rc2
  • 5.0.0-rc1
41 results

FunctionsLibTest.php

Blame
  • functions.inc.php 57.49 KiB
    <?php
    /* Copyright (C) 2000-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
     * Copyright (C) 2003      Jean-Louis Bergamo   <jlb@j1b.org>
     * Copyright (C) 2004-2005 Laurent Destailleur  <eldy@users.sourceforge.net>
     * Copyright (C) 2004      Sebastien Di Cintio  <sdicintio@ressource-toi.org>
     * Copyright (C) 2004      Benoit Mortier       <benoit.mortier@opensides.be>
     * Copyright (C) 2004      Christophe Combelles <ccomb@free.fr>
     *
     * 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 2 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, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     * or see http://www.gnu.org/
     *
     * $Id$
     * $Source$
     */
    
    /**
    	    \file       htdocs/lib/functions.inc.php
    		\brief      Ensemble de fonctions de base de dolibarr sous forme d'include
    		\author     Rodolphe Quiedeville
    		\author	    Jean-Louis Bergamo
    		\author	    Laurent Destailleur
    		\author     Sebastien Di Cintio
    		\author     Benoit Mortier
    		\version    $Revision$
    
    		Ensemble de fonctions de base de dolibarr sous forme d'include
    */
    
    
    /**
    		\brief      Renvoi une version en chaine depuis une version en tableau
    		\param	    versionarray        Tableau de version (vermajeur,vermineur,autre)
            \return     string              Chaine version
    */
    function versiontostring($versionarray)
    {
        $string='?';
        if (isset($versionarray[0])) $string=$versionarray[0];
        if (isset($versionarray[1])) $string.='.'.$versionarray[1];
        if (isset($versionarray[2])) $string.='.'.$versionarray[2];
        return $string;
    }
    
    /**
    		\brief      Compare 2 versions
    		\param	    versionarray1       Tableau de version (vermajeur,vermineur,autre)
    		\param	    versionarray2       Tableau de version (vermajeur,vermineur,autre)
            \return     int                 <0 si versionarray1>versionarray2, 0 si =, >0 si versionarray1>versionarray2
    */
    function versioncompare($versionarray1,$versionarray2)
    {
        $ret=0;
        $i=0;
        while ($i < max(sizeof($versionarray1),sizeof($versionarray1)))
        {
            $operande1=isset($versionarray1[$i])?$versionarray1[$i]:0;
            $operande2=isset($versionarray2[$i])?$versionarray2[$i]:0;
            if ($operande1 < $operande2) { $ret = -1; break; }
            if ($operande1 > $operande2) { $ret =  1; break; }
            $i++;
        }    
        return $ret;
    }
    
    
    /**
    		\brief      Compare 2 versions
            \return     array               Tableau de version (vermajeur,vermineur,autre)
    */
    function versionphp()
    {
        return split('\.',PHP_VERSION);
    }
    
    
    /**
    		\brief      Renvoi vrai si l'email est syntaxiquement valide
    		\param	    address     adresse email (Ex: "toto@titi.com", "John Do <johndo@titi.com>")
            \return     boolean     true si email valide, false sinon
    */
    function ValidEmail($address)
    {
      if (ereg( ".*<(.+)>", $address, $regs)) {
        $address = $regs[1];
      }
      if (ereg( "^[^@  ]+@([a-zA-Z0-9\-]+\.)+([a-zA-Z0-9\-]{2}|net|com|gov|mil|org|edu|info|name|int)\$",$address))
        {
          return true;
        }
      else
        {
          return false;
        }
    }
    
    /**
    		\brief      Renvoi vrai si l'email a un nom de domaine qui rsoud via dns
    		\param	    mail        adresse email (Ex: "toto@titi.com", "John Do <johndo@titi.com>")
            \return     boolean     true si email valide, false sinon
    */
    function check_mail ($mail)
    {
      list($user, $domain) = split("@", $mail, 2);
      if (checkdnsrr($domain, "MX"))
        {
          return true;
        }
      else
        {
          return false;
        }
    }
    
    /**
            \brief          Nettoie chaine de caractre des accents
            \param          str             Chaine a nettoyer
            \return         string          Chaine nettoy
    */
    function unaccent($str)
    {
      $acc = array("","","","","","","","","","","","'");
      $uac = array("a","a","e","e","e","i","i","o","o","u","u","");
    
      return str_replace($acc, $uac, $str);
    }
    
    /**
            \brief          Nettoie chaine de caractre de caractres spciaux
            \param          str             Chaine a nettoyer
            \return         string          Chaine nettoy
    */
    function sanitize_string($str)
    {
        $forbidden_chars=array(" ","'","/","\\",":","*","?","\"","<",">","|","[","]",",",";","="); 
        return str_replace($forbidden_chars,"_",$str);
    }
    
    
    /**
       \brief       Envoi des messages dolibarr dans syslog ou dans un fichier
                    Pour syslog:    facility dfini par SYSLOG_FACILITY
                    Pour fichier:   fichier dfini par SYSLOG_FILE
       \param       message		    Message a envoyer a syslog
       \param       level           Niveau de l'erreur
       \remarks     Cette fonction n'a un effet que si le module syslog est activ.
                    Warning, les fonctions syslog sont buggus sous Windows et gnrent des
                    fautes de protection mmoire. Pour rsoudre, utiliser le loggage fichier,
                    au lieu du loggage syslog (configuration du module).
    */
    function dolibarr_syslog($message, $level=LOG_ERR)
    {
        global $conf,$user,$langs;
        
        if ($conf->syslog->enabled)
        {
            // Ajout user a la log
            $login='???';
            if (is_object($user) && $user->id) $login=$user->login;
            $message=sprintf("%-8s",$login)." ".$message;
    
            if (defined("SYSLOG_FILE") && SYSLOG_FILE)
            {
                $file=fopen(SYSLOG_FILE,"a+");
                if ($file) {
                    fwrite($file,strftime("%Y-%m-%d %H:%M:%S",time())." ".$level." ".$message."\n");
                    fclose($file);
                }
                else {
                    $langs->load("main");
                    print $langs->trans("ErrorFailedToOpenFile",SYSLOG_FILE);
                }
            }
            else
            {
    			//define_syslog_variables(); dj dfinit dans master.inc.php
            
                if (defined("MAIN_SYSLOG_FACILITY") && MAIN_SYSLOG_FACILITY)
                {
                    $facility = MAIN_SYSLOG_FACILITY;
                }
                elseif (defined("SYSLOG_FACILITY") && SYSLOG_FACILITY && defined(SYSLOG_FACILITY))
                {
                    // Exemple: SYSLOG_FACILITY vaut LOG_USER qui vaut 8. On a besoin de 8 dans $facility.
                    $facility = constant(SYSLOG_FACILITY);
                }
                else
                {
                    $facility = LOG_USER;
                }
            
                openlog("dolibarr", LOG_PID | LOG_PERROR, $facility);
            
                if (! $level)
                {
                    syslog(LOG_ERR, $message);
                }
                else
                {
                    syslog($level, $message);
                }
            
                closelog();
            }
        }
    }
    
    
    /**
    		\brief      Affiche le header d'une fiche
    		\param	    links		Tableau de titre d'onglets
    		\param	    active      0=onglet non actif, 1=onglet actif
    		\param      title       Titre tabelau ("" par defaut)
    */
    function dolibarr_fiche_head($links, $active=0, $title='')
    {
        print '<div class="tabs">'."\n";
    
        // Affichage titre
        if ($title)
        {
            $limittitle=30;
            print '<a class="tabTitle">';
            print 
    			((!defined('MAIN_USE_SHORT_TITLE')) || (defined('MAIN_USE_SHORT_TITLE') &&  MAIN_USE_SHORT_TITLE))
    			? dolibarr_trunc($title,$limittitle)
    			: $title;
            print '</a>';
        }
    
        // Affichage onglets
        for ($i = 0 ; $i < sizeof($links) ; $i++)
        {
            if ($links[$i][2] == 'image')
            {
                print '<a class="tabimage" href="'.$links[$i][0].'">'.$links[$i][1].'</a>'."\n";
            }
            else
            {
                if ($i == $active)
                {
                    print '<a id="active" class="tab" href="'.$links[$i][0].'">'.$links[$i][1].'</a>'."\n";
                }
                else
                {
                    print '<a class="tab" href="'.$links[$i][0].'">'.$links[$i][1].'</a>'."\n";
                }
            }
        }
    
        print "</div>\n";
        
        print '<div class="tabBar">'."\n\n";
    }
    
    /**
    		\brief      Rcupre une constante depuis la base de donnes.
    		\see        dolibarr_del_const, dolibarr_set_const
    		\param	    db          Handler d'accs base
    		\param	    name		Nom de la constante
    		\return     string      Valeur de la constante
    */
    function dolibarr_get_const($db, $name)
    {
        $value='';
        
        $sql ="SELECT value";
        $sql.=" FROM llx_const";
        $sql.=" WHERE name = '$name';"; 		
        $resql=$db->query($sql);	
        if ($resql)
        {
            $obj=$db->fetch_object($resql);
            $value=$obj->value;
        }
        return $value;
    }
    
    
    /**
    		\brief      Insertion d'une constante dans la base de donnes.
    		\see        dolibarr_del_const, dolibarr_get_const
    		\param	    db          Handler d'accs base
    		\param	    name		Nom de la constante
    		\param	    value		Valeur de la constante
    		\param	    type		Type de constante (chaine par dfaut)
    		\param	    visible	    La constante est elle visible (0 par dfaut)
    		\param	    note		Explication de la constante
    		\return     int         <0 si ko, >0 si ok
    */
    function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='')
    {
        global $conf;
        
        $db->begin();
        
        //dolibarr_syslog("dolibarr_set_const name=$name, value=$value");
        $sql = "DELETE FROM llx_const WHERE name = '$name';"; 		
        $resql=$db->query($sql);	
        
        $sql = "INSERT INTO llx_const(name,value,type,visible,note)";
        $sql.= " VALUES ('$name','".addslashes($value)."','$type',$visible,'".addslashes($note)."');";
        $resql=$db->query($sql);	
    
        if ($resql)
        {
            $db->commit();
            $conf->global->$name=$value;
            return 1;
        }
        else
        {
            $db->rollback();
            return -1;
        }
    }
    
    /**
    		\brief      Effacement d'une constante dans la base de donnes
    		\see        dolibarr_get_const, dolibarr_sel_const
    		\param	    db          Handler d'accs base
    		\param	    name		Nom ou rowid de la constante
    		\return     int         <0 si ko, >0 si ok
    */
    function dolibarr_del_const($db, $name)
    {
        $sql = "DELETE FROM llx_const WHERE name='$name' or rowid='$name'";
        $resql=$db->query($sql);
    
        if ($resql)
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }
    
    /**
    		\brief  Formattage des nombres
    		\param	ca			valeur a formater
    		\return	int			valeur formate
    */
    function dolibarr_print_ca($ca)
    {
        global $langs,$conf;
        
        if ($ca > 1000)
        {
          $cat = round(($ca / 1000),2);
          $cat = "$cat K".$langs->trans("Currency".$conf->monnaie);
        }
        else
        {
          $cat = round($ca,2);
          $cat = "$cat ".$langs->trans("Currency".$conf->monnaie);
        }
    
        if ($ca > 1000000)
        {
          $cat = round(($ca / 1000000),2);
          $cat = "$cat M".$langs->trans("Currency".$conf->monnaie);
        }
    
        return $cat;
    }
    
    
    /**
    		\brief      Effectue un dcalage de date par rapport  une dure
    		\param	    time                Date timestamp ou au format YYYY-MM-DD
    		\param	    duration_value      Valeur de la dure  ajouter
    		\param	    duration_unit       Unit de la dure  ajouter (d, m, y)
    		\return     int                 Nouveau timestamp
    */
    function dolibarr_time_plus_duree($time,$duration_value,$duration_unit)
    {
        $deltastring="+$duration_value";
        if ($duration_unit == 'd') { $deltastring.=" day"; }
        if ($duration_unit == 'm') { $deltastring.=" month"; }
        if ($duration_unit == 'y') { $deltastring.=" year"; }
        return strtotime($deltastring,$time);
    }
    
    
    /**
    		\brief      Formattage de la date en fonction de la langue $conf->langage
    		\param	    time        Date 'timestamp' ou format 'YYYY-MM-DD' ou 'YYYY-MM-DD HH:MM:SS'
    		\param	    format      Format d'affichage de la date ("%d %b %Y", "%d/%m/%Y", ...)
    		\return     string      Date formate ou '?' si time null
    */
    function dolibarr_print_date($time,$format='')
    {
        global $conf;
        
        // Si format non dfini, on prend $conf->format_date_text_short
        if (! $format) $format=$conf->format_date_text_short;
    
        // Si date non dfinie, on renvoie '?'
        if (! $time) return '?';
    
        // Analyse de la date
        if (eregi('^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?',$time,$reg))
        {
            // Date est au format 'YYYY-MM-DD' ou 'YYYY-MM-DD HH:MM:SS'
            $syear = $reg[1];
            $smonth = $reg[2];
            $sday = $reg[3];
            $shour = $reg[4];
            $smin = $reg[5];
            if ($syear < 1970 && isset($_SERVER["WINDIR"]))
            {
                // Le formatage ne peut etre appliqu car windows ne supporte pas la fonction
                // mktime si l'anne est infrieur  1970. On retourne un format fixe
                return "$syear-$smonth-$sday";
            }
            else
            {
                return strftime($format,mktime($shour,$smin,0,$smonth,$sday,$syear));
            }
        }
        else
        {
            // Date est un timestamps
            return strftime($format,$time);
        }
    }
    
    
    /**
    		\brief  Affiche les informations d'un objet
    		\param	object			objet a afficher
    */
    function dolibarr_print_object_info($object)
    {
        global $langs;
    
        if (isset($object->user_creation) && $object->user_creation->fullname)
            print $langs->trans("CreatedBy")." : " . $object->user_creation->fullname . '<br>';
    
        if (isset($object->date_creation))
            print $langs->trans("DateCreation")." : " . dolibarr_print_date($object->date_creation,"%A %d %B %Y %H:%M:%S") . '<br>';
        
        if (isset($object->user_modification) && $object->user_modification->fullname)
            print $langs->trans("ModifiedBy")." : " . $object->user_modification->fullname . '<br>';
            
        if (isset($object->date_modification))
            print $langs->trans("DateLastModification")." : " . dolibarr_print_date($object->date_modification,"%A %d %B %Y %H:%M:%S") . '<br>';
        
        if (isset($object->user_validation) && $object->user_validation->fullname)
            print $langs->trans("ValidatedBy")." : " . $object->user_validation->fullname . '<br>';
        
        if (isset($object->date_validation))
            print $langs->trans("DateValidation")." : " . dolibarr_print_date($object->date_validation,"%A %d %B %Y %H:%M:%S") . '<br>';
    
        if (isset($object->user_cloture) && $object->user_cloture->fullname )
            print $langs->trans("ClosedBy")." : " . $object->user_cloture->fullname . '<br>';
    
        if (isset($object->date_cloture))
            print $langs->trans("DateClosing")." : " . dolibarr_print_date($object->date_cloture,"%A %d %B %Y %H:%M:%S") . '<br>';
    
        if (isset($object->user_rappro) && $object->user_rappro->fullname )
            print $langs->trans("ConciliatedBy")." : " . $object->user_rappro->fullname . '<br>';
    
        if (isset($object->date_rappro))
            print $langs->trans("DateConciliating")." : " . dolibarr_print_date($object->date_rappro,"%A %d %B %Y %H:%M:%S") . '<br>';
    }
    
    /**
            \brief      Formatage des numros de telephone en fonction du format d'un pays
            \param	    phone			Numro de telephone  formater
            \param	    country			Pays selon lequel formatter
            \return     string			Numro de tlphone format
    */
    function dolibarr_print_phone($phone,$country="FR")
    {
        $phone=trim($phone);
        if (strstr($phone, ' ')) { return $phone; }
        if (strtoupper($country) == "FR") {
            // France
            if (strlen($phone) == 10) {
                return substr($phone,0,2)."&nbsp;".substr($phone,2,2)."&nbsp;".substr($phone,4,2)."&nbsp;".substr($phone,6,2)."&nbsp;".substr($phone,8,2);
            }
            elseif (strlen($phone) == 7)
            {
                return substr($phone,0,3)."&nbsp;".substr($phone,3,2)."&nbsp;".substr($phone,5,2);
            }
            elseif (strlen($phone) == 9)
            {
                return substr($phone,0,2)."&nbsp;".substr($phone,2,3)."&nbsp;".substr($phone,5,2)."&nbsp;".substr($phone,7,2);
            }
            elseif (strlen($phone) == 11)
            {
                return substr($phone,0,3)."&nbsp;".substr($phone,3,2)."&nbsp;".substr($phone,5,2)."&nbsp;".substr($phone,7,2)."&nbsp;".substr($phone,9,2);
            }
            elseif (strlen($phone) == 12)
            {
                return substr($phone,0,4)."&nbsp;".substr($phone,4,2)."&nbsp;".substr($phone,6,2)."&nbsp;".substr($phone,8,2)."&nbsp;".substr($phone,10,2);
            }
        }
        return $phone;
    }
    
    /**
            \brief      Tronque une chaine  une taille donne en ajoutant les points de suspension si cela dpasse
            \param      string		Chaine  tronquer
            \param      size		Longueur max de la chaine
            \return     string		Chaine tronque
    */
    function dolibarr_trunc($string,$size=40)
    {
    	if (strlen($string) > $size)
    		return substr($string,0,$size).'...';
    	else
    		return $string;
    }
    
    /**
            \brief      Affiche picto propre  une notion/module (fonction gnrique)
            \param      alt         Texte sur le alt de l'image
            \param      object      Objet pour lequel il faut afficher le logo (exemple: user, group, action, bill, contract, propal, product, ...)
            \return     string      Retourne tag img
    */
    function img_object($alt, $object)
    {
      global $conf,$langs;
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/object_'.$object.'.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche picto (fonction gnrique)
            \param      alt         Texte sur le alt de l'image
            \param      picto       Nom de l'image a afficher
            \return     string      Retourne tag img
    */
    function img_picto($alt, $picto)
    {
      global $conf,$langs;
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/'.$picto.'.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo action
            \param      alt         Texte sur le alt de l'image
            \param      numaction   Determine image action
            \return     string      Retourne tag img
    */
    function img_action($alt = "default", $numaction)
    {
      global $conf,$langs;
      if ($alt=="default") {
        if ($numaction == -1) $alt=$langs->trans("ChangeDoNotContact");
        if ($numaction == 0)  $alt=$langs->trans("ChangeNeverContacted");
        if ($numaction == 1)  $alt=$langs->trans("ChangeToContact");
        if ($numaction == 2)  $alt=$langs->trans("ChangeContactInProcess");
        if ($numaction == 3)  $alt=$langs->trans("ChangeContactDone");
      }
      return '<img align="absmiddle" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/stcomm'.$numaction.'.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo statut
            \param      num         Numro statut
            \param      alt         Texte a afficher sur alt
            \return     string      Retourne tag img
    */
    function img_statut($num,$alt = "default")
    {
        global $conf,$langs;
        if ($alt=="default") {
            if ($num == 0) $alt=$langs->trans("Draft");
            if ($num == 1) $alt=$langs->trans("Late");
            if ($num == 4) $alt=$langs->trans("Running");
            if ($num == 5) $alt=$langs->trans("Closed");
        } 
        return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/statut'.$num.'.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo fichier
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_file($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Show");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/file.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo dossier
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_folder($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Dossier");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/folder.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo nouveau fichier
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_file_new($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Show");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/filenew.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo pdf
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_pdf($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Show");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/pdf.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo +
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_edit_add($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Add");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/edit_add.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    /**
            \brief      Affiche logo -
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_edit_remove($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Remove");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/edit_remove.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo editer/modifier fiche
            \param      alt         Texte sur le alt de l'image
            \param      float       Si il faut y mettre le style "float: right"
            \return     string      Retourne tag img
    */
    function img_edit($alt = "default",$float=0)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Modify");
        $img='<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/edit.png" border="0" alt="'.$alt.'" title="'.$alt.'"';
        if ($float) $img.=' style="float: right"';
        $img.='>';
        return $img;
    }
    
    /**
            \brief      Affiche logo effacer
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_delete($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Delete");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/delete.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo dsactiver
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_disable($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Disable");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/disable.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    
    /**
            \brief      Affiche logo help avec curseur "?"
            \return     string      Retourne tag img
    */
    function img_help()
    {
      global $conf,$langs;
      return '<img style="cursor: help;" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/help.png" border="0" alt="" title="">';
    }
    /**
            \brief      Affiche picto calendrier "?"
            \return     string      Retourne tag img
    */
    function img_cal()
    {
      global $conf,$langs;
      return '<img style="vertical-align:middle" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/calendar.png" border="0" alt="" title="">';
    }
    
    /**
            \brief      Affiche logo info
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_info($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Informations");
      return '<img style="cursor: help;" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/info.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo warning
            \param      alt         Texte sur le alt de l'image
            \param      float       Si il faut afficher le style "float: right"
            \return     string      Retourne tag img
    */
    function img_warning($alt = "default",$float=0)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Warning");
        $img='<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/warning.png" border="0" alt="'.$alt.'" title="'.$alt.'"';
        if ($float) $img.=' style="float: right"';
        $img.='>';
        
        return $img;
    }
    
    /**
            \brief      Affiche logo warning
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_error($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Error");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/error.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo alerte
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_alerte($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Alert");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/alerte.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo tlphone in
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_phone_in($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Modify");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/call.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo tlphone out
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_phone_out($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Modify");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/call.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo suivant
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_next($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") {
        $alt=$langs->trans("Next");
      }
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/next.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo prcdent
            \param      alt     Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_previous($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Previous");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/previous.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo bas
            \param      alt         Texte sur le alt de l'image
            \param      selected    Affiche version "selected" du logo
            \return     string      Retourne tag img
    */
    function img_down($alt = "default", $selected=1)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Down");
        if ($selected) return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1downarrow.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
        else return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1downarrow_notselected.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo haut
            \param      alt         Texte sur le alt de l'image
            \param      selected    Affiche version "selected" du logo
            \return     string      Retourne tag img
    */
    function img_up($alt = "default", $selected=1)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Up");
        if ($selected) return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1uparrow.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
        else return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1uparrow_notselected.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo gauche
            \param      alt         Texte sur le alt de l'image
            \param      selected    Affiche version "selected" du logo
            \return     string      Retourne tag img
    */
    function img_left($alt = "default", $selected=1)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Left");
        if ($selected) return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1leftarrow.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
        else return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1leftarrow_notselected.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo droite
            \param      alt         Texte sur le alt de l'image
            \param      selected    Affiche version "selected" du logo
            \return     string      Retourne tag img
    */
    function img_right($alt = "default", $selected=1)
    {
        global $conf,$langs;
        if ($alt=="default") $alt=$langs->trans("Right");
        if ($selected) return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1rightarrow.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
        else return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/1rightarrow_notselected.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche logo tick
            \param      alt         Texte sur le alt de l'image
            \return     string      Retourne tag img
    */
    function img_tick($alt = "default")
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Active");
      return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/tick.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
    }
    
    /**
            \brief      Affiche le logo tick si allow
            \param      allow       Authorise ou non
            \return     string      Retourne tag img
    */
    function img_allow($allow)
    {
      global $conf,$langs;
      if ($alt=="default") $alt=$langs->trans("Active");
    
      if ($allow == 1)
        {
          return '<img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/tick.png" border="0" alt="'.$alt.'" title="'.$alt.'">';
        }
      else
        {
          return "-";
        }
    }
    
    /**
    		\brief      Affiche formulaire de login
    		\remarks    il faut changer le code html dans cette fonction pour changer le design
    */
    function loginfunction()
    {
        global $langs,$conf;
        $langs->load("main");
        
        $conf->css  = "theme/".$conf->theme."/".$conf->theme.".css";
        // Si feuille de style en php existe
        if (file_exists(DOL_DOCUMENT_ROOT.'/'.$conf->css.".php")) $conf->css.=".php";
        
        print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
        print "\n<html><head><title>Dolibarr Authentification</title>\n";
        
        print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/'.$conf->css.'">'."\n";
        
        
        
        print '<style type="text/css">'."\n";
        print '<!--'."\n";
        print '#login {';
        print '  margin-top: 70px;';
        print '  margin-bottom: 50px;';
        print '  text-align: center;';
        print '  font: 12px arial,helvetica;';
        print '}'."\n";
        print '#login table {';
        print '  border: 1px solid #C0C0C0;';
        if (file_exists(DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/login_background.png'))
        {
          print 'background: #F0F0F0 url('.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/login_background.png) repeat-x;';
        }
        else
        {
          print 'background: #F0F0F0 url('.DOL_URL_ROOT.'/theme/login_background.png) repeat-x;';
        }
        print 'font-size: 12px;';
        print '}'."\n";
        print '-->'."\n";
        print '</style>'."\n";
        print '<script type="text/javascript">'."\n";
        print "function donnefocus() {\n";
        print "document.getElementsByTagName('INPUT')[0].focus();";
        print "}\n";
        print '</script>'."\n";
        print '</head>'."\n";
        print '<body class="body" onload="donnefocus();">';
        
        print '<form id="login" method="post" action="';
        print $_SERVER['PHP_SELF'];
        print $_SERVER["QUERY_STRING"]?'?'.$_SERVER["QUERY_STRING"]:'';
        print '" name="identification">';
        
        print '<table cellpadding="0" cellspacing="0" border="0" align="center" width="350">';
        
        
        if (file_exists(DOL_DOCUMENT_ROOT.'/logo.png'))
        {
          print '<tr><td colspan="3" style="text-align:center;">';
          print '<img src="/logo.png"></td></tr>';
        }
        else
        {
          print '<tr class="vmenu"><td>Dolibarr '.DOL_VERSION.'</td></tr>';
        }
        
        print'</table>
    
    <br>
    
    <table cellpadding="2" align="center" width="350">
    
    <tr><td colspan="3">&nbsp;</td></tr>
    
    <tr><td align="left"> &nbsp; <b>'.$langs->trans("Login").'</b>  &nbsp;</td>
    <td><input name="username" class="flat" size="15" maxlength="25" value="" tabindex="1" /></td>
    ';
    
        // Affiche logo du theme si existe, sinon logo commun
        if (file_exists(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/login_logo.png'))
        {
            print '<td rowspan="2"><img src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/login_logo.png"></td>';
        }
        else 
        {
            print '<td rowspan="2"><img src="'.DOL_URL_ROOT.'/theme/login_logo.png"></td>';
        }
    
        print '
    </tr>
    
    <tr><td align="left"> &nbsp; <b>'.$langs->trans("Password").'</b> &nbsp; </a></td>
    <td><input name="password" class="flat" type="password" size="15" maxlength="30" tabindex="2" />
    </td></tr>
    
    <tr><td colspan="3" style="text-align:center;"><br>
    <input type="submit" class="button" value="&nbsp; '.$langs->trans("Connection").' &nbsp;" tabindex="4" />
    </td></tr>
    ';
        print '
    </table>
    <input type="hidden" name="loginfunction" value="loginfunction" />
    ';
    
        print '</form>';
    
    }
    
    
    /**
    		\brief      Affiche message erreur de type acces interdit et arrete le programme
    		\remarks    L'appel a cette fonction termine le code.
    */
    function accessforbidden()
    {
      global $user, $langs;
      $langs->load("other");
      
      llxHeader();
      print '<div class="error">'.$langs->trans("ErrorForbidden").'</div>';
      print '<br>';
      if ($user->login)
      {
        print $langs->trans("CurrentLogin").': <font class="error">'.$user->login.'</font><br>';
        print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users"));
      }
      elseif (! empty($_SERVER["REMOTE_USER"]))
      {
        print $langs->trans("CurrentLogin").': <font class="error">'.$_SERVER["REMOTE_USER"]."</font><br>";
        print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users"));
      }
      else
      {
        print $langs->trans("ErrorForbidden3");
      }
      llxFooter();
      exit(0);
    }
    
    
    /**
    		\brief      Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte des bugs.
                        On doit appeler cette fonction quand une erreur technique bloquante est rencontre.
                        Toutefois, il faut essayer de ne l'appeler qu'au sein de pages php, les classes devant
                        renvoyer leur erreur par l'intermdiaire de leur proprit "error".
            \param      db      Handler de base utilis
            \param      msg     Message complmentaire  afficher
    */
    function dolibarr_print_error($db='',$msg='')
    {
        global $langs;
        $syslog = '';
        
        // Si erreur intervenue avant chargement langue
        if (! $langs) {
            require_once(DOL_DOCUMENT_ROOT ."/translate.class.php");
            $langs = new Translate(DOL_DOCUMENT_ROOT ."/langs", "en_US");
            $langs->load("main");
        }
        
        if ($_SERVER['DOCUMENT_ROOT'])    // Mode web
        {
            print $langs->trans("DolibarrHasDetectedError").".<br>\n";
            print $langs->trans("InformationToHelpDiagnose").":<br><br>\n";
        
            print "<b>".$langs->trans("Server").":</b> ".$_SERVER["SERVER_SOFTWARE"]."<br>\n";;
            print "<b>".$langs->trans("Dolibarr").":</b> ".DOL_VERSION."<br>\n";;
            print "<b>".$langs->trans("RequestedUrl").":</b> ".$_SERVER["REQUEST_URI"]."<br>\n";;
            print "<b>QUERY_STRING:</b> ".$_SERVER["QUERY_STRING"]."<br>\n";;
            print "<b>".$langs->trans("Referer").":</b> ".$_SERVER["HTTP_REFERER"]."<br>\n";;
            $syslog.="url=".$_SERVER["REQUEST_URI"];
            $syslog.=", query_string=".$_SERVER["QUERY_STRING"];
        }
        else                              // Mode CLI
        {
        
            print $langs->trans("ErrorInternalErrorDetected")."\n";
            $syslog.="pid=".getmypid();
        }
        
        if ($db)
        {
            if ($_SERVER['DOCUMENT_ROOT'])  // Mode web
            {
                print "<br>\n";
                print "<b>".$langs->trans("DatabaseTypeManager").":</b> ".$db->type."<br>\n";
                print "<b>".$langs->trans("RequestLastAccess").":</b> ".($db->lastqueryerror()?$db->lastqueryerror():$langs->trans("ErrorNoRequestInError"))."<br>\n";
                print "<b>".$langs->trans("ReturnCodeLastAccess").":</b> ".$db->errno()."<br>\n";
                print "<b>".$langs->trans("InformationLastAccess").":</b> ".$db->error()."<br>\n";
            }
            else                            // Mode CLI
            {
                print $langs->trans("DatabaseTypeManager").":\n".$db->type."\n";
                print $langs->trans("RequestLastAccess").":\n".($db->lastqueryerror()?$db->lastqueryerror():$langs->trans("ErrorNoRequestInError"))."\n";
                print $langs->trans("ReturnCodeLastAccess").":\n".$db->errno()."\n";
                print $langs->trans("InformationLastAccess").":\n".$db->error()."\n";
        
            }
            $syslog.=", sql=".$db->lastquery();
            $syslog.=", db_error=".$db->error();
        }
        
        if ($msg) {
            if ($_SERVER['DOCUMENT_ROOT'])  // Mode web
            {
                print "<b>".$langs->trans("Message").":</b> ".$msg."<br>\n" ;
            }
            else                            // Mode CLI
            {
                print $langs->trans("Message").":\n".$msg."\n" ;
            }
            $syslog.=", msg=".$msg;
        }
        
        dolibarr_syslog("Error $syslog");
    }
    
    
    /**
    		\brief  Deplacer les fichiers telechargs
    		\param	src_file	fichier source
    		\param	dest_file	fichier de destination
    		\return int         le resultat du move_uploaded_file
    */
    function doliMoveFileUpload($src_file, $dest_file)
    {
      $file_name = $dest_file;
    
      if (substr($file_name, strlen($file_name) -3 , 3) == 'php')
        {
          $file_name = $dest_file . ".txt";
        }
    
      return move_uploaded_file($src_file, $file_name);
    }
    
    
    /**
    		\brief      Sauvegarde parametrage personnel
    		\param	    db          Handler d'accs base
    		\param	    user        Objet utilisateur
    		\param	    url         Si defini, on sauve parametre du tableau tab dont cl = sortfield, sortorder, begin et page
    		                        Si non defini on sauve tous parametres du tableau tab
    		\param	    tab         Tableau (cl=>valeur) des paramtres  sauvegarder
    */
    function dolibarr_set_user_page_param($db, &$user, $url='', $tab)
    {
        $db->begin();
        
        // On efface paramtres anciens
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_param";
        $sql.= " WHERE fk_user = ".$user->id;
        if ($url) $sql.=" AND page='".$url."'";
        else $sql.=" AND page=''";
        $sql.=";";
        $resql=$db->query($sql);
        if (! $resql)
        {
            dolibarr_print_error($db);
        }
        dolibarr_syslog("functions.inc.php::dolibarr_set_user_page_param $sql");
    
        foreach ($tab as $key=>$value)
        {
            // On positionne nouveaux paramtres
            if ($value && (! $url || in_array($key,array('sortfield','sortorder','begin','page'))))
            {
                $sql = "INSERT INTO ".MAIN_DB_PREFIX."user_param(fk_user,page,param,value)";
                $sql.= " VALUES (".$user->id.",";
                if ($url) $sql.= " '".urlencode($url)."',";
                else $sql.= " '',";
                $sql.= " '".$key."','".addslashes($value)."');";
                dolibarr_syslog("functions.inc.php::dolibarr_set_user_page_param $sql");
                $db->query($sql);
    
                $user->page_param[$key] = $value;
            }
        }
    
        $db->commit();
    }
    
    /**
    		\brief  Transcodage de francs en euros
    		\param	zonein		zone de depart
    		\param	devise		type de devise
    		\return	r           resultat transcod
    */
    function transcoS2L($zonein,$devise)
    {
      // Open source offert par <A HREF="mailto:alainfloch@free.fr?subject=chif2let">alainfloch@free.fr</A> 28/10/2001, sans garantie.
      // dbut de la fonction de transcodification de somme en toutes lettres
    
      /*  $zonein = "123,56";
       *  $devise = "E"; // prciser F si francs , sinon ce sera de l'euro
       *  $r = transcoS2L($zonein,$devise); // appeler la fonction
       *  echo "rsultat   vaut $r<br>";
       *  $zonelettresM =  strtoupper($r); // si vous voulez la mme zone mais tout en majuscules
       *  echo "rsultat en Majuscules  vaut $zonelettresM<br>";
       *  $zonein = "1,01";
       *  $r = transcoS2L($zonein,$devise);
       *  echo "rsultat   vaut $r<br>";
       */
    
    
      if ($devise == "F")
        {
          $unite_singulier = " franc ";
          $unite_pluriel = " francs ";
          $cent_singulier = " centime";
        }
      else
        {
          $unite_singulier = " euro ";
          $unite_pluriel = " euros ";
          $cent_singulier = " centime";
        }
    
      $arr1_99 = array("zro","un","deux","trois",
    		   "quatre","cinq","six","sept",
    		   "huit","neuf","dix","onze","douze",
    		   "treize","quatorze","quinze","seize",
    		   "dix-sept","dix-huit","dix-neuf","vingt ");
    
      $arr1_99[30] = "trente ";
      $arr1_99[40] = "quarante ";
      $arr1_99[50] = "cinquante ";
      $arr1_99[60] = "soixante ";
      $arr1_99[70] = "soixante-dix ";
      $arr1_99[71] = "soixante et onze";
      $arr1_99[80] = "quatre-vingts ";
      $i = 22;
      while ($i < 63) {// initialise la  table
        $arr1_99[$i - 1] = $arr1_99[$i - 2]." et un";
        $j = 0;
        while ($j < 8) {
          $k = $i + $j;
          $arr1_99[$k] = $arr1_99[$i - 2].$arr1_99[$j + 2];
          $j++;
        }
        $i = $i + 10;
      } // fin initialise la table
    
      $i = 12;
      while ($i < 20) {// initialise la  table (suite)
        $j = 60 + $i;
        $arr1_99[$j] = "soixante-".$arr1_99[$i];
        $i++;
      } // fin initialise la  table (suite)
    
      $i = 1;
      while ($i < 20) {// initialise la  table (fin)
        $j = 80 + $i;
        $arr1_99[$j] = "quatre-vingt-".$arr1_99[$i];
        $i++;
      } // fin initialise la  table (fin)
      // echo "Pour une valeur en entre = $zonein<br>"; //pour ceux qui ne croient que ce qu'ils voient !
      // quelques petits controles s'imposent !! 
      $valid = "[a-zA-Z\&\\"\'\(\-\\_\\\)\=\;\:\!\*\$\^\<\>]";
      if (ereg($valid,$zonein))
        {
          $r = "<b>la chane ".$zonein." n'est pas valide</b>";
          return($r);
        }
      $zone = explode(" ",$zonein); // supprimer les blancs sparateurs
      $zonein = implode("",$zone); // reconcatne la zone input
      $zone = explode(".",$zonein); // supprimer les points sparateurs
      $zonein = implode("",$zone); // reconcatne la zone input, a c'est fort ! merci PHP
      $virg = strpos($zonein,",",1); //  la poursuite de la virgule
      $i = strlen($zonein); // et de la longueur de la zone input
      if ($virg == 0) { // ya pas de virgule
        if ($i > 7)
          {
    	$r = "<b>la chane ".$zonein." est trop longue (maxi = 9 millions)</b>";
    	return($r);
          }
        $deb = 7 - $i;
        $zoneanaly = substr($zonechiffres,0,$deb).$zonein.",00";
      }
      else
        { //ya une virgule
          $ti = explode(",",$zonein); // mettre de ct ce qu'il y a devant la virgule
          $i = strlen($ti[0]); // en controler la longueur
          $zonechiffres = "0000000,00";
          if ($i > 7)
    	{
    	  $r = "<b>la chane ".$zonein." est trop longue (maxi = 9 millions,00)</b>";
    	  return($r);
    	}
          $deb = 7 - $i;
          $zoneanaly = substr($zonechiffres,0,$deb).$zonein;
        }
      $M= substr($zoneanaly,0,1);
      if ($M != 0)
        { // qui veut gagner des millions
          $r =   $arr1_99[$M]." million";
          if ($M ==1) $r =  $r." ";
          else $r = $r."s ";
          if (substr($zoneanaly,1,6)==0)
    	{
    	  if ($devise == 'F') $r = $r." de ";
    	  else $r = $r."d'";
    	}
        }
      $CM= substr($zoneanaly,1,1);
      if ($CM == 1)
        { // qui veut gagner des centaines de mille
          $r = $r." cent ";
        }
     else
       { // ya des centaines de mille
    	if ($CM > 1)
    	  {
    	    $r = $r. $arr1_99[$CM]." cent ";
    		}
       } // fin du else ya des centaines de mille
      $MM= substr($zoneanaly,2,2);
      if (substr($zoneanaly,2,1)==0){ $MM = substr($zoneanaly,3,1);} // enlever le zro des milliers cause indexation
      if ($MM ==0 && $CM > 0)
        {
          $r = $r."mille ";
        }
      if ($MM != 0)
        {
          if ($MM == 80)
    	{
    	  $r = $r."quatre-vingt mille ";
    	}
          else
    	{
    	  if ($MM > 1 )
    	    {
    	      $r = $r.$arr1_99[$MM]." mille ";
    	    }
    	  else
    	    {
    	      if ($CM == 0)	$r = $r." mille ";
    	      else
    		{
    		  $r = $r.$arr1_99[$MM]." mille ";
    		}
    	    }
    	}
        }
      $C2= substr($zoneanaly,5,2);
      if (substr($zoneanaly,5,1)==0){ $C2 = substr($zoneanaly,6,1);} // enlever le zro des centaines cause indexation
      $C1= substr($zoneanaly,4,1);
      if ($C2 ==0 && $C1 > 1)
        {
          $r = $r.$arr1_99[$C1]." cents ";
        }
      else
        {
          if ($C1 == 1) $r = $r." cent ";
          else
    	{
    	  if ($C1 > 1) $r = $r.$arr1_99[$C1]." cent ";
    	}
        }
      if ($C2 != 0)
        {
          $r = $r.$arr1_99[$C2];
        }
      if ($virg !=0)
        {
          if ($ti[0] > 1) $r = $r. $unite_pluriel; else $r = "un ".$unite_singulier;
        }
      else
        {
          if ($zonein > 1) $r = $r.$unite_pluriel; else $r = "un ".$unite_singulier;
        }
      $UN= substr($zoneanaly,8,2);
      if ($UN != "00")
        {
          $cts = $UN;
          if (substr($UN,0,1)==0){ $cts = substr($UN,1,1);} // enlever le zro des centimes cause indexation
          $r = $r." et ". $arr1_99[$cts].$cent_singulier;
          if ($UN > 1) $r =$r."s"; // accorde au pluriel
        }
      $r1 = ltrim($r); // enleve quelques blancs possibles en dbut de zone
      $r = ucfirst($r1); // met le 1er caractre en Majuscule, c'est + zoli
      return($r); // retourne le rsultat
    } // fin fonction transcoS2L
    
    
    /**
    		\brief      Affichage de la ligne de titre d'un tabelau
    		\param	    name        libelle champ
    		\param	    file        url pour clic sur tri
    		\param	    field       champ de tri
    		\param	    begin       ("" par defaut)
    		\param	    options     ("" par defaut)
    		\param      td          options de l'attribut td ("" par defaut)
    		\param      sortfield   nom du champ sur lequel est effectu le tri du tableau
    		\param      sortorder   ordre du tri
    */
    function print_liste_field_titre($name, $file, $field, $begin="", $options="", $td="", $sortfield="", $sortorder="")
    {
        global $conf;
        // Le champ de tri est mis en vidence.
        // Exemple si (sortfield,field)=("nom","xxx.nom") ou (sortfield,field)=("nom","nom")
        if ($sortfield == $field || $sortfield == ereg_replace("^[^\.]+\.","",$field))
        {
            print '<td class="liste_titre_sel" '. $td.'>';
        }
        else
        {
            print '<td class="liste_titre" '. $td.'>';
        }
        print $name."&nbsp;";
        if (! $sortorder)
        {
            print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=asc&amp;begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
            print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=desc&amp;begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
        }
        else
        {
            if ($field != $sortfield) {
                print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=asc&amp;begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
                print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=desc&amp;begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
            }
            else {
                if ($sortorder == 'DESC' ) {
                    print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=asc&amp;begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
                    print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=desc&amp;begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
                }
                if ($sortorder == 'ASC' ) {
                    print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=asc&amp;begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
                    print '<a href="'.$file.'?sortfield='.$field.'&amp;sortorder=desc&amp;begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
                }
            }
        }
        print "</td>";
    }
    
    /**
    		\brief  Affichage d'un titre
    		\param	titre			Le titre a afficher
    */
    function print_titre($titre)
    {
        print '<div class="titre">'.$titre.'</div>';
    }
    
    /**
    		\brief  Affichage d'un titre d'une fiche, align a gauche
    		\param	titre			Le titre a afficher
    		\param	mesg			Message suplmentaire  afficher  droite
    */
    function print_fiche_titre($titre, $mesg='')
    {
        print "\n";
        print '<table width="100%" border="0" class="notopnoleftnoright">';
        print '<tr><td class="notopnoleftnoright"><div class="titre">'.$titre.'</div></td>';
        if (strlen($mesg))
        {
            print '<td align="right" valign="middle"><b>'.$mesg.'</b></td>';
        }
        print '</tr></table>'."\n";
    }
    
    /**
    		\brief  Effacement d'un fichier
    		\param	file			fichier a effacer
    */
    function dol_delete_file($file)
    {
      return unlink($file);
    }
    
    
    /**
    		\brief  Fonction print_barre_liste
    		\param	titre			titre de la page
    		\param	page			numro de la page
    		\param	file			lien
    		\param	options         options cellule td ('' par defaut)
    		\param	sortfield       champ de tri ('' par defaut)
    		\param	sortorder       ordre de tri ('' par defaut)
    		\param	center          chaine du centre ('' par defaut)
    		\param	num             nombre d'lment total
    */
    function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1)
    {
        global $conf;
    
        if ($num > $conf->liste_limit or $num == -1)
        {
            $nextpage = 1;
        }
        else
        {
            $nextpage = 0;
        }
    
        print '<table width="100%" border="0" class="notopnoleftnoright">';
    
        if ($page > 0 || $num > $conf->liste_limit)
        {
            print '<tr><td><div class="titre">'.$titre.' - page '.($page+1);
            print '</div></td>';
        }
        else
        {
            print '<tr><td class="notopnoleftnoright"><div class="titre">'.$titre.'</div></td>';
        }
    
        if ($center)
        {
            print '<td align="left">'.$center.'</td>';
        }
    
        print '<td align="right">';
    
        if ($sortfield) $options .= "&amp;sortfield=$sortfield";
        if ($sortorder) $options .= "&amp;sortorder=$sortorder";
    
        // Affichage des fleches de navigation
        print_fleche_navigation($page,$file,$options,$nextpage);
    
        print '</td></tr></table>';
    }
    
    /**
    		\brief  Fonction servant a afficher les fleches de navigation dans les pages de listes
    		\param	page			numro de la page
    		\param	file			lien
    		\param	options         autres parametres d'url a propager dans les liens ("" par defaut)
    		\param	nextpage	    faut-il une page suivante
    */
    function print_fleche_navigation($page,$file,$options='',$nextpage)
    {
      global $conf, $langs;
      if ($page > 0)
        {
          print '<a href="'.$file.'?page='.($page-1).$options.'">'.img_previous($langs->trans("Previous")).'</a>';
        }
    
      if ($nextpage > 0)
        {
          print '<a href="'.$file.'?page='.($page+1).$options.'">'.img_next($langs->trans("Next")).'</a>';
        }
    }
    
    
    /**
    		\brief  Fonction servant a afficher les heures/minutes dans un liste droulante
    		\param	prefix
    		\param	begin (1 par defaut)
    		\param	end (23 par defaut)
    */
    function print_heure_select($prefix,$begin=1,$end=23) {
      
      print '<select name="'.$prefix.'hour">';
      for ($hour = $begin ; $hour <= $end ; $hour++) {
        print "<option value=\"$hour\">$hour";
      }
      print "</select>&nbsp;H&nbsp;";
      print '<select name="'.$prefix.'min">';
      for ($min = 0 ; $min < 60 ; $min=$min+5) {
        if ($min < 10) {
          $min = "0" . $min;
        }
        print "<option value=\"$min\">$min";
      }
      print "</select>\n";  
    }
    
    /**
    		\brief  Fonction servant a afficher une dure dans une liste droulante
    		\param	prefix  prefix
    */
    function print_duree_select($prefix)
    {  
      print '<select name="'.$prefix.'hour">';
      print "<option value=\"0\">0</option>";
      print "<option value=\"1\" selected=\"true\">1</option>";
    
      for ($hour = 2 ; $hour < 13 ; $hour++)
        {
          print "<option value=\"$hour\">$hour</option>";
        }
      print "</select>&nbsp;H&nbsp;";
      print '<select name="'.$prefix.'min">';
      for ($min = 0 ; $min < 55 ; $min=$min+5)
        {
          print "<option value=\"$min\">$min</option>";
        }
      print "</select>\n";  
    }
    
    
    /**
    		\brief      Fonction qui retourne un montant montaire format
    		\remarks    Fonction utilise dans les pdf et les pages html
    		\param	    amount		montant a formater
    		\param	    html		formatage html ou pas (0 par defaut)
    
    */
    function price($amount, $html=0)
    {
      if ($html)
        {
    
          $dec='.'; $thousand=' ';
          return ereg_replace(' ','&nbsp;',number_format($amount, 2, $dec, $thousand));
    
        }
      else
        {
          return number_format($amount, 2, '.', ' ');
        }
    
    }
    
    /**
    		\brief      Fonction qui retourne un numrique depuis un montant format
    		\remarks    Fonction  appeler sur montants saisi avant un insert
    		\param	    amount		montant a formater
    */
    function price2num($amount)
    {
        $amount=ereg_replace(',','.',$amount);
        $amount=ereg_replace(' ','',$amount);
        return $amount;
    }
    
    
    /**
     *		\brief      Fonction qui renvoie la tva d'une ligne (en fonction du vendeur, acheteur et taux du produit)
     *      \remarks    Si vendeur non assujeti  TVA, TVA par dfaut=0. Fin de rgle.
     *                  Si le (pays vendeur = pays acheteur) alors la TVA par dfaut=TVA du produit vendu. Fin de rgle.
     *                  Si vendeur et acheteur dans Communaut europenne et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par dfaut=0 (La TVA doit tre pay par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de rgle.
     *                  Si vendeur et acheteur dans Communaut europenne et bien vendu autre que transport neuf alors la TVA par dfaut=TVA du produit vendu. Fin de rgle.
     *                  Sinon la TVA propose par dfaut=0. Fin de rgle.
     *      \param      societe_vendeuse    Objet socit vendeuse
     *      \param      societe_acheteuse   Objet socit acheteuse
     *      \param      taux_produit        Taux par defaut du produit vendu
     *      \return     float               Taux de tva de la ligne
     */
    function get_default_tva($societe_vendeuse='', $societe_acheteuse='', $taux_produit='')
    {
    	// Si vendeur non assujeti  TVA
    	if (! $societe_vendeuse->tva_assuj) return 0;
    	
    	// Si le (pays vendeur = pays acheteur) alors la TVA par dfaut=TVA du produit vendu. Fin de rgle.	
    	if ($societe_vendeuse->pays_id == $societe_acheteuse->pays_id)
    	{
    	    return $taux_produit;
    	}
    	
    	// Si vendeur et acheteur dans Communaut europenne et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par dfaut=0 (La TVA doit tre pay par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de rgle.
    	// Non gr
    	
     	// Si vendeur et acheteur dans Communaut europenne et bien vendu autre que transport neuf alors la TVA par dfaut=TVA du produit vendu. Fin de rgle.
    	if ($societe_vendeuse->isInEEC() && $societe_vendeuse->isInEEC())
    	{
    	    return $taux_produit;
    	}
    
    	// Sinon la TVA propose par dfaut=0. Fin de rgle.
        return 0;
    }
    
    
    /**
    		\brief  Renvoie oui ou non dans la langue choisie
    		\param	yesno			variable pour test si oui ou non
    		\param	case			Oui/Non ou oui/non
    */
    function yn($yesno, $case=1) {
        global $langs;
        if ($yesno == 0 || $yesno == 'no' || $yesno == 'false') 
            return $case?$langs->trans("No"):$langs->trans("no");
        if ($yesno == 1 || $yesno == 'yes' || $yesno == 'true') 
            return $case?$langs->trans("Yes"):$langs->trans("yes");
        return "unknown";
    }
    
    
    /**
    		\brief      Fonction pour crer un mot de passe alatoire
    		\param	    longueur    longueur du mot de passe (8 par defaut)
    		\param	    sel			donne alatoire
    		\remarks    la fonction a t prise sur http://www.uzine.net/spip
    */
    function creer_pass_aleatoire($longueur = 8, $sel = "") {
      $seed = (double) (microtime() + 1) * time();
      srand($seed);
    
      for ($i = 0; $i < $longueur; $i++) {
        if (!$s) {
          if (!$s) $s = rand();
          $s = substr(md5(uniqid($s).$sel), 0, 16);
        }
        $r = unpack("Cr", pack("H2", $s.$s));
        $x = $r['r'] & 63;
        if ($x < 10) $x = chr($x + 48);
        else if ($x < 36) $x = chr($x + 55);
        else if ($x < 62) $x = chr($x + 61);
        else if ($x == 63) $x = '/';
        else $x = '.';
        $pass .= $x;
        $s = substr($s, 2);
      }
      return $pass;
    }
    
    /**
    		\brief      Fonction pour initialiser sel
    		\remarks    la fonction a t prise sur http://www.uzine.net/spip
    */
    function initialiser_sel() {
      global $htsalt;
    
      $htsalt = '$1$'.creer_pass_aleatoire();
    }
    
    /**
    		\brief  Fonction pour qui retourne le rowid d'un departement par son code
    		\param  db          handler d'accs base
    		\param	code		Code rgion
    		\param	pays_id		Id du pays
    */
    function departement_rowid($db,$code, $pays_id)
    {
      $sql = "SELECT c.rowid FROM ".MAIN_DB_PREFIX."c_departements as c,".MAIN_DB_PREFIX."c_regions as r";
      $sql .= " WHERE c.code_departement=". $code;
      $sql .= " AND c.fk_region = r.code_region";
      $sql .= " AND r.fk_pays =".$pays_id;
    
      if ($db->query($sql))
        {
          $num = $db->num_rows();
          if ($num)
    	{
    	  $obj = $db->fetch_object();
    	  return  $obj->rowid;
    	}
          else
    	{
    	  return 0;
    	}
          $db->free();
        }
      else
        {
          return 0;
        }
    }
    
    /**
     *      \brief      Renvoi un chemin de classement rpertoire en fonction d'un id
     *                  Examples: 1->"0/0/1/", 15->"0/1/5/"
     *      \param      $num        id  dcomposer
     */
    function get_exdir($num)
    {
        $num = substr("000".$num, -3);
        return substr($num, 0,1).'/'.substr($num, 1,1).'/'.substr($num, 2,1).'/';
    }
    
    /**
     *      \brief      Cration de rpertoire recursive
     *      \param      $dir        Rpertoire  crer
     *      \return     int         < 0 si erreur, >= 0 si succs
     */
    function create_exdir($dir)
    {
        dolibarr_syslog("functions.inc.php::create_exdir dir=$dir");
    
        $nberr=0;
        $nbcreated=0;
    
        $ccdir = '';
        $cdir = explode("/",$dir);
        for ($i = 0 ; $i < sizeof($cdir) ; $i++)
        {
            if ($i > 0) $ccdir .= '/'.$cdir[$i];
            else $ccdir = $cdir[$i];
            if (eregi("^.:$",$ccdir,$regs)) continue;     // Si chemin Windows incomplet, on poursuit par rep suivant
    
            //print "${ccdir}<br>\n";
            if ($ccdir && ! is_dir($ccdir))
            {
                umask(0);
                if (! @mkdir($ccdir, 0755))
                {
                    dolibarr_syslog("functions.inc.php::create_exdir Erreur: Le rpertoire '$ccdir' n'existe pas et Dolibarr n'a pu le crer.");
                    $nberr++;
                }
                else
                {
                    dolibarr_syslog("functions.inc.php::create_exdir Directory '$ccdir' created");
                    $nbcreated++;
                }
            }
        }
        return ($nberr ? -$nberr : $nbcreated);
    }
    
    ?>