PHP: HTML fájl feldolgozása és manipulálása

Már az elején lelövöm a poént: Ha a PHP saját XML DOM parserét használod, biztosan kevesebb hajad marad a nap végére. A SimpleXML sajnos kevés ehhez, de a csodafegyver itt van: http://simplehtmldom.sourceforge.net/manual.htm .

Történt ugyanis, hogy HTML sablon alaján kell PDF-et generálnom. A sablonban táblázatok vannak formázva ( na itt bukott el a PHP XML DOM osztály, mert piszok kacifántos vele xHTML-t manipulálni ), aminek a formázását meg kellene őrizni, hisz’ ez adja majd a PDF stílusát. De vannak mezők, amik helyére be kell helyettesíteni a megfelelő értékeket.

Olvass tovább…

2016.02.29. 12:52 - legyes

PHP és MySQL adattípus túlcsordulások

Azt ügye tudjuk, hogy a PHP-ben automatikus típuskonverzió van, amire oda kellene figyelni. A PHP-ban a számok ábrázolására 2 típus áll rendelkezésre (+boolean):
– (signed) integer
– (signed) float

Ezek minden esetben előjellel vannak ellátva, így az integer típusban maximum 2^63 érték tárolható egy 64 bites rendszeren, 64 bites PHP-val. Viszont! A MySQL-ben rendelkezésre áll az előjel nélküli változat, az unsigned bigint, ami ugyanezen körülmények között 2^64 tud ábrázolni, előjel nélkül. Így marad egy nagy hézag a kettő között.  Mivel a PHP-ban automatikus típuskonverzió van, így az (unsigned big)int átalakul a PHP-ben float típussá, amiből mi semmit sem veszünk észre. A float típussal ügye csak pontosságot vesztettünk.

De mi van akkor, ha a PHP által adott választ egy szigorúbb nyelvvel akarjuk feldolgozni – vagy mert int-et várunk -, erőltetjük az int típust:

echo (int) ((int) PHP_INT_MAX+1); // -9223372036854775808

Akkor az bizony a PHP-ban is túlcsordul, ahogy azt a MySQL-ben is tenné ha signed bigint lenne és ebből mi semmit sem veszünk észre. Ugyanez, automatikus típuskonverzióval:
echo(PHP_INT_MAX+1); // 9.2233720368548E+18

Hogy ez miért okozhat gondot?

Elterjedt szokás, hogy biztonsági okok miatt lehetőleg csak ID-ket (azonosító számokat) küldünk szerver oldalra, mivel ezeket jóval könnyebb szűrni, mint a stringeket. Az adatbázisban pedig az azonosítók legtöbb esetben integer típusok, leginkább unsigned bigint-ek, autoincrement tulajdonsággal. Később pedig a szerver oldali vizsgálatnál – mivel számot várunk és az autotincrement alapból 1-ről indul – lustaságból ezt alkalmazzuk és úgy gondoljuk, hogy ezzel macera nélkül (prepared statements) meg is oldottuk az SQL injection elleni védelmet:


$id = abs($_GET['id']); // barmi nem szamra 0-t ad, ami az alap autoincerement 1-es kezdosorszama miatt nem letezo sorra mutat az adatbazisban
$results = $pdo->query('UPDATE users SET money=money+1000 WHERE id='.$id);

Ok, de eddig még sohasem okozott gondot a túlcsordulás, miért kellene rá figyelnem? 

Hát például ezért:
echo (int) PHP_INT_MAX; // 9223372036854775807
echo (int) ((PHP_INT_MAX+1000000)-1000000); // 9223372036854774784

Természetesen ez oda-vissza érvényes, azaz figyelni kell arra, hogy a PHP integer típusa több egész szám tárolására képes, mint a MySQL bizonyos integer típusai. A MySQL persze dob warningot, de ha külön nem kérdezzük meg róla, akkor jó eséllyel nem fogjuk észrevenni PHP-ben.

 

Sok forráskódban láttam már a fent említett lustaságból alkalmazott szám-konverziós védelmet. A baj az, hogy úgy hiszik elegendő csupán (int) -el erőltetni a típust. Csak hogy az negatív számokat is elfogad, így a túlcsordítással máris pozitív számmá változtathatjuk, ami viszont már tutira létezik az adatbázisban a tipikus autoincrementes megoldásoknál. Kiszámolni pedig könnyű a megfelelő mértékű túlcsordítást okozó számot, hogy a kért ID-t kapjuk eredményül. 

2015.07.19. 15:10 - legyes

JavaScript dump() a PHP-s print_r-hez hasonlóan

/**
 * Function : dump()
 * Arguments: The data - array,hash(associative array),object
 *    The level - OPTIONAL
 * Returns  : The textual representation of the array.
 * This function was inspired by the print_r function of PHP.
 * This will accept some data as the argument and return a
 * text that will be a more readable version of the
 * array/hash/object that is given.
 * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
 */
function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;

	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j "" + value + ""n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}
//Calling the function...
function init() {
	var arra = new Array("So long",'s',42,42.13,"Hello World");
	var assoc = {
		"val"  : "New",
		"number" : 8,
		"theting" : arra
	};

	alert(dump(assoc));
}
window.onload=init;
'val' => "New"
'number' => "8"
'theting' ...
   '0' => "So long"
   '1' => "s"
   '2' => "42"
   '3' => "42.13"
   '4' => "Hello World"

Forrás: http://www.openjs.com/scripts/others/dump_function_php_print_r.php

2013.04.29. 08:02 - legyes

PHP: felesleges nullák eltüntetése a MySQL DECIMAL típusból

Gondoltam lusta leszek és rákeresek a Google tudástárban, hogy hátha van ilyen paramétere mondjuk a numer_format() -nak.

A probléma az, hogy ha az adatbázisból pl. DECIMAL 6,2 formátumban érkezik egy egész szám, akkor a “.00” ott lesz a végén, pedig értelme ebben az esetben nem sok.

// $szam = "12.00";
echo $szam;
// 12.00

Aztán eszembe jutott az automatikus típuskonverzió, így a megoldás:

echo ($szam*1);
2012.05.07. 07:21 - legyes
1 2