altocompta/include/lib/ac_common.php

1856 lines
No EOL
51 KiB
PHP

<?php
/*
* This file is part of NOALYSS.
*
* NOALYSS 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.
*
* NOALYSS 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 NOALYSS; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Copyright Author Dany De Bontridder danydb@aevalys.eu
/**
* @file
* @brief common utilities for a lot of procedure, classe
*/
require_once NOALYSS_INCLUDE.'/lib/function_javascript.php';
/**
* \brief to protect again bad characters which can lead to a cross scripting attack
the string to be diplayed must be protected. Side effects with htmlentities, especially for
* the date (transform dot in &periode;) and number
*/
function h($p_string)
{
return ( $p_string === null)?"":htmlspecialchars($p_string,ENT_QUOTES|ENT_HTML5,'UTF-8',true);
}
function p($p_string)
{
return '<p>'.$p_string."</p>";
}
function span($p_string, $p_extra='')
{
return '<span ' . $p_extra . '>' . $p_string . '</span>';
}
function hi($p_string)
{
return '<i>' . h($p_string) . '</i>';
}
function hb($p_string)
{
return '<b>' . h($p_string) . '</b>';
}
function th($p_string, $p_extra='',$raw='')
{
return '<th ' . $p_extra . '>' . h($p_string).$raw . '</th>';
}
function h2info($p_string)
{
return '<h2 class="info">' . h($p_string) . '</h2>';
}
function h2($p_string, $p_class="",$raw="")
{
return '<h2 ' . $p_class . '>' . $raw.h($p_string) . '</h2>';
}
function h1($p_string, $p_class="")
{
return '<h1 ' . $p_class . '>' . h($p_string) . '</h1>';
}
/**
* \brief surround the string with td
* \param $p_string string to surround by TD
* \param $p_extra extra info (class, style, javascript...)
* \return string surrounded by td
*/
function td($p_string='', $p_extra='')
{
return '<td ' . $p_extra . '>' . $p_string . '</td>';
}
function tr($p_string, $p_extra='')
{
return '<tr ' . $p_extra . '>' . $p_string . '</tr>';
}
/**
* @brief escape correctly php string to javascript
*/
function j($p_string)
{
$a = preg_replace("/\r?\n/", "\\n", addslashes($p_string));
$a = noalyss_str_replace("'", '\'', $a);
return $a;
}
/**
* format the number for the CSV export
* @param $p_number number
*/
function nb($p_number)
{
$r=trim($p_number);
$r = sprintf('%.4f', $p_number);
$r = noalyss_str_replace('.', ',', $r);
return $r;
}
/**
* return D if the number is smaller than 0 , C if bigger and an empty string if
* equal to 0. Used for displaying saldo D / C (debit / credit )
* @param float $p_number
*/
function findSide($p_number)
{
$return ='';
if ( $p_number > 0 ) {
$return ='D';
}else {
$return =($p_number== 0)?"":"C";
}
return $return;
}
/**
* format the number with a sep. for the thousand
* @param $p_number number
* @param $p_dec number of decimal to display
*/
function nbm($p_number,$p_dec = 2)
{
if (noalyss_trim($p_number) == '')
return '';
if ($p_number == 0)
return "0,00";
$a = doubleval($p_number);
$r = number_format($a, $p_dec, ",", ".");
if (trim($r) == '')
{
var_dump($r);
var_dump($p_number);
var_dump($a);
exit();
}
return $r;
}
/**
* \brief log error into the /tmp/noalyss_error.log it doesn't work on windows
*
* \param p_log message
* \param p_line line number
* \param p_message is the message
*
* \return nothing
*
*/
function echo_error($p_log, $p_line="", $p_message="")
{
$msg="ERREUR :" . $p_log . " " . $p_line . " " . $p_message;
echo $msg;
syslog(LOG_ERR,$msg);
}
/**
* \brief Compare 2 dates
* \param p_date
* \param p_date_oth
*
* \return
* - == 0 les dates sont identiques
* - > 0 date1 > date2
* - < 0 date1 < date2
*/
function cmpDate($p_date, $p_date_oth)
{
date_default_timezone_set('Europe/Brussels');
$l_date = isDate($p_date);
$l2_date = isDate($p_date_oth);
if ($l_date == null || $l2_date == null)
{
throw new Exception("erreur date [$p_date] [$p_date_oth]");
}
$l_adate = explode(".", $l_date);
$l2_adate = explode(".", $l2_date);
$l_mkdate = mktime(0, 0, 0, $l_adate[1], $l_adate[0], $l_adate[2]);
$l2_mkdate = mktime(0, 0, 0, $l2_adate[1], $l2_adate[0], $l2_adate[2]);
// si $p_date > $p_date_oth return > 0
return $l_mkdate - $l2_mkdate;
}
/***!
* @brief check if the argument is a number
*
* @param $p_int number to test
*
* @return
* - 1 it's a number
* - 0 it is not
*/
function isNumber($p_int)
{
if (strlen(noalyss_trim($p_int)) == 0)
return 0;
if (is_numeric($p_int) === true)
return 1;
else
return 0;
}
/***
* \brief Verifie qu'une date est bien formaté
* en d.m.y et est valable
* \param $p_date
*
* \return
* - null si la date est invalide ou malformaté
* - $p_date si tout est bon
*
*/
function isDate($p_date)
{
if (noalyss_strlentrim($p_date) == 0)
return null;
if (preg_match("/^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}$/", $p_date) == 0)
{
return null;
}
else
{
$l_date = explode(".", $p_date);
if (sizeof($l_date) != 3)
return null;
if ($l_date[2] > COMPTA_MAX_YEAR || $l_date[2] < COMPTA_MIN_YEAR)
{
return null;
}
if (checkdate($l_date[1], $l_date[0], $l_date[2]) == false)
{
return null;
}
}
return $p_date;
}
/**
* \brief Default page header for each page
*
* \param p_theme default theme
* \param $p_script
* \param $p_script2 another js script
* Must be called only once
* \return none
*/
function html_page_start($p_theme="", $p_script="", $p_script2="")
{
// check not called twiced
static $already_call=0;
if ( $already_call==1)return;
$already_call=1;
$cn = new Database();
if ($p_theme != "")
{
$Res = $cn->exec_sql("select the_filestyle from theme
where the_name=$1" ,[$p_theme]);
if (Database::num_row($Res) == 0)
{
$style = "style-classic7.css";
}
else
{
$s = Database::fetch_array($Res, 0);
$style = $s['the_filestyle'];
}
}
else
{
$style = "style-classic7.css";
} // end if
$title="NOALYSS";
if ( isset ($_REQUEST['ac'])) {
$ac=strip_tags($_REQUEST['ac']);
if (strpos($ac,'/') <> 0)
{
$m= explode('/',$ac);
$title=$m[count($m)-1]." ".$title;
}
else
$title=$ac." ".$title;
}
$is_msie=is_msie();
if ($is_msie == 0 )
{
echo '<!doctype html>';
printf("\n");
}
else {
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN" >';
printf("\n");
}
echo '<HTML>';
if ($p_script2!="")
{
$p_script2='<script src="'.$p_script2.'" type="text/javascript"></script>';
}
$style=trim($style);
echo "<HEAD>";
echo '<meta charset="utf-8">';
echo "<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
if ($is_msie==1)
{
echo ' <meta http-equiv="x-ua-compatible" content="IE=edge"/>';
}
global $version_noalyss;
echo <<<EOF
<TITLE>$title</TITLE>
<link rel="icon" type="image/ico" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<LINK id="bootstrap" REL="stylesheet" type="text/css" href="css/bootstrap.min.css" media="screen"/>
<LINK id="fontello" REL="stylesheet" type="text/css" href="css/font/fontello/css/fontello.css" media="screen"/>
<LINK id="pagestyle" REL="stylesheet" type="text/css" href="css/$style?version=$version_noalyss" media="screen"/>
<link rel="stylesheet" type="text/css" href="css/style-print.css?version=$version_noalyss" media="print"/>
$p_script2
EOF;
// preload font
echo '<link rel="preload" href="css/font/OpenSansRegular.woff" as="font" crossorigin="anonymous" />';
echo '<link rel="preload" href="css/font/SansationLight/SansationLight.woff" as="font" crossorigin="anonymous" />';
echo '<link rel="preload" href="css/font/fontello/fontello.woff" as="font" crossorigin="anonymous" />';
echo '<script language="javascript" src="js/calendar.js"></script>
<script type="text/javascript" src="js/lang/calendar-en.js"></script>';
if (isset($_SESSION[SESSION_KEY.'g_lang']) && $_SESSION[SESSION_KEY.'g_lang']=='fr_FR.utf8' )
{
echo '<script type="text/javascript" src="js/lang/calendar-fr.js"></script>';
}
if (isset($_SESSION[SESSION_KEY.'g_lang']) && $_SESSION[SESSION_KEY.'g_lang']=='nl_NL.utf8' )
{
echo '<script type="text/javascript" src="js/lang/calendar-nl.js"></script>';
}
echo '
<script language="javascript" src="js/calendar-setup.js"></script>
<LINK REL="stylesheet" type="text/css" href="css/calendar-blue.css" media="screen">
';
// language
if (isset($_SESSION[SESSION_KEY.'g_lang']))
{
set_language();
}
echo load_all_script();
// Retrieve colors for this folder
if ( isset($_REQUEST['gDossier']) ) {
$noalyss_appearance=new Noalyss_Appearance();
$noalyss_appearance->print_css();
}
echo ' </HEAD> ';
echo "<BODY $p_script>";
echo '<div id="info_div"></div>';
echo '<div id="error_div">'.
HtmlInput::title_box(_("Erreur"), 'error_div','hide').
'<div id="error_content_div">'.
'</div>'.
'<p style="text-align:center">'.
HtmlInput::button_action('Valider','$(\'error_div\').style.visibility=\'hidden\';$(\'error_content_div\').innerHTML=\'\';').
'</p>'.
'</div>';
}
/**
* \brief Minimal page header for each page, used for small popup window
*
* \param p_theme default theme
* \param $p_script
* \param $p_script2 another js script
*
* \return none
*/
function html_min_page_start($p_theme="", $p_script="", $p_script2="")
{
$cn = new Database();
if ($p_theme != "")
{
$Res = $cn->exec_sql("select the_filestyle from theme
where the_name='" . $p_theme . "'");
if (Database::num_row($Res) == 0)
$style = "style-classic7.css";
else
{
$s = Database::fetch_array($Res, 0);
$style = $s['the_filestyle'];
}
}
else
{
$style = "style-classic7.css";
} // end if
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">';
echo "<HTML>";
if ($p_script2!="")
{
$p_script2='<script src="'.$p_script2.'" type="text/javascript"></script>';
}
echo "<HEAD>
<TITLE>NOALYSS</TITLE>
<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF8\">
<LINK REL=\"stylesheet\" type=\"text/css\" href=\"css/$style\" media=\"screen\">
<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style-print.css\" media=\"print\">" .
$p_script2 . "
<script src=\"js/prototype.js\" type=\"text/javascript\"></script>
<script src=\"js/noalyss_script.js\" type=\"text/javascript\"></script>
<script src=\"js/acc_ledger.js\" type=\"text/javascript\"></script>
<script src=\"js/smoke.js\" type=\"text/javascript\"></script>";
echo "<LINK id=\"pagestyle\" REL=\"stylesheet\" type=\"text/css\" href=\"css/font/fontello/css/fontello.css\" media=\"screen\"/>";
include_once NOALYSS_INCLUDE.'/lib/message_javascript.php';
// Retrieve colors for this folder
if ( isset($_REQUEST['gDossier']) ) {
$noalyss_appearance=new Noalyss_Appearance();
$noalyss_appearance->print_css();
}
echo '</HEAD>';
echo "<BODY $p_script>";
/* If we are on the user_login page */
if (basename($_SERVER['PHP_SELF']) == 'user_login.php')
{
return;
}
}
/**
* \brief end tag
*
*/
function html_page_stop()
{
echo "</BODY>";
echo "</HTML>";
}
/**
* \brief Echo no access and stop
*
* \return nothing
*/
function NoAccess($js=1)
{
if ($js == 1)
{
echo "<script>";
echo "alert ('" . _('Cette action ne vous est pas autorisée Contactez votre responsable') . "');";
echo "</script>";
}
else
{
echo '<div class="redcontent">';
echo '<h2 class="error">' . _(' Cette action ne vous est pas autorisée Contactez votre responsable') . '</h2>';
echo '</div>';
}
exit - 1;
}
/**
* @brief replaced by sql_string
* @deprecated
*/
function FormatString($p_string)
{
return sql_string($p_string);
}
/**
* \brief Fix the problem with the quote char for the database
*
* \param $p_string
* \return a string which won't let strange char for the database
*/
function sql_string($p_string)
{
$p_string = trim($p_string??"");
if (strlen($p_string) == 0)
return null;
$p_string = noalyss_str_replace("'", "''", $p_string);
$p_string = noalyss_str_replace('\\', '\\\\', $p_string);
return $p_string;
}
/**
* \brief store the string which print
* the content of p_array in a table
* used to display the menu
* \param $p_array array like ( 0=>HREF reference, 1=>visible item (name),2=>Help(opt),
* 3=>selected (opt) 4=>javascript (normally a onclick event) (opt)
* \param $p_dir direction of the menu (H Horizontal V vertical)
* \param $class CSS for li tag
* \param $class_ref CSS for the A tag
* \param $default selected item
* \param $p_extra extra code for the table tag (CSS or javascript)
*/
/* \return : string */
function ShowItem($p_array, $p_dir='V', $class="nav-item", $class_ref="nav-link", $default="", $p_extra="nav nav-pills nav-fill")
{
$ret = '';
// for comptability with old application mtitle for anchor is replace by nav-link
// direction Vertical
if ($p_dir == 'V')
{
$ret .= "<ul class=\"$p_extra noprint \" flex-row>";
} else {
$ret .= "<ul class=\"$p_extra noprint \" >";
}
foreach ($p_array as $all => $href)
{
$javascript = (isset($href[4])) ? $href[4] : "";
$title = "";
$set = "XX";
if (isset($href[2]))
{
$title=$href[2];
}
if (isset($href[3]))
{
$set=$href[3];
}
if ($set==$default)
{
$ret.='<li class="nav-item"><A class="'.$class_ref.' active'.'" HREF="'.$href[0].'" title="'.$title.'" '.$javascript.'>'.$href[1].'</A></li>';
}
else
{
$ret.='<li class="nav-item"><A class="'.$class_ref.'" HREF="'.$href[0].'" title="'.$title.'" '.$javascript.'>'.$href[1].'</A></li>';
}
}
$ret.="</ul>";
return $ret;
}
/**
* \brief warns
*
* \param p_string error message
* gen :
* - none
* \return:
* - none
*/
function echo_warning($p_string)
{
echo '<span class="warning">' . $p_string . '</span>';
}
/**
* \brief Show the periode which found thanks its id
*
*
* \param $p_cn database connection
* \param p_id
* \param pos Start or end
*
* \return: string
*/
function getPeriodeName($p_cn, $p_id, $pos='p_start')
{
if ($pos != 'p_start' && $pos != 'p_end')
{
echo_error('lib/ac_common.php' . "-" . __LINE__ . ' UNDEFINED PERIODE');
throw new Exception(_("paramètre invalide"));
}
if ( isNumber($p_id) == 0 )
{
throw new Exception("Paramètre invalide");
return;
}
$ret = $p_cn->get_value("select to_char($pos,'Mon YYYY') as t from parm_periode where p_id=$1",
array( $p_id));
return $ret;
}
/**
* \brief Return the period corresponding to the
* date
*
* \param p_cn database connection
* \param p_date the month + year 'MM.YYYY'
*
* \return:
* parm_periode.p_id
*/
function getPeriodeFromMonth($p_cn, $p_date)
{
$R = $p_cn->get_value("select p_id from parm_periode where
to_char(p_start,'DD.MM.YYYY') = $1", array('01.'.$p_date));
if ($R == "")
return -1;
return $R;
}
/**
* \brief Decode the html for the widegt richtext and remove newline
* \param $p_html string to decode
* \return the html code without new line
*/
function Decode($p_html)
{
$p_html = noalyss_str_replace('%0D', '', $p_html);
$p_html = noalyss_str_replace('%0A', '', $p_html);
$p_html = urldecode($p_html);
return $p_html;
}
/**
* @brief transform the SQL for ANALYTIC table operation_analytique
* @see sql_filter_per
* @param string $p_sql
*/
function transform_sql_filter_per($p_sql)
{
$result=noalyss_str_replace("j_tech_per in (select p_id from parm_periode where","",$p_sql);
$result=noalyss_str_replace("jr_tech_per in (select p_id from parm_periode where","",$result);
$result=noalyss_str_replace("j_tech_per = (select p_id from parm_periode where p_start "," oa_date ",$result);
$result=noalyss_str_replace("p_start >= to_date","oa_date >= to_date",$result);
$result=noalyss_str_replace("p_end <= to_date","oa_date <= to_date",$result);
$result="( $result";
return $result;
}
/**
* \brief Create the condition to filter on the j_tech_per
* thanks a from and to date.
* \param $p_cn database conx
* \param $p_from start date (date)
* \param $p_to end date (date)
* \param $p_form if the p_from and p_to are date or p_id
* \param $p_field column name
* \return a string containg the query
*/
function sql_filter_per($p_cn, $p_from, $p_to, $p_form='p_id', $p_field='jr_tech_per')
{
if ($p_form != 'p_id' && $p_form != 'date')
{
echo_error(__FILE__, __LINE__, 'Mauvais parametres ');
exit(-1);
}
$p_from= sql_string($p_from);
$p_to= sql_string($p_to);
$p_field= sql_string($p_field);
if ($p_form == 'p_id')
{
if ( isNUmber($p_from)==0 || isNUmber($p_to)==0){
throw new Exception("SFP1"._("Nombre invalide")."\$p_from=$p_from \$p_to=$p_to");
}
// retrieve the date
$pPeriode = new Periode($p_cn);
$a_start = $pPeriode->get_date_limit($p_from);
$a_end = $pPeriode->get_date_limit($p_to);
if ($a_start==null||$a_end==null)
{
throw new Exception(__FILE__.__LINE__.sprintf(_('Attention periode
non trouvee periode p_from= %s p_to_periode = %s'), $p_from, $p_to));
}
$p_from = $a_start['p_start'];
$p_to = $a_end['p_end'];
}else {
if ( isDate($p_from)==NULL || isDate($p_to)==NULL){
throw new Exception("SFP2"._("Date invalide")."\$p_from=$p_from \$p_to=$p_to");
}
}
if ($p_from==$p_to)
{
$periode=" $p_field = (select p_id from parm_periode ".
" where ".
" p_start = to_date('$p_from','DD.MM.YYYY')) ";
}
else
{
$periode="$p_field in (select p_id from parm_periode ".
" where p_start >= to_date('$p_from','DD.MM.YYYY') and p_end <= to_date('$p_to','DD.MM.YYYY')) ";
}
return $periode;
}
/**
* \brief alert in javascript
* \param $p_msg is the message
* \param $buffer if false, echo directly and execute the javascript, if $buffer is true, the alert javascript
* is in the return string
* \return string with alert javascript if $buffer is true
*/
function alert($p_msg, $buffer=false)
{
$r = '<script>';
$r.= 'alert_box(\'' . j($p_msg) . '\')';
$r.= '</script>';
if ($buffer)
{
return $r;
}
echo $r;
}
/**
* @brief set the lang thanks the _SESSION['g_lang'] var.
*/
function set_language()
{
// desactivate local check
if (defined("LOCALE")&&LOCALE==0)
{
return;
}
if (!isset($_SESSION[SESSION_KEY.'g_lang']))
{
return;
}
/*
* If translation is not supported by current
*/
if (!function_exists("bindtextdomain"))
{
return;
}
$dir = "";
// set differently the language depending of the operating system
if (what_os() == 1)
{
$dir = setlocale(LC_MESSAGES, $_SESSION[SESSION_KEY.'g_lang']);
if ($dir == "")
{
$g_lang = 'fr_FR.utf8';
$dir = setlocale(LC_MESSAGES, $g_lang);
// echo '<span class="notice">' . $_SESSION[SESSION_KEY.'g_lang'] . ' domaine non supporté</h2>';
}
bindtextdomain('messages', NOALYSS_HOME.'/lang');
textdomain('messages');
bind_textdomain_codeset('messages', 'UTF8');
return;
}
// for windows
putenv('LANG=' . $_SESSION[SESSION_KEY.'g_lang']);
$dir = setlocale(LC_ALL, $_SESSION[SESSION_KEY.'g_lang']);
bindtextdomain('messages', '.\\lang');
textdomain('messages');
bind_textdomain_codeset('messages', 'UTF8');
}
/**
* @brief try to determine on what os you are running the pĥpcompte
* server
* @return
* 0 it is a windows
* 1 it is a Unix like
*/
function what_os()
{
$inc_path = get_include_path();
if (strpos($inc_path, ";") != 0)
{
$os = 0; /* $os is 0 for windoz */
}
else
{
$os = 1; /* $os is 1 for unix */
}
return $os;
}
/**
* @brief shrink the date, make a date shorter for the printing
* @param $p_date format DD.MM.YYYY
* @return date in the format DDMMYY (size = 13 mm in arial 8)
*/
function shrink_date($p_date)
{
$date = noalyss_str_replace('.', '', $p_date);
$str_date = substr($date, 0, 4) . substr($date, 6, 2);
return $str_date;
}
/**
* @brief shrink the date, make a date shorter for the printing
* @param $p_date format DD.MM.YYYY
* @return date in the format DD.MM.YY (size = 13 mm in arial 8)
*/
function smaller_date($p_date)
{
if (empty ($p_date)) return "";
$str_date = substr($p_date, 0, 6) . substr($p_date, 8, 2);
return $str_date;
}
/**
* @brief format the date, when taken from the database the format
* is MM-DD-YYYY
* @param $p_date format
* @exception 1 if invalid format
* DOMEntity@param
* @return date in the format DD.MM.YYYY
*/
function format_date($p_date, $p_from_format = 'YYYY-MM-DD',$p_to_format='DD.MM.YYYY')
{
if (empty($p_date)) {return $p_date;}
if ($p_from_format == 'YYYY-MM-DD')
{
$date = explode('-', $p_date);
if (count($date) != 3)
return $p_date;
}
if ($p_from_format == 'DD.MM.YYYY')
{
$temp_date = explode('.', $p_date);
if (count($temp_date) != 3)
return $p_date;
$date[0] = $temp_date[2]; // 0 is year
$date[1] = $temp_date[1]; // 1 for month
$date[2] = $temp_date[0]; // 2 for day
}
switch ($p_to_format)
{
case 'DD.MM.YYYY':
$str_date = $date[2] . '.' . $date[1] . '.' . $date[0];
break;
case 'DD-MM-YYYY':
$str_date = $date[2] . '-' . $date[1] . '-' . $date[0];
break;
case 'YYYY-MM-DD':
$str_date = $date[0] . '-' . $date[1] . '-' . $date[2];
break;
case 'YYYYMMDD':
$str_date = $date[0] . $date[1] . $date[2];
break;
case 'YYYY/MM/DD':
$str_date = $date[0] . '/' . $date[1] . '/' . $date[2];
break;
case "DD.MM.YY":
$str_date = $date[2] . '.' . $date[1] . '.' . substr($date[0],2,2);
break;
case "DD-MM-YY":
$str_date = $date[2] . '-' . $date[1] . '-' . substr($date[0],2,2);
break;
default:
throw new Exception(_("Format Invalide"),1);
}
return $str_date;
}
/**
*@brief Should a dialog box when you are disconnected from an ajax call
* propose to reload or to connect in another tab
*/
function ajax_disconnected($p_div)
{
echo HtmlInput::title_box(_("Déconnecté"), $p_div);
echo h2(_('Données non disponibles'), 'class="error" ');
echo h2(_('Veuillez vous reconnecter soit dans une autre fenêtre soit '
. ' en cliquant sur le bouton'), 'class="error"');
// Reload button
$reload=new IButton("reload");
$reload->value=_("Se connecter");
$reload->class="button";
$reload->javascript='window.location.reload()';
// Link to log in another tab
echo '<p style="text-align:center">';
echo $reload->input();
echo HtmlInput::button_close($p_div,'button');
echo '</p>';
}
/**
* @brief Show the modules
* @param int $selected module selected profile_menu.pm_id
*/
function show_module($selected)
{
global $g_user;
$cn = Dossier::connect();
$amodule = $cn->get_array("select
me_code,me_menu,me_url,me_javascript,p_order,me_type,me_description
from v_all_menu
where
p_id=$1
and p_type_display='M'
order by p_order", array($g_user->get_profile()));
if ($selected != -1)
{
$selected_module=$cn->get_value('select me_code from profile_menu where'
. ' pm_id = $1 ', array($selected));
require_once NOALYSS_TEMPLATE.'/module.php';
$file = $cn->get_array("select me_file,me_parameter,me_javascript,me_type,me_description from v_all_menu
where pm_id=$1 and p_id=$2", array($selected,$g_user->get_profile()));
if ( count($file ) == 0 )
{
echo '</div>';
echo '</div>';
echo '<div class="content">';
echo_warning(_("Module inexistant")."[ $selected ] ");
echo '</div>';
exit();
}
if ($file[0]['me_file'] != '')
{
if ($file[0]['me_parameter'] != "")
{
// if there are paramter put them in superglobal
$array=compute_variable($file[0]['me_parameter']);
put_global($array);
}
// if file is not a plugin, include the file, otherwise
// include the plugin launcher
if ($file[0]['me_type'] != 'PL')
{
require_once $file[0]['me_file'];
}
else
{
// nothing : direct call to plugin
}
}
if ( $file[0]['me_javascript'] != '')
{
create_script($file[0]['me_javascript']);
}
}
}
/**
* @brief Find the default module or the first one
* @var $g_user $g_user
* @return default module (string)
*/
function find_default_module()
{
global $g_user;
$cn = Dossier::connect();
$default_module = $cn->get_array("select me_code
from profile_menu join profile_user using (p_id)
where
p_type_display='M' and
user_name=$1 and pm_default=1", array($g_user->login));
/*
* Try to find the smallest order for module
*/
if (empty($default_module))
{
$default_module = $cn->get_array("select me_code
from profile_menu join profile_user using (p_id)
where
p_type_display='M' and
user_name=$1 order by p_order limit 1", array($g_user->login));
// if no default try to find the default menu
if ( empty ($default_module))
{
$default_module = $cn->get_array("select me_code
from profile_menu join profile_user using (p_id)
where
p_type_display='E' and
user_name=$1 and pm_default=1 ", array($g_user->login));
/*
* Try to find a default menu by order
*/
if (empty ($default_module))
{
$default_module = $cn->get_array("select me_code
from profile_menu join profile_user using (p_id)
where
user_name=$1 and p_order=(select min(p_order) from profile_menu join profile_user using (p_id)
where user_name=$2) limit 1", array($g_user->login, $g_user->login));
}
/*
* if nothing found, there is no profile for this user => exit
*/
if (empty ($default_module))
{
/*
* If administrateur, then we insert a default profile (1)
* for him
*/
if ( $g_user->admin == 1 )
{
$cn->exec_sql('insert into profile_user(user_name,p_id) values ($1,1) ',array($g_user->login));
return find_default_module();
}
echo_warning(_("Utilisateur n'a pas de profil, votre administrateur doit en configurer un dans C0SEC"));
exit();
}
}
return $default_module[0]['me_code'];
}
if (count($default_module) > 1)
{
// return the first module found
return $default_module[0]['me_code'];
}
elseif (count($default_module) == 1)
{
return $default_module[0]['me_code'];
}
}
/**
* @brief show the module
* @var $g_user
* @param $module the $_REQUEST['ac'] exploded into an array
* @param $idx the index of the array : the AD code is splitted into an array thanks the slash
*/
function show_menu($module)
{
if ($module == 0)return;
static $level=0;
global $g_user;
$http=new HttpInput();
$access_code=$http->request("ac");
$cn = Dossier::connect();
/**
* Show the submenus
*/
$amenu = $cn->get_array("
select
pm_id,
me_code,
pm_id_dep,
me_file,
me_javascript,
me_url,
me_menu,
me_description,
me_description_etendue
from profile_menu
join menu_ref using (me_code)
where pm_id_dep=$1 and p_id=$2
order by p_order", array($module, $g_user->get_profile()));
// There are submenuS, so show them
if (!empty($amenu) && count($amenu) > 1)
{
$a_style_menu=array('topmenu','menu2','menu3');
if ( $level > count($a_style_menu))
$style_menu='menu3';
else {
$style_menu=$a_style_menu[$level];
}
require NOALYSS_TEMPLATE.'/menu.php';
$level++;
return;
} elseif (count($amenu) == 1)
{
// there is only one submenu so we include the code or javascript
// or we show the submenu
if ( trim($amenu[0]['me_url']??"") != "" ||
trim ($amenu[0]['me_file']??"") != "" ||
trim ($amenu[0]['me_javascript']??"") != "" )
{
echo '<div class="topmenu">';
echo h2info(_($amenu[0]['me_menu']));
echo '</div>';
$module = $amenu[0]['pm_id'];
display_menu($module);
$level++;
return;
} else {
$url=$access_code.'/'.$amenu[0]['me_code'];
echo '<a href="do.php?gDossier='.Dossier::id().'&ac='.$url.'">';
echo _($amenu[0]['me_menu']);
echo '</a>';
$level++;
return;
}
}
// !!! this point should never be reached
// There is no submenu or only one
if (empty($amenu) || count($amenu) == 1)
{
display_menu($module);
}
$level++;
}
/**
* @brief Display a menu
* @global type $g_user
* @param type $p_menuid
* @return type
*/
function display_menu($p_menuid)
{
if ($p_menuid == 0) return;
global $g_user;
$cn=Dossier::connect();
$file = $cn->get_array("
select me_file,me_parameter,me_javascript,me_type
from menu_ref
join profile_menu using (me_code)
join profile_user using (p_id)
where
pm_id=$1 and
user_name=$2 and
(me_file is not null or trim(me_file) <>'' or
me_javascript is not null or trim (me_javascript) <> '')", array($p_menuid,$g_user->login));
if (count($file)==0)
{
return;
}
if ($file[0]['me_file'] != "")
{
if ($file[0]['me_parameter'] !== "")
{
// if there are paramter put them in superglobal
$array=compute_variable($file[0]['me_parameter']);
put_global($array);
}
\Noalyss\Dbg::echo_var(1,$file[0]['me_file']." ".$file[0]['me_parameter']);
/*
* Log the file we input to put in the folder test-noalyss for replaying it
*/
if (LOGINPUT) {
$file_loginput=fopen($_ENV['TMP'].'/scenario-'.$_SERVER['REQUEST_TIME'].'.php','a+');
fwrite($file_loginput, "include '".$file[0]['me_file']."';");
fwrite($file_loginput,"\n");
fclose($file_loginput);
}
// if file is not a plugin, include the file, otherwise
// include the plugin launcher
if ( $file[0]['me_type'] != 'PL') {
if (file_exists ($file[0]['me_file']) )
{
require_once $file[0]['me_file'];
} elseif ( file_exists(NOALYSS_INCLUDE.'/'.$file[0]['me_file'])) {
require_once NOALYSS_INCLUDE.'/'.$file[0]['me_file'];
}else {
echo echo_warning(_("Fichier non trouvé"));
}
} else {
require 'extension_get.inc.php';
}
exit();
} elseif ( $file[0]['me_javascript'] != '')
{
$js= noalyss_str_replace('<DOSSIER>', dossier::id(), $file[0]['me_javascript']);
echo create_script($js);
}
}
/**
* @brief Send an header CSV with a filename
* @param string $p_filename , file name , caution , it must be sanitized BEFORE calling this function
*/
function header_csv($p_filename)
{
header('Pragma: public');
header('Content-type: application/csv');
header("Content-Disposition: attachment;filename=\"{$p_filename}\"",
FALSE);
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').'GMT');
}
/**
* @brief Put in superglobal (get,post,request) the value contained in
* the parameter field (me_parameter)
* @param $array [key] [value]
*/
function put_global($array)
{
for ($i=0;$i<count($array);$i++)
{
$key=$array[$i]['key'];
$value=$array[$i]['value'];
$_GET[$key]=$value;
$_POST[$key]=$value;
$_REQUEST[$key]=$value;
}
}
/**
* @brief the string has the format a=b&c=d, it is parsed and an array[][key,value]
* is returned
* @param $p_string
* @return $array usable in put_global
*/
function compute_variable($p_string)
{
$array=array();
if ($p_string == '') return $array;
$var=explode("&",$p_string);
if (empty ($var)) return $array;
for ($i=0;$i < count($var);$i++)
{
$var2=explode('=',$var[$i]);
$array[$i]['key']=$var2[0];
$array[$i]['value']=$var2[1];
}
return $array;
}
function ajax_xml_error($p_code,$p_string)
{
$html = escape_xml($p_string);
header('Content-type: text/xml; charset=UTF-8');
echo <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<data>
<code>$p_code</code>
<value>$html</value>
</data>
EOF;
}
function get_array_column($p_array,$key)
{
$array=array();
for ($i=0;$i<count($p_array);$i++)
{
$r=$p_array[$i];
if ( isset($r[$key])) {
$array[]=$r[$key];
}
}
return $array;
}
/**
* @brief This function create a ledger object and return the right one.
* It uses the factory pattern
* @param Database $p_cn
* @param type $ledger_id
* @return Acc_Ledger
* @throws Exception
*/
function factory_Ledger(Database &$p_cn, $ledger_id)
{
$ledger=new Acc_Ledger($p_cn, $ledger_id);
$type=$ledger->get_type();
switch ($type)
{
case 'VEN':
$obj=new Acc_Ledger_Sale($p_cn, $ledger_id);
break;
case 'ACH':
$obj=new Acc_Ledger_Purchase($p_cn, $ledger_id);
break;
case 'FIN':
$obj= new Acc_Ledger_Fin($p_cn, $ledger_id);
break;
case 'ODS':
$obj=$ledger;
break;
default:
throw new Exception('Ledger type not found');
}
return $obj;
}
/**
* @brief Check if we use IE 8 or 9
* @return int 1 for IE8-9;0 otherwise
*/
function is_msie()
{
if ( strpos ($_SERVER['HTTP_USER_AGENT'],'MSIE 8.0') != 0 ||
strpos ($_SERVER['HTTP_USER_AGENT'],'MSIE 9.0') != 0 )
$is_msie=1;
else
$is_msie=0;
return $is_msie;
}
/**
*@brief Record an error message into the log file of the server or in the log folder of NOALYSS
* Record also the GET and POST data
* @param $p_message string message to display
*/
function record_log($p_message)
{
$date=date('Y.m.d');
// variable: $handle_log resource on log file ,
$handle_log=fopen(NOALYSS_BASE."/log/noalyss-{$date}.log","a+");
if ($handle_log == false )
{
if ( gettype ($p_message) == "object" && method_exists($p_message,"getTraceAsString") == 1) {
$exc=$p_message;
do {
error_log("noalyss exception message [".$exc->getMessage()."]",0);
error_log("noalyss exception code [".$exc->getCode()."]",0);
error_log("noalyss exception trace ".$exc->getTraceAsString(),0);
error_log("------ ",0);
$exc=$exc->getPrevious();
if ($exc != null )fwrite ($handle_log,"*********************** Previous *********************** \n");
} while ($exc != null);
} else {
error_log("noalyss".var_export($p_message,true),0);
}
error_log("noalyss GET [".json_encode($_GET,0,10)."]");
error_log("_POST [".json_encode($_POST,0,10)."]",0);
} else {
if ( gettype ($p_message) == "object" && method_exists($p_message,"getTraceAsString") == 1) {
error_log("noalyss exception ".$p_message->getMessage(),0);
error_log("noalyss exception".$p_message->getTraceAsString(),0);
} else {
error_log("noalyss".var_export($p_message,true),0);
}
$now=date('y-m-d H:i');
fwrite ($handle_log,str_repeat("=", 80)."\n");
fwrite ($handle_log,"ERROR: {$now}\n");
fwrite($handle_log,"noalyss GET [".var_export($_GET,true)."]");
fwrite ($handle_log,"\n");
fwrite($handle_log,"_POST [".var_export($_POST,true)."]");
fwrite ($handle_log,"\n");
if ( gettype ($p_message) == "object" && method_exists($p_message,"getTraceAsString") == 1) {
$exc=$p_message;
do {
fwrite($handle_log,"noalyss exception message [".$exc->getMessage()."]");
fwrite ($handle_log,"\n");
fwrite($handle_log,"noalyss exception code [".$exc->getCode()."]");
fwrite ($handle_log,"\n");
fwrite($handle_log,"noalyss exception trace \n".$exc->getTraceAsString());
fwrite ($handle_log,"\n");
$exc=$exc->getPrevious();
if ($exc != null )fwrite ($handle_log,"*********************** Previous *********************** \n");
} while ($exc != null);
} else {
fwrite($handle_log,"noalyss".var_export($p_message,true));
fwrite ($handle_log,"\n");
}
fwrite ($handle_log,str_repeat("=", 80)."\n");
fclose($handle_log);
}
}
if(!function_exists('tracedebug')) {
function tracedebug($file,$var, $label = NULL) {
$tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$file;
if ( ! is_writable($tmp_file)) return;
$output = '';
$output .= date('d-m-y H:i');
if(!is_null($label)) {
$output .= $label . ': ';
}
if ( gettype ($var) == 'object' && get_class($var)=='DOMDocument')
{
$var->formatOutput=true;
$output.=$var->saveXML() .PHP_EOL;
} else
{
$output .= print_r($var, 1) . PHP_EOL;
}
file_put_contents($tmp_file, $output, FILE_APPEND);
}
}
/**
* @brief encode the string for RTF, return a string
* @param $p_string string to convert
* @return string
*/
function convert_to_rtf($p_string)
{
$result="";
$p_string2=mb_convert_encoding($p_string,'ISO-8859-1','UTF-8');
$p_string2=iconv('UTF-8','ISO-8859-1//IGNORE',$p_string);
$nb_result=strlen($p_string2);
for ($i = 0 ; $i < $nb_result ; $i++ ){
if (ord($p_string[$i]) < 127 ) {
$result.=$p_string[$i];
} else {
$result.='\u'.ord($p_string[$i]).chr(92).chr(39).'3f';
}
}
return $result;
}
/**
* @brief When it is needed to eval a formula , this function prevent the divide by zero.
* the formula is a math operation to evaluate like : 1.0+2.0/1 (...) , it is used in "report",
* it removes the operation "divide by 0 "
*
* @param string $p_formula string containing a operation to evaluate
*
* @see Impress::parse_formula
*/
function remove_divide_zero($p_formula)
{
$test=noalyss_str_replace(" ","",$p_formula).";";
$p_formula=preg_replace("![0-9]+\.*[0-9]*/0\.{0,1}0*(\+|-|\*|/|;){1}!","0$1",$test);
$p_formula=trim($p_formula,';');
return $p_formula;
}
/**
* @brief Create randomly a string
* @param int $p_length length of the generate string
*/
function generate_random_string($p_length,$special=1)
{
$string="";
if ($special == 1)
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789*/+-=";
if ($special == 0)
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789";
$microtime=microtime(true)*microtime(true)*100;
srand(0);
srand((int)$microtime);
for ($i=0; $i<$p_length; $i++)
{
$string .= $chaine[rand()%strlen($chaine)];
}
return $string;
}
/**
*@brief generate a string of p_car character and a input text with name p_ctl_name
* work like a kind of captcha.The control code for checking is ctlcode.
* You compare the content of the variable p_ctl_name with ctlcode
* @param $p_ctl_name name of the HTML input text
* @param $p_car length of the string
*/
function confirm_with_string($p_ctl_name,$p_car)
{
$code=generate_random_string($p_car );
$r = HtmlInput::hidden("ctlcode",$code);
$r.='<span style="margin-left:1.2em;margin-right:1.2em;font-size:112%;font-weight:bold;border:navy solid 1px ; padding:0.5rem">'. $code.'</span>';
$ctl=new IText($p_ctl_name);
$r.=$ctl->input();
return $r;
}
/**
* @brief Find the menu marked as default in the given profile
* @param number $pn_menu (profile_menu.id)
*/
function find_default_menu($pn_menu)
{
$cn=Dossier::connect();
$sql = ' select pm_id from profile_menu where pm_default =1 and pm_id_dep = $1';
$aresult=$cn->get_array($sql, [$pn_menu]);
if (empty($aresult)) {
return 0;
}
return $aresult[0]['pm_id'];
}
/**
* @brief Check if there is a default menu for this user and add it. The array is filling from 1 to 3
* @verbatim
*
* COMPTA 0 - 0 - 173
* COMPTA/MENUACH 0 - 173 - 3
* COMPTA/MENUACH/ACH 173 - 3 - 85
*
* @endverbatim
*
*
* @param array $pa_menu if the array of option ; index pm_id_v1 , pm_id_v2 and pm_id_v3
*
*/
function complete_default_menu($pa_menu)
{
$a_result=$pa_menu;
// find the first one which is null
if ($pa_menu[0]['pm_id_v2'] == 0) {
$tmp=find_default_menu($pa_menu[0]['pm_id_v1']);
if ( $tmp <> 0 ) {
$a_result[0]['pm_id_v2']=$pa_menu[0]['pm_id_v1'];
$a_result[0]['pm_id_v1']=$tmp;
}
}
if ($pa_menu[0]['pm_id_v3'] == 0) {
$tmp=find_default_menu($a_result[0]['pm_id_v1']);
if ( $tmp <> 0 ) {
$a_result[0]['pm_id_v3']=$a_result[0]['pm_id_v2'];
$a_result[0]['pm_id_v2']=$a_result[0]['pm_id_v1'];
$a_result[0]['pm_id_v1']=$tmp;
}
}
return $a_result;
}
/**
* @brief rebuild the access code
* @see complete_default_menu
* @param array of number $pan_code index row [0] = index pm_id_v1 , pm_id_v2 and pm_id_v3
*/
function rebuild_access_code($pan_code)
{
if ( empty ($pan_code)) {return;}
$s_result="";
$cn=Dossier::connect();
$an_code=['pm_id_v3','pm_id_v2','pm_id_v1'];
$sep="";
for ($i=0;$i<3;$i++)
{
$ix=$an_code[$i];
$s_result.=$sep.$cn->get_value("select me_code from profile_menu where pm_id=$1",[ $pan_code[0][$ix] ]);
$sep=($s_result != "" )?"/":"";
}
return $s_result;
}
/***
*@brief Transform a http link into a clickable link
*/
function add_http_link($text)
{
$ret=preg_replace("!http[s]{0,1}://[[:graph:]*]*!",'<a href="\\0" target="_blank">\0</a>',$text);
return $ret;
}
//---------------------------------------------------------------------------------------------------------------------
//
// PHP 8.2 fails with these functions when a NULL is given as argument
//
//---------------------------------------------------------------------------------------------------------------------
function noalyss_strlen($p_string) :int{
if ($p_string ==null ) return 0;
else return strlen($p_string);
}
function noalyss_trim($p_string) {
if ($p_string===null) return "";
else return trim($p_string);
}
function noalyss_strlentrim($p_string) :int {
if ($p_string ==null ) return 0;
return strlen(trim($p_string));
}
function noalyss_str_replace($search,$replace,$string) {
if ($string===null) return "";
else return str_replace($search,$replace??"",$string);
}
function noalyss_bcsub($p_first,$p_second,$p_decimal=4)
{
$p_first=(empty($p_first))?0:$p_first;
$p_second=(empty($p_second))?0:$p_second;
return bcsub($p_first,$p_second,$p_decimal);
}
function noalyss_bcadd($p_first,$p_second,$p_decimal=4)
{
$p_first=(empty($p_first))?0:$p_first;
$p_second=(empty($p_second))?0:$p_second;
return bcadd($p_first,$p_second,$p_decimal);
}
function noalyss_strip_tags($p_string)
{
if ($p_string===null) return "";
return strip_tags($p_string);
}
function noalyss_bcmul($p_first,$p_second)
{
$p_first=(empty($p_first))?0:$p_first;
$p_second=(empty($p_second))?0:$p_second;
return bcmul($p_first??0,$p_second??0);
}
function noalyss_round($p_first,$p_second)
{
$p_first=(empty($p_first))?0:$p_first;
$p_second=(empty($p_second))?0:$p_second;
return round($p_first??0,$p_second??0);
}
/**
* @brief to avoid deprecated in PHP8.1 : explode cannot use a null
* @param $separator
* @param $string
* @return array | empty string
*/
function noalyss_explode($separator,$string) {
if ($string===null) return '';
return explode($separator,$string);
}
/**
* @brief compose a HTML string with phone
* @param string $p_tel
* @return false|string returns false if $p_tel is empty
*/
function phoneTo($p_tel) {
if (!empty($p_tel)) {
$r=sprintf('<a href="tel:%s">%s</a>',h($p_tel),h($p_tel));
return $r;
}
return false;
}
/**
* @brief compose a HTML string with email
* @param string $p_email email or emails separated by a comma
* @return false|string returns false if email not valide
*/
function mailTo($p_email) {
if (empty($p_email )) return "";
$nComma=preg_match("/,/",$p_email);
if ( $nComma > 0) {
$aEmail=explode(",",$p_email);
} else {
$aEmail[0]=$p_email;
}
$r="";
foreach ($aEmail as $email) {
if ( filter_var(trim($email),FILTER_VALIDATE_EMAIL) ) {
$r.=sprintf('<a href="mailto:%s">%s</a> ',h($email),h($email));
} else {
$r.=sprintf("%s",h($email));
$r.=Icon_Action::warnbulle(83);
}
}
return $r;
}
/**
* @brief compose a HTML string with fax
* @param string $p_fax fax number
* @return false|string returns false if $p_fax is empty
*/
function FaxTo($p_tel) {
if (!empty($p_tel)) {
$r=sprintf('<a href="fax:%s">%s</a>',h($p_tel),h($p_tel));
return $r;
}
return false;
}
function linkTo($p_url)
{
if (empty($p_url) ) return "";
if (filter_var(trim($p_url,FILTER_VALIDATE_URL)) ) {
return sprintf('<a href="%s" target="_blank">%s</a>',$p_url,$p_url);
} else {
return $p_url;
}
}
/**
* @brief When you want to prevent users to connect, create a file in noalyss/ (NOALYSS_BASE) with the
* message in Html
* @param string $p_file file in NOALYSS_BASE
*/
function MaintenanceMode($p_file)
{
if ( file_exists(NOALYSS_BASE."/".$p_file )) {
include NOALYSS_BASE."/".$p_file;
exit;
}
}
/**
* @brief returns an double array with the error found and code , if the count is 0 then the password is very string, 5 means it is
* empty ,4 weak, ... the array contains the errors, [msg]=>array message [code] => array of code
* Codes are
* - 1 : too short
* - 2 : missing digit
* - 3 : missing lowercase letter
* - 4 : missing uppercase letter
* - 5 : too many time same letter or symbol..
* - 6 : missing special char
*
* If the password is strong returns an empty array
*
* @param $password string
* @code
$error = check_password_strength($password);
if ( count($error['msg']) > 0 ) {
echo "password to weak";
foreach ($error['msg'] as $item_error) {
echo "error $item_error";
}
} else {
echo "OK password strong";
}
* @endcode
*/
function check_password_strength($password) {
$errors=array();
$error_code=array();
$len=strlen($password??"");
if ( $len < 8) {
$errors[] = _("mot de passe de 8 lettres minimum");
$error_code[]=1;
}
if (!preg_match("#[0-9]+#", $password)) {
$errors[] = _("mot de passe doit inclure au moins un chiffre");
$error_code[]=2;
}
if (!preg_match("#[a-z]+#", $password)) {
$errors[] = _("mot de passe doit inclure au moins une minuscule");
$error_code[]=3;
}
if (!preg_match("#[A-Z]+#", $password)) {
$errors[] = _("mot de passe doit inclure au moins une majuscule");
$error_code[]=4;
}
if ( $len > 0 ) {
$cnt_diff=count(count_chars($password,1));
$ratio_diff=$len/$cnt_diff;
if ($ratio_diff > 2) {
$errors[] = _("Trop souvent le(s) même(s) symbole(s)");
$error_code[]=5;
}
$special_char=preg_replace('/[[:alnum:]]/','',$password);
if ( strlen($special_char??"")==0)
{
$errors[] = _("mot de passe doit inclure au moins un caractére spécial '+-/*[...'");
$error_code[]=6;
}
}
return array( 'msg'=>$errors, 'code'=>$error_code);
}
/**
* @brief generate a strong random password
* @param $car int length of the password, minimum 8
*
*/
function generate_random_password($car):string
{
$string="";
$car=($car < 8 )?8:$car;
$max_loop=20;$loop=0;
do
{
$loop++;
$string="";
$chaine="abcdefghijklmnpqrstuvwxy";
// srand( (int)microtime()*1020030);
for ($i=0; $i<$car; $i++)
{
$string .= $chaine[rand()%strlen($chaine)];
}
$chaine="ABCDEFGHIJKLMNPQRSTUVWXY";
for ($i=0;$i<2;$i++) {
$string[rand()%$car]=$chaine[rand()%strlen($chaine)];;
}
$chaine="0123456789";
for ($i=0;$i<2;$i++) {
$string[rand()%$car]=$chaine[rand()%strlen($chaine)];;
}
$special_set="+-/*;,.=:&()[]";
$special_car=$special_set[rand()%strlen($special_set)];
$string[rand()%$car]=$special_car;
// echo $string."\n";
}while ( count(check_password_strength($string)['msg'])> 0 && $loop<$max_loop);
return $string;
}
/**
* @brief removed invalid character when computing a filename, the suffix is kept
* @param $filename String filename to sanitize
* @return string without offending char
*/
function sanitize_filename($filename)
{
// save the suffix
$pos_prefix=strrpos($filename, ".");
if ($pos_prefix==0)
{
$filename_suff=".pdf";
$filename.=$filename_suff;
$pos_prefix=strrpos($filename, ".");
}
else
$filename_suff=substr($filename, $pos_prefix, strlen($filename));
$filename=str_replace(array('/', '*', '<', '>', ';', ',', '\\', '.', ':', '(', ')', ' ', '[', ']'), "-", $filename);
$filename_no=substr($filename, 0, $pos_prefix);
$new_filename=strtolower($filename_no)."-".date("Ymd-Hi").$filename_suff;
return $new_filename;
}