PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/common/libraries/plugin/phpfreechat/src/pfccommand.class.php

https://bitbucket.org/renaatdemuynck/chamilo
PHP | 411 lines | 184 code | 42 blank | 185 comment | 29 complexity | 6cd93e5b0b770c8eb5583aae49ffafd5 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0
  1. <?php
  2. /**
  3. * pfccommand.class.php
  4. *
  5. * Copyright Š 2006 Stephane Gully <stephane.gully@gmail.com>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the
  19. * Free Software Foundation, 51 Franklin St, Fifth Floor,
  20. * Boston, MA 02110-1301 USA
  21. */
  22. require_once dirname(__FILE__) . "/pfci18n.class.php";
  23. require_once dirname(__FILE__) . "/pfcuserconfig.class.php";
  24. /**
  25. * pfcCommand is an abstract class (interface) which must be inherited by each concrete commands
  26. * Commands examples : /nick /me /update ...
  27. *
  28. * @example ../demo/demo27_customized_command.php
  29. * @author Stephane Gully <stephane.gully@gmail.com>
  30. */
  31. class pfcCommand
  32. {
  33. /**
  34. * Command name (lowercase)
  35. */
  36. var $name = '';
  37. /**
  38. * Contains the command syntaxe (how to use the command)
  39. */
  40. var $usage = '';
  41. /**
  42. * Not used for now
  43. */
  44. var $desc = '';
  45. var $help = '';
  46. /**
  47. * Used to instanciate a command
  48. * $tag is the command name : "nick", "me", "update" ...
  49. */
  50. function &Factory($name)
  51. {
  52. $c = & pfcGlobalConfig :: Instance();
  53. // instanciate the real command
  54. $cmd = NULL;
  55. $cmd_name = $name;
  56. $cmd_classname = "pfcCommand_" . $name;
  57. $cmd_filename = $c->cmd_path_default . '/' . $cmd_name . '.class.php';
  58. if (file_exists($cmd_filename))
  59. require_once ($cmd_filename);
  60. $cmd_filename = $c->cmd_path . '/' . $cmd_name . '.class.php';
  61. if (file_exists($cmd_filename))
  62. require_once ($cmd_filename);
  63. if (! class_exists($cmd_classname))
  64. {
  65. $tmp = NULL;
  66. return $tmp;
  67. }
  68. $cmd = & new $cmd_classname();
  69. $cmd->name = $cmd_name;
  70. // instanciate the proxies chaine
  71. $firstproxy = & $cmd;
  72. for($i = count($c->proxies) - 1; $i >= 0; $i --)
  73. {
  74. $proxy_name = $c->proxies[$i];
  75. $proxy_classname = "pfcProxyCommand_" . $proxy_name;
  76. // try to include the proxy class file from the default path or from the customized path
  77. $proxy_filename = $c->proxies_path_default . '/' . $proxy_name . ".class.php";
  78. if (file_exists($proxy_filename))
  79. require_once ($proxy_filename);
  80. $proxy_filename = $c->proxies_path . '/' . $proxy_name . ".class.php";
  81. if (file_exists($proxy_filename))
  82. require_once ($proxy_filename);
  83. if (! class_exists($proxy_classname))
  84. return $firstproxy;
  85. // instanciate the proxy
  86. $proxy = & new $proxy_classname();
  87. $proxy->name = $cmd_name;
  88. $proxy->proxyname = $proxy_name;
  89. $proxy->linkTo($firstproxy);
  90. $firstproxy = & $proxy;
  91. }
  92. /*
  93. $tmp = '';
  94. $cur = $firstproxy;
  95. while($cur)
  96. {
  97. $tmp .= (isset($cur->proxyname)?$cur->proxyname:$cur->name).'|';
  98. $cur = $cur->next;
  99. }
  100. $tmp .= var_export($firstproxy,true);
  101. file_put_contents('/tmp/debug1',$tmp);
  102. */
  103. // return the proxy, not the command (the proxy will forward the request to the real command)
  104. return $firstproxy;
  105. }
  106. /**
  107. * Constructor
  108. * @private
  109. */
  110. function __construct()
  111. {
  112. }
  113. /**
  114. * Virtual methode which must be implemented by concrete commands
  115. * It is called by the phpFreeChat::HandleRequest function to execute the wanted command
  116. */
  117. function run(&$xml_reponse, $p)
  118. {
  119. die(_pfc("%s must be implemented", get_class($this) . "::" . __FUNCTION__));
  120. }
  121. /**
  122. * Force whois reloading
  123. */
  124. function forceWhoisReload($nickid)
  125. {
  126. $c = & pfcGlobalConfig :: Instance();
  127. $u = & pfcUserConfig :: Instance();
  128. $ct = & pfcContainer :: Instance();
  129. // list the users in the same channel as $nickid
  130. $channels = $ct->getMeta("nickid-to-channelid", $nickid);
  131. $channels = $channels['value'];
  132. $channels = array_diff($channels, array('SERVER'));
  133. $otherids = array();
  134. foreach ($channels as $chan)
  135. {
  136. $ret = $ct->getOnlineNick($ct->decode($chan));
  137. $otherids = array_merge($otherids, $ret['nickid']);
  138. }
  139. // alert them that $nickid user info just changed
  140. foreach ($otherids as $otherid)
  141. {
  142. $cmdstr = 'whois2';
  143. $cmdp = array();
  144. $cmdp['params'] = array($nickid);
  145. pfcCommand :: AppendCmdToPlay($otherid, $cmdstr, $cmdp);
  146. /*
  147. $cmdtoplay = $ct->getUserMeta($otherid, 'cmdtoplay');
  148. $cmdtoplay = ($cmdtoplay == NULL) ? array() : unserialize($cmdtoplay);
  149. $cmdtmp = array("whois2", // cmdname
  150. $nicktorewhois, // param
  151. NULL, // sender
  152. NULL, // recipient
  153. NULL, // recipientid
  154. );
  155. if (!in_array($cmdtmp, $cmdtoplay))
  156. {
  157. $cmdtoplay[] = $cmdtmp;
  158. $ct->setUserMeta($otherid, 'cmdtoplay', serialize($cmdtoplay));
  159. }
  160. */
  161. }
  162. }
  163. /**
  164. * Add command to be played onto command stack
  165. * @param $nickid is the user that entered the command
  166. * @param $cmdstr is the command
  167. * @param $cmdp is the command's parameters
  168. * @return false if $nickid is blank, true for all other values of $nickid
  169. */
  170. function AppendCmdToPlay($nickid, $cmdstr, $cmdp)
  171. {
  172. $c = & pfcGlobalConfig :: Instance();
  173. $u = & pfcUserConfig :: Instance();
  174. $ct = & pfcContainer :: Instance();
  175. // check for empty nickid
  176. if ($nickid == "")
  177. return false;
  178. // get new command id
  179. $cmdtoplay_id = $ct->incMeta("nickid-to-cmdtoplayid", $nickid, 'cmdtoplayid');
  180. if (count($cmdtoplay_id["value"]) == 0)
  181. $cmdtoplay_id = 0;
  182. else
  183. $cmdtoplay_id = $cmdtoplay_id["value"][0];
  184. // create command array
  185. $cmdtoplay = array();
  186. $cmdtoplay['cmdstr'] = $cmdstr;
  187. $cmdtoplay['params'] = $cmdp;
  188. // store command to play
  189. $ct->setCmdMeta($nickid, $cmdtoplay_id, serialize($cmdtoplay));
  190. return true;
  191. }
  192. /**
  193. * Run all commands to be played for a user
  194. * @param $nickid is the user that entered the command
  195. * @param $context
  196. * @param $xml_reponse
  197. */
  198. function RunPendingCmdToPlay($nickid, $context, &$xml_reponse)
  199. {
  200. $c = & pfcGlobalConfig :: Instance();
  201. $u = & pfcUserConfig :: Instance();
  202. $ct = & pfcContainer :: Instance();
  203. // Get all queued commands to be played
  204. $cmdtoplay_ids = $ct->getCmdMeta($nickid);
  205. // process each command and parse content
  206. foreach ($cmdtoplay_ids as $cid)
  207. {
  208. // take a command from the list
  209. $cmdtoplay = $ct->getCmdMeta($nickid, $cid);
  210. $cmdtoplay = ($cmdtoplay == NULL || count($cmdtoplay) == 0) ? array() : unserialize($cmdtoplay[0]);
  211. // play the command
  212. $cmd = & pfcCommand :: Factory($cmdtoplay['cmdstr']);
  213. $cmdp = $cmdtoplay['params'];
  214. if (! isset($cmdp['param']))
  215. $cmdp['param'] = '';
  216. if (! isset($cmdp['sender']))
  217. $cmdp['sender'] = $context['sender'];
  218. if (! isset($cmdp['recipient']))
  219. $cmdp['recipient'] = $context['recipient'];
  220. if (! isset($cmdp['recipientid']))
  221. $cmdp['recipientid'] = $context['recipientid'];
  222. $cmdp['clientid'] = $context['clientid']; // the clientid must be the current user one
  223. $cmdp['cmdtoplay'] = true; // used to run some specials actions in the command (ex: if the cmdtoplay is a 'leave' command, then show an alert to the kicked or banished user)
  224. if ($c->debug)
  225. $cmd->run($xml_reponse, $cmdp);
  226. else
  227. @$cmd->run($xml_reponse, $cmdp);
  228. // delete command when complete
  229. $ct->rmMeta("nickid-to-cmdtoplay", $nickid, $cid);
  230. }
  231. }
  232. function trace(&$xml_reponse, $msg, $data = NULL)
  233. {
  234. if ($data != NULL)
  235. {
  236. require_once dirname(__FILE__) . '/pfcjson.class.php';
  237. $json = new pfcJSON();
  238. $js = $json->encode($data);
  239. $xml_reponse->script("trace('" . $msg . " -> " . $js . "');");
  240. }
  241. else
  242. $xml_reponse->script("trace('" . $msg . "');");
  243. }
  244. function ParseCommand($cmd_str, $one_parameter = false)
  245. {
  246. $pattern_quote = '/([^\\\]|^)"([^"]+[^\\\])"/';
  247. $pattern_quote = '/"([^"]+)"/';
  248. $pattern_noquote = '/([^"\s]+)/';
  249. $pattern_command = '/^\/([a-z0-9]+)\s*([a-z0-9]+)\s*([a-z0-9]+)\s*(.*)/';
  250. $result = array();
  251. // parse the command name (ex: '/invite')
  252. if (preg_match($pattern_command, $cmd_str, $res))
  253. {
  254. $cmd = $res[1];
  255. $clientid = $res[2];
  256. $recipientid = $res[3];
  257. $params_str = $res[4];
  258. // don't parse multiple parameters for special commands with only one parameter
  259. // this make possible to send double quotes (") in these commands
  260. if ($one_parameter || $cmd == 'send' || $cmd == 'notice' || $cmd == 'me')
  261. {
  262. $result['cmdstr'] = $cmd_str;
  263. $result['cmdname'] = $cmd;
  264. $result['params'] = array($clientid, $recipientid, $params_str);
  265. return $result;
  266. }
  267. // parse the quotted parameters (ex: '/invite "nickname with spaces"')
  268. preg_match_all($pattern_quote, $params_str, $res1, PREG_OFFSET_CAPTURE);
  269. $params_res = $res1[1];
  270. // split the parameters string
  271. $nospaces = preg_split($pattern_quote, $params_str, - 1, PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY);
  272. foreach ($nospaces as $p)
  273. {
  274. // parse the splited blocks with unquotted parameter pattern (ex: '/invite nicknamewithoutspace')
  275. preg_match_all($pattern_noquote, $p[0], $res2, PREG_OFFSET_CAPTURE);
  276. foreach ($res2[1] as $p2)
  277. {
  278. $p2[1] += $p[1];
  279. $params_res[] = $p2;
  280. }
  281. }
  282. // order the array by offset
  283. $params = array();
  284. foreach ($params_res as $p)
  285. $params[$p[1]] = $p[0];
  286. ksort($params);
  287. $params = array_values($params);
  288. $params = array_map("trim", $params);
  289. $params = array_merge(array($clientid, $recipientid), $params);
  290. $result['cmdstr'] = $cmd_str;
  291. $result['cmdname'] = $cmd;
  292. $result['params'] = $params;
  293. }
  294. return $result;
  295. }
  296. /*
  297. // THIS IS ANOTHER WAY TO PARSE THE PARAMETERS
  298. // IT'S NOT SIMPLIER BUT MAYBE FASTER
  299. // @todo : take the faster methode
  300. function ParseCommand($cmd_str, $one_parameter = false)
  301. {
  302. $pattern_command = '/^\/([a-z0-9]+)\s*([a-z0-9]+)\s*([a-z0-9]+)\s*(.*)/';
  303. $result = array();
  304. // parse the command name (ex: '/invite')
  305. if (preg_match($pattern_command, $cmd_str, $res))
  306. {
  307. $cmd = $res[1];
  308. $clientid = $res[2];
  309. $recipientid = $res[3];
  310. $params_str = $res[4];
  311. // don't parse multiple parameters for special commands with only one parameter
  312. // this make possible to send double quotes (") in these commands
  313. if ($one_parameter || $cmd == 'send' || $cmd == 'notice' || $cmd == 'me')
  314. {
  315. $result['cmdstr'] = $cmd_str;
  316. $result['cmdname'] = $cmd;
  317. $result['params'] = array($clientid, $recipientid, $params_str);
  318. return $result;
  319. }
  320. $params = array($clientid, $recipientid);
  321. $sep = preg_match('/[^\\\\]"/',$params_str) ? '"' : ' ';
  322. if ($sep == ' ') $params_str = ' ' . $params_str;
  323. $offset = 0;
  324. while (1)
  325. {
  326. $i1 = strpos($params_str,$sep,$offset);
  327. // capture the parameter value
  328. if ($i1 !== FALSE)
  329. {
  330. // remove multi-separators
  331. while (1)
  332. {
  333. if (strpos($params_str,$sep,$i1+1) - $i1 == 1)
  334. $i1++;
  335. else
  336. break;
  337. }
  338. // search the parameter terminason
  339. $offset = $i1+1;
  340. $i2 = strpos($params_str,$sep,$offset);
  341. if ($i2 !== FALSE)
  342. {
  343. $offset = $i2 + ($sep == '"' ? 1 : 0);
  344. $p = substr($params_str, $i1+1, $i2-$i1-1);
  345. if (!preg_match('/^\s*$/',$p))
  346. $params[] = $p;
  347. }
  348. else
  349. break;
  350. }
  351. else
  352. break;
  353. }
  354. // append the tail
  355. if ($offset < strlen($params_str))
  356. $params[] = substr($params_str,$offset);
  357. $result['cmdstr'] = $cmd_str;
  358. $result['cmdname'] = $cmd;
  359. $result['params'] = $params;
  360. }
  361. return $result;
  362. }
  363. */
  364. }
  365. ?>