Örökölt mód eltávolítása 2. rész

A JoomlaWiki wikiből

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 komponens paraméterei

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:

  1. $component = new mosComponent( $database );
  2. $component->load( $letterman_id );
  3. $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:

  1. jimport( 'joomla.application.component.helper' );
  2. $lm_params = JComponentHelper::getParams( 'com_letterman' );
  3. $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).

Adatbázis limitek

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:

  1. 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:

  1. 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:

  1. $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.

Adatbázis kérések

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:

  1. $sql = "SELECT subscriber_name
  2. FROM #__letterman_subscribers
  3. WHERE 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:

  1. $sql = 'SELECT subscriber_name' .
  2.     ' FROM #__letterman_subscribers' .
  3.     ' WHERE subscriber_email=' . $database->Quote( $email );
  4. $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:

  1. $sql = "SELECT id
  2. FROM #__users, #__letterman_subscribers
  3. WHERE user_id=id AND user_id='".$my->id."'";

Ennek így kell kinéznie:

  1. $sql = 'SELECT id' .
  2.     ' FROM #__users, #__letterman_subscribers' .
  3.     ' 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.

A loadObject metódus

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. // 1.0 esetén
  2. $database->loadObject( $result );
  1. // 1.5 esetén
  2. $result = $database->loadObject();

Abszolút elérési út és live site

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:

  1. // require_once( $mosConfig_absolute_path .
  2. //    '/administrator/components/com_letterman/includes/contentRenderer.class.php' );
  3. 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:

  1. // változtassuk meg ezt a sort
  2. $path = JPATH_SITE . '/mambots/' . $folder . '/' . $element . '.php';
  3.  // a következőre
  4. $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:

  1. // global $mosConfig_live_site; // ezt sort töröljük
  2. $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.

További konfigurációs beállítások

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:

  1. $mainframe->getCfg( 'list_limit', 10 );

Azonban ha így használtuk:

  1. global $mosConfig_list_limit;

akkor meg kell változtatnunk. Az egyik lehetőség, hogy lecserélünk minden előfordulást erre:

  1. global $mainframe;
  2. $listLimit = $mainframe->getCfg( 'list_limit', 10 );

Használhatjuk még a JFactory osztályt hogy megkapjuk a konfigurciós objektum másolatát:

  1. $config = JFactory::getConfig();
  2. $listLimit = $config->get( 'config.list_limit' );

Információ a jelenlévő felhasználóról

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:

  1. // A régi mód
  2. // global $my;
  3.  // Az új mód:
  4. $user = &JFactory::getUser();

Ez a metódus egy objektumot ad vissza (tulajdonképpen a JObejct-et). A tulajdonságaihoz így férhetünk hozzá:

  1. $id = $user->id;
  2. $access = $user->aid;
  3. $groupId = $user->gid;
  4. $name = $user->name;

Vagy így:

  1. $id = $user->get( 'id' );
  2. $access = $user->get( 'aid' );
  3. $groupId = $user->get( 'gid' );
  4. $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 és a JRequest

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:

get

A JRequest::get segítségével a PHP request változóinak szűrt értékeit kaphatjuk meg. Például:

  1. $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:

  1. $showPrint = JRequest::getBool( 'print' );

getCmd

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:

  1. // URL paramétere: &task=Abcdef#123.
  2. $task = JRequest::getCmd( 'task' );
  3. // $task = Abcdef123.

getFloat

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:

  1. $userId = JRequest::getInt( 'user_id', 0, 'post' );

getVar

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:

  1. // átadja a kérés cid tömbjét
  2. $cid = JRequest::getVar( 'cid', array(), 'post', 'array' );
  1. // átad egy szöveget
  2. $name = Jrequest::getVar( 'name', 'no name supplied' );
  1. // átadja egy süti értékét
  2. $returning = Jrequest::getVar( 'mycookie', '', 'cookie' );

getWord

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:

  1. // URL paramétere: &task=A_bcdef#123.
  2. $task = JRequest::getWord( 'task' );
  3. // $task = A_bcdef

Ezzel 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:

  1. // $cid = mosGetParam( $_POST, 'cid', array(0) );
  2. // $task = mosGetParam( $_REQUEST, 'task' );
  3. // $no_html = mosGetParam( $_REQUEST, 'no_html' );
  4. $cid  = JRequest::getVar( 'cid', array(0), 'post', 'array' );
  5. $task = JRequest::getWord( 'task' );
  6. $no_html = JRequest::getBool( 'no_html' );
  7. // $mails_per_pageload  = intval( mosGetParam( $_POST, "mails_per_pageload", 100 ));
  8. $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!