//structure class channel { public $name; public $ci = null; public $creation_time; public $topic = null; //array('topic' => '', 'by' => '', 'at' => 0); public $modes = null; public $bans = null; public $excepts = null; public $invex = null; public $userlist = array(); // array( 'user' => &$u, 'modes' => new cumodes, 'flags' => 0 ); public $tag = 0; //1-nethack;2-forbidden;4-suspended function __construct () { $this->modes = new cmodes($this); $this->bans =& $this->modes->lb; $this->excepts =& $this->modes->le; $this->invex =& $this->modes->ui; } function destroy() { global $i, $channels; run_callback('destroy_chan',$i,$this); unset($channels[strtolower($this->name)]); } } class cumodes { //public $q = false, $a = false, $o = false, $h = false, $v = false; protected $channel, $user; public function __construct(channel &$channel, user &$user) { //if ($channel instanceof channel) $this->channel =& $channel; $this->user =& $user; } public function __set ( $name, $value ) { if (!isset($this->$name)) { return error_log("error setting mode $name for cumode"); } $mm = "l".$name; if ($value) $this->channel->modes->$mm[$this->user->lnick()] =& $this->user; else unset($this->channel->modes->$mm[$this->user->lnick()]); } public function __get ( $name ) { if (!isset($this->$name)) { return error_log("error setting mode $name for cumode"); } $mm = "l".$name; return array_key_exists($this->user->lnick(), $this->channel->modes->$mm); } public function __isset ( $name ) { return in_array($name,array('q','a','o','h','v')); } } class cmodes { private $parent = null; public $lb = array(), $le = array(), $ui = array(); public $lq = array(), $la = array(), $lo = array(), $lh = array(), $lv = array(); public $lc = false, $lf = false, $li = false, $lj = false, $lk = false, $ll = false, $lm = false, $ln = false, $lp = false, $lr = false, $ls = false, $lt = false, $lz = false, $ua = false, $uc = false, $ug = false, $um = false, $uk = false, $ul = false, $un = false, $uo = false, $uq = false, $ur = false, $us = false, $ut = false, $uv = false, $lu = false; function __construct(&$parent) { $this->parent =& $parent; } function cmodetype ($mode) { if (in_array($mode,array('c','i','m','n','p','r','s','t','z','A','C','G','M','K','N','O','Q','R','S','T','V','u'))) return CM_BOO; if (in_array($mode,array('l'))) return CM_INT; if (in_array($mode,array('k','L'))) return CM_STR; if (in_array($mode,array('j'))) return CM_ARR; if (in_array($mode,array('f'))) return CM_FLD; if (in_array($mode,array('q','a','o','h','v'))) return CM_USR; if (in_array($mode,array('b','e','I'))) return CM_WLD; return 0; } function apply($modes, $realworld = true, &$cleanmodes = '', &$cleanpars = array()) { //apply ( str $modes e.g. +nt-f+Q, bool $realworld is sandbox or is protocol ... ) global $users; $modes = firstword($modes, $params); $params = explode(' ',trim($params)); $plus = true; for ($i = 0; $i < strlen($modes); ++$i) { if ($modes{$i} == '+') { $plus = true; if ($i and in_array($modes{$i-1},array('+','-'))) $cleanmodes = substr($cleanmodes,0,-1); $cleanmodes .= '+'; continue; } if ($modes{$i} == '-') { $plus = false; if ($i and in_array($modes{$i-1},array('+','-'))) $cleanmodes = substr($cleanmodes,0,-1); $cleanmodes .= '-'; continue; } $mm = (abs(strcmp($modes{$i},strtolower($modes{$i}))) ? 'u' : 'l') . strtolower($modes{$i}); $mt = $this->cmodetype($modes{$i}); if (!$mt) { errlog("{$this->parent->name}->apply","Unknown mode {$modes{$i}}"); if ($realworld) return; continue; } if ($mt == CM_BOO) { if ($this->$mm != $plus) $cleanmodes .= $modes{$i}; $this->$mm = $plus; } elseif (!$plus and $mt <= CM_FLD) { if ($this->$mm) { $cleanmodes .= $modes{$i}; if ($mm == 'lk') { //stupid stupid unreal $cleanpars[] = $this->$mm; } } $this->$mm = false; } else { if ($this->$mm === false and $mt < CM_FLD) { $cleanmodes .= $modes{$i}; $cleanpars[] = current($params); } switch ($mt) { case CM_INT: $this->$mm = (int)current($params); break; case CM_STR: $this->$mm = current($params); break; case CM_ARR: $this->$mm = explode(':',current($params),2); break; case CM_FLD: if (!preg_match('/^\[[0-9]*[cjkmnt](#[CmMiRKNb][0-9]*)?(,[0-9]*[cjkmnt](#[CmMiRKNb][0-9]*)?)*\]:[0-9]+$/',current($params))) { //if ($realworld) throw new Exception("Bad CM_FLD ".current($params)."; Referenced at {$this->parent->name}->apply"); errlog("{$this->parent->name}->apply","Bad CM_FLD ".current($params)); continue; } $this->$mm = current($params); break; case CM_USR: if (!ake(strtolower(current($params)),$users)) { errlog("{$this->parent->name}->apply","Unknown user ".current($params)." not in \$users"); //if ($realworld) return; next($params); continue; } if (!ake(strtolower(current($params)),$this->parent->userlist)) { //if ($realworld) throw new Exception("Unknown user ".current($params)."; Not found in channel userlist; Referenced at {$this->parent->name}->apply"); errlog("{$this->parent->name}->apply","Unknown user ".current($params)." not in channel userlist"); next($params); continue; } if (($plus and !ake(strtolower(current($params)),$this->$mm)) or (!$plus and ake(strtolower(current($params)),$this->$mm))) { $cleanmodes .= $modes{$i}; $cleanpars[] = current($params); } $thismm =& $this->$mm; if ($plus) { $thismm[strtolower(current($params))] =& $users[strtolower(current($params))]; } else { unset($thismm[strtolower(current($params))]); } //$this->parent->userlist[strtolower(current($params))]['modes']->$modes{$i} = $plus; break; case CM_WLD: if ($plus and !ake(strtolower(current($params)),$this->$mm)) { $cleanmodes .= $modes{$i}; $cleanpars[] = current($params); $this->{$mm}[strtolower(current($params))] = current($params); } elseif (!$plus and ake(strtolower(current($params)),$this->$mm)) { $cleanmodes .= $modes{$i}; $cleanpars[] = current($params); unset($this->{$mm}[strtolower(current($params))]); } break; } if ($mt != CM_BOO and $mt != CM_USR and $this->$mm) { $cleanmodes .= $modes{$i}; $cleanpars[] = current($params); } if ($mt and $mt != CM_BOO) next($params); } } $cleanmodes = rtrim($cleanmodes,'+-'); } } //------------------------------------------------------------------------------ // on nick change } else { $newnick = firstword($par,$ts); global $users; if (!ake(strtolower($source),$users)) return "didn't find user $source; nick change to $newnick failed"; last_corruptor_check($users[strtolower($source)],$this); $u =& $users[strtolower($source)]; run_callback('newnick',$this,$u,$newnick); $u->nick = $newnick; $u->signon = $ts; $users[$u->lnick()] =& $u; unset($users[strtolower($source)]); $servusers =& $u->server->users; $servusers[$u->lnick()] =& $u; unset($servusers[strtolower($source)]); foreach($u->channels as &$chan) { $chan->userlist[$u->lnick()] =& $chan->userlist[strtolower($source)]; /*array('user' => &$u, 'modes' => $chan->userlist[strtolower($source)]['modes'], 'flags' => $chan->userlist[strtolower($source)]['flags']);*/ //$chan->userlist[strtolower($source)]['modes'] = new cumodes(); unset($chan->userlist[strtolower($source)]); if (ake(strtolower($source),$chan->userlist)) return "failed to clean up at $chan->name for $source >> $u->nick"; foreach (array('lq','la','lo','lh','lv') as $mm) { if (!ake(strtolower($source),$chan->modes->$mm)) continue; $chan->modes->$mm[$u->lnick()] =& $u; unset($chan->modes->$mm[strtolower($source)]); } } }