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