void IrcChannel::joinIrcUsers(const QList<IrcUser *> &users, const QStringList &modes) { if (users.isEmpty()) return; if (users.count() != modes.count()) { qWarning() << "IrcChannel::addUsers(): number of nicks does not match number of modes!"; return; } QStringList newNicks; QStringList newModes; QList<IrcUser *> newUsers; IrcUser *ircuser; for (int i = 0; i < users.count(); i++) { ircuser = users[i]; if (!ircuser || _userModes.contains(ircuser)) { addUserMode(ircuser, modes[i]); continue; } _userModes[ircuser] = modes[i]; ircuser->joinChannel(this); connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString))); // connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); // if you wonder why there is no counterpart to ircUserJoined: // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience newNicks << ircuser->nick(); newModes << modes[i]; newUsers << ircuser; } if (newNicks.isEmpty()) return; SYNC_OTHER(joinIrcUsers, ARG(newNicks), ARG(newModes)); emit ircUsersJoined(newUsers); }
void Channel::setModes(Client *setter, char *modestr) { chanClient *info; chanClient tinfo; bool set=true; char tbuff[64]; int modep=0; bool canVoice; char oldMode = this->auditorium; char *p=strchr(modestr,' '); if(p != NULL) *p++ = 0; memset(&tinfo,0,sizeof(tinfo)); bool operoverride=false; char *tbuffptr; if(setter->getRights()&OPERPRIVS_OPEROVERRIDE) operoverride=true; //if(setter->getRights()&OPERPRIVS_GLOBALOWNER) operoverride=true; info = getUserInfo(setter); if(info == NULL) info = &tinfo; if(info->owner) info->op = true; if(info->op) info->halfop = true; for(int i=0;i<strlen(modestr);i++) { switch(modestr[i]) { case '-': set = false; break; case '+': set = true; break; case 'e': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->mode_ops_obey_channel_limit == set) break; this->mode_ops_obey_channel_limit = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+e":"-e"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'm': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->moderated == set) break; this->moderated = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+m":"-m"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'n': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->nooutsidemsgs == set) break; this->nooutsidemsgs = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+n":"-n"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'i': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->inviteonly == set) break; this->inviteonly = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+i":"-i"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'l': //set channel limit if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { int len = 0; if(set) { if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; len = atoi(tbuff); if(len < 1) return; } if(set) { sendMessage(false,false,setter,"MODE %s +l %d",getName(),len); } else { sendMessage(false,false,setter,"MODE %s -l",getName()); } this->limit = len; } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'k': //set channel key if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(set) { if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; sendMessage(false,false,setter,"MODE %s +k %s",getName(),tbuff); strcpy(key,tbuff); } else { sendMessage(false,false,setter,"MODE %s -k",getName()); memset(key,0,sizeof(key)); } } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 't': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->topic_protect == set) break; this->topic_protect = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+t":"-t"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'p': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->secret && set) { this->secret = false; sendMessage(false,false,setter,"MODE %s -s",getName()); } if(this->priv == set) break; this->priv = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+p":"-p"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 's': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(this->priv && set) { this->priv = false; sendMessage(false,false,setter,"MODE %s -p",getName()); } if(this->secret == set) break; this->secret = set; sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+s":"-s"); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'q': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(set && this->auditorium == 2) { sendMessage(false,false,setter,"MODE %s %s",getName(),!set?"+u":"-u"); } if((set && this->auditorium == 1) || (!set && this->auditorium != 1)) break; this->auditorium = (set==true?1:0); sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+q":"-q"); auditoriumUpdate(oldMode); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'u': if(info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) { if(set && this->auditorium == 1) { sendMessage(false,false,setter,"MODE %s %s",getName(),!set?"+q":"-q"); } if((set && this->auditorium == 2) || (!set && this->auditorium != 2)) break; this->auditorium = (set==true?2:0); sendMessage(false,false,setter,"MODE %s %s",getName(),set?"+u":"-u"); auditoriumUpdate(oldMode); } else sendNotEnoughPrivs(ENotEnough_HALFOP,setter,set?"set mode":"remove mode"); break; case 'o': //op someone if(info->owner || operoverride && !(this->onlyowner == 1 && info->owner == false)) { chanClient *tclient; Client *opclient; if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; opclient = find_user(tbuff); if(opclient != NULL) { tclient = this->getUserInfo(opclient); if(tclient != NULL) { if(tclient->op == set) break; sendMessage(false,false,setter,"MODE %s %s %s",getName(),set?"+o":"-o",tbuff); if(set == false) tclient->owner = set; tclient->op=set; tclient->halfop = set; } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { sendNotEnoughPrivs(ENotEnough_OWNER,setter,"change ops"); } break; case 'v': //voice someone //checking isn't instant because you could be devoicing yourself chanClient *tclient; Client *opclient; if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } canVoice = info->halfop || info->op || info->owner || operoverride && (this->onlyowner != 1 || info->owner); find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; opclient = find_user(tbuff); if(opclient != NULL) { tclient = this->getUserInfo(opclient); if(tclient != NULL) { if(!canVoice && (tclient->client != setter || set == true)) { sendNotEnoughPrivs(ENotEnough_HALFOP,setter,"change voice"); break; } if(tclient->voice == set) break; sendMessage(false,false,setter,"MODE %s %s %s",getName(),set?"+v":"-v",tbuff); tclient->voice=set; } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } break; case 'h': //halfop someone if(info->op || operoverride && !(this->onlyowner == 1 && info->owner == false)) { chanClient *tclient; Client *opclient; if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; opclient = find_user(tbuff); if(opclient != NULL) { tclient = this->getUserInfo(opclient); if(tclient != NULL) { if(tclient->halfop == set) break; if(tclient->op == true || tclient->owner == true && info->owner == false) break; sendMessage(false,false,setter,"MODE %s %s %s",getName(),set?"+o":"-o",tbuff); tclient->halfop = set; } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { sendNotEnoughPrivs(ENotEnough_OP,setter,"set halfop"); } break; case 'O': //owner someone if(info->owner || operoverride && !(this->onlyowner == 1 && info->owner == false)) { chanClient *tclient; Client *opclient; if(p == NULL) { info->client->send_numeric(461, "%c :Not enough parameters",modestr[i]); return; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; opclient = find_user(tbuff); if(opclient != NULL) { tclient = this->getUserInfo(opclient); if(tclient != NULL) { if(tclient->owner == set) break; sendMessage(false,false,setter,"MODE %s %s %s",getName(),set?"+o":"-o",tbuff); tclient->owner = set; tclient->op = set; tclient->halfop = set; } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { setter->send_numeric(401,"%s :No such nick/channel",tbuff); break; } } else { sendNotEnoughPrivs(ENotEnough_OWNER,setter,"change owner"); } break; case 'b': //ban/unban someone if((info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) || p == NULL) { if(p == NULL) { //list bans std::list<userMode *>::iterator iterator=server.usermodes_list.begin(); userMode *um; char *nick; info->client->getUserInfo(&nick,NULL,NULL,NULL); while(iterator != server.usermodes_list.end()) { um=*iterator; if(match(um->chanmask,getName()) == 0) { if(um->hostmask[0] != 0 && um->modeflags & EModeFlags_Ban) info->client->send_numeric(367,"%s *!*@%s %s@%s %d",getName(), um->hostmask, um->setbynick[0] == 0?"SERVER":um->setbynick,um->setbyhost[0] == 0||info->halfop==false?"*":um->setbyhost,um->setondate); } iterator++; } info->client->send_numeric(368,"%s :End of channel ban list",getName()); break; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; char setstr[128]; memset(&setstr,0, sizeof(setstr)); tbuffptr = (char *)&tbuff; if(strchr(tbuffptr,'@') != NULL) tbuffptr = strchr(tbuffptr,'@')+1; sprintf(setstr,"\\hostmask\\%s\\modeflags\\b\\comment\\Banned by MODE command (Persist)",tbuffptr); if(set) { addUserMode(info->client,this->getName(),setstr); } else { userMode *usermode = findRemoveableUsermode(getName(),tbuff,EModeFlags_Ban,setter->getRights()&OPERPRIVS_GLOBALOWNER); if(usermode != NULL) { removeUsermode(usermode); } } //tbuff = ban name } else { sendNotEnoughPrivs(ENotEnough_HALFOP,setter,"set mode"); } break; case 'I': //invite/uninvite someone if((info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) || p == NULL) { if(p == NULL) { //list bans std::list<userMode *>::iterator iterator=server.usermodes_list.begin(); userMode *um; char *nick; info->client->getUserInfo(&nick,NULL,NULL,NULL); while(iterator != server.usermodes_list.end()) { um=*iterator; if(match(um->chanmask,getName())) { if(um->hostmask[0] != 0 && um->modeflags & EModeFlags_Invited) info->client->send_numeric(367,"%s *!*@%s %s@%s %d",getName(), um->hostmask, um->setbynick[0] == 0?"SERVER":um->setbynick,um->setbyhost[0] == 0||info->halfop==false?"*":um->setbyhost,um->setondate); } iterator++; } info->client->send_numeric(368,"%s :End of channel invite list",getName()); break; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; char setstr[128]; memset(&setstr,0, sizeof(setstr)); tbuffptr = (char *)&tbuff; if(strchr(tbuffptr,'@') != NULL) tbuffptr = strchr(tbuffptr,'@')+1; sprintf(setstr,"\\hostmask\\%s\\modeflags\\I\\comment\\Invited by MODE command (Persist)",tbuffptr); if(set) { addUserMode(info->client,this->getName(),setstr); } else { userMode *usermode = findRemoveableUsermode(getName(),tbuff,EModeFlags_Invited,setter->getRights()&OPERPRIVS_GLOBALOWNER); if(usermode != NULL) { removeUsermode(usermode); } } //tbuff = ban name } else { sendNotEnoughPrivs(ENotEnough_HALFOP,setter,"set mode"); } break; case 'E': //excempt/unexcempt someone if((info->halfop || operoverride && !(this->onlyowner == 1 && info->owner == false)) || p == NULL) { if(p == NULL) { //list bans std::list<userMode *>::iterator iterator=server.usermodes_list.begin(); userMode *um; char *nick; info->client->getUserInfo(&nick,NULL,NULL,NULL); while(iterator != server.usermodes_list.end()) { um=*iterator; if(match(um->chanmask,getName())) { if(um->hostmask[0] != 0 && um->modeflags & EModeFlags_BanExcempt) info->client->send_numeric(367,"%s *!*@%s %s@%s %d",getName(), um->hostmask, um->setbynick[0] == 0?"SERVER":um->setbynick,um->setbyhost[0] == 0||info->halfop==false?"*":um->setbyhost,um->setondate); } iterator++; } info->client->send_numeric(368,"%s :End of channel exempt list",getName()); break; } find_nth(p,modep++,tbuff,sizeof(tbuff)); if(strlen(tbuff)<1) return; char setstr[128]; memset(&setstr,0, sizeof(setstr)); tbuffptr = (char *)&tbuff; if(strchr(tbuffptr,'@') != NULL) tbuffptr = strchr(tbuffptr,'@')+1; sprintf(setstr,"\\hostmask\\%s\\modeflags\\E\\comment\\Exempt by MODE command (Persist)",tbuffptr); if(set) { addUserMode(info->client,this->getName(),setstr); } else { userMode *usermode = findRemoveableUsermode(getName(),tbuff,EModeFlags_BanExcempt,setter->getRights()&OPERPRIVS_GLOBALOWNER); if(usermode != NULL) { removeUsermode(usermode); } } } else { sendNotEnoughPrivs(ENotEnough_HALFOP,setter,"set mode"); } break; default: setter->send_numeric(472,"%c :is unknown mode to me for %s",modestr[i],getName()); break; } } return; }