/* * m_topic * parv[1] = channel name * parv[2] = new topic, if setting topic */ static int m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char *p = NULL; const char *name; int operspy = 0; if((p = strchr(parv[1], ','))) *p = '\0'; name = parv[1]; if(IsOperSpy(source_p) && parv[1][0] == '!') { name++; operspy = 1; if(EmptyString(name)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "TOPIC"); return 0; } } if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); chptr = find_channel(name); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } /* setting topic */ if(parc > 2) { msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(MyClient(source_p) && !is_chanop_voiced(msptr) && !IsOper(source_p) && !add_channel_target(source_p, chptr)) { sendto_one(source_p, form_str(ERR_TARGCHANGE), me.name, source_p->name, chptr->chname); return 0; } if(((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || get_channel_access(source_p, chptr, msptr, MODE_ADD, NULL) >= CHFL_CHANOP) && (!MyClient(source_p) || can_send(chptr, source_p, msptr))) { char topic[TOPICLEN + 1]; char topic_info[USERHOST_REPLYLEN]; rb_strlcpy(topic, parv[2], sizeof(topic)); rb_sprintf(topic_info, "%s!%s@%s", source_p->name, source_p->username, source_p->host); if (ConfigChannel.strip_topic_colors) strip_colour(topic); set_channel_topic(chptr, topic, topic_info, rb_current_time()); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", use_id(source_p), chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); } else sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), get_id(&me, source_p), get_id(source_p, source_p), name); } else if(MyClient(source_p)) { if(operspy) report_operspy(source_p, "TOPIC", chptr->chname); if(!IsMember(source_p, chptr) && SecretChannel(chptr) && !operspy) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(chptr->topic == NULL) sendto_one(source_p, form_str(RPL_NOTOPIC), me.name, source_p->name, name); else { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, (unsigned long)chptr->topic_time); } } return 0; }
/* * m_topic * parv[1] = channel name * parv[2] = new topic, if setting topic */ static int m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char *p = NULL; const char *name; int operspy = 0; if((p = strchr(parv[1], ','))) *p = '\0'; name = parv[1]; if(IsOperSpy(source_p) && parv[1][0] == '!') { name++; operspy = 1; if(EmptyString(name)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "TOPIC"); return 0; } } if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsChannelName(name)) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } chptr = find_channel(name); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } /* setting topic */ if(parc > 2) { char topic_info[USERHOST_REPLYLEN]; msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(MyClient(source_p) && !is_chanop_voiced(msptr) && !IsOper(source_p) && !add_channel_target(source_p, chptr)) { sendto_one(source_p, form_str(ERR_TARGCHANGE), me.name, source_p->name, chptr->chname); return 0; } if(MyClient(source_p) && (chptr->mode.mode & MODE_TOPICLIMIT) && !is_any_op(msptr)) { if(IsOverride(source_p)) { sendto_wallops_flags(UMODE_WALLOP, &me, "%s is overriding TOPIC on [%s]", get_oper_name(source_p), chptr->chname); sendto_server(NULL, chptr, NOCAPS, NOCAPS, ":%s WALLOPS :%s is overriding TOPIC on [%s]", me.name, get_oper_name(source_p), chptr->chname); } else { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, parv[1]); return 0; } } if(ConfigChannel.host_in_topic) sprintf(topic_info, "%s!%s@%s", source_p->name, source_p->username, source_p->host); else rb_strlcpy(topic_info, source_p->name, sizeof(topic_info)); set_channel_topic(chptr, parv[2], topic_info, rb_current_time()); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", use_id(source_p), chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); } else if(MyClient(source_p)) { if(operspy) report_operspy(source_p, "TOPIC", chptr->chname); if(!IsMember(source_p, chptr) && SecretChannel(chptr) && !operspy) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(chptr->topic == NULL) sendto_one(source_p, form_str(RPL_NOTOPIC), me.name, source_p->name, name); else { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } } return 0; }
/* * m_mode - MODE command handler * parv[1] - channel */ static int m_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; int n = 2; const char *dest; int operspy = 0; dest = parv[1]; if(IsOperSpy(source_p) && *dest == '!') { dest++; operspy = 1; if(EmptyString(dest)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MODE"); return 0; } } /* Now, try to find the channel in question */ if(!IsChanPrefix(*dest)) { /* if here, it has to be a non-channel name */ user_mode(client_p, source_p, parc, parv); return 0; } if(!check_channel_name(dest)) { sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]); return 0; } chptr = find_channel(dest); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } /* Now know the channel exists */ if(parc < n + 1) { if(operspy) report_operspy(source_p, "MODE", chptr->chname); sendto_one(source_p, form_str(RPL_CHANNELMODEIS), me.name, source_p->name, parv[1], operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p)); sendto_one(source_p, form_str(RPL_CREATIONTIME), me.name, source_p->name, parv[1], chptr->channelts); } else { msptr = find_channel_membership(chptr, source_p); /* Finish the flood grace period... */ if(MyClient(source_p) && !IsFloodDone(source_p)) { if(!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0'))) flood_endgrace(source_p); } set_channel_mode(client_p, source_p, chptr, msptr, parc - n, parv + n); } return 0; }
/* mo_list() * parv[1] = channel */ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct ListClient *params; char *p; char *args = NULL; int i; int operspy = 0; if (source_p->localClient->safelist_data != NULL) { sendto_one_notice(source_p, ":/LIST aborted"); safelist_client_release(source_p); return 0; } if (parc > 1) { args = LOCAL_COPY(parv[1]); } if (args && *args == '!' && IsOperSpy(source_p)) { args++; report_operspy(source_p, "LIST", args); operspy = 1; } /* Single channel. */ if (args && IsChannelName(args)) { safelist_channel_named(source_p, args, operspy); return 0; } /* Multiple channels, possibly with parameters. */ params = rb_malloc(sizeof(struct ListClient)); /* XXX rather arbitrary -- jilles */ params->users_min = 3; params->users_max = INT_MAX; params->operspy = operspy; params->created_min = params->topic_min = params->created_max = params->topic_max = 0; if (args && !EmptyString(args)) { /* Cancel out default minimum. */ params->users_min = 0; for (i = 0; i < 7; i++) { if ((p = strchr(args, ',')) != NULL) *p++ = '\0'; if (*args == '<') { args++; if (IsDigit(*args)) { params->users_max = atoi(args); if (params->users_max == 0) params->users_max = INT_MAX; else params->users_max--; } } else if (*args == '>') { args++; if (IsDigit(*args)) params->users_min = atoi(args) + 1; else params->users_min = 0; } else if (*args == 'C' || *args == 'c') { args++; if (*args == '>') { /* Creation time earlier than last x minutes. */ args++; if (IsDigit(*args)) { params->created_max = rb_current_time() - (60 * atoi(args)); } } else if (*args == '<') { /* Creation time within last x minutes. */ args++; if (IsDigit(*args)) { params->created_min = rb_current_time() - (60 * atoi(args)); } } } else if (*args == 'T' || *args == 't') { args++; if (*args == '>') { /* Topic change time earlier than last x minutes. */ args++; if (IsDigit(*args)) { params->topic_max = rb_current_time() - (60 * atoi(args)); } } else if (*args == '<') { /* Topic change time within last x minutes. */ args++; if (IsDigit(*args)) { params->topic_min = rb_current_time() - (60 * atoi(args)); } } } if (EmptyString(p)) break; else args = p; } } safelist_client_instantiate(source_p, params); return 0; }