/* ** m_quit ** parv[1] = comment */ static int m_quit(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char comment[REASONLEN + 1]; /* Better safe than sorry */ char reason[REASONLEN + 1]; source_p->flags |= FLAGS_NORMALEX; strip_colour((parc > 1 && parv[1]) ? parv[1] : client_p->name, comment, REASONLEN); if(ConfigFileEntry.client_exit && comment[0]) { rb_snprintf(reason, sizeof(reason), "Quit: %s", comment); rb_strlcpy(comment, reason, REASONLEN + 1); } if(!IsOper(source_p) && !EmptyString(ConfigFileEntry.static_quit)) { exit_client(client_p, source_p, source_p, ConfigFileEntry.static_quit); return 0; } if(!IsOper(source_p) && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) > rb_current_time()) { exit_client(client_p, source_p, source_p, "Client Quit"); return 0; } exit_client(client_p, source_p, source_p, comment); return 0; }
/* ** m_part ** parv[0] = sender prefix ** parv[1] = channel ** parv[2] = reason */ static int m_part(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char *p, *name; char reason[REASONLEN + 1]; char *s = LOCAL_COPY(parv[1]); reason[0] = '\0'; if(parc > 2) strlcpy(reason, parv[2], sizeof(reason)); name = strtoken(&p, s, ","); /* Finish the flood grace period... */ if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); strip_colour(reason); while(name) { part_one_client(client_p, source_p, name, reason); name = strtoken(&p, NULL, ","); } return 0; }
/* ** m_quit ** parv[1] = comment */ static int m_quit(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char *comment = LOCAL_COPY((parc > 1 && parv[1]) ? parv[1] : client_p->name); char reason[REASONLEN + 1]; source_p->flags |= FLAGS_NORMALEX; if(strlen(comment) > (size_t) REASONLEN) comment[REASONLEN] = '\0'; strip_colour(comment); if(ConfigFileEntry.client_exit && comment[0]) { rb_snprintf(reason, sizeof(reason), "Quit: %s", comment); comment = reason; } if(!IsOper(source_p) && !EmptyString(ConfigFileEntry.static_quit)) { exit_client(client_p, source_p, source_p, ConfigFileEntry.static_quit); return 0; } if(!IsOper(source_p) && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) > rb_current_time()) { exit_client(client_p, source_p, source_p, "Client Quit"); return 0; } exit_client(client_p, source_p, source_p, comment); return 0; }
/* * m_quit * parv[0] = sender prefix * parv[1] = comment */ int m_quit(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) #ifdef TIDY_QUIT { buf[0] = '\0'; if ((parc > 1) && parv[1]) { if (strlen(parv[1]) > (MAX_QUIT_LENGTH - 2)) parv[1][MAX_QUIT_LENGTH - 2] = '\0'; /* Don't add quotes to a null message */ if (MyConnect(sptr) && *parv[1]) { strncpy_irc(buf, "\"", 2); strncat(buf, strip_colour(parv[1]), MAX_QUIT_LENGTH - 2); strncat(buf, "\"", 1); } else strncpy_irc(buf, parv[1], BUFSIZE); } sptr->flags |= FLAGS_NORMALEX; #ifdef ANTI_SPAM_EXIT_MESSAGE /* Your quit message is suppressed if: * * You haven't been connected to the server for long enough */ if( !IsServer(sptr) && MyConnect(sptr) && (sptr->firsttime + ANTI_SPAM_EXIT_MESSAGE_TIME) > CurrentTime) strcpy(buf, "Client Quit"); else if (MyConnect(sptr) && IsPerson(sptr)) { /* Or you are in a channel to which you cannot send */ struct SLink *chptr; for (chptr = sptr->user->channel; chptr; chptr = chptr->next) { if (can_send(sptr, chptr->value.chptr) != 0) { strcpy(buf, "Client Quit"); break; } } } #endif if (IsPerson(sptr)) { sendto_local_ops_flag(UMODE_CCONN, "Client exiting: %s (%s@%s) [%s] [%s] [%s]", sptr->name, sptr->username, sptr->host, #ifdef WINTRHAWK buf, #else (sptr->flags & FLAGS_NORMALEX) ? "Client Quit" : comment, #endif /* WINTRHAWK */ sptr->sockhost, sptr->servptr ? sptr->servptr->name : "<null>"); } return IsServer(sptr) ? 0 : exit_client(cptr, sptr, sptr, buf); }
/* * 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_chanop(msptr) || !MyConnect(source_p) || ((can_send(chptr, source_p, msptr) > 0 && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) { if(chptr->mode.mode & MODE_NOCOLOR) { 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); }
/* * list_one_channel() * * inputs - client pointer, channel pointer, whether normally visible * outputs - none * side effects - a channel is listed */ static void list_one_channel(struct Client *source_p, struct Channel *chptr, int visible) { char topic[TOPICLEN + 1]; if (chptr->topic != NULL) rb_strlcpy(topic, chptr->topic, sizeof topic); else topic[0] = '\0'; strip_colour(topic); sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name, visible ? "" : "!", chptr->chname, rb_dlink_list_length(&chptr->members), topic); }
static void chm_nocolour_process(hook_data_privmsg_channel *data) { /* don't waste CPU if message is already blocked */ if (data->approved) return; if (data->chptr->mode.mode & mode_nocolour) { rb_strlcpy(buf, data->text, sizeof buf); strip_colour(buf); data->text = buf; } }
/* ** send_message ** Internal utility which appends given buffer to the sockets ** sendq. */ static void send_message(struct Client *to, char *buf, int len) { #ifdef INVARIANTS if (IsMe(to)) { sendto_realops_flags(UMODE_ALL, L_ALL, "Trying to send message to myself!"); return; } #endif if (HasUmode(to, UMODE_NOCOLOUR)) strip_colour(buf); if (dbuf_length(&to->localClient->buf_sendq) + len > get_sendq(to)) { if (IsServer(to)) sendto_realops_flags(UMODE_ALL, L_ALL, "Max SendQ limit exceeded for %s: %lu > %lu", get_client_name(to, HIDE_IP), (unsigned long)(dbuf_length(&to->localClient->buf_sendq) + len), get_sendq(to)); if (IsClient(to)) SetSendQExceeded(to); dead_link_on_write(to, 0); return; } dbuf_put(&to->localClient->buf_sendq, buf, len); /* ** Update statistics. The following is slightly incorrect ** because it counts messages even if queued, but bytes ** only really sent. Queued bytes get updated in SendQueued. */ to->localClient->sendM += 1; me.localClient->sendM += 1; if (dbuf_length(&to->localClient->buf_sendq) > (IsServer(to) ? (unsigned int) 1024 : (unsigned int) 4096)) send_queued_write(to); }
static void h_can_send(void *vdata) { char text[BUFSIZE]; hook_data_channel_approval *data = (hook_data_channel_approval *) vdata; if(data->chptr->mode.mode & mymode && (!ConfigChannel.exempt_cmode_c || !is_any_op(data->msptr))) { strip_colour((char *)data->data, text, BUFSIZE); if (EmptyString(text)) { if(data->cmd == COMMAND_PRIVMSG) sendto_one(data->client, form_str(ERR_NOTEXTTOSEND), me.name, data->client->name); data->approved = CAN_SEND_NO_NONOTIFY; return; } /* Copy it */ rb_strlcpy(data->data, text, BUFSIZE); } return; }
/* * 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(IsOperAuspex(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]; char topic[BUFSIZE]; 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) == 0 || is_chanop(msptr)) && can_send(chptr, source_p, msptr))) { if(IsOverride(source_p)) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is overriding TOPIC on [%s]", get_oper_name(source_p), chptr->chname); else { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), get_id(&me, source_p), get_id(source_p, source_p), name); return 0; } } rb_strlcpy(topic, parv[2], BUFSIZE); strip_colour(topic); rb_sprintf(topic_info, "%s!%s@%s", source_p->name, source_p->username, source_p->host); 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 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; }
static int m_message(struct Client *cptr, struct Client *sptr, int parc, char *parv[], int notice) { struct Client *acptr; #ifdef NEED_TLD_FOR_MASS_NOTICE char *s; #endif struct Channel *chptr; char *nick, *server, *host; char errbuf[BUFSIZE]; const char *cmd; int type=0, msgs=0; #ifdef FLUD int flud; #endif cmd = notice ? MSG_NOTICE : MSG_PRIVATE; if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, form_str(ERR_NORECIPIENT), me.name, parv[0], cmd); return -1; } if (parc < 3 || *parv[2] == '\0') { sendto_one(sptr, form_str(ERR_NOTEXTTOSEND), me.name, parv[0]); return -1; } if (MyConnect(sptr)) { #ifdef ANTI_SPAMBOT #ifndef ANTI_SPAMBOT_WARN_ONLY /* if its a spambot, just ignore it */ if(sptr->join_leave_count >= MAX_JOIN_LEAVE_COUNT) return 0; #endif #endif #ifdef NO_DUPE_MULTI_MESSAGES if (strchr(parv[1],',')) parv[1] = canonize(parv[1]); #endif } /* ** channels are privmsg'd a lot more than other clients, moved up here ** plain old channel msg ? */ while(msgs < MAX_MULTI_MESSAGES) { if(!msgs) nick = strtok(parv[1], ","); else nick = strtok(NULL, ","); if(!nick && msgs == 0) nick = parv[1]; else if(!nick) break; if( IsChanPrefix(*nick) && (IsPerson(sptr) && (chptr = hash_find_channel(nick, NullChn)))) { #ifdef FLUD #ifdef DEATHFLUD if(!notice && check_for_ctcp(parv[2]) && check_for_flud(sptr, NULL, chptr, 1)) return 0; if((flud = check_for_spam(sptr, NULL, chptr, parv[2]))) { if (check_for_flud(sptr, NULL, chptr, flud)) return 0; } #else /* DEATHFLUD */ if(!notice) if(check_for_ctcp(parv[2])) check_for_flud(sptr, NULL, chptr, 1); #endif /* DEATHFLUD */ #endif /* FLUD */ /* * Channel color blocking. Usually set with the +c chanmode. * - Andre Guibert de Bruet <*****@*****.**> */ if(chptr->mode.mode & MODE_NOCOLOR) strip_colour(parv[2]); switch (can_send(sptr, chptr)) { case 0: sendto_channel_message_butone(cptr, sptr, chptr, cmd, parv[2]); break; case MODE_QUIETUNIDENT: if (!notice) sendto_one(sptr, form_str(ERR_QUIETUNIDENT), me.name, parv[0], nick); break; case MODE_MODERATED: if (chptr->mode.mode & MODE_OPMODERATE) { /* The flag MODE_OPMODERATE will instruct sendto_channel_type() * to put bare #channel in the message (instead of @#channel); * it will still be sent to ops and servers with ops only. * Strange things will happen if the user is not banned * remotely. * -- jilles */ sendto_channel_type(cptr, sptr, chptr, MODE_CHANOP | MODE_OPMODERATE, nick, cmd, parv[2]); } else { if (!notice) sendto_one(sptr, form_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick); } break; default: break; } msgs++; continue; } /* ** @# type of channel msg? */ if(*nick == '@') type = MODE_CHANOP; else if(*nick == '+') type = MODE_CHANOP|MODE_VOICE; if(type) { /* Strip if using DALnet chanop/voice prefix. */ if (*(nick+1) == '@' || *(nick+1) == '+') { nick++; *nick = '@'; type = MODE_CHANOP|MODE_VOICE; } /* suggested by Mortiis */ if(!*nick) /* if its a '\0' dump it, there is no recipient */ { sendto_one(sptr, form_str(ERR_NORECIPIENT), me.name, parv[0], cmd); return -1; } if (!IsPerson(sptr)) /* This means, servers can't send messages */ return -1; /* At this point, nick+1 should be a channel name i.e. #foo or &foo * if the channel is found, fine, if not report an error */ if ( (chptr = hash_find_channel(nick+1, NullChn)) ) { #ifdef FLUD #ifdef DEATHFLUD if(!notice && check_for_ctcp(parv[2]) && check_for_flud(sptr, NULL, chptr, 1)) return 0; if((flud = check_for_spam(sptr, NULL, chptr, parv[2]))) { if (check_for_flud(sptr, NULL, chptr, flud)) return 0; } #else /* DEATHFLUD */ if(!notice) if(check_for_ctcp(parv[2])) check_for_flud(sptr, NULL, chptr, 1); #endif /* DEATHFLUD */ #endif /* FLUD */ if (!is_chan_op(sptr,chptr)) { if (!notice) { sendto_one(sptr, form_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick); } msgs++; continue; } else { sendto_channel_type(cptr, sptr, chptr, type, nick+1, cmd, parv[2]); } } else { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick); msgs++; continue; } return 0; } /* ** nickname addressed? */ if ((acptr = find_person(nick, NULL))) { #ifdef FLUD #ifdef DEATHFLUD if(!notice && MyConnect(sptr) && check_for_ctcp(parv[2]) && check_for_flud(sptr, acptr, NULL, 1)) return 0; if(MyConnect(sptr) && (flud = check_for_spam(sptr, acptr, NULL, parv[2]))) { if (check_for_flud(sptr, acptr, NULL, flud)) return 0; } #else /* DEATHFLUD */ if(!notice && MyConnect(sptr)) if(check_for_ctcp(parv[2])) if(check_for_flud(sptr, acptr, NULL, 1)) return 0; #endif /* DEATHFLUD */ #endif /* FLUD */ #ifdef ANTI_DRONE_FLOOD if(MyConnect(acptr) && IsClient(sptr) && !NoFloodProtection(sptr) && DRONETIME) { if((acptr->first_received_message_time+DRONETIME) < CurrentTime) { acptr->received_number_of_privmsgs=1; acptr->first_received_message_time = CurrentTime; acptr->drone_noticed = 0; } else { if(acptr->received_number_of_privmsgs > DRONECOUNT) { if(acptr->drone_noticed == 0) /* tiny FSM */ { sendto_ops_flag(UMODE_BOTS, "Possible Drone Flooder %s [%s@%s] on %s target: %s", sptr->name, sptr->username, sptr->host, sptr->user->server, acptr->name); acptr->drone_noticed = 1; } /* heuristic here, if target has been getting a lot * of privmsgs from clients, and sendq is above halfway up * its allowed sendq, then throw away the privmsg, otherwise * let it through. This adds some protection, yet doesn't * DOS the client. * -Dianora */ if(DBufLength(&acptr->sendQ) > (get_sendq(acptr)/2UL)) { if(acptr->drone_noticed == 1) /* tiny FSM */ { sendto_ops_flag(UMODE_BOTS, "ANTI_DRONE_FLOOD SendQ protection activated for %s", acptr->name); sendto_one(acptr, ":%s NOTICE %s :*** Notice -- Server drone flood protection activated for %s", me.name, acptr->name, acptr->name); acptr->drone_noticed = 2; } } if(DBufLength(&acptr->sendQ) <= (get_sendq(acptr)/4UL)) { if(acptr->drone_noticed == 2) { sendto_one(acptr, ":%s NOTICE %s :*** Notice -- Server drone flood protection de-activated for %s", me.name, acptr->name, acptr->name); acptr->drone_noticed = 1; } } if(acptr->drone_noticed > 1) return 0; } else acptr->received_number_of_privmsgs++; } } #endif /* * Simple herustic here... If PRIVMSG is locked down via * F:noidprivmsg:1, then act like every client is +E. * Otherwise, assume the normal behaviour. All in a nice * single if statement. --nenolod */ if (MyClient(sptr) && sptr != acptr && (GlobalSetOptions.noidprivmsg != 0 || HasUmode(acptr,UMODE_BLOCK_NOTID)) && !HasUmode(sptr,UMODE_IDENTIFIED) && !sptr->user->servlogin[0] && !HasUmode(acptr,UMODE_DONTBLOCK) && !HasUmode(sptr,UMODE_DONTBLOCK)) { /* Replace errbuf with either the default or custom message, * then send the numeric on... * --nenolod */ if (GlobalSetOptions.noidprivmsg != 0 && GlobalSetOptions.noidprivmsg_notice[0]) { strncpy_irc(errbuf, GlobalSetOptions.noidprivmsg_notice, BUFSIZE); } else { ircsnprintf(errbuf, BUFSIZE, get_str(STR_NOTID_DEFAULT), nick); } sendto_one(sptr, form_str(ERR_BLOCKING_NOTID), me.name, parv[0], errbuf); return 0; } #ifdef SILENCE /* only check silence masks at the recipient's server -- jilles */ if (!MyConnect(acptr) || !is_silenced(sptr, acptr)) { #endif if (MyConnect(sptr) && acptr->user && (sptr != acptr)) { #ifdef NCTCP /* NCTCP (umode +C) checks -- PMA */ if (parv[2][0] == 1) /* is CTCP */ /* Huh? No way, NOCTCP means NOCTCP. */ /* if (!HasUmode(sptr,UMODE_IMMUNE) && */ /* !HasUmode(acptr,UMODE_IMMUNE)) */ if (HasUmode(acptr,UMODE_NOCTCP) || /* block to +C */ (notice && HasUmode(sptr,UMODE_NOCTCP))) /* block replies from +C */ return 0; /* kill it! */ #endif /* NCTCP */ if (!notice && acptr->user->away) sendto_one(sptr, form_str(RPL_AWAY), me.name, parv[0], acptr->name, acptr->user->away); } { /* here's where we actually send the message */ int is_ctcp = check_for_ctcp(parv[2]); int cap = is_ctcp ? CAP_IDENTIFY_CTCP : CAP_IDENTIFY_MSG; sendto_prefix_one(acptr, sptr, ":%s %s %s :%s%s", parv[0], cmd, nick, !(acptr->caps & cap) ? "" : (HasUmode(sptr, UMODE_IDENTIFIED) ? "+" : "-"), parv[2]); } #ifdef SILENCE } #endif msgs++; continue; } /* Everything below here should be reserved for opers * as pointed out by Mortiis, user%[email protected] * syntax could be used to flood without FLUD protection * its also a delightful way for non-opers to find users who * have changed nicks -Dianora * * Grrr it was pointed out to me that x@service is valid * for non-opers too, and wouldn't allow for flooding/stalking * -Dianora * * Valid or not, @servername is unacceptable, it reveals what server * a person is on. Auspexen only. * -- asuffield */ /* ** the following two cases allow masks in NOTICEs ** (for OPERs only) (with +M -- asuffield) ** ** Armin, 8Jun90 ([email protected]) */ if ((*nick == '$' || *nick == '>')) { if(!HasUmode(sptr,UMODE_MASSNOTICE)) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick); return -1; } #ifdef NEED_TLD_FOR_MASS_NOTICE if (!(s = (char *)strrchr(nick, '.'))) { sendto_one(sptr, form_str(ERR_NOTOPLEVEL), me.name, parv[0], nick); msgs++; continue; } while (*++s) if (*s == '.' || *s == '*' || *s == '?') break; if (*s == '*' || *s == '?') { sendto_one(sptr, form_str(ERR_WILDTOPLEVEL), me.name, parv[0], nick); msgs++; continue; } #endif /* NEED_TLD_FOR_MASS_NOTICE */ sendto_match_butone(IsServer(cptr) ? cptr : NULL, sptr, nick + 1, (*nick == '>') ? MATCH_HOST : MATCH_SERVER, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]); msgs++; continue; } /* ** user[%host]@server addressed? */ if ((server = (char *)strchr(nick, '@')) && (acptr = find_server(server + 1))) { int count = 0; /* Disable the whole farping mess for non-auspexen * -- asuffield */ if (!HasUmode(sptr,UMODE_AUSPEX)) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick); msgs++; continue; } /* Disable the user%host@server form for non-opers * -Dianora */ /* Disabled. This isn't very useful and I don't feel like mucking around with privs for it * -- asuffield */ if((char *)strchr(nick,'%')) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick); msgs++; continue; } /* ** Not destined for a user on me :-( */ if (!IsMe(acptr)) { sendto_one(acptr,":%s %s %s :%s", parv[0], cmd, nick, parv[2]); msgs++; continue; } *server = '\0'; /* special case opers@server */ /* We don't want this on OPN -- asuffield */ #if 0 if(!irccmp(nick,"opers") && SendWallops(sptr)) { sendto_realops("To opers: From %s: %s",sptr->name,parv[2]); msgs++; continue; } #endif if ((host = (char *)strchr(nick, '%'))) *host++ = '\0'; /* ** Look for users which match the destination host ** (no host == wildcard) and if one and one only is ** found connected to me, deliver message! */ acptr = find_userhost(nick, host, NULL, &count); if (server) *server = '@'; if (host) *--host = '%'; if (acptr) { if (count == 1) sendto_prefix_one(acptr, sptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]); else if (!notice) sendto_one(sptr, form_str(ERR_TOOMANYTARGETS), me.name, parv[0], nick, MAX_MULTI_MESSAGES); } if (acptr) { msgs++; continue; } } /* Let's not send these remotely for channels */ if (MyConnect(sptr) || (nick[0] != '#')) sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick); msgs++; } if (strtok(NULL, ",")) sendto_one(sptr, form_str(ERR_TOOMANYTARGETS), me.name, parv[0], cmd, MAX_MULTI_MESSAGES); return 0; }