A sorozat második része egy meglévő komponens módosítását mutatja be, hogy az natívan működjön az 1.5-ös verzió alatt. Legutóbbi alkalommal megnéztük az örökölt módot, javítottuk a közvetlen elérést megakadályozó kódot és néhány adatbázissal kapcsolatos problémát. Megnéztük még, hogy mit kell tennünk a fordítással kapcsolatban. Tehát folytassuk és derítsük ki, hogy mi a következő hibaüzenet forrása.
Tartalomjegyzék |
A következő hibaüzenet akkor jelenik meg, amikor a komponens a mosComponent osztályt próbálja használni a komponens paramétereinek a lekérdezéséhez. Ezt a módszert nem sokszor láthattuk az 1.0-ás komponensekben, mert sok fejlesztő nem is ismerte ezt a funkciót.
A LetterMan letterman.class.php fájljában ezeket a sorokat találjuk:
$component = new mosComponent( $database );
$component->load( $letterman_id );
$GLOBALS['lm_params'] = $lm_params = new mosParameters( $component->params );
Van egy úgynevezett JComponentHelper osztály, amellyel könnyen megkaphatjuk a komponens paramétereit. Ezt a részt valami ilyesmivel cserélhetjük le:
jimport( 'joomla.application.component.helper' );
$lm_params = JComponentHelper::getParams( 'com_letterman' );
$GLOBALS['lm_params'] = $lm_params;
Amint láthajuk, a getParams metódust használtuk, amelynek paraméterként átadtuk a komponens könyvtárának a nevét. A kódban lejjebb haladva a LetterMan elmenti megint a paramétereket, tehát itt problémába ütközünk, később bemutatunk egy egyszerűbb módot a komponens konfigurációjának kezelésére, de ebben a részben ezt most kihagyjuk. A getParams metódus a JParameter objektummal tér vissza (amely az 1.0-ban létező mosParameter objektumot cseréli le).
Néhány sorral lejjebb felfigyelhetünk valamire, amit meg kell változtatnunk, amely még a Mambo időkből maradt ránk (hogy miért kerül említésre a Mambo az egy hosszú történet, de a rövid változat az, hogy a Mambo összes fejlesztője otthagyta a Mambot és létrehozta a Joomlát egy új vezetéssel). Egy adatbázis kérés található ott, amely így végződik:
LIMIT 0, 1
Nem használunk kéréseket a limit paranccsal többé. Az adatbázist kezelő setQuery metódus néhány további argumentummal rendelkezik. Nézzük meg ezeket az argumentumokat:
function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' )
Tehát a LIMIT-et ki kell vennünk a kérésből és meghívnunk a setQuery metódust ezekkel az argumentumokkal, például:
$database->setQuery( $sql, 0, 1 );
Erre azért volt szükség, hogy később új adatbázisokkal is működjön (mint például Oracle). Habár technikailag ez nem egy 1.0-ról 1.5-re átállás, érdemes így felépítenünk a kéréseket.
Ha már az adatbázisnál tartunk, mutatunk pár dolgot, amit rendszeresen el kell végezni. A kérésekben idézőjelek vagy aposztrófok közé kell tenni a szövegeket és a számokat a különböző injekciós támadások csökkentése érdekében. Itt egy jó példa:
$sql = "SELECT subscriber_name
FROM #__letterman_subscribersWHERE subscriber_email='$email'";
A LetterMan aposztrófokat használt a $email változónál, de egy jobb megoldás ennél az adatbázis Quote metódusának a használata. Ezért tehát megváltoztatjuk a kódot erre:
$sql = 'SELECT subscriber_name' .
' FROM #__letterman_subscribers' .
' WHERE subscriber_email=' . $database->Quote( $email );
$database->setQuery( $sql );
Ezáltal megmarad a $email eredeti értéke, hogy további dolgokra lehessen felhasználni (például e-mail küldésére). A Quote metódus bővíthető különböző adatbázisok kezeléséhez, tehát ugyanazon okból használjuk, mint a korlátozásokat (limit). Érdemes ezt a módszert használni, mert nem minden adatbázis használja ugyanazt a jelet.
A másik példa amikor olyan adatokkal dolgozunk, amelyekről tudjuk, hogy integer típusúak - minden alkalommal használjuk (még akkor is, ha az adatbázisból olvastuk ki). Egy példa egy ilyen kérésre:
$sql = "SELECT id
FROM #__users, #__letterman_subscribersWHERE user_id=id AND user_id='".$my->id."'";
Ennek így kell kinéznie:
$sql = 'SELECT id' .
' FROM #__users, #__letterman_subscribers' .
' WHERE user_id=id AND user_id=' . (int) $my->id;
Tulajdonképpen még ezt is megváltoztathatnánk úgy, hogy a JOIN parancsot használja. de ezt majd egy másik alkalommal. Majd később belemegyünk abba, hogy tegyük biztonságosabbá a kéréseket, ha már működik a komponens.
Hamar problémába ütközünk a loadObject alkalmazásakor. Az 1.0-ás verziókban egy objektumot adtunk át argumentumként. Az 1.5-ben ez egy objektumot ad vissza. A módosítás egyszerű:
// 1.0 esetén$database->loadObject( $result );
// 1.5 esetén$result = $database->loadObject();
A következő probléma nem olyan nyilvánvaló. Az 1.5-ös verzióban már nem létezik többé a $mosConfig_absolute_path nevű globális változó. Helyette számos konstans létezik.
JPATH_SITE - Az oldal útvonala - megegyezik a $mosConfig_absolute_path változóval JPATH_ADMINISTRATOR - Az administrator könyvtár elérési útvonala JPATH_COMPONENT - A komponens útvonala, amelyen dolgozunk
Számos egyéb konstans létezik (ezeket megnézhetjük az includes/defines.php fájlban), de ezek a leggyakrabban használtak. A feladat annyi, hogy rákeresünk az összes $mosConfig_absolute_path változóra, majd lecserééljük a JPATH_SITE konstansra. Mindamellett itt egy jó példa arra, hogy mikor használjuk a JPATH_COMPONENT konstansot:
// require_once( $mosConfig_absolute_path .// '/administrator/components/com_letterman/includes/contentRenderer.class.php' );require_once( JPATH_COMPONENT.DS.'includes'.DS.'contentRenderer.class.php' );
Ha már az útvonalaknál vagyunk, az 1.5 tartalmaz egy rövidítést a PHP DIRECTORY_SEPEARATOR konstansához DS néven. Jó ötlet a DS-t használni amikor fájlrendszer útvonalat hozunk létre, például:
// változtassuk meg ezt a sort$path = JPATH_SITE . '/mambots/' . $folder . '/' . $element . '.php';
// a következőre$path = JPATH_SITE.DS.'mambots'.DS.$folder.DS.$element.'.php';
A következő változás, hogy a $mosConfig_live_site változó sem létezik már. Le lett cserélve a JURI::base() hívásra. A keresés és csere egy kicsit nehéz lenne itt, de a legkönnyebb mód a probléma megoldására, ha töröljük az összes global $mosConfig_live_site referenciát és helyette a következő sort használjuk:
// global $mosConfig_live_site; // ezt sort töröljük$mosConfig_live_site = JURI::base( true ); //majd adjuk hozzá ezt
A JURI::base() használata argumentumok nélkül a teljes elérési útvonalat fogja adni egy / jellel a végén.
Ha ezt a kódot használtuk a globális konfigurációs változókhoz, akkor valószínűleg nem lesz problémánk ezen a téren:
$mainframe->getCfg( 'list_limit', 10 );
Azonban ha így használtuk:
global $mosConfig_list_limit;
akkor meg kell változtatnunk. Az egyik lehetőség, hogy lecserélünk minden előfordulást erre:
global $mainframe;
$listLimit = $mainframe->getCfg( 'list_limit', 10 );
Használhatjuk még a JFactory osztályt hogy megkapjuk a konfigurciós objektum másolatát:
$config = JFactory::getConfig();
$listLimit = $config->get( 'config.list_limit' );
Ez a hiba még nem jelentkezett, de a későbbiekben fog, tehát javítsuk ki, ha már úgyis kereséssel és cserével foglalkozunk. Az 1.0-ban volt egy úgynevezett $my globális változó, amely a bejelentkezett felhasználóról tartalmazott információt. Ez a változó megszűnt az 1.5-ben, de JFactory osztály getUser metódusával helyettesíthetjük, valahogy így:
// A régi mód// global $my; // Az új mód:$user = &JFactory::getUser();
Ez a metódus egy objektumot ad vissza (tulajdonképpen a JObejct-et). A tulajdonságaihoz így férhetünk hozzá:
$id = $user->id;
$access = $user->aid;
$groupId = $user->gid;
$name = $user->name;
Vagy így:
$id = $user->get( 'id' );
$access = $user->get( 'aid' );
$groupId = $user->get( 'gid' );
$name = $user->get( 'name', 'a név nem áll rendelkezésre' );
A második módszer használata akkor előnyös, ha alapértelmezett értéket is akarunk a változónak adni.
A mosGetParam az a funkció, amelyet valószínűleg a legtöbbször használtunk (talán az adatbázis metódusokhoz viszonyítható). A mosGetParam szerepe megváltozott és bővítésre került a JRequest nevű osztályban.
A JRequest használható kérésekből adódó információk átadásához, de egy sokkal fontosabb szerepe a támadások kivédése. Most nézzük meg utoljára a sorozat ezen részében, de időd szánunk a részletek bemutatására.
A JRequest osztály a Joomla! libraries könyvtárában található az API részeként (libraries/joomla/environment/request.php). Megéri megnézni ezt az osztályt, hiszen csak 500 sorból áll. A következő 'get' metódusok minden fejlesztő érdeklődését felkelthetik. Amíg argumentumokkal nem határozunk meg más módot, a metódus megtisztítja a változókat a Joomla! beviteli mező szűrőjén keresztül. Alapértelmezésként az összes HTML tagot és egyéb támadók által használt kódot eltávolítja. Javítja még a perjelből eredő hibákat, tehát a változóból törli a perjeleket (természetesen csak akkor, ha az nem a kérés része).
A legtöbb metódus (a 'get' kivételével) három argumentumot fogad: a változó nevét, az alapértelmezett értéket és a kérés módját (pl. get vagy post). Ennyi elég is a bevezetéshez, nézzük meg a metódusokat:
A JRequest::get segítségével a PHP request változóinak szűrt értékeit kaphatjuk meg. Például:
$post = JRequest::get( 'post' );
Ez a kód a $post változóhoz hozzárendeli a $_POST szűrt változatát beleértve a kérés összes tömbjét. Argumentumok nélkül a $_REQUEST tömböt adja át. getBool
Biztosítja, hogy az érték egy boolean változó, például:
$showPrint = JRequest::getBool( 'print' );
Biztosítja, hogy az érték csak az A-Z, 0-9, _ (aláhúzás), . (pont) és - (kötőjel) karaktereket tartalmazza. A nagy és kisbetű nem számít. Például:
// URL paramétere: &task=Abcdef#123.$task = JRequest::getCmd( 'task' );
// $task = Abcdef123.Biztosítja, hogy az érték egy float típusú változó. getInt
Biztosítja, hogy az érték integer típusú. Ezt általában azonosítókhoz (id) használjuk, például:
$userId = JRequest::getInt( 'user_id', 0, 'post' );
Ez az általános mód egy request változó értékének átadásához. Egy negyedik attribútummal rendelkezik, amely a változó típusa. Az összes többi getValami metódus ennek az álmetódusa. Néhány példa a használatára:
// átadja a kérés cid tömbjét$cid = JRequest::getVar( 'cid', array(), 'post', 'array' );
// átad egy szöveget$name = Jrequest::getVar( 'name', 'no name supplied' );
// átadja egy süti értékét$returning = Jrequest::getVar( 'mycookie', '', 'cookie' );
Biztosítja, hogy az érték csak az A-Z és az _ (aláhúzás) karaktereket tartalmazza. A kis és nagybetű nem számít. Például:
// URL paramétere: &task=A_bcdef#123.$task = JRequest::getWord( 'task' );
// $task = A_bcdefEzzel a tudással már vissza is térhetünk a komponensünkre. Az összes mosGetParam-ot egyenként kell megnéznünk. Néhány példa a szemléltetéshez. Az összes esetben kommentelésre került az eredeti kód és alatta található az új:
// $cid = mosGetParam( $_POST, 'cid', array(0) );// $task = mosGetParam( $_REQUEST, 'task' );// $no_html = mosGetParam( $_REQUEST, 'no_html' );$cid = JRequest::getVar( 'cid', array(0), 'post', 'array' );
$task = JRequest::getWord( 'task' );
$no_html = JRequest::getBool( 'no_html' );
// $mails_per_pageload = intval( mosGetParam( $_POST, "mails_per_pageload", 100 ));$mails_per_pageload = JRequest::getInt( 'mails_per_pageload', 100, 'post' );
Ezzel be is fejezzük a sorozat második részét, amelyben egy meglévő komponens átalakítását mutatjuk be. A következő részben megszabadulunk a hibaüzenetektől és a fehér képernyőktől.
A cikk forrása: The Art of Joomla!