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);
}
Beispiel #2
0
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;
}