Fix DOS attack by using num_public_holiday() - repeated sql in loop

This commit is contained in:
Laurent Destailleur
2024-09-23 13:09:45 +02:00
parent 073facfee5
commit 6ca2e746ca

View File

@@ -762,7 +762,7 @@ function getGMTEasterDatetime($year)
*/
function num_public_holiday($timestampStart, $timestampEnd, $country_code = '', $lastday = 0, $includesaturday = -1, $includesunday = -1, $includefriday = -1, $includemonday = -1)
{
global $db, $mysoc;
global $conf, $db, $mysoc;
$nbFerie = 0;
@@ -789,21 +789,10 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
$country_id = dol_getIdFromCode($db, $country_code, 'c_country', 'code', 'rowid');
$i = 0;
while ((($lastday == 0 && $timestampStart < $timestampEnd) || ($lastday && $timestampStart <= $timestampEnd))
&& ($i < 50000)) { // Loop end when equals (Test on i is a security loop to avoid infinite loop)
$ferie = false;
$specialdayrule = array();
$jour = (int) gmdate("d", $timestampStart);
$mois = (int) gmdate("m", $timestampStart);
$annee = (int) gmdate("Y", $timestampStart);
//print "jour=".$jour." month=".$mois." year=".$annee." includesaturday=".$includesaturday." includesunday=".$includesunday."\n";
if (empty($conf->cache['arrayOfActivePublicHolidays_'.$country_id])) {
// Loop on public holiday defined into hrm_public_holiday for the day, month and year analyzed
// TODO Execute this request first and store results into an array, then reuse this array.
$sql = "SELECT code, entity, fk_country, dayrule, year, month, day, active";
$tmpArrayOfPublicHolidays = array();
$sql = "SELECT id, code, entity, fk_country, dayrule, year, month, day, active";
$sql .= " FROM ".MAIN_DB_PREFIX."c_hrm_public_holiday";
$sql .= " WHERE active = 1 and fk_country IN (0".($country_id > 0 ? ", ".$country_id : 0).")";
$sql .= " AND entity IN (0," .getEntity('holiday') .")";
@@ -814,34 +803,55 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
$i = 0;
while ($i < $num_rows) {
$obj = $db->fetch_object($resql);
if (!empty($obj->dayrule) && $obj->dayrule != 'date') { // For example 'easter', '...'
$specialdayrule[$obj->dayrule] = $obj->dayrule;
} else {
$match = 1;
if (!empty($obj->year) && $obj->year != $annee) {
$match = 0;
}
if ($obj->month != $mois) {
$match = 0;
}
if ($obj->day != $jour) {
$match = 0;
}
if ($match) {
$ferie = true;
}
}
$tmpArrayOfPublicHolidays[$obj->id] = array('dayrule' => $obj->dayrule, 'year' => $obj->year, 'month' => $obj->month, 'day' => $obj->day);
$i++;
}
} else {
dol_syslog($db->lasterror(), LOG_ERR);
return 'Error sql '.$db->lasterror();
}
//var_dump($specialdayrule)."\n";
//print "ferie=".$ferie."\n";
//var_dump($tmpArrayOfPublicHolidays);
$conf->cache['arrayOfActivePublicHolidays_'.$country_id] = $tmpArrayOfPublicHolidays;
}
$arrayOfPublicHolidays = $conf->cache['arrayOfActivePublicHolidays_'.$country_id];
$i = 0;
while ((($lastday == 0 && $timestampStart < $timestampEnd) || ($lastday && $timestampStart <= $timestampEnd))
&& ($i < 50000)) { // Loop end when equals (Test on i is a security loop to avoid infinite loop)
$ferie = false;
$specialdayrule = array();
$jour = (int) gmdate("d", $timestampStart);
$mois = (int) gmdate("m", $timestampStart);
$annee = (int) gmdate("Y", $timestampStart);
//print "jour=".$jour." month=".$mois." year=".$annee." includesaturday=".$includesaturday." includesunday=".$includesunday."\n";
foreach ($arrayOfPublicHolidays as $entrypublicholiday) {
if (!empty($entrypublicholiday['dayrule']) && $entrypublicholiday['dayrule'] != 'date') { // For example 'easter', '...'
$specialdayrule[$entrypublicholiday['dayrule']] = $entrypublicholiday['dayrule'];
} else {
$match = 1;
if (!empty($entrypublicholiday['year']) && $entrypublicholiday['year'] != $annee) {
$match = 0;
}
if ($entrypublicholiday['month'] != $mois) {
$match = 0;
}
if ($entrypublicholiday['day'] != $jour) {
$match = 0;
}
if ($match) {
$ferie = true;
}
}
$i++;
}
//var_dump($specialdayrule)."\n";
//print "ferie=".$ferie."\n";
if (!$ferie) {
// Special dayrules
@@ -955,9 +965,9 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
// Geneva fast in Switzerland
}
}
//print "ferie=".$ferie."\n";
//print "ferie=".$ferie."\n";
// If we have to include Friday, Saturday and Sunday
// If we have to include Friday, Saturday and Sunday
if (!$ferie) {
if ($includefriday || $includesaturday || $includesunday) {
$jour_julien = unixtojd($timestampStart);
@@ -979,18 +989,18 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
}
}
}
//print "ferie=".$ferie."\n";
//print "ferie=".$ferie."\n";
// We increase the counter of non working day
// We increase the counter of non working day
if ($ferie) {
$nbFerie++;
}
// Increase number of days (on go up into loop)
$timestampStart = dol_time_plus_duree($timestampStart, 1, 'd');
//var_dump($jour.' '.$mois.' '.$annee.' '.$timestampStart);
// Increase number of days (on go up into loop)
$timestampStart = dol_time_plus_duree($timestampStart, 1, 'd');
//var_dump($jour.' '.$mois.' '.$annee.' '.$timestampStart);
$i++;
$i++;
}
//print "nbFerie=".$nbFerie."\n";