PunBB fórum

Pokud jste se už podívali na moje diskusní fórum, možná jste si všimli, že nepoužívám žádné ze standardních fór ale poměrně neznámé PunBB. Proč jsem si zvolil právě tohle fórum a ne PhpBB, SMF nebo vBulletin? Důvodů je víc. Mohl bych jmenovat rychlost a jednoduchost, poměrně kvalitní kód (i když rozhodnutí umisťovat pluginy do XML souborů nebylo zrovna šťastné) nebo malou rozšířenost, která pomáhá při boji se spamem, ale hlavním důvodem bylo to, že PunBB šlo docela jednoduše upravit tak, aby se integrovalo do kódu Studny – aby se uživatel registrací do Studny automaticky zaregistroval i do fóra, a co víc, aby byl uživatel přihlášený do Studny automaticky přihlášen i do fóra.

Nebudu se tu zabývat používáním fóra, to si může každý sám vyzkoušet klidně i u mě, ani instalací. Podívám se ale na pár zajímavých programovacích záležitostí.

PHP a databáze

PunBB je od začátku psané tak, aby jeho kód byl rychlý a bezpečný, dal se snadno rozšiřovat a jeho výstup aby odpovídal standardu XHTML. Do určité míry se to podařilo: PunBB je určité malé, jednoduché a čistě napsané, dá se dobře rozšiřovat a jeho kód odpovídá požadavkům na XHTML, ale nejsem už úplně přesvědčen o rychlosti: částečně za to můžou už hlavní vlastnosti fóra (pokud má být program snadno rozšiřitelný, tak se jen obtížně obejde bez kódu, který tu rozšiřitelnost zajistí – a ten kód samozřejmě i něco stojí; podpora dalších databází vedle obligátního MySQL také obvykle vede ke zhoršení výkonnosti, u interpretovaných jazyků zvlášť), částečně ale také fakt, kterým se autoři PunBB příliš nechlubí, ale který vyplave na povrch hned, jak se do kódu trochu podíváte:

PunBB je zcela evidentně založeno – přinejmenším ideově, když už ne kódem – na PhpBB verze 2. Už samotný pohled na to, jak jsou fóra a příspěvky v nich uspořádány, vyvolává vzpomínky na dost tragickou starou verzi PunBB, a jakmile se podíváte na strukturu PHP kódu (jak je rozdělen do jednotlivých souborů a jak jsou jednotlivé operace uživatelského rozhraní vzájemně provázány) a/nebo na strukturu databáze (tabulky a jejich obsah), je jasno: PunBB je ve své podstatě PhpBB přepsané do mírně čistější podoby. To se ostatně naplno projevilo na tom, jak jsem migroval Studnu z PhpBB2 na PunBB: Celá „konverze“ spočívala v tom, že jsem obsahy tabulek téměř beze změny přesypal z jedné databáze do druhé a bylo hotovo. Nebylo potřeba upravovat žádné odkazy (z článků na Studně se odkazuje na jednotlivá témata do fóra, a naopak), z velké části nebylo třeba měnit texty příspěvků. S trochou nadsázky by se dalo říct, že přechod od PhpBB k PunBB znamená nainstalovat nové fórum a sekvencí několika SQL příkazů INSERT INTO punbb_tabulka (...) SELECT ... FROM phpbb_tabulka celé fórum převést.

Rozšíření (pluginy)

Co mě na PunBB (ve verzi 1.3) velice potěšilo, je snadná tvorba pluginů. Filozofie je podobná jako u WordPressu: Celý kód PunBB je protkán rozsáhlou sítí „hooks“, míst, která jde „napíchnout“ a nahradit nebo doplnit vlastním kódem. Tvorba pluginu pak spočívá v tom, že najdu v kódu PunBB vhodný hook a předepsaným způsobem k němu přiřadím svůj program. Řekněme, že bych chtěl rozšířit jazyk BBcode o vlastní značky. Najdu tedy v kódu místo, kde se BBcode zpracovává, což je v tomto konkrétním případě soubor include/parser.php a konkrétně jeho funkce do_bbcode:

function do_bbcode($text, $is_signature = false)
{
	global $lang_common, $forum_user, $forum_config;

	$return = ($hook = get_hook('ps_do_bbcode_start')) ? eval($hook) : null;
	if ($return != null)
		return $return;

	...

	$pattern[] = '#\[b\](.*?)\[/b\]#ms';
	$pattern[] = '#\[i\](.*?)\[/i\]#ms';
	$pattern[] = '#\[u\](.*?)\[/u\]#ms';
	$pattern[] = '#\[colou?r=([a-zA-Z]{3,20}|\#[0-9a-fA-F]{6}|\#[0-9a-fA-F]{3})](.*?)\[/colou?r\]#ms';
	$pattern[] = '#\[h\](.*?)\[/h\]#ms';

	$replace[] = '<strong>$1</strong>';
	$replace[] = '<em>$1</em>';
	$replace[] = '<span class="bbu">$1</span>';
	$replace[] = '<span style="color: $1">$2</span>';
	$replace[] = '</p><h5>$1</h5><p>';

	...

	$return = ($hook = get_hook('ps_do_bbcode_replace')) ? eval($hook) : null;
	if ($return != null)
		return $return;

	// This thing takes a while!
	$text = preg_replace($pattern, $replace, $text);

	$return = ($hook = get_hook('ps_do_bbcode_end')) ? eval($hook) : null;
	if ($return != null)
		return $return;

	return $text;
}

Všimněte si řádků 5-7, 25-27, 32-34: To jsou právě zmíněné „hooks“; ps_do_bbcode_start se volá na začátku zpracování BBcode a umožňuje celou funkci potlačit a nahradit vlastní. ps_do_bbcode_replace se volá těsně před nahrazením původního BBcode novým XHTML a lze ji použít k snadnému přidání dalších značek (prostě tak, že do polí $pattern a $replace přidám další regulární výrazy. ps_do_bbcode_end se volá na samotném konci funkce a lze ho použít pro případné dodatečné úpravy poté, co už proběhlo hlavní nahrazování.

Příkladem, jak se to dá využít, je implementace speciálního tagu [size], který BBcode standardně nemá. Ideální je napíchnout na ps_do_bbcode_end nějakým takovýmhle kódem:

	if (!function_exists('bbcode_size_pregcallback')) {
		function bbcode_size_pregcallback($matches) {
			$sizes = array('1'=>'xx-small', '2'=>'x-small', '3'=>'small', '4'=>'medium', '5'=>'large', '6'=>'x-large', '7'=>'xx-large',
				'+1'=>'150%', '+2'=>'200%', '+3'=>'300%', '-1'=>'80%', '-2'=>'60%', '-3'=>'40%');
			if (isset($sizes[$matches[1]]))
				return '<span style="font-size: '.$sizes[$matches[1]].';">'.$matches[2].'</span>';
			else
				return $matches[0];
		}
	}
	$text = preg_replace_callback('~\\[size=([1-7]|[+-][1-3])\\]([^<>]*)\\[/size\\]~isU', 'bbcode_size_pregcallback', $text);

Tento kód vezme výsledek funkce do_bbcode (v proměnné $text) a prožene ho ještě jedním speciálním regulárním výrazem, který nahradí tagy [size=1..7] (absolutní velikost) resp. [size=-3..+3] (relativní velikost) příslušně ostylovaným tagem <span>. Jistě že by to šlo napsat i do hooku ps_do_bbcode_replace doplněním vhodných sekvencí do $patterns a $replace, ale protože vztah mezi parametrem [size] a parametrem font-size není regulárním výrazem dobře popsatelný, je výhodnější mnou uvedená verze.

Obdobně jde přidávat i další funkcionalitu do fóra – na konci článku naleznete několik vytvořených pluginů.

Celé je to krásně jednoduché a má to vlastně jen jednu vadu na kráse: Autoři PunBB zvolili poměrně nešťastný způsob, jak rozšíření instalovat. Jde o to, že plugin je povinně tvořen XML souborem, který obsahuje popis pluginu i použitý kód. Do jisté míry to chápu – takovéto pojetí se dá velice jednoduše strojově zpracovávat, není třeba složitě parsovat poznámky jako u rozšíření WordPressu a doufat, že uživatel dodržel požadovaný formát. Na druhou stranu to ale také znamená, že případný útočník má značně zjednodušenou cestu ke zdrojovým kódům rozšíření – například u všech standardních rozšíření si můžete prostě stáhnout soubor http://www.adresa-fóra.cz/forum/extensions/jméno-pluginu/manifest.xml a kochat se tím, jak je rozšíření napsáno. Některé vnitřnosti cizího PunBB, například strukturu databáze uživatelů, tak dostáváte doslova na stříbrném podnosu. Navíc není zrovna jednoduché to zablokovat, pokud nemáte možnost použít vlastní .htaccess soubor pro omezení přístupu…

Integrace PunBB do jiného webu

Jednou z věcí, které se mi na PunBB líbí, je to, že se příliš nebrání integraci do jiných webů – je možné PunBB upravit tak, aby využil uživatelskou databázi, ale i přímo přihlášení uživatele, z mateřského webu, a samo se staralo jen o vlastní fórum. Úplně bezpracné to ale také není – je sice pravda, že PunBB tomu nebrání, ale také tomu nepomáhá: Integraci zařídit lze, ale není to zrovna bezpracné. Ovšem mezi slepými jednooký králem, že…

Když pomineme dva základní způsoby „integrace“, které podporují ostatní fóra (tzn. duplicitní a neustále synchronizovaná databáze uživatelů, což je horror sám o sobě, a možnost „nepoužívejte správu uživatelů vašeho redakčního systému ale použijte místo toho správu uživatelů fóra“, což je snad ještě horší), lze v PunBB použít ještě třetí způsob, který už je skutečnou integrací: Lze zařídit, aby PunBB „sahal“ přímo do tabulky uživatelů vašeho redakčního systému, s tím, že některé funkce fóra (např. registraci nového uživatele nebo změnu hesla) zablokujete, aby uživatel musel využít příslušných služeb redakčního systému.

Nejjednodušší je využít, pokud je vaše databáze podporuje, pohledů: pomocí vhodného CREATE VIEW můžete pro PunBB vytvořit virtuální tabulku uživatelů, která si ve skutečnosti bude brát data z tabulky uživatelů r.s., jen vhodně transformovaná (přejmenované sloupečky tabulky, přeměněné typy dat a podobně). Je ro rychlé, elegantní a jednoduché a má to vlastně jen jednu „drobnou“ vadu: U databází, které plně nepodporují updatovatelné pohledy, to nebude fungovat správně.

Druhá cesta je využít hooků, které vám PunBB dává k dispozici, a všechny odkazy na tabulku uživatelů přepsat na použití tabulky uživatelů vašeho redakčního systému. Ano, je to hodně různých hooků, ale není to zase tak strašné – jak vím z vlastní praxe, protože právě tímhle způsobem jsem integroval PunBB do Studny. Abyste měli trochu inspiraci, osamostatnil jsem právě jen tuhle práci s uživateli do rozšíření, které si ode mne můžete stáhnout a příslušně upravit. Podotýkám ale, že bez té úpravy se to neobejde: rozšíření je psané na míru Studny a pro použití na jiném webu je třeba zohlednit odlišnou strukturu tabulky uživatelů, kterou tento web bude mít. Navíc speciálně pro Studnu jsem musel upravit i dva „nativní“ soubory PunBB, /include/functions.php a /include/dblayer/mysql.php. Berte toto rozšíření jako inspiraci, ne jako hotový produkt!

Download

Několik málo pluginů k downloadu:

  • Antispam v0.02 (2010-08-22, 3 KB): Jednoduchý, ale překvapivě účinný antispam pro PunBB. Funguje na principu skrytého pole formuláře, které uživatel neuvidí a tudíž nevyplní, ale robot do něj napíše nějaký text a tím se prozradí. Jde tedy o klasický případ security by obscurity, kdy by robot mohl naprosto triviálně obejít, kdyby chtěl (a kdyby se jeho autor zaměřil speciálně na moje fórum), ale dokud nebude příliš rozšířený, funguje velice dobře – za ty dva roky, co běží, jsem nemazal ani jeden spam. Pro uživatele je příjemný v tom, že neobsahuje žádnou captchu ani nic podobného.

    Verze 0.02: Nedovolí uživateli nastavit si URL nebo podpis do doby, než bude mít tři schválené příspěvky (ochrana proti robotům, kteří se registrují jen proto, aby se v seznamu uživatelů zobrazil jejich odkaz).

  • BBcode: Relative URL (1 KB): Maličký plugin, který dovoluje v BBcode tagu [url] používat i relativní cesty – tzn. něco jako [url=./viewtopic?tid=123]Téma 123[/url]. Hodí se zejména pro odkazování na další příspěvky ve fóru, případně na články na stejném webu, protože „přežije“ i změnu domény nebo adresáře. Aby zůstala zachována tradiční BBcode podpora pro neúplné odkazy ([url=www.pepak.net]pepak.net[/url]), zpracovává plugin pouze adresy začínající tečkou nebo lomítkem.

  • BBcode: Size (1 KB): Další maličký plugin pro podporu BBcode tagu [size] pro změnu velikosti písma v příspěvcích. Popis je uveden výše.

  • Studna (36 KB): Plugin, který demonstruje, jak se dá PunBB integrovat do jiného webu. Popis je uveden výše. Pozor, na rozdíl od ostatních pluginů toto není hotový plugin, ale nanejvýš „polotovar“ – vlastní úprava je nezbytná!

Podobné příspěvky:

7 komentářů “PunBB fórum”

  1. avatar pepak napsal:

    Jirka: Od té doby, co jsem psal o PunBB, uběhla spousta vody a já jsem od něj zase odešel. Takže teď mohu jen odhadovat, že požadovaná změna bude v souboru viewtopic.php, zběžným pohledem (pro verzi 1.3.6) zřejmě kolem řádku 240 (hook vt_pre_header_load a řádky bezprostředně před ním).

  2. avatar Jirka napsal:

    Dobrý den,

    mám velkou prosbu. Poradíte mi, prosím, kam se dá sahnout, aby v hlavičce stránky například zde http://www.pravni-poradna.eu/viewforum.php?id=9 nebylo Občanské právo (Stránka 1) – Právní poradna ale Občanské právo – Právní poradna … tedy jde mi o to , aby z toho nadpisu zmizelo (Stránka 1) … za případnou odpověď velmi děkuji.

    P.S.: Skvělý plugin ten antispam!

  3. avatar pepak napsal:

    Antispam verze 0.02: Nedovolí uživateli nastavit si URL nebo podpis do doby, než bude mít tři schválené příspěvky (ochrana proti robotům, kteří se registrují jen proto, aby se v seznamu uživatelů zobrazil jejich odkaz).

  4. avatar pepak napsal:

    Když tak napiš, které, třeba by se daly opravit pluginem.

  5. avatar Danoboss napsal:

    No áno, ale ty asi svoje školské práce nevešiaš na web aby ich ľudia používali. Skrátka všetko má svoje pre a proti a u PunBB sa mi zdá, že vývojári asi iba chceli mať vo svojom portfóliu aj fórum. 🙁 Pretože sa mi zdá, že ho sami nepoužívajú, inak by niektoré drobnosti už opravili.

  6. avatar pepak napsal:

    PunBB ve mě přesně vyvolává ten pocit, který jsem měl u svých školních prací – „napíšu něco podobného, jako je XYZ, ale aby to bylo co nejjednodušší a přitom ještě použitelné“.

  7. avatar Danoboss napsal:

    Čo sa týka punBB, tak výhodou je, že sa dá naň migrovať z rozšíreného phpBB bez straty údajov v databáze. Bohužiaľ, čo chytilo na kvalite kódu to stráca na iných veciach typu „pozretie posledných používateľských príspevkov“… sú tam nedomyslené veci niektoré.

Leave a Reply

Themocracy iconWordPress Themes

css.php