PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/chamilo/chamilo/
PHP | 401 lines | 170 code | 46 blank | 185 comment | 29 complexity | 4cc2e5bd87c2088563dbdca3c2874ea5 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  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)) require_once($cmd_filename);
  59. $cmd_filename = $c->cmd_path.'/'.$cmd_name.'.class.php';
  60. if (file_exists($cmd_filename)) require_once($cmd_filename);
  61. if (!class_exists($cmd_classname)) { $tmp = NULL; return $tmp; }
  62. $cmd =& new $cmd_classname;
  63. $cmd->name = $cmd_name;
  64. // instanciate the proxies chaine
  65. $firstproxy =& $cmd;
  66. for($i = count($c->proxies)-1; $i >= 0; $i--)
  67. {
  68. $proxy_name = $c->proxies[$i];
  69. $proxy_classname = "pfcProxyCommand_" . $proxy_name;
  70. // try to include the proxy class file from the default path or from the customized path
  71. $proxy_filename = $c->proxies_path_default.'/'.$proxy_name.".class.php";
  72. if (file_exists($proxy_filename)) require_once($proxy_filename);
  73. $proxy_filename = $c->proxies_path.'/'.$proxy_name.".class.php";
  74. if (file_exists($proxy_filename)) require_once($proxy_filename);
  75. if (!class_exists($proxy_classname))
  76. return $firstproxy;
  77. // instanciate the proxy
  78. $proxy =& new $proxy_classname;
  79. $proxy->name = $cmd_name;
  80. $proxy->proxyname = $proxy_name;
  81. $proxy->linkTo($firstproxy);
  82. $firstproxy =& $proxy;
  83. }
  84. /*
  85. $tmp = '';
  86. $cur = $firstproxy;
  87. while($cur)
  88. {
  89. $tmp .= (isset($cur->proxyname)?$cur->proxyname:$cur->name).'|';
  90. $cur = $cur->next;
  91. }
  92. $tmp .= var_export($firstproxy,true);
  93. file_put_contents('/tmp/debug1',$tmp);
  94. */
  95. // return the proxy, not the command (the proxy will forward the request to the real command)
  96. return $firstproxy;
  97. }
  98. /**
  99. * Constructor
  100. * @private
  101. */
  102. function __construct()
  103. {
  104. }
  105. /**
  106. * Virtual methode which must be implemented by concrete commands
  107. * It is called by the phpFreeChat::HandleRequest function to execute the wanted command
  108. */
  109. function run(&$xml_reponse, $p)
  110. {
  111. die(_pfc("%s must be implemented", get_class($this)."::".__FUNCTION__));
  112. }
  113. /**
  114. * Force whois reloading
  115. */
  116. function forceWhoisReload($nickid)
  117. {
  118. $c =& pfcGlobalConfig::Instance();
  119. $u =& pfcUserConfig::Instance();
  120. $ct =& pfcContainer::Instance();
  121. // list the users in the same channel as $nickid
  122. $channels = $ct->getMeta("nickid-to-channelid", $nickid);
  123. $channels = $channels['value'];
  124. $channels = array_diff($channels, array('SERVER'));
  125. $otherids = array();
  126. foreach($channels as $chan)
  127. {
  128. $ret = $ct->getOnlineNick($ct->decode($chan));
  129. $otherids = array_merge($otherids, $ret['nickid']);
  130. }
  131. // alert them that $nickid user info just changed
  132. foreach($otherids as $otherid)
  133. {
  134. $cmdstr = 'whois2';
  135. $cmdp = array();
  136. $cmdp['params'] = array($nickid);
  137. pfcCommand::AppendCmdToPlay($otherid, $cmdstr, $cmdp);
  138. /*
  139. $cmdtoplay = $ct->getUserMeta($otherid, 'cmdtoplay');
  140. $cmdtoplay = ($cmdtoplay == NULL) ? array() : unserialize($cmdtoplay);
  141. $cmdtmp = array("whois2", // cmdname
  142. $nicktorewhois, // param
  143. NULL, // sender
  144. NULL, // recipient
  145. NULL, // recipientid
  146. );
  147. if (!in_array($cmdtmp, $cmdtoplay))
  148. {
  149. $cmdtoplay[] = $cmdtmp;
  150. $ct->setUserMeta($otherid, 'cmdtoplay', serialize($cmdtoplay));
  151. }
  152. */
  153. }
  154. }
  155. /**
  156. * Add command to be played onto command stack
  157. * @param $nickid is the user that entered the command
  158. * @param $cmdstr is the command
  159. * @param $cmdp is the command's parameters
  160. * @return false if $nickid is blank, true for all other values of $nickid
  161. */
  162. function AppendCmdToPlay($nickid, $cmdstr, $cmdp)
  163. {
  164. $c =& pfcGlobalConfig::Instance();
  165. $u =& pfcUserConfig::Instance();
  166. $ct =& pfcContainer::Instance();
  167. // check for empty nickid
  168. if ($nickid == "") return false;
  169. // get new command id
  170. $cmdtoplay_id = $ct->incMeta("nickid-to-cmdtoplayid", $nickid, 'cmdtoplayid');
  171. if (count($cmdtoplay_id["value"]) == 0)
  172. $cmdtoplay_id = 0;
  173. else
  174. $cmdtoplay_id = $cmdtoplay_id["value"][0];
  175. // create command array
  176. $cmdtoplay = array();
  177. $cmdtoplay['cmdstr'] = $cmdstr;
  178. $cmdtoplay['params'] = $cmdp;
  179. // store command to play
  180. $ct->setCmdMeta($nickid, $cmdtoplay_id, serialize($cmdtoplay));
  181. return true;
  182. }
  183. /**
  184. * Run all commands to be played for a user
  185. * @param $nickid is the user that entered the command
  186. * @param $context
  187. * @param $xml_reponse
  188. */
  189. function RunPendingCmdToPlay($nickid, $context, &$xml_reponse)
  190. {
  191. $c =& pfcGlobalConfig::Instance();
  192. $u =& pfcUserConfig::Instance();
  193. $ct =& pfcContainer::Instance();
  194. // Get all queued commands to be played
  195. $cmdtoplay_ids = $ct->getCmdMeta($nickid);
  196. // process each command and parse content
  197. foreach ( $cmdtoplay_ids as $cid )
  198. {
  199. // take a command from the list
  200. $cmdtoplay = $ct->getCmdMeta($nickid, $cid);
  201. $cmdtoplay = ($cmdtoplay == NULL || count($cmdtoplay) == 0) ? array() : unserialize($cmdtoplay[0]);
  202. // play the command
  203. $cmd =& pfcCommand::Factory($cmdtoplay['cmdstr']);
  204. $cmdp = $cmdtoplay['params'];
  205. if (!isset($cmdp['param'])) $cmdp['param'] = '';
  206. if (!isset($cmdp['sender'])) $cmdp['sender'] = $context['sender'];
  207. if (!isset($cmdp['recipient'])) $cmdp['recipient'] = $context['recipient'];
  208. if (!isset($cmdp['recipientid'])) $cmdp['recipientid'] = $context['recipientid'];
  209. $cmdp['clientid'] = $context['clientid']; // the clientid must be the current user one
  210. $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)
  211. if ($c->debug)
  212. $cmd->run($xml_reponse, $cmdp);
  213. else
  214. @$cmd->run($xml_reponse, $cmdp);
  215. // delete command when complete
  216. $ct->rmMeta("nickid-to-cmdtoplay", $nickid, $cid);
  217. }
  218. }
  219. function trace(&$xml_reponse, $msg, $data = NULL)
  220. {
  221. if ($data != NULL)
  222. {
  223. require_once dirname(__FILE__).'/pfcjson.class.php';
  224. $json = new pfcJSON();
  225. $js = $json->encode($data);
  226. $xml_reponse->script("trace('".$msg." -> ".$js."');");
  227. }
  228. else
  229. $xml_reponse->script("trace('".$msg."');");
  230. }
  231. function ParseCommand($cmd_str, $one_parameter = false)
  232. {
  233. $pattern_quote = '/([^\\\]|^)"([^"]+[^\\\])"/';
  234. $pattern_quote = '/"([^"]+)"/';
  235. $pattern_noquote = '/([^"\s]+)/';
  236. $pattern_command = '/^\/([a-z0-9]+)\s*([a-z0-9]+)\s*([a-z0-9]+)\s*(.*)/';
  237. $result = array();
  238. // parse the command name (ex: '/invite')
  239. if (preg_match($pattern_command, $cmd_str, $res))
  240. {
  241. $cmd = $res[1];
  242. $clientid = $res[2];
  243. $recipientid = $res[3];
  244. $params_str = $res[4];
  245. // don't parse multiple parameters for special commands with only one parameter
  246. // this make possible to send double quotes (") in these commands
  247. if ($one_parameter || $cmd == 'send' || $cmd == 'notice' || $cmd == 'me')
  248. {
  249. $result['cmdstr'] = $cmd_str;
  250. $result['cmdname'] = $cmd;
  251. $result['params'] = array($clientid, $recipientid, $params_str);
  252. return $result;
  253. }
  254. // parse the quotted parameters (ex: '/invite "nickname with spaces"')
  255. preg_match_all($pattern_quote,$params_str,$res1,PREG_OFFSET_CAPTURE);
  256. $params_res = $res1[1];
  257. // split the parameters string
  258. $nospaces = preg_split($pattern_quote,$params_str,-1,PREG_SPLIT_OFFSET_CAPTURE|PREG_SPLIT_NO_EMPTY);
  259. foreach($nospaces as $p)
  260. {
  261. // parse the splited blocks with unquotted parameter pattern (ex: '/invite nicknamewithoutspace')
  262. preg_match_all($pattern_noquote,$p[0],$res2,PREG_OFFSET_CAPTURE);
  263. foreach( $res2[1] as $p2 )
  264. {
  265. $p2[1] += $p[1];
  266. $params_res[] = $p2;
  267. }
  268. }
  269. // order the array by offset
  270. $params = array();
  271. foreach($params_res as $p) $params[$p[1]] = $p[0];
  272. ksort($params);
  273. $params = array_values($params);
  274. $params = array_map("trim",$params);
  275. $params = array_merge(array($clientid,$recipientid), $params);
  276. $result['cmdstr'] = $cmd_str;
  277. $result['cmdname'] = $cmd;
  278. $result['params'] = $params;
  279. }
  280. return $result;
  281. }
  282. /*
  283. // THIS IS ANOTHER WAY TO PARSE THE PARAMETERS
  284. // IT'S NOT SIMPLIER BUT MAYBE FASTER
  285. // @todo : take the faster methode
  286. function ParseCommand($cmd_str, $one_parameter = false)
  287. {
  288. $pattern_command = '/^\/([a-z0-9]+)\s*([a-z0-9]+)\s*([a-z0-9]+)\s*(.*)/';
  289. $result = array();
  290. // parse the command name (ex: '/invite')
  291. if (preg_match($pattern_command, $cmd_str, $res))
  292. {
  293. $cmd = $res[1];
  294. $clientid = $res[2];
  295. $recipientid = $res[3];
  296. $params_str = $res[4];
  297. // don't parse multiple parameters for special commands with only one parameter
  298. // this make possible to send double quotes (") in these commands
  299. if ($one_parameter || $cmd == 'send' || $cmd == 'notice' || $cmd == 'me')
  300. {
  301. $result['cmdstr'] = $cmd_str;
  302. $result['cmdname'] = $cmd;
  303. $result['params'] = array($clientid, $recipientid, $params_str);
  304. return $result;
  305. }
  306. $params = array($clientid, $recipientid);
  307. $sep = preg_match('/[^\\\\]"/',$params_str) ? '"' : ' ';
  308. if ($sep == ' ') $params_str = ' ' . $params_str;
  309. $offset = 0;
  310. while (1)
  311. {
  312. $i1 = strpos($params_str,$sep,$offset);
  313. // capture the parameter value
  314. if ($i1 !== FALSE)
  315. {
  316. // remove multi-separators
  317. while (1)
  318. {
  319. if (strpos($params_str,$sep,$i1+1) - $i1 == 1)
  320. $i1++;
  321. else
  322. break;
  323. }
  324. // search the parameter terminason
  325. $offset = $i1+1;
  326. $i2 = strpos($params_str,$sep,$offset);
  327. if ($i2 !== FALSE)
  328. {
  329. $offset = $i2 + ($sep == '"' ? 1 : 0);
  330. $p = substr($params_str, $i1+1, $i2-$i1-1);
  331. if (!preg_match('/^\s*$/',$p))
  332. $params[] = $p;
  333. }
  334. else
  335. break;
  336. }
  337. else
  338. break;
  339. }
  340. // append the tail
  341. if ($offset < strlen($params_str))
  342. $params[] = substr($params_str,$offset);
  343. $result['cmdstr'] = $cmd_str;
  344. $result['cmdname'] = $cmd;
  345. $result['params'] = $params;
  346. }
  347. return $result;
  348. }
  349. */
  350. }
  351. ?>