/* * set_topic * * inputs - source_p pointer * - channel pointer * - topicts to set * - who to set as who doing the topic * - topic * output - none * Side effects - simply propagates topic as needed * little helper function, could be removed */ static void set_topic(struct Client *source_p, struct Channel *chptr, time_t topicts, const char *topicwho, const char *topic) { int new_topic = strcmp(chptr->topic ? chptr->topic : "", topic); set_channel_topic(chptr, topic, topicwho, topicts); /* Only send TOPIC to channel if it's different */ if (new_topic) sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s", ConfigServerHide.hide_servers ? me.name : source_p->name, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_server(source_p, chptr, CAP_TBURST, NOCAPS, ":%s TBURST %lu %s %lu %s :%s", me.name, (unsigned long)chptr->channelts, chptr->chname, (unsigned long)chptr->topic_time, chptr->topic_info == NULL ? "" : chptr->topic_info, chptr->topic == NULL ? "" : chptr->topic); sendto_server(source_p, chptr, CAP_TB, CAP_TBURST, ":%s TB %s %lu %s :%s", me.name, chptr->chname, (unsigned long)chptr->topic_time, chptr->topic_info == NULL ? "" : chptr->topic_info, chptr->topic == NULL ? "" : chptr->topic); }
static void ms_away(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { if (!IsClient(source_p)) return; if (parc < 2 || EmptyString(parv[1])) { /* Marking as not away */ if (source_p->away[0]) { /* we now send this only if they were away before --is */ sendto_server(client_p, CAP_TS6, NOCAPS, ":%s AWAY", ID(source_p)); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s AWAY", source_p->name); source_p->away[0] = '\0'; } return; } strlcpy(source_p->away, parv[1], sizeof(source_p->away)); sendto_server(client_p, CAP_TS6, NOCAPS, ":%s AWAY :%s", ID(source_p), source_p->away); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s AWAY :%s", source_p->name, source_p->away); }
/* * mo_wallops (write to *all* opers currently online) * parv[0] = sender prefix * parv[1] = message text */ static void mo_wallops(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { const char *message = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_WALLOPS)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "wallops"); return; } if (EmptyString(message)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "WALLOPS"); return; } sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", message); sendto_server(NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", ID(source_p), message); sendto_server(NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", source_p->name, message); }
/* * ms_wallops (write to *all* opers currently online) * parv[1] = message text */ static int ms_wallops(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { const char *prefix = ""; if(MyClient(source_p) && !IsOperWallops(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "wallops"); return 0; } if (IsPerson(source_p)) { if (!strncmp(parv[1], "OPERWALL - ", 11)) prefix = "WALLOPS - "; } sendto_wallops_flags(UMODE_WALLOP, source_p, "%s%s", prefix, parv[1]); sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", use_id(source_p), parv[1]); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", source_p->name, parv[1]); return 0; }
static void ms_gnotice(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *message; int flags, level; message = parv[3]; level = atoi(parv[2]); flags = atoi(parv[1]); if (EmptyString(message)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "GNOTICE"); return; } sendto_realops_remote(source_p, flags, level, message); sendto_server(client_p, CAP_TS6, NOCAPS, ":%s GNOTICE %d %d :%s", ID(source_p), flags, level, message); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s GNOTICE %d %d :%s", source_p->name, flags, level, message); }
/* ** m_away ** parv[1] = away message */ static int m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if(MyClient(source_p) && source_p->localClient->next_away && !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsClient(source_p)) return 0; if(parc < 2 || EmptyString(parv[1])) { /* Marking as not away */ if(source_p->user->away != NULL) { /* we now send this only if they were away before --is */ sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY", use_id(source_p)); free_away(source_p); sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY", source_p->name, source_p->username, source_p->host); } if(MyConnect(source_p)) sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY)); return 0; } /* Rate limit this because it is sent to common channels. */ if (MyClient(source_p)) { if(!IsOper(source_p) && source_p->localClient->next_away > rb_current_time()) { sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name, "AWAY"); return 0; } if(source_p->localClient->next_away < rb_current_time() - ConfigFileEntry.away_interval) source_p->localClient->next_away = rb_current_time(); else source_p->localClient->next_away = rb_current_time() + ConfigFileEntry.away_interval; } if(source_p->user->away == NULL) allocate_away(source_p); if(strncmp(source_p->user->away, parv[1], AWAYLEN - 1)) { rb_strlcpy(source_p->user->away, parv[1], AWAYLEN); sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY :%s", use_id(source_p), source_p->user->away); } if(MyConnect(source_p)) sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY)); sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY :%s", source_p->name, source_p->username, source_p->host, source_p->user->away); return 0; }
/* * mo_operwall - OPERWALL message handler * (write to *all* local opers currently online) * parv[0] = sender prefix * parv[1] = message text */ static void mo_operwall(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { const char *message = parv[1]; if (!IsOperWall(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "operwall"); return; } if (EmptyString(message)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "OPERWALL"); return; } sendto_server(NULL, source_p, NULL, CAP_TS6, NOCAPS, LL_ICLIENT, ":%s OPERWALL :%s", ID(source_p), message); sendto_server(NULL, source_p, NULL, NOCAPS, CAP_TS6, LL_ICLIENT, ":%s OPERWALL :%s", source_p->name, message); sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", message); }
/* ** mr_user ** parv[0] = sender prefix ** parv[1] = username (login name, account) ** parv[2] = client host name (used only from other servers) ** parv[3] = server host name (used only from other servers) ** parv[4] = users real name info */ static void mr_user(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *p; char *user; if (source_p->localClient->listener->flags & LISTENER_SERVER) { exit_client(source_p, &me, "Use a different port"); return; } if ((p = strchr(parv[1], '@')) != NULL) *p = '\0'; if (EmptyString(parv[4])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name[0] ? source_p->name : "*", "USER"); return; } if(!EmptyString(source_p->name)) { user = parv[1]; if(*user == '&') { user++; if(EmptyString(user)) user = parv[1]; else { if(!EmptyString(source_p->certfp)) { char buf[SHA_DIGEST_LENGTH*2+1]; base16_encode(buf, sizeof(buf), source_p->certfp, sizeof(source_p->certfp)); sendto_server(&me, NULL, NOCAPS, NOCAPS, ":%s AUTH 1 %s %s %s", me.name, user, source_p->name, buf); } else { sendto_server(&me, NULL, NOCAPS, NOCAPS, ":%s AUTH 0 %s %s %s", me.name, user, source_p->name, source_p->localClient->passwd); } strlcpy(source_p->info, parv[4], sizeof(source_p->info)); return; } } } do_local_user(parv[0], client_p, source_p, parv[1], /* username */ parv[2], /* host */ parv[3], /* server */ parv[4] /* users real name */ ); }
/*! \brief AWAY command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = away message */ static int ms_away(struct Client *source_p, int parc, char *parv[]) { const char *const message = parv[1]; if (EmptyString(message)) { /* Marking as not away */ if (source_p->away[0]) { source_p->away[0] = '\0'; /* We now send this only if they were away before --is */ sendto_server(source_p, 0, 0, ":%s AWAY", source_p->id); sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY", source_p->name, source_p->username, source_p->host); } return 0; } strlcpy(source_p->away, message, sizeof(source_p->away)); sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s", source_p->name, source_p->username, source_p->host, source_p->away); sendto_server(source_p, 0, 0, ":%s AWAY :%s", source_p->id, source_p->away); return 0; }
/* Disable this because of the abuse potential -- jilles * No, make it toggleable via ./configure. --nenolod */ static int mo_chghost(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } if (!(target_p = find_named_person(parv[1]))) { sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]); return 0; } if (!clean_host(parv[2])) { sendto_one_notice(source_p, ":Hostname %s is invalid", parv[2]); return 0; } do_chghost(source_p, target_p, parv[2], 0); sendto_server(NULL, NULL, CAP_EUID | CAP_TS6, NOCAPS, ":%s CHGHOST %s %s", use_id(source_p), use_id(target_p), parv[2]); sendto_server(NULL, NULL, CAP_TS6, CAP_EUID, ":%s ENCAP * CHGHOST %s :%s", use_id(source_p), use_id(target_p), parv[2]); return 0; }
static void ms_topic(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Channel *chptr = NULL; const char *from, *to; char topic_info[USERHOST_REPLYLEN]; if (IsCapable(source_p->from, CAP_TS6) && HasID(source_p)) { from = me.id; to = source_p->id; } else { from = me.name; to = source_p->name; } if (EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), from, to, "TOPIC"); return; } if ((chptr = hash_find_channel(parv[1])) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), from, to, parv[1]); return; } if (!IsClient(source_p)) strlcpy(topic_info, source_p->name, sizeof(topic_info)); else snprintf(topic_info, sizeof(topic_info), "%s!%s@%s", source_p->name, source_p->username, source_p->host); set_channel_topic(chptr, parv[2], topic_info, CurrentTime, 0); sendto_server(client_p, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", ID(source_p), chptr->chname, chptr->topic); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s TOPIC %s :%s", source_p->name, chptr->chname, chptr->topic); if (!IsClient(source_p)) sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :%s", source_p->name, chptr->chname, chptr->topic); else sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic); }
/* part_one_client() * * inputs - pointer to server * - pointer to source client to remove * - char pointer of name of channel to remove from * output - none * side effects - remove ONE client given the channel name */ static void part_one_client(struct Client *client_p, struct Client *source_p, const char *name, char *reason) { struct Channel *chptr = NULL; struct Membership *ms = NULL; if ((chptr = hash_find_channel(name)) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, source_p->name, name); return; } if ((ms = find_channel_link(source_p, chptr)) == NULL) { sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name, source_p->name, name); return; } if (MyConnect(source_p) && !IsOper(source_p)) check_spambot_warning(source_p, NULL); /* * Remove user from the old channel (if any) * only allow /part reasons in -m chans */ if(msg_has_colors(reason) && (chptr->mode.mode & MODE_NOCOLOR)) reason = strip_color(reason); if (reason[0] && (!MyConnect(source_p) || ((can_send(chptr, source_p, ms) && (source_p->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < CurrentTime)))) { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s :%s", ID(source_p), chptr->chname, reason); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s PART %s :%s", source_p->name, chptr->chname, reason); sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, reason); } else { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", ID(source_p), chptr->chname); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s PART %s", source_p->name, chptr->chname); sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s", source_p->name, source_p->username, source_p->host, chptr->chname); } remove_user_from_channel(ms); }
static void mo_away(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *cur_away_msg = source_p->user->away; char *new_away_msg; size_t nbytes = 0; if (!IsFloodDone(source_p)) flood_endgrace(source_p); if (parc < 2 || EmptyString(parv[1])) { /* Marking as not away */ if (cur_away_msg) { /* we now send this only if they were away before --is */ sendto_server(client_p, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS, ":%s AWAY", ID(source_p)); sendto_server(client_p, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS, ":%s AWAY", source_p->name); MyFree(cur_away_msg); source_p->user->away = NULL; } sendto_one(source_p, form_str(RPL_UNAWAY), me.name, parv[0]); return; } source_p->user->last_away = CurrentTime; new_away_msg = parv[1]; nbytes = strlen(new_away_msg); if (nbytes > (size_t)TOPICLEN) { new_away_msg[TOPICLEN] = '\0'; nbytes = TOPICLEN; } /* we now send this only if they * weren't away already --is */ if (!cur_away_msg) { sendto_server(client_p, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS, ":%s AWAY :%s", ID(source_p), new_away_msg); sendto_server(client_p, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS, ":%s AWAY :%s", source_p->name, new_away_msg); } else MyFree(cur_away_msg); cur_away_msg = MyMalloc(nbytes + 1); strcpy(cur_away_msg, new_away_msg); source_p->user->away = cur_away_msg; sendto_one(source_p, form_str(RPL_NOWAWAY), me.name, parv[0]); }
static int m_cycle(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char *p, *name; char *s = LOCAL_COPY(parv[1]); struct Channel *chptr; struct membership *msptr; name = rb_strtok_r(s, ",", &p); /* Finish the flood grace period... */ if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); while(name) { if((chptr = find_channel(name)) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } 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(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p)) check_spambot_warning(source_p, NULL); if((is_any_op(msptr) || !MyConnect(source_p) || ((can_send(chptr, source_p, msptr) > 0 && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s :Cycling", use_id(source_p), chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :Cycling", source_p->name, source_p->username, source_p->host, chptr->chname); } else { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", use_id(source_p), chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s", source_p->name, source_p->username, source_p->host, chptr->chname); } remove_user_from_channel(msptr); chptr = NULL; msptr = NULL; name = rb_strtok_r(NULL, ",", &p); } user_join(client_p, source_p, parv[1], parc > 2 ? parv[2] : NULL); return 0; }
/* * part_one_client * * inputs - pointer to server * - pointer to source client to remove * - char pointer of name of channel to remove from * output - none * side effects - remove ONE client given the channel name */ static void part_one_client(struct Client *client_p, struct Client *source_p, char *name, char *reason) { struct Channel *chptr; struct membership *msptr; if((chptr = find_channel(name)) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return; } msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return; } if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p)) check_spambot_warning(source_p, NULL); /* * Remove user from the old channel (if any) * only allow /part reasons in -m chans */ if(reason[0] && (is_chanop(msptr) || !MyConnect(source_p) || ((can_send(chptr, source_p, msptr) > 0 && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < CurrentTime)))) { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s :%s", use_id(source_p), chptr->chname, reason); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s PART %s :%s", source_p->name, chptr->chname, reason); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, reason); } else { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", use_id(source_p), chptr->chname); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s PART %s", source_p->name, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s", source_p->name, source_p->username, source_p->host, chptr->chname); } remove_user_from_channel(msptr); }
/* * ms_operwall - OPERWALL message handler * (write to *all* local opers currently online) * parv[0] = sender prefix * parv[1] = message text */ static int ms_operwall(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s OPERWALL :%s", use_id(source_p), parv[1]); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s OPERWALL :%s", source_p->name, parv[1]); sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]); return 0; }
static void ms_away(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *cur_away_msg = NULL; char *new_away_msg = NULL; size_t nbytes = 0; if (!IsClient(source_p)) return; cur_away_msg = source_p->away; if (parc < 2 || EmptyString(parv[1])) { /* Marking as not away */ if (cur_away_msg) { /* we now send this only if they were away before --is */ sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY", ID(source_p)); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s AWAY", source_p->name); MyFree(cur_away_msg); source_p->away = NULL; } return; } new_away_msg = parv[1]; nbytes = strlen(new_away_msg); if (nbytes > (size_t)AWAYLEN) { new_away_msg[AWAYLEN] = '\0'; nbytes = AWAYLEN; } /* we now send this only if they * weren't away already --is */ if (!cur_away_msg) { sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY :%s", ID(source_p), new_away_msg); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s AWAY :%s", source_p->name, new_away_msg); } else MyFree(cur_away_msg); cur_away_msg = MyMalloc(nbytes + 1); strcpy(cur_away_msg, new_away_msg); source_p->away = cur_away_msg; }
static int mr_authenticate(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *agent_p = NULL; /* They really should use CAP for their own sake. */ if(!IsCapable(source_p, CLICAP_SASL)) return 0; if (strlen(client_p->id) == 3) { exit_client(client_p, client_p, client_p, "Mixing client and server protocol"); return 0; } if(source_p->preClient->sasl_complete) { sendto_one(source_p, form_str(ERR_SASLALREADY), me.name, EmptyString(source_p->name) ? "*" : source_p->name); return 0; } if(strlen(parv[1]) > 400) { sendto_one(source_p, form_str(ERR_SASLTOOLONG), me.name, EmptyString(source_p->name) ? "*" : source_p->name); return 0; } if(!*source_p->id) { /* Allocate a UID. */ strcpy(source_p->id, generate_uid()); add_to_id_hash(source_p->id, source_p); } if(*source_p->preClient->sasl_agent) agent_p = find_id(source_p->preClient->sasl_agent); if(agent_p == NULL) { if (!strcmp(parv[1], "EXTERNAL") && source_p->certfp != NULL) sendto_server(NULL, NULL, CAP_TS6|CAP_ENCAP, NOCAPS, ":%s ENCAP * SASL %s * S %s %s", me.id, source_p->id, parv[1], source_p->certfp); else sendto_server(NULL, NULL, CAP_TS6|CAP_ENCAP, NOCAPS, ":%s ENCAP * SASL %s * S %s", me.id, source_p->id, parv[1]); } else sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s", me.id, agent_p->servptr->name, source_p->id, agent_p->id, parv[1]); source_p->preClient->sasl_out++; return 0; }
/* m_tb() * * parv[1] - channel * parv[2] - topic ts * parv[3] - optional topicwho/topic * parv[4] - topic */ static int ms_tb(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; const char *newtopic; const char *newtopicwho; time_t newtopicts; chptr = find_channel(parv[1]); if(chptr == NULL) return 0; newtopicts = atol(parv[2]); if(parc == 5) { newtopic = parv[4]; newtopicwho = parv[3]; } else { newtopic = parv[3]; newtopicwho = source_p->name; } if(EmptyString(newtopic)) return 0; if(chptr->topic == NULL || (chptr->topic != NULL && chptr->topic->topic_time > newtopicts)) { /* its possible the topicts is a few seconds out on some * servers, due to lag when propagating it, so if theyre the * same topic just drop the message --fl */ if(chptr->topic != NULL && strcmp(chptr->topic->topic, newtopic) == 0) return 0; set_channel_topic(chptr, newtopic, newtopicwho, newtopicts); sendto_channel_local(ALL_MEMBERS, chptr, ":%s TOPIC %s :%s", source_p->name, chptr->chname, newtopic); sendto_server(client_p, chptr, CAP_TB | CAP_TS6, NOCAPS, ":%s TB %s %ld %s%s:%s", use_id(source_p), chptr->chname, (long)chptr->topic->topic_time, ConfigChannel.burst_topicwho ? chptr->topic->topic_info : "", ConfigChannel.burst_topicwho ? " " : "", chptr->topic->topic); sendto_server(client_p, chptr, CAP_TB, CAP_TS6, ":%s TB %s %ld %s%s:%s", source_p->name, chptr->chname, (long)chptr->topic->topic_time, ConfigChannel.burst_topicwho ? chptr->topic->topic_info : "", ConfigChannel.burst_topicwho ? " " : "", chptr->topic->topic); } return 0; }
/* send_message_remote() * * inputs - pointer to client from message is being sent * - pointer to client to send to * - pointer to preformatted buffer * - length of input buffer * output - none * side effects - Despite the function name, this only sends to directly * connected clients. * */ static void send_message_remote(struct Client *to, struct Client *from, char *buf, int len) { if (!MyConnect(to)) { sendto_realops_flags(UMODE_ALL, L_ALL, "server send message to %s [%s] dropped from %s(Not local server)", to->name, to->from->name, from->name); return; } /* Optimize by checking if (from && to) before everything */ /* we set to->from up there.. */ if (!MyClient(from) && IsPerson(to) && (to == from->from)) { if (IsServer(from)) { sendto_realops_flags(UMODE_ALL, L_ALL, "Send message to %s [%s] dropped from %s(Fake Dir)", to->name, to->from->name, from->name); return; } sendto_realops_flags(UMODE_ALL, L_ALL, "Ghosted: %s[%s@%s] from %s[%s@%s] (%s)", to->name, to->username, to->host, from->name, from->username, from->host, to->from->name); sendto_server(NULL, CAP_TS6, NOCAPS, ":%s KILL %s :%s (%s[%s@%s] Ghosted %s)", me.id, to->name, me.name, to->name, to->username, to->host, to->from->name); sendto_server(NULL, NOCAPS, CAP_TS6, ":%s KILL %s :%s (%s[%s@%s] Ghosted %s)", me.name, to->name, me.name, to->name, to->username, to->host, to->from->name); SetKilled(to); if (IsPerson(from)) sendto_one(from, form_str(ERR_GHOSTEDCLIENT), me.name, from->name, to->name, to->username, to->host, to->from); exit_client(NULL, to, &me, "Ghosted client"); return; } send_message(to, buf, len); }
/* * m_away * parv[0] = sender prefix * parv[1] = away message */ static void m_away(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { if (!IsFloodDone(source_p)) flood_endgrace(source_p); if (parc < 2 || EmptyString(parv[1])) { /* Marking as not away */ if (source_p->away[0]) { source_p->away[0] = '\0'; /* we now send this only if they were away before --is */ sendto_server(client_p, CAP_TS6, NOCAPS, ":%s AWAY", ID(source_p)); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s AWAY", source_p->name); sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY", source_p->name, source_p->username, source_p->host); } sendto_one(source_p, form_str(RPL_UNAWAY), me.name, source_p->name); return; } if ((CurrentTime - source_p->localClient->last_away) < ConfigFileEntry.pace_wait) { sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name); return; } source_p->localClient->last_away = CurrentTime; sendto_one(source_p, form_str(RPL_NOWAWAY), me.name, source_p->name); if (!strncmp(source_p->away, parv[1], sizeof(source_p->away) - 1)) return; strlcpy(source_p->away, parv[1], sizeof(source_p->away)); sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s", source_p->name, source_p->username, source_p->host, source_p->away); sendto_server(client_p, CAP_TS6, NOCAPS, ":%s AWAY :%s", ID(source_p), source_p->away); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s AWAY :%s", source_p->name, source_p->away); }
/* * ms_wallops (write to *all* opers currently online) * parv[1] = message text */ static int ms_wallops(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if (IsClient(source_p)) sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]); else sendto_wallops_flags(UMODE_WALLOP, source_p, "%s", parv[1]); sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", use_id(source_p), parv[1]); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", source_p->name, parv[1]); return 0; }
/* * ms_operwall - OPERWALL message handler * (write to *all* local opers currently online) * parv[0] = sender prefix * parv[1] = message text */ static void ms_operwall(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { const char *message = parv[1]; if (EmptyString(message)) return; sendto_server(client_p, CAP_TS6, NOCAPS, ":%s OPERWALL :%s", ID(source_p), message); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s OPERWALL :%s", source_p->name, message); sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", message); }
/* * part_one_client * * inputs - pointer to server * - pointer to source client to remove * - char pointer of name of channel to remove from * output - none * side effects - remove ONE client given the channel name */ static void part_one_client(struct Client *client_p, struct Client *source_p, char *name, char *reason) { struct Channel *chptr; struct membership *msptr; char reason2[BUFSIZE]; if((chptr = find_channel(name)) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return; } msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return; } if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p)) check_spambot_warning(source_p, NULL); /* * Remove user from the old channel (if any) * only allow /part reasons in -m chans */ if(reason[0] && (is_any_op(msptr) || !MyConnect(source_p) || ((can_send(chptr, source_p, msptr) > 0 && ConfigFileEntry.use_part_messages && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) { if(chptr->mode.mode & MODE_NOCOLOR && (!ConfigChannel.exempt_cmode_c || !is_any_op(msptr))) { rb_strlcpy(reason2, reason, BUFSIZE); strip_colour(reason2); reason = reason2; } sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s :%s", use_id(source_p), chptr->chname, reason); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :\"%s\"", source_p->name, source_p->username, source_p->host, chptr->chname, reason); } else { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", use_id(source_p), chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s", source_p->name, source_p->username, source_p->host, chptr->chname); } remove_user_from_channel(msptr); }
/* If the client never finished authenticating but is * registering anyway, abort the exchange. */ static void abort_sasl(struct Client *data) { if(data->localClient->sasl_out == 0 || data->localClient->sasl_complete) return; data->localClient->sasl_out = data->localClient->sasl_complete = 0; ServerStats.is_sbad++; if(!IsClosing(data)) sendto_one(data, form_str(ERR_SASLABORTED), me.name, EmptyString(data->name) ? "*" : data->name); if(*data->localClient->sasl_agent) { struct Client *agent_p = find_id(data->localClient->sasl_agent); if(agent_p) { sendto_one(agent_p, ":%s ENCAP %s SASL %s %s D A", me.id, agent_p->servptr->name, data->id, agent_p->id); return; } } sendto_server(NULL, NULL, CAP_TS6|CAP_ENCAP, NOCAPS, ":%s ENCAP * SASL %s * D A", me.id, data->id); }
/* * mo_operwall (write to *all* opers currently online) * parv[1] = message text */ static int mo_operwall(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if (!IsOperOperwall(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "operwall"); return 0; } sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]); sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s OPERWALL :%s", use_id(source_p), parv[1]); sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s OPERWALL :%s", source_p->name, parv[1]); return 0; }
void kick_list(struct Client *client_p, struct Client *source_p, struct Channel *chptr, dlink_list *list,char *chname) { struct Client *who; dlink_node *m; dlink_node *next_m; for (m = list->head; m; m = next_m) { next_m = m->next; who = m->data; sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :CLEARCHAN", source_p->name, chname, who->name); sendto_server(NULL, source_p, chptr, NOCAPS, NOCAPS, LL_ICLIENT, ":%s KICK %s %s :CLEARCHAN", source_p->name, chname, who->name); remove_user_from_channel(chptr, who); } /* Join the user themselves to the channel down here, so they dont see a nicklist * or people being kicked */ sendto_one(source_p, ":%s!%s@%s JOIN %s", source_p->name, source_p->username, source_p->host, chname); channel_member_names(source_p, chptr, chname, 1); }
/* check_clean_nick() * * input - pointer to source * - * - nickname * - truncated nickname * - origin of client * - pointer to server nick is coming from * output - none * side effects - if nickname is erroneous, or a different length to * truncated nickname, return 1 */ static int check_clean_nick(struct Client *source_p, char *nick, struct Client *server_p) { /* * The old code did some wacky stuff here, if the nick is invalid, kill it * and don't bother messing at all */ if (!valid_nickname(nick, 0)) { ++ServerStats.is_kill; sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Bad/long Nick: %s From: %s(via %s)", nick, server_p->name, source_p->from->name); sendto_one(source_p, ":%s KILL %s :%s (Bad Nickname)", me.name, nick, me.name); /* Bad nick change */ if (IsClient(source_p) && !MyConnect(source_p)) { sendto_server(source_p, 0, 0, ":%s KILL %s :%s (Bad Nickname)", me.id, source_p->id, me.name); AddFlag(source_p, FLAGS_KILLED); exit_client(source_p, "Bad Nickname"); } return 1; } return 0; }
/*! * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * * - parv[0] = command * - parv[1] = nickname * - parv[2] = timestamp */ static void change_remote_nick(struct Client *source_p, char *parv[]) { int samenick = !irccmp(source_p->name, parv[1]); assert(!EmptyString(parv[1])); assert(IsClient(source_p)); assert(source_p->name[0]); /* Client changing their nick */ if (!samenick) { DelUMode(source_p, UMODE_REGISTERED); watch_check_hash(source_p, RPL_LOGOFF); source_p->tsinfo = atol(parv[2]); assert(source_p->tsinfo > 0); } sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, parv[1]); whowas_add_history(source_p, 1); sendto_server(source_p, 0, 0, ":%s NICK %s :%lu", source_p->id, parv[1], (unsigned long)source_p->tsinfo); /* Set the new nick name */ hash_del_client(source_p); strlcpy(source_p->name, parv[1], sizeof(source_p->name)); hash_add_client(source_p); if (!samenick) watch_check_hash(source_p, RPL_LOGON); }
/* * ms_wallops (write to *all* opers currently online) * parv[1] = message text */ static int ms_wallops(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { const char *prefix = ""; if (MyClient(source_p) && !IsOperMassNotice(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "mass_notice"); return 0; } if (IsPerson(source_p)) { if (!strncmp(parv[1], "OPERWALL - ", 11) || !strncmp(parv[1], "LOCOPS - ", 9) || !strncmp(parv[1], "SLOCOPS - ", 10) || !strncmp(parv[1], "ADMINWALL - ", 12)) prefix = "WALLOPS - "; } sendto_wallops_flags(UMODE_WALLOP, source_p, "%s%s", prefix, parv[1]); sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", use_id(source_p), parv[1]); return 0; }