Spúšťanie systémových programov
Občas môžeme potrebovať spustiť nejaký systémový program na počítači, na ktorom je bot spustený. Môže nám to ušetriť prácu, napríklad keď si nebudeme písať vlastný program pre výpis súborov v priečinku ale použijeme program ls (predpokladám že bot bude spustený na počítači s linuxom). Môžeme si dokonca vytvoriť modul, pomocou ktorého zmeníme bota na „príkazový riadok“. Každá správa bude znamenať príkaz, ktorý ma bot spustiť. Štandardný výstup programu nám pošle ako správu.
Príkaz exec
Pomocou príkazu exec (execute – vykonať) budeme, ako som už spomenul vyššie, spúšťat systémové príkazy, ktorých výstup nám bot odošle ako správu. Vytvoríme si súbor exec v priečinku commands:
<?php
if (preg_match("/^\!exec (.*)$/", $message, $match)){
$o = shell_exec($match[1]);
$o = explode("\n", $o);
foreach ($o as $row){
sendmsg($act_chan, $row);
usleep(200000);
}
}
?>
Najprv sa uloží všetko za !exec (napr. !exec ls) do $match[1]. Obsah tejto premennej sa spustí ako systémový príkaz pomocou funkcie shell_exec, ktorej výstup uložíme do $o. Tú následne rozdelíme po riadkoch a tie odošleme naspäť.
Toto riešenie je ale veľmi nebezpečné, pretože dovoľuje spustiť akékoľvek programy. Preto je potrebné zaviesť zoznam povolených príkazov. V priečinku, v ktorom máme „jadro“ bota, vytvorme súbor s názvom napr. „povolene“. Jeho obsah bude takýto:
<?php
$allow[] = '/^date$/';
$allow[] = '/^ping [a-z\.]+ \-c 3$/';
$allow[] = '/^pwd$/';
$allow[] = '/^uptime$/';
$allow[] = '/^ls$/';
$allow[] = '/^figlet [a-zA-Z0-9 ]+( \-f [a-z]+)?$/';
$allow[] = '/^cal( \-3)?$/';
?>
Ako vidíte, do polí premennej $allow uložíme zoznam regulárnych výrazov, ktorým ak bude príkaz odpovedať, bude sa môcť spustiť. Upravíme súbor exec, aby všetky príkazy preveroval.
<?php
include("povolene");
if (preg_match("/^\!exec (.*)$/", $message, $match)){
foreach ($allow as $command){
if (preg_match($command, $match[1]) || $sender=="VAS_NICK"){ //ak bude odpovedať regulárnemu výrazu, alebo ak sme príkaz poslali my
$o = shell_exec($match[1]);
$o = explode("\n", $o);
foreach ($o as $row){
sendmsg($act_chan, $row);
usleep(200000);
}
break; //Ak bol uz prikaz spusteny, ukoncime cyklus foreach
}
}
}
unset($allow);
?>
Vytvoríme ešte príkaz na výpis povolených systémových príkazov. Nazvime ho napríklad „povolene“.
<?php
include("povolene");
foreach ($allow as $command){
sendmsg($act_chan, $command);
usleep(200000);
}
unset($allow);
?>
Shell
Vytvoríme si súbor shell v priečinku modules. Shell aktivujeme poslanim správy botovi s obsahom SHEL_MODE ON. (bot: SHELL_MODE ON). Vypneme ho podobným spôsobom, nahradením OFF za ON. Bez parametru bot vypíše, či je shell zapnutý alebo vypnutý. Vykonávané príkazy nekontrolujeme, keďže bot prijíma príkazy iba od nás (treba dávať pozor na zmenu nicku).
<?php
if (!isset($shell_mode)) $shell_mode = '';
if ($sender=='VAS_NICK' && $message==$nick.': SHELL_MODE ON'){
$shell_mode = 'on';
sendmsg($act_chan, 'SHELL MODE IS ON');
}
if ($sender=='VAS_NICK' && $message==$nick.': SHELL_MODE OFF'){
$shell_mode = '';
sendmsg($act_chan, 'SHELL MODE IS OFF');
}
if ($sender=='VAS_NICK' && $message==$nick.': SHELL_MODE'){
sendmsg($act_chan, 'SHELL MODE IS '.(($shell_mode=='on') ? 'ON' : 'OFF'));
}
if ($shell_mode=="on" && $sender=='VAS_NICK'){
if (!isset($pwd)) $pwd = shell_exec('pwd');
$o = shell_exec("cd $pwd\n".$message);
$o = explode("\n", $o);
foreach ($o as $row){
$row = trim($row);
if (empty($row)) continue;
sendmsg($act_chan, $row);
sleep(1);
}
if (preg_match("/cd (.*)$/", $message, $match)){
$pwd = trim(exec("cd \"$pwd\";cd {$match[1]};pwd"));
sendmsg($act_chan, $pwd);
}
}
?>
Vysvetlíme si iba načo slúži premenná $pwd. Pri práci sa bežne pohybujeme medzi rôznymi priečinkami. A keďže si funkcia shell_exec nepamätá, v ktorom priečinku sme skončili pri jej poslednom použití, musíme najprv vykonať príkaz pre zmenu pracovného priečinka na taký, aký sme mali pri minulom použití funkcie shell_exec. Tento priečinok (jeho umiestnenie) sa ukladá do premennej $pwd.
$o = shell_exec("cd $pwd\n".$message);
Vždy, keď sa použije príkaz cd (change directory), musíme premennú $pwd zmeniť. Najprv vojdeme do priečinka kde sme boli minule, vykonáme príkaz cd a použijeme príkaz pwd, ktorý vypisuje aktualny adresár a ten si opäť uložíme do $pwd.
$pwd = trim(exec("cd \"$pwd\";cd {$match[1]};pwd"));