.TH "channels.cpp" 3 "14 Dec 2005" "Version 1.0Betareleases" "InspIRCd" \" -*- nroff -*- .ad l .nh .SH NAME channels.cpp \- .SH SYNOPSIS .br .PP \fC#include 'inspircd_config.h'\fP .br \fC#include 'inspircd.h'\fP .br \fC#include 'inspircd_io.h'\fP .br \fC#include 'inspircd_util.h'\fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include \fP .br \fC#include 'users.h'\fP .br \fC#include 'ctables.h'\fP .br \fC#include 'globals.h'\fP .br \fC#include 'modules.h'\fP .br \fC#include 'dynamic.h'\fP .br \fC#include 'commands.h'\fP .br \fC#include 'wildcard.h'\fP .br \fC#include 'message.h'\fP .br \fC#include 'mode.h'\fP .br \fC#include 'xline.h'\fP .br \fC#include 'inspstring.h'\fP .br \fC#include 'helperfuncs.h'\fP .br \fC#include 'typedefs.h'\fP .br .SS "Namespaces" .in +1c .ti -1c .RI "namespace \fBstd\fP" .br .in -1c .SS "Defines" .in +1c .ti -1c .RI "#define \fBnspace\fP std" .br .in -1c .SS "Functions" .in +1c .ti -1c .RI "\fBchanrec\fP * \fBForceChan\fP (\fBchanrec\fP *Ptr, \fBucrec\fP &a, \fBuserrec\fP *user, int created)" .br .ti -1c .RI "\fBchanrec\fP * \fBadd_channel\fP (\fBuserrec\fP *user, const char *cn, const char *key, bool override)" .br .ti -1c .RI "\fBchanrec\fP * \fBdel_channel\fP (\fBuserrec\fP *user, const char *cname, const char *reason, bool local)" .br .ti -1c .RI "void \fBkick_channel\fP (\fBuserrec\fP *src, \fBuserrec\fP *user, \fBchanrec\fP *Ptr, char *reason)" .br .in -1c .SS "Variables" .in +1c .ti -1c .RI "\fBServerConfig\fP * \fBConfig\fP" .br .ti -1c .RI "int \fBMODCOUNT\fP = -1" .br .ti -1c .RI "std::vector< \fBModule\fP * > \fBmodules\fP" .br .ti -1c .RI "std::vector< \fBircd_module\fP * > \fBfactory\fP" .br .ti -1c .RI "int \fBWHOWAS_STALE\fP" .br .ti -1c .RI "int \fBWHOWAS_MAX\fP" .br .ti -1c .RI "time_t \fBTIME\fP" .br .ti -1c .RI "\fBchan_hash\fP \fBchanlist\fP" .br .ti -1c .RI "std::vector< \fBModeParameter\fP > \fBcustom_mode_params\fP" .br .in -1c .SH "Define Documentation" .PP .SS "#define nspace std" .PP Definition at line 55 of file channels.cpp. .SH "Function Documentation" .PP .SS "\fBchanrec\fP* add_channel (\fBuserrec\fP * user, const char * cn, const char * key, bool override)" .PP Definition at line 195 of file channels.cpp. .PP References chanrec::bans, chanrec::binarymodes, chanlist, userrec::chans, CM_INVITEONLY, CM_NOEXTERNAL, CM_TOPICLOCK, DEBUG, DEFAULT, connection::fd, FindChan(), ForceChan(), FOREACH_RESULT, userrec::GetFullHost(), has_channel(), userrec::IsInvited(), chanrec::key, chanrec::limit, log(), userrec::modes, chanrec::name, userrec::nick, userrec::RemoveInvite(), TIME, and WriteServ(). .PP Referenced by Server::JoinUserToChannel(). .PP .nf 196 { 197 if ((!user) || (!cn)) 198 { 199 log(DEFAULT,'*** BUG *** add_channel was given an invalid parameter'); 200 return 0; 201 } 202 203 int created = 0; 204 char cname[MAXBUF]; 205 int MOD_RESULT = 0; 206 strncpy(cname,cn,CHANMAX); 207 208 log(DEBUG,'add_channel: %s %s',user->nick,cname); 209 210 chanrec* Ptr = FindChan(cname); 211 212 if (!Ptr) 213 { 214 if (user->fd > -1) 215 { 216 MOD_RESULT = 0; 217 FOREACH_RESULT(OnUserPreJoin(user,NULL,cname)); 218 if (MOD_RESULT == 1) 219 return NULL; 220 } 221 /* create a new one */ 222 chanlist[cname] = new chanrec(); 223 strlcpy(chanlist[cname]->name, cname,CHANMAX); 224 chanlist[cname]->binarymodes = CM_TOPICLOCK | CM_NOEXTERNAL; 225 chanlist[cname]->created = TIME; 226 strcpy(chanlist[cname]->topic, ''); 227 strncpy(chanlist[cname]->setby, user->nick,NICKMAX); 228 chanlist[cname]->topicset = 0; 229 Ptr = chanlist[cname]; 230 log(DEBUG,'add_channel: created: %s',cname); 231 /* set created to 2 to indicate user 232 * is the first in the channel 233 * and should be given ops */ 234 created = 2; 235 } 236 else 237 { 238 /* Already on the channel */ 239 if (has_channel(user,Ptr)) 240 return NULL; 241 242 // remote users are allowed us to bypass channel modes 243 // and bans (used by servers) 244 if (user->fd > -1) 245 { 246 MOD_RESULT = 0; 247 FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname)); 248 if (MOD_RESULT == 1) 249 { 250 return NULL; 251 } 252 else 253 { 254 if (*Ptr->key) 255 { 256 MOD_RESULT = 0; 257 FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : '')); 258 if (!MOD_RESULT) 259 { 260 if (!key) 261 { 262 log(DEBUG,'add_channel: no key given in JOIN'); 263 WriteServ(user->fd,'475 %s %s :Cannot join channel (Requires key)',user->nick, Ptr->name); 264 return NULL; 265 } 266 else 267 { 268 if (strcasecmp(key,Ptr->key)) 269 { 270 log(DEBUG,'add_channel: bad key given in JOIN'); 271 WriteServ(user->fd,'475 %s %s :Cannot join channel (Incorrect key)',user->nick, Ptr->name); 272 return NULL; 273 } 274 } 275 } 276 } 277 if (Ptr->binarymodes & CM_INVITEONLY) 278 { 279 MOD_RESULT = 0; 280 FOREACH_RESULT(OnCheckInvite(user, Ptr)); 281 if (!MOD_RESULT) 282 { 283 log(DEBUG,'add_channel: channel is +i'); 284 if (user->IsInvited(Ptr->name)) 285 { 286 /* user was invited to channel */ 287 /* there may be an optional channel NOTICE here */ 288 } 289 else 290 { 291 WriteServ(user->fd,'473 %s %s :Cannot join channel (Invite only)',user->nick, Ptr->name); 292 return NULL; 293 } 294 } 295 user->RemoveInvite(Ptr->name); 296 } 297 if (Ptr->limit) 298 { 299 MOD_RESULT = 0; 300 FOREACH_RESULT(OnCheckLimit(user, Ptr)); 301 if (!MOD_RESULT) 302 { 303 if (usercount(Ptr) >= Ptr->limit) 304 { 305 WriteServ(user->fd,'471 %s %s :Cannot join channel (Channel is full)',user->nick, Ptr->name); 306 return NULL; 307 } 308 } 309 } 310 if (Ptr->bans.size()) 311 { 312 log(DEBUG,'add_channel: about to walk banlist'); 313 MOD_RESULT = 0; 314 FOREACH_RESULT(OnCheckBan(user, Ptr)); 315 if (!MOD_RESULT) 316 { 317 for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++) 318 { 319 if (match(user->GetFullHost(),i->data)) 320 { 321 WriteServ(user->fd,'474 %s %s :Cannot join channel (You're banned)',user->nick, Ptr->name); 322 return NULL; 323 } 324 } 325 } 326 } 327 } 328 } 329 else 330 { 331 log(DEBUG,'Overridden checks'); 332 } 333 created = 1; 334 } 335 336 log(DEBUG,'Passed channel checks'); 337 338 for (unsigned int index =0; index < user->chans.size(); index++) 339 { 340 if (user->chans[index].channel == NULL) 341 { 342 return ForceChan(Ptr,user->chans[index],user,created); 343 } 344 } 345 /* XXX: If the user is an oper here, we can just extend their user->chans vector by one 346 * and put the channel in here. Same for remote users which are not bound by 347 * the channel limits. Otherwise, nope, youre boned. 348 */ 349 if (user->fd < 0) 350 { 351 ucrec a; 352 chanrec* c = ForceChan(Ptr,a,user,created); 353 user->chans.push_back(a); 354 return c; 355 } 356 else if (strchr(user->modes,'o')) 357 { 358 /* Oper allows extension up to the OPERMAXCHANS value */ 359 if (user->chans.size() < OPERMAXCHANS) 360 { 361 ucrec a; 362 chanrec* c = ForceChan(Ptr,a,user,created); 363 user->chans.push_back(a); 364 return c; 365 } 366 } 367 log(DEBUG,'add_channel: user channel max exceeded: %s %s',user->nick,cname); 368 WriteServ(user->fd,'405 %s %s :You are on too many channels',user->nick, cname); 369 return NULL; 370 } .fi .PP .SS "\fBchanrec\fP* del_channel (\fBuserrec\fP * user, const char * cname, const char * reason, bool local)" .PP Definition at line 401 of file channels.cpp. .PP References chanlist, userrec::chans, DEBUG, DEFAULT, chanrec::DelUser(), FindChan(), FOREACH_MOD, log(), chanrec::name, userrec::nick, and WriteChannel(). .PP Referenced by Server::PartUserFromChannel(). .PP .nf 402 { 403 if ((!user) || (!cname)) 404 { 405 log(DEFAULT,'*** BUG *** del_channel was given an invalid parameter'); 406 return NULL; 407 } 408 409 chanrec* Ptr = FindChan(cname); 410 411 if (!Ptr) 412 return NULL; 413 414 FOREACH_MOD OnUserPart(user,Ptr); 415 log(DEBUG,'del_channel: removing: %s %s',user->nick,Ptr->name); 416 417 for (unsigned int i =0; i < user->chans.size(); i++) 418 { 419 /* zap it from the channel list of the user */ 420 if (user->chans[i].channel == Ptr) 421 { 422 if (reason) 423 { 424 WriteChannel(Ptr,user,'PART %s :%s',Ptr->name, reason); 425 } 426 else 427 { 428 WriteChannel(Ptr,user,'PART :%s',Ptr->name); 429 } 430 user->chans[i].uc_modes = 0; 431 user->chans[i].channel = NULL; 432 log(DEBUG,'del_channel: unlinked: %s %s',user->nick,Ptr->name); 433 break; 434 } 435 } 436 437 Ptr->DelUser((char*)user); 438 439 /* if there are no users left on the channel */ 440 if (!usercount(Ptr)) 441 { 442 chan_hash::iterator iter = chanlist.find(Ptr->name); 443 444 log(DEBUG,'del_channel: destroying channel: %s',Ptr->name); 445 446 /* kill the record */ 447 if (iter != chanlist.end()) 448 { 449 log(DEBUG,'del_channel: destroyed: %s',Ptr->name); 450 delete Ptr; 451 chanlist.erase(iter); 452 } 453 } 454 455 return NULL; 456 } .fi .PP .SS "\fBchanrec\fP * ForceChan (\fBchanrec\fP * Ptr, \fBucrec\fP & a, \fBuserrec\fP * user, int created)" .PP Definition at line 372 of file channels.cpp. .PP References chanrec::AddUser(), ucrec::channel, DEBUG, FOREACH_MOD, log(), chanrec::name, chanrec::setby, chanrec::topic, chanrec::topicset, ucrec::uc_modes, UCMODE_OP, WriteChannel(), and WriteServ(). .PP Referenced by add_channel(). .PP .nf 373 { 374 if (created == 2) 375 { 376 /* first user in is given ops */ 377 a.uc_modes = UCMODE_OP; 378 } 379 else 380 { 381 a.uc_modes = 0; 382 } 383 a.channel = Ptr; 384 Ptr->AddUser((char*)user); 385 WriteChannel(Ptr,user,'JOIN :%s',Ptr->name); 386 log(DEBUG,'Sent JOIN to client'); 387 if (Ptr->topicset) 388 { 389 WriteServ(user->fd,'332 %s %s :%s', user->nick, Ptr->name, Ptr->topic); 390 WriteServ(user->fd,'333 %s %s %s %lu', user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset); 391 } 392 userlist(user,Ptr); 393 WriteServ(user->fd,'366 %s %s :End of /NAMES list.', user->nick, Ptr->name); 394 FOREACH_MOD OnUserJoin(user,Ptr); 395 return Ptr; 396 } .fi .PP .SS "void kick_channel (\fBuserrec\fP * src, \fBuserrec\fP * user, \fBchanrec\fP * Ptr, char * reason)" .PP Definition at line 459 of file channels.cpp. .PP References AC_KICK, ACR_DEFAULT, ACR_DENY, chanlist, userrec::chans, cstatus(), DEBUG, DEFAULT, chanrec::DelUser(), connection::fd, FOREACH_MOD, FOREACH_RESULT, has_channel(), is_uline(), log(), chanrec::name, userrec::nick, userrec::server, STATUS_HOP, WriteChannel(), and WriteServ(). .PP .nf 460 { 461 if ((!src) || (!user) || (!Ptr) || (!reason)) 462 { 463 log(DEFAULT,'*** BUG *** kick_channel was given an invalid parameter'); 464 return; 465 } 466 467 if ((!Ptr) || (!user) || (!src)) 468 { 469 return; 470 } 471 472 log(DEBUG,'kick_channel: removing: %s %s %s',user->nick,Ptr->name,src->nick); 473 474 if (!has_channel(user,Ptr)) 475 { 476 WriteServ(src->fd,'441 %s %s %s :They are not on that channel',src->nick, user->nick, Ptr->name); 477 return; 478 } 479 480 int MOD_RESULT = 0; 481 FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK)); 482 if ((MOD_RESULT == ACR_DENY) && (!is_uline(src->server))) 483 return; 484 485 if ((MOD_RESULT == ACR_DEFAULT) || (!is_uline(src->server))) 486 { 487 if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) 488 { 489 if (cstatus(src,Ptr) == STATUS_HOP) 490 { 491 WriteServ(src->fd,'482 %s %s :You must be a channel operator',src->nick, Ptr->name); 492 } 493 else 494 { 495 WriteServ(src->fd,'482 %s %s :You must be at least a half-operator to change modes on this channel',src->nick, Ptr->name); 496 } 497 498 return; 499 } 500 } 501 502 if (!is_uline(src->server)) 503 { 504 MOD_RESULT = 0; 505 FOREACH_RESULT(OnUserPreKick(src,user,Ptr,reason)); 506 if (MOD_RESULT) 507 return; 508 } 509 510 FOREACH_MOD OnUserKick(src,user,Ptr,reason); 511 512 for (unsigned int i =0; i < user->chans.size(); i++) 513 { 514 /* zap it from the channel list of the user */ 515 if (user->chans[i].channel) 516 if (!strcasecmp(user->chans[i].channel->name,Ptr->name)) 517 { 518 WriteChannel(Ptr,src,'KICK %s %s :%s',Ptr->name, user->nick, reason); 519 user->chans[i].uc_modes = 0; 520 user->chans[i].channel = NULL; 521 log(DEBUG,'del_channel: unlinked: %s %s',user->nick,Ptr->name); 522 break; 523 } 524 } 525 526 Ptr->DelUser((char*)user); 527 528 /* if there are no users left on the channel */ 529 if (!usercount(Ptr)) 530 { 531 chan_hash::iterator iter = chanlist.find(Ptr->name); 532 533 log(DEBUG,'del_channel: destroying channel: %s',Ptr->name); 534 535 /* kill the record */ 536 if (iter != chanlist.end()) 537 { 538 log(DEBUG,'del_channel: destroyed: %s',Ptr->name); 539 delete Ptr; 540 chanlist.erase(iter); 541 } 542 } 543 } .fi .PP .SH "Variable Documentation" .PP .SS "\fBchan_hash\fP \fBchanlist\fP" .PP Referenced by add_channel(), del_channel(), and kick_channel(). .SS "\fBServerConfig\fP* \fBConfig\fP" .PP .SS "std::vector<\fBModeParameter\fP> \fBcustom_mode_params\fP" .PP Definition at line 70 of file channels.cpp. .PP Referenced by chanrec::GetModeParameter(), and chanrec::SetCustomModeParam(). .SS "std::vector<\fBircd_module\fP*> factory" .PP .SS "int \fBMODCOUNT\fP = -1" .PP Definition at line 930 of file modules.cpp. .PP Referenced by Server::FindModule(). .SS "std::vector<\fBModule\fP*> modules" .PP Referenced by Server::FindModule(). .SS "time_t \fBTIME\fP" .PP Referenced by add_channel(), and userrec::userrec(). .SS "int \fBWHOWAS_MAX\fP" .PP .SS "int \fBWHOWAS_STALE\fP" .PP .SH "Author" .PP Generated automatically by Doxygen for InspIRCd from the source code.