diff --git a/GameEngine/Market.php b/GameEngine/Market.php index 7fda94dd..c2af5d46 100755 --- a/GameEngine/Market.php +++ b/GameEngine/Market.php @@ -806,35 +806,20 @@ class Market exit; } - // Prevent selling more resources than available - if ( - ( - (int)$post['m2'][0] < 0 && - round($village->awood) + (int)$post['m2'][0] < 0 - ) || - ( - (int)$post['m2'][1] < 0 && - round($village->aclay) + (int)$post['m2'][1] < 0 - ) || - ( - (int)$post['m2'][2] < 0 && - round($village->airon) + (int)$post['m2'][2] < 0 - ) || - ( - (int)$post['m2'][3] < 0 && - round($village->acrop) + (int)$post['m2'][3] < 0 - ) - ) { + // Sanitize the requested distribution: never negative, never above the + // warehouse / granary capacity. Guards against a forged or NaN-corrupted + // POST (issue #211: NPC distribution). + $maxstore = (int) $village->maxstore; + $maxcrop = (int) $village->maxcrop; - header('Location: build.php?id=' . $post['id'] . '&t=3'); - exit; - } + $m2 = [ + max(0, min($maxstore, (int)($post['m2'][0] ?? 0))), + max(0, min($maxstore, (int)($post['m2'][1] ?? 0))), + max(0, min($maxstore, (int)($post['m2'][2] ?? 0))), + max(0, min($maxcrop, (int)($post['m2'][3] ?? 0))), + ]; - $newTotal = - (int)$post['m2'][0] + - (int)$post['m2'][1] + - (int)$post['m2'][2] + - (int)$post['m2'][3]; + $newTotal = $m2[0] + $m2[1] + $m2[2] + $m2[3]; $currentTotal = round($village->awood) + @@ -853,10 +838,10 @@ class Market $village->wid, ['wood', 'clay', 'iron', 'crop'], [ - $post['m2'][0], - $post['m2'][1], - $post['m2'][2], - $post['m2'][3] + $m2[0], + $m2[1], + $m2[2], + $m2[3] ] ); $this->forget(); diff --git a/Templates/Build/17_3.tpl b/Templates/Build/17_3.tpl index 5d693a0b..d365f3de 100644 --- a/Templates/Build/17_3.tpl +++ b/Templates/Build/17_3.tpl @@ -8,9 +8,23 @@ if ($session->gold <= 2) { } $level = (int)$village->resarray['f'.$id]; -$totalRes = floor($village->awood + $village->aclay + $village->airon + $village->acrop); -$maxstore = (int)$village->maxstore; -$maxcrop = (int)$village->maxcrop; + +// Defensive: a resource computed as NaN/INF (PHP float) would be echoed as +// "NAN"/"INF" into org4/summe and lock the NPC distribution on "Rest: NaN" +// (issue #211). Coerce every value the template/JS relies on to a valid, +// non-negative integer before it reaches the page. +$resSafe = static function ($v) { + $v = (float) $v; + return (is_finite($v) && $v > 0) ? (int) floor($v) : 0; +}; +$awood = $resSafe($village->awood); +$aclay = $resSafe($village->aclay); +$airon = $resSafe($village->airon); +$acrop = $resSafe($village->acrop); + +$totalRes = $awood + $aclay + $airon + $acrop; +$maxstore = max(0, (int)$village->maxstore); +$maxcrop = max(0, (int)$village->maxcrop); // valori prefill din GET $r = []; @@ -62,6 +76,9 @@ $completed = isset($_GET['c']); document.getElementById("overall").innerHTML=overall+"%"; } function normalize() { calculateRes(); resObj=document.getElementsByName("m2"); for (i=0; i 0 && isFinite(a)) ? Math.round(a / b) : 0; } function calculateRest() { resObj=document.getElementsByName("m2[]"); overall=0; for (i=0; imax123)) newRes=max123; if ((i==3) && (newRes>max4)) newRes=max4; resObj[i].value=newRes; } dif=newRes-parseInt(document.getElementById("org"+i).innerHTML); newHTML=dif; if (dif>0) newHTML="+"+dif; document.getElementById("diff"+i).innerHTML=newHTML; overall+=newRes; } - document.getElementById("newsum").innerHTML=overall; rest=parseInt(document.getElementById("org4").innerHTML)-overall; document.getElementById("remain").innerHTML=rest; testSum(); + if (!isFinite(overall)) overall=0; + var total=parseInt(document.getElementById("org4").innerHTML); if (!isFinite(total)) total=summe; + rest=total-overall; if (!isFinite(rest)) rest=0; + document.getElementById("newsum").innerHTML=overall; document.getElementById("remain").innerHTML=rest; testSum(); } function fillup(nr) { resObj=document.getElementsByName("m2[]"); if (nr<3) { resObj[nr].value=max123; } else { resObj[nr].value=max4; } calculateRest(); } - function portionOut() { /*... cod original neschimbat... */ restRes=parseInt(document.getElementById("remain").innerHTML); rest=restRes; resObj=document.getElementsByName("m2[]"); nullCount=0; notNullCount=0; for (j=0; j0) && (resObj[j].value=="")) nullCount++; if ((restRes<0) && (resObj[j].value!="")) notNullCount++; } nullCount2=0; if (restRes>0) { if (nullCount==0) { for (i=0; i0) { resObj[j].value=(parseInt(resObj[j].value)+Math.round(rest/notNullCount)); rest=rest-Math.round(rest/notNullCount); notNullCount--; } } } calculateRest(); if (rest>0) { if (max123>max4) { for (j=0; j<3; j++) { if (parseInt(resObj[j].value)0) && (resObj[j].value=="")) nullCount++; if ((restRes<0) && (resObj[j].value!="")) notNullCount++; } nullCount2=0; if (restRes>0) { if (nullCount==0) { for (i=0; i0) { resObj[j].value=(parseInt(resObj[j].value)+npcDiv(rest,notNullCount)); rest=rest-npcDiv(rest,notNullCount); notNullCount--; } } } calculateRest(); if (rest>0) { if (max123>max4) { for (j=0; j<3; j++) { if (parseInt(resObj[j].value) @@ -88,10 +108,10 @@ $completed = isset($_GET['c']); awood, 'r1', LUMBER], - ['clay', $village->aclay, 'r2', CLAY], - ['iron', $village->airon, 'r3', IRON], - ['crop', $village->acrop, 'r4', CROP], + ['wood', $awood, 'r1', LUMBER], + ['clay', $aclay, 'r2', CLAY], + ['iron', $airon, 'r3', IRON], + ['crop', $acrop, 'r4', CROP], ]; foreach ($resData as $idx => $rd):?>