/* * RPL_NOWON - Online at the moment (Succesfully added to WATCH-list) * RPL_NOWOFF - Offline at the moement (Succesfully added to WATCH-list) * RPL_WATCHOFF - Succesfully removed from WATCH-list. * ERR_TOOMANYWATCH - Take a guess :> Too many WATCH entries. */ static void show_watch(aClient *cptr, char *name, int rpl1, int rpl2, int awaynotify) { aClient *acptr; if ((acptr = find_person(name, NULL))) { if (awaynotify && acptr->user->away) { sendto_one(cptr, rpl_str(RPL_NOWISAWAY), me.name, cptr->name, acptr->name, acptr->user->username, IsHidden(acptr) ? acptr->user->virthost : acptr->user-> realhost, acptr->user->lastaway); return; } sendto_one(cptr, rpl_str(rpl1), me.name, cptr->name, acptr->name, acptr->user->username, IsHidden(acptr) ? acptr->user->virthost : acptr->user-> realhost, acptr->lastnick); } else { sendto_one(cptr, rpl_str(rpl2), me.name, cptr->name, name, "*", "*", 0L); } }
/* ** m_admin ** parv[0] = sender prefix ** parv[1] = servername */ DLLFUNC CMD_FUNC(m_admin) { ConfigItem_admin *admin; /* Users may want to get the address in case k-lined, etc. -- Barubary * Only allow remote ADMINs if registered -- Barubary */ if (IsPerson(sptr) || IsServer(cptr)) if (hunt_server(cptr, sptr, ":%s ADMIN :%s", 1, parc, parv) != HUNTED_ISME) return 0; if (!conf_admin_tail) { sendto_one(sptr, err_str(ERR_NOADMININFO), me.name, parv[0], me.name); return 0; } sendto_one(sptr, rpl_str(RPL_ADMINME), me.name, parv[0], me.name); /* cycle through the list backwards */ for (admin = conf_admin_tail; admin; admin = (ConfigItem_admin *) admin->prev) { if (!admin->next) sendto_one(sptr, rpl_str(RPL_ADMINLOC1), me.name, parv[0], admin->line); else if (!admin->next->next) sendto_one(sptr, rpl_str(RPL_ADMINLOC2), me.name, parv[0], admin->line); else sendto_one(sptr, rpl_str(RPL_ADMINEMAIL), me.name, parv[0], admin->line); } return 0; }
/* ** m_whowas ** parv[0] = sender prefix ** parv[1] = nickname queried */ DLLFUNC CMD_FUNC(m_whowas) { aWhowas *temp; int cur = 0; int max = -1, found = 0; char *p, *nick; if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (parc > 2) max = atoi(parv[2]); if (parc > 3) if (hunt_server_token(cptr, sptr, MSG_WHOWAS, TOK_WHOWAS, "%s %s :%s", 3, parc, parv)) return 0; if (!MyConnect(sptr) && (max > 20)) max = 20; p = (char *)strchr(parv[1], ','); if (p) *p = '\0'; nick = parv[1]; temp = WHOWASHASH[hash_whowas_name(nick)]; found = 0; for (; temp; temp = temp->next) { if (!mycmp(nick, temp->name)) { sendto_one(sptr, rpl_str(RPL_WHOWASUSER), me.name, parv[0], temp->name, temp->username, (IsOper(sptr) ? temp->hostname : (*temp->virthost != '\0') ? temp->virthost : temp->hostname), temp->realname); if (!((Find_uline(temp->servername)) && !IsOper(sptr) && HIDE_ULINES)) sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], temp->name, temp->servername, myctime(temp->logoff)); cur++; found++; } if (max > 0 && cur >= max) break; } if (!found) sendto_one(sptr, err_str(ERR_WASNOSUCHNICK), me.name, parv[0], nick); sendto_one(sptr, rpl_str(RPL_ENDOFWHOWAS), me.name, parv[0], parv[1]); return 0; }
/* * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce * the need for complicated requests like WHOIS. It returns user/host * information only (no spurious AWAY labels or channels). * Re-written by Dianora 1999 */ DLLFUNC CMD_FUNC(m_userhost) { char *p; /* scratch end pointer */ char *cn; /* current name */ struct Client *acptr; char response[5][NICKLEN * 2 + CHANNELLEN + USERLEN + HOSTLEN + 30]; int i; /* loop counter */ if (parc < 2) { sendto_one(sptr, rpl_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERHOST"); return 0; } /* The idea is to build up the response string out of pieces * none of this strlen() nonsense. * 5 * (NICKLEN*2+CHANNELLEN+USERLEN+HOSTLEN+30) is still << sizeof(buf) * and our ircsprintf() truncates it to fit anyway. There is * no danger of an overflow here. -Dianora */ response[0][0] = response[1][0] = response[2][0] = response[3][0] = response[4][0] = '\0'; cn = parv[1]; for (i = 0; (i < 5) && cn; i++) { if ((p = strchr(cn, ' '))) *p = '\0'; if ((acptr = find_person(cn, NULL))) { ircsprintf(response[i], "%s%s=%c%s@%s", acptr->name, (IsAnOper(acptr) && (!IsHideOper(acptr) || sptr == acptr || IsAnOper(sptr))) ? "*" : "", (acptr->user->away) ? '-' : '+', acptr->user->username, ((acptr != sptr) && !IsOper(sptr) && IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost)); } if (p) p++; cn = p; } sendto_one(sptr, rpl_str(RPL_USERHOST), me.name, parv[0], response[0], response[1], response[2], response[3], response[4]); return 0; }
static int do_jumpserver_exit_client(aClient *sptr) { #ifdef USE_SSL if (IsSecure(sptr) && jss->ssl_server) sendto_one(sptr, rpl_str(RPL_REDIR), me.name, BadPtr(sptr->name) ? "*" : sptr->name, jss->ssl_server, jss->ssl_port); else #endif sendto_one(sptr, rpl_str(RPL_REDIR), me.name, BadPtr(sptr->name) ? "*" : sptr->name, jss->server, jss->port); return exit_client(sptr, sptr, sptr, jss->reason); }
/* * Heavily modified from the ircu m_motd by codemastr * Also svsmotd support added */ DLLFUNC CMD_FUNC(m_rules) { ConfigItem_tld *ptr; aMotd *temp; char userhost[USERLEN + HOSTLEN + 6]; if (IsServer(sptr)) return 0; if (hunt_server_token(cptr, sptr, MSG_RULES, TOK_RULES, ":%s", 1, parc, parv) != HUNTED_ISME) return 0; #ifndef TLINE_Remote if (!MyConnect(sptr)) { temp = rules; goto playrules; } #endif strlcpy(userhost,make_user_host(cptr->user->username, cptr->user->realhost), sizeof userhost); ptr = Find_tld(sptr, userhost); if (ptr) { temp = ptr->rules; } else temp = rules; playrules: if (temp == NULL) { sendto_one(sptr, err_str(ERR_NORULES), me.name, parv[0]); return 0; } sendto_one(sptr, rpl_str(RPL_RULESSTART), me.name, parv[0], me.name); while (temp) { sendto_one(sptr, rpl_str(RPL_RULES), me.name, parv[0], temp->line); temp = temp->next; } sendto_one(sptr, rpl_str(RPL_ENDOFRULES), me.name, parv[0]); return 0; }
void SnomaskDel(Snomask *sno) { if (loop.ircd_rehashing) sno->unloaded = 1; else { int i; for (i = 0; i <= LastSlot; i++) { aClient *cptr = local[i]; long oldsno; if (!cptr || !IsPerson(cptr)) continue; oldsno = cptr->user->snomask; cptr->user->snomask &= ~sno->mode; if (oldsno != cptr->user->snomask) sendto_one(cptr, rpl_str(RPL_SNOMASK), me.name, cptr->name, get_snostr(cptr->user->snomask)); } sno->flag = '\0'; } if (sno->owner) { ModuleObject *snoobj; for (snoobj = sno->owner->objects; snoobj; snoobj = snoobj->next) { if (snoobj->type == MOBJ_SNOMASK && snoobj->object.snomask == sno) { DelListItem(snoobj, sno->owner->objects); MyFree(snoobj); break; } } sno->owner = NULL; } return; }
void unload_all_unused_snomasks() { long removed_sno = 0; int i; for (i = 0; i < UMODETABLESZ; i++) { if (Snomask_Table[i].unloaded) { removed_sno |= Snomask_Table[i].mode; Snomask_Table[i].flag = '\0'; Snomask_Table[i].unloaded = 0; } } if (!removed_sno) /* Nothing was unloaded */ return; for (i = 0; i <= LastSlot; i++) { aClient *cptr = local[i]; long oldsno; if (!cptr || !IsPerson(cptr)) continue; oldsno = cptr->user->snomask; cptr->user->snomask &= ~(removed_sno); if (oldsno != cptr->user->snomask) sendto_one(cptr, rpl_str(RPL_SNOMASK), me.name, cptr->name, get_snostr(cptr->user->snomask)); } }
int add_dccallow(aClient *sptr, aClient *optr) { Link *lp; int cnt = 0; for (lp = sptr->user->dccallow; lp; lp = lp->next) { if (lp->flags != DCC_LINK_ME) continue; if (++cnt >= MAXDCCALLOW) { sendto_one(sptr, err_str(ERR_TOOMANYDCC), me.name, sptr->name, optr->name, MAXDCCALLOW); return 0; } else if (lp->value.cptr == optr) return 0; } lp = make_link(); lp->value.cptr = optr; lp->flags = DCC_LINK_ME; lp->next = sptr->user->dccallow; sptr->user->dccallow = lp; lp = make_link(); lp->value.cptr = sptr; lp->flags = DCC_LINK_REMOTE; lp->next = optr->user->dccallow; optr->user->dccallow = lp; sendto_one(sptr, rpl_str(RPL_DCCSTATUS), me.name, sptr->name, optr->name, "added to"); return 0; }
DLLFUNC int listreg(Cmdoverride *anoverride, aClient *cptr, aClient *sptr, int parc, char *parv[]) { if (!IsAnOper(sptr)) { if (!IsARegNick(sptr)) { sendto_one(sptr, ":%s %s %s :in order to use this command to need to register your nickname", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name); sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, sptr->name); sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name); return 0; } } return CallCmdoverride(listreg_override, cptr, sptr, parc, parv); }
DLLFUNC int m_delaylist(Cmdoverride *anoverride, aClient *cptr, aClient *sptr, int parc, char *parv[]) { if (!IsAnOper(sptr)) { if (sptr->firsttime + 10 > TStime()) { /* DENIED! */ sendto_one(sptr, ":%s %s %s :*** You have not been connected long enough " "to use /list. You must wait 30 seconds after connecting", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name); /* if we don't do this, some clients have a hissy :p */ sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, sptr->name); sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name); return 0; } } /* aww, no fun. they've been connected a while :( - let it through */ return CallCmdoverride(delaylist_override, cptr, sptr, parc, parv); }
DLLFUNC CMD_FUNC(m_starttls) { if (!MyConnect(sptr) || !IsUnknown(sptr)) return 0; #ifndef USE_SSL /* sendnotice(sptr, "This server does not support SSL"); */ /* or numeric 691? */ /* actually... it's probably best to just act like we don't know this command...? */ sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS"); return 0; #else if (iConf.ssl_options & SSLFLAG_NOSTARTTLS) { sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS"); return 0; } if (IsSecure(sptr)) { sendto_one(sptr, err_str(ERR_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*", "STARTTLS failed. Already using TLS."); return 0; } dbuf_delete(&sptr->recvQ, 1000000); /* Clear up any remaining plaintext commands */ sendto_one(sptr, rpl_str(RPL_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*"); send_queued(sptr); SetSSLStartTLSHandshake(sptr); Debug((DEBUG_DEBUG, "Starting SSL handshake (due to STARTTLS) for %s", sptr->sockhost)); if ((sptr->ssl = SSL_new(ctx_server)) == NULL) goto fail; sptr->flags |= FLAGS_SSL; SSL_set_fd(sptr->ssl, sptr->fd); SSL_set_nonblocking(sptr->ssl); if (!ircd_SSL_accept(sptr, sptr->fd)) { Debug((DEBUG_DEBUG, "Failed SSL accept handshake in instance 1: %s", sptr->sockhost)); SSL_set_shutdown(sptr->ssl, SSL_RECEIVED_SHUTDOWN); SSL_smart_shutdown(sptr->ssl); SSL_free(sptr->ssl); goto fail; } /* HANDSHAKE IN PROGRESS */ return 0; fail: /* Failure */ sendto_one(sptr, err_str(ERR_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*", "STARTTLS failed"); sptr->ssl = NULL; sptr->flags &= ~FLAGS_SSL; SetUnknown(sptr); return 0; #endif }
int del_dccallow(aClient *sptr, aClient *optr) { Link **lpp, *lp; int found = 0; for (lpp = &(sptr->user->dccallow); *lpp; lpp=&((*lpp)->next)) { if ((*lpp)->flags != DCC_LINK_ME) continue; if ((*lpp)->value.cptr == optr) { lp = *lpp; *lpp = lp->next; free_link(lp); found++; break; } } if (!found) { sendto_one(sptr, ":%s %d %s :%s is not in your DCC allow list", me.name, RPL_DCCINFO, sptr->name, optr->name); return 0; } for (found = 0, lpp = &(optr->user->dccallow); *lpp; lpp=&((*lpp)->next)) { if ((*lpp)->flags != DCC_LINK_REMOTE) continue; if ((*lpp)->value.cptr == sptr) { lp = *lpp; *lpp = lp->next; free_link(lp); found++; break; } } if (!found) sendto_realops("[BUG!] %s was in dccallowme list of %s but not in dccallowrem list!", optr->name, sptr->name); sendto_one(sptr, rpl_str(RPL_DCCSTATUS), me.name, sptr->name, optr->name, "removed from"); return 0; }
/** Report privileges of \a client to \a to. * @param[in] to Client requesting privilege list. * @param[in] client Client whos privileges should be listed. * @return Zero. */ int client_report_privs(struct Client *to, struct Client *client) { struct MsgBuf *mb; int found1 = 0; int i; mb = msgq_make(to, rpl_str(RPL_PRIVS), cli_name(&me), cli_name(to), cli_name(client)); for (i = 0; privtab[i].name; i++) if (HasPriv(client, privtab[i].priv)) msgq_append(0, mb, "%s%s", found1++ ? " " : "", privtab[i].name); send_buffer(to, mb, 0); /* send response */ msgq_clean(mb); return 0; }
void send_snomask (aClient * client_p, aClient * source_p, int old, int sendmask, char *umode_buf) { int *s, flag; char *m; /* * build a string in umode_buf to represent the change in the user's * mode between the new (source_p->flag) and 'old'. */ m = umode_buf; m = buf; for (s = snomask_chars; (flag = *s) && (m - buf < BUFSIZE - 4); s += 2) { if (client_p->snomask & flag) *m++ = (char) (*(s + 1)); } *m = '\0'; if (*umode_buf && client_p) sendto_one (client_p, rpl_str(RPL_SNOMASKIS), me.name, source_p->name, umode_buf); }
void m_info_send(aClient *sptr) { char **text = unrealinfo; sendto_one(sptr, ":%s %d %s :=-=-=-= %s =-=-=-=", me.name, RPL_INFO, sptr->name, IRCDTOTALVERSION); while (*text) sendto_one(sptr, ":%s %d %s :| %s", me.name, RPL_INFO, sptr->name, *text++); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| Credits - Type /Credits", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| DALnet Credits - Type /DalInfo", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| This is an UnrealIRCd-style server", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| If you find any bugs, please report them at:", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| http://bugs.unrealircd.org/", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| UnrealIRCd Homepage: http://www.unrealircd.com", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :Birth Date: %s, compile # %s", me.name, RPL_INFO, sptr->name, creation, generation); sendto_one(sptr, ":%s %d %s :On-line since %s", me.name, RPL_INFO, sptr->name, myctime(me.firsttime)); sendto_one(sptr, ":%s %d %s :ReleaseID (%s)", me.name, RPL_INFO, sptr->name, buildid); sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, sptr->name); }
DLLFUNC CMD_FUNC(m_ison) { char namebuf[USERLEN + HOSTLEN + 4]; aClient *acptr; char *s, **pav = parv, *user; int len; char *p = NULL; if (parc < 2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "ISON"); return 0; } ircsnprintf(buf, sizeof(buf), rpl_str(RPL_ISON), me.name, *parv); len = strlen(buf); for (s = strtok_r(*++pav, " ", &p); s; s = strtok_r(NULL, " ", &p)) { if ((user = index(s, '!'))) *user++ = '\0'; if ((acptr = find_person(s, NULL))) { if (user) { ircsnprintf(namebuf, sizeof(namebuf), "%s@%s", acptr->user->username, GetHost(acptr)); if (match(user, namebuf)) continue; *--user = '******'; } (void)strncat(buf, s, sizeof(buf) - (len+1)); len += strlen(s); (void)strncat(buf, " ", sizeof(buf) - (len+1)); len++; } } sendto_one(sptr, "%s", buf); return 0; }
static void report_unsortable_klines(aClient *sptr,char *need_host) { aConfItem *found_conf; char *host; char *pass; char *name; int port; for(found_conf = unsortable_list_klines; found_conf;found_conf=found_conf->next) { host = BadPtr(found_conf->host) ? null : found_conf->host; pass = BadPtr(found_conf->passwd) ? null : found_conf->passwd; name = BadPtr(found_conf->name) ? null : found_conf->name; port = (int)found_conf->port; if(!match(host,need_host)) { sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name, sptr->name, 'K', host, name, pass); } } }
/* ** m_whois ** parv[0] = sender prefix ** parv[1] = nickname masklist */ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Membership *lp; anUser *user; aClient *acptr, *a2cptr; aChannel *chptr; char *nick, *tmp, *name; char *p = NULL; int found, len, mlen, cnt = 0; char querybuf[BUFSIZE]; if (IsServer(sptr)) return 0; if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (parc > 2) { if (hunt_server(cptr, sptr, ":%s WHOIS %s :%s", 1, parc, parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } strcpy(querybuf, parv[1]); for (tmp = canonize(parv[1]); (nick = strtok_r(tmp, ",", &p)); tmp = NULL) { unsigned char invis, showchannel, member, wilds, hideoper; /* <- these are all boolean-alike */ if (++cnt > MAXTARGETS) break; found = 0; /* We do not support "WHOIS *" */ wilds = (index(nick, '?') || index(nick, '*')); if (wilds) continue; if ((acptr = find_client(nick, NULL))) { if (IsServer(acptr)) continue; /* * I'm always last :-) and acptr->next == NULL!! */ if (IsMe(acptr)) break; /* * 'Rules' established for sending a WHOIS reply: * - only send replies about common or public channels * the target user(s) are on; */ if (!IsPerson(acptr)) continue; user = acptr->user; name = (!*acptr->name) ? "?" : acptr->name; invis = acptr != sptr && IsInvisible(acptr); member = (user->channel) ? 1 : 0; a2cptr = find_server_quick(user->server); hideoper = 0; if (IsHideOper(acptr) && (acptr != sptr) && !IsAnOper(sptr)) hideoper = 1; if (IsWhois(acptr) && (sptr != acptr)) { sendnotice(acptr, "*** %s (%s@%s) did a /whois on you.", sptr->name, sptr->user->username, sptr->user->realhost); } sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, parv[0], name, user->username, IsHidden(acptr) ? user->virthost : user->realhost, acptr->info); if (IsOper(sptr) || acptr == sptr) { char sno[512]; strcpy(sno, get_sno_str(acptr)); /* send the target user's modes */ sendto_one(sptr, rpl_str(RPL_WHOISMODES), me.name, parv[0], name, get_mode_str(acptr), sno[1] == 0 ? "" : sno); } if ((acptr == sptr) || IsAnOper(sptr)) { sendto_one(sptr, rpl_str(RPL_WHOISHOST), me.name, parv[0], acptr->name, (MyConnect(acptr) && strcmp(acptr->username, "unknown")) ? acptr->username : "******", user->realhost, user->ip_str ? user->ip_str : ""); } if (IsARegNick(acptr)) sendto_one(sptr, rpl_str(RPL_WHOISREGNICK), me.name, parv[0], name); found = 1; mlen = strlen(me.name) + strlen(parv[0]) + 10 + strlen(name); for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next) { chptr = lp->chptr; showchannel = 0; if (ShowChannel(sptr, chptr)) showchannel = 1; if (OPCanSeeSecret(sptr)) showchannel = 1; if ((acptr->umodes & UMODE_HIDEWHOIS) && !IsMember(sptr, chptr) && !IsAnOper(sptr)) showchannel = 0; if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr)) showchannel = 0; if (acptr == sptr) showchannel = 1; /* Hey, if you are editting here... don't forget to change the webtv w_whois ;p. */ if (showchannel) { long access; if (len + strlen(chptr->chname) > (size_t)BUFSIZE - 4 - mlen) { sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISCHANNELS, parv[0], name, buf); *buf = '\0'; len = 0; } #ifdef SHOW_SECRET if (IsAnOper(sptr) #else if (IsNetAdmin(sptr) #endif && SecretChannel(chptr) && !IsMember(sptr, chptr)) *(buf + len++) = '?'; if (acptr->umodes & UMODE_HIDEWHOIS && !IsMember(sptr, chptr) && IsAnOper(sptr)) *(buf + len++) = '!'; access = get_access(acptr, chptr); if (!SupportNAMESX(sptr)) { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; else if (access & CHFL_CHANPROT) *(buf + len++) = '&'; else #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; else if (access & CHFL_HALFOP) *(buf + len++) = '%'; else if (access & CHFL_VOICE) *(buf + len++) = '+'; } else { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; if (access & CHFL_CHANPROT) *(buf + len++) = '&'; #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; if (access & CHFL_HALFOP) *(buf + len++) = '%'; if (access & CHFL_VOICE) *(buf + len++) = '+'; } if (len) *(buf + len) = '\0'; (void)strcpy(buf + len, chptr->chname); len += strlen(chptr->chname); (void)strcat(buf + len, " "); len++; } } if (buf[0] != '\0') sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, parv[0], name, buf); if (!(IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES)) sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], name, user->server, a2cptr ? a2cptr->info : "*Not On This Net*"); if (user->away) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, user->away); /* makesure they aren't +H (we'll also check before we display a helpop or IRCD Coder msg) -- codemastr */ if ((IsAnOper(acptr) || IsServices(acptr)) && !hideoper) { buf[0] = '\0'; if (IsNetAdmin(acptr)) strlcat(buf, "a Network Administrator", sizeof buf); else if (IsSAdmin(acptr)) strlcat(buf, "a Services Administrator", sizeof buf); else if (IsAdmin(acptr) && !IsCoAdmin(acptr)) strlcat(buf, "a Server Administrator", sizeof buf); else if (IsCoAdmin(acptr)) strlcat(buf, "a Co Administrator", sizeof buf); else if (IsServices(acptr)) strlcat(buf, "a Network Service", sizeof buf); else if (IsOper(acptr)) strlcat(buf, "an IRC Operator", sizeof buf); else strlcat(buf, "a Local IRC Operator", sizeof buf); if (buf[0]) { if (IsOper(sptr) && MyClient(acptr)) sendto_one(sptr, ":%s 313 %s %s :is %s (%s)", me.name, parv[0], name, buf, acptr->user->operlogin); else sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR), me.name, parv[0], name, buf); } } if (IsHelpOp(acptr) && !hideoper && !user->away) sendto_one(sptr, rpl_str(RPL_WHOISHELPOP), me.name, parv[0], name); if (acptr->umodes & UMODE_BOT) sendto_one(sptr, rpl_str(RPL_WHOISBOT), me.name, parv[0], name, ircnetwork); if (acptr->umodes & UMODE_SECURE) sendto_one(sptr, rpl_str(RPL_WHOISSECURE), me.name, parv[0], name, "is using a Secure Connection"); if (!BadPtr(user->swhois) && !hideoper) sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISSPECIAL, parv[0], name, acptr->user->swhois); /* * display services account name if it's actually a services account name and * not a legacy timestamp. --nenolod */ if (!isdigit(*user->svid)) sendto_one(sptr, rpl_str(RPL_WHOISLOGGEDIN), me.name, parv[0], name, user->svid); /* * Umode +I hides an oper's idle time from regular users. * -Nath. */ if (MyConnect(acptr) && (IsAnOper(sptr) || !(acptr->umodes & UMODE_HIDLE))) { sendto_one(sptr, rpl_str(RPL_WHOISIDLE), me.name, parv[0], name, TStime() - acptr->last, acptr->firsttime); } } if (!found) sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick); } sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], querybuf); return 0; }
/* * Heavily modified from the ircu m_motd by codemastr * Also svsmotd support added */ int short_motd(aClient *sptr) { ConfigItem_tld *tld; aMotdFile *themotd; aMotdLine *motdline; struct tm *tm; char userhost[HOSTLEN + USERLEN + 6]; char is_short; tm = NULL; is_short = 1; strlcpy(userhost,make_user_host(sptr->user->username, sptr->user->realhost), sizeof userhost); tld = Find_tld(sptr, userhost); /* * Try different sources of short MOTDs, falling back to the * long MOTD. */ themotd = &smotd; if (tld && tld->smotd.lines) themotd = &tld->smotd; /* try long MOTDs */ if (!themotd->lines) { is_short = 0; if (tld && tld->motd.lines) themotd = &tld->motd; else themotd = &motd; } if (!themotd->lines) { sendto_one(sptr, err_str(ERR_NOMOTD), me.name, sptr->name); return 0; } if (themotd->last_modified.tm_year) { tm = &themotd->last_modified; /* for readability */ sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, sptr->name, me.name); sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_MOTD, sptr->name, tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year, tm->tm_hour, tm->tm_min); } if (is_short) { sendto_one(sptr, rpl_str(RPL_MOTD), me.name, sptr->name, "This is the short MOTD. To view the complete MOTD type /motd"); sendto_one(sptr, rpl_str(RPL_MOTD), me.name, sptr->name, ""); } motdline = NULL; if (themotd) motdline = themotd->lines; while (motdline) { sendto_one(sptr, rpl_str(RPL_MOTD), me.name, sptr->name, motdline->line); motdline = motdline->next; } sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, sptr->name); return 0; }
static void report_sub_mtrie(aClient *sptr, int flags, DOMAIN_LEVEL *dl_ptr) { DOMAIN_PIECE *dp_ptr; aConfItem *aconf; int i; char *p; char *host; char *pass; char *name; char *mask; int port; char c; if(!dl_ptr) return; for(i=0; i < MAX_PIECE_LIST; i++) { for(dp_ptr=dl_ptr->piece_list[i];dp_ptr; dp_ptr = dp_ptr->next_piece) { report_sub_mtrie(sptr,flags,dp_ptr->next_level); if(dp_ptr->conf_ptr) { /* Only show desired I/K lines */ aconf = dp_ptr->conf_ptr; if(aconf->status & flags) { host = BadPtr(aconf->host) ? null : aconf->host; pass = BadPtr(aconf->passwd) ? null : aconf->passwd; name = BadPtr(aconf->name) ? null : aconf->name; mask = BadPtr(aconf->mask) ? null : aconf->mask; port = (int)aconf->port; if (aconf->status == CONF_KILL) { sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name, sptr->name, 'K', host, name, pass); } else { c = 'I'; #ifdef LITTLE_I_LINES if(IsConfLittleI(aconf)) c = 'i'; #endif sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name, sptr->name, c, mask, show_iline_prefix(sptr,aconf,name), host, port, get_conf_class(aconf)); } } } if(dp_ptr->wild_conf_ptr) { aconf = dp_ptr->wild_conf_ptr; if(aconf->status & flags) { host = BadPtr(aconf->host) ? null : aconf->host; pass = BadPtr(aconf->passwd) ? null : aconf->passwd; name = BadPtr(aconf->name) ? null : aconf->name; mask = BadPtr(aconf->mask) ? null : aconf->mask; port = (int)aconf->port; if (aconf->status == CONF_KILL) { sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name, sptr->name, 'K', host, name, pass); } else { sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name, sptr->name, c, mask, show_iline_prefix(sptr,aconf,name), host, port, get_conf_class(aconf)); } } } } } }
void report_mtrie_conf_links(aClient *sptr, int flags) { aConfItem *found_conf; char *host; char *pass; char *name; char *mask; int port; char c; /* conf char used for CONF_CLIENT only */ if(trie_list) report_sub_mtrie(sptr,flags,trie_list); /* If requesting I lines do this */ if(flags & CONF_CLIENT) { for(found_conf = unsortable_list_ilines; found_conf;found_conf=found_conf->next) { host = BadPtr(found_conf->host) ? null : found_conf->host; pass = BadPtr(found_conf->passwd) ? null : found_conf->passwd; name = BadPtr(found_conf->name) ? null : found_conf->name; mask = BadPtr(found_conf->mask) ? null : found_conf->mask; port = (int)found_conf->port; c = 'I'; #ifdef LITTLE_I_LINES if(IsConfLittleI(found_conf)) c = 'i'; #endif sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name, sptr->name, c, mask, show_iline_prefix(sptr,found_conf,name), host, port, get_conf_class(found_conf)); } for(found_conf = wild_card_ilines; found_conf;found_conf=found_conf->next) { host = BadPtr(found_conf->host) ? null : found_conf->host; pass = BadPtr(found_conf->passwd) ? null : found_conf->passwd; name = BadPtr(found_conf->name) ? null : found_conf->name; mask = BadPtr(found_conf->mask) ? null : found_conf->mask; port = (int)found_conf->port; if(!(found_conf->status&CONF_CLIENT)) continue; c = 'I'; #ifdef LITTLE_I_LINES if(IsConfLittleI(found_conf)) c = 'i'; #endif sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name, sptr->name, c, mask, show_iline_prefix(sptr,found_conf,name), host, port, get_conf_class(found_conf)); } } else { report_dline_hash(sptr,CONF_KILL); for(found_conf = unsortable_list_klines; found_conf;found_conf=found_conf->next) { host = BadPtr(found_conf->host) ? null : found_conf->host; pass = BadPtr(found_conf->passwd) ? null : found_conf->passwd; name = BadPtr(found_conf->name) ? null : found_conf->name; port = (int)found_conf->port; sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name, sptr->name, 'K', host, name, pass); } } }
DLLFUNC CMD_FUNC(m_names) { int uhnames = (MyConnect(sptr) && SupportUHNAMES(sptr)); // cache UHNAMES support int bufLen = NICKLEN + (!uhnames ? 0 : (1 + USERLEN + 1 + HOSTLEN)); int mlen = strlen(me.name) + bufLen + 7; aChannel *chptr; aClient *acptr; int member; Member *cm; int idx, flag = 1, spos; char *s, *para = parv[1]; char nuhBuffer[NICKLEN+USERLEN+HOSTLEN+3]; if (parc < 2 || !MyConnect(sptr)) { sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*"); return 0; } for (s = para; *s; s++) { if (*s == ',') { if (strlen(para) > TRUNCATED_NAMES) para[TRUNCATED_NAMES] = '\0'; sendto_realops("names abuser %s %s", get_client_name(sptr, FALSE), para); sendto_one(sptr, err_str(ERR_TOOMANYTARGETS), me.name, sptr->name, "NAMES"); return 0; } } chptr = find_channel(para, (aChannel *)NULL); if (!chptr || (!ShowChannel(sptr, chptr) && !OPCanSeeSecret(sptr))) { sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para); return 0; } /* cache whether this user is a member of this channel or not */ member = IsMember(sptr, chptr); if (PubChannel(chptr)) buf[0] = '='; else if (SecretChannel(chptr)) buf[0] = '@'; else buf[0] = '*'; idx = 1; buf[idx++] = ' '; for (s = chptr->chname; *s; s++) buf[idx++] = *s; buf[idx++] = ' '; buf[idx++] = ':'; /* If we go through the following loop and never add anything, we need this to be empty, otherwise spurious things from the LAST /names call get stuck in there.. - lucas */ buf[idx] = '\0'; spos = idx; /* starting point in buffer for names! */ for (cm = chptr->members; cm; cm = cm->next) { acptr = cm->cptr; if (IsInvisible(acptr) && !member && !IsNetAdmin(sptr)) continue; if (chptr->mode.mode & MODE_AUDITORIUM) if (!is_chan_op(sptr, chptr) && !is_chanprot(sptr, chptr) && !is_chanowner(sptr, chptr)) if (!(cm-> flags & (CHFL_CHANOP | CHFL_CHANPROT | CHFL_CHANOWNER)) && acptr != sptr) continue; if (!SupportNAMESX(sptr)) { /* Standard NAMES reply */ #ifdef PREFIX_AQ if (cm->flags & CHFL_CHANOWNER) buf[idx++] = '~'; else if (cm->flags & CHFL_CHANPROT) buf[idx++] = '&'; else #endif if (cm->flags & CHFL_CHANOP) buf[idx++] = '@'; else if (cm->flags & CHFL_HALFOP) buf[idx++] = '%'; else if (cm->flags & CHFL_VOICE) buf[idx++] = '+'; } else { /* NAMES reply with all rights included (NAMESX) */ #ifdef PREFIX_AQ if (cm->flags & CHFL_CHANOWNER) buf[idx++] = '~'; if (cm->flags & CHFL_CHANPROT) buf[idx++] = '&'; #endif if (cm->flags & CHFL_CHANOP) buf[idx++] = '@'; if (cm->flags & CHFL_HALFOP) buf[idx++] = '%'; if (cm->flags & CHFL_VOICE) buf[idx++] = '+'; } if (!uhnames) { s = acptr->name; } else { strlcpy(nuhBuffer, make_nick_user_host(acptr->name, acptr->user->username, GetHost(acptr)), bufLen + 1); s = nuhBuffer; } /* 's' is intialized above to point to either acptr->name (normal), * or to nuhBuffer (for UHNAMES). */ for (; *s; s++) buf[idx++] = *s; buf[idx++] = ' '; buf[idx] = '\0'; flag = 1; if (mlen + idx + bufLen > BUFSIZE - 7) { sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf); idx = spos; flag = 0; } } if (flag) sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf); sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para); return 0; }
/* m_dccallow: * HISTORY: * Taken from bahamut 1.8.1 */ DLLFUNC int m_dccallow(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Link *lp; char *p, *s; aClient *acptr; int didlist = 0, didhelp = 0, didanything = 0; char **ptr; static char *dcc_help[] = { "/DCCALLOW [<+|->nick[,<+|->nick, ...]] [list] [help]", "You may allow DCCs of files which are otherwise blocked by the IRC server", "by specifying a DCC allow for the user you want to recieve files from.", "For instance, to allow the user Bob to send you file.exe, you would type:", "/DCCALLOW +bob", "and Bob would then be able to send you files. Bob will have to resend the file", "if the server gave him an error message before you added him to your allow list.", "/DCCALLOW -bob", "Will do the exact opposite, removing him from your dcc allow list.", "/dccallow list", "Will list the users currently on your dcc allow list.", NULL }; if (!MyClient(sptr)) return 0; if (parc < 2) { sendnotice(sptr, "No command specified for DCCALLOW. " "Type '/DCCALLOW HELP' for more information."); return 0; } for (p = NULL, s = strtoken(&p, parv[1], ", "); s; s = strtoken(&p, NULL, ", ")) { if (*s == '+') { didanything = 1; if (!*++s) continue; acptr = find_person(s, NULL); if (acptr == sptr) continue; if (!acptr) { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, s); continue; } add_dccallow(sptr, acptr); } else if (*s == '-') { didanything = 1; if (!*++s) continue; acptr = find_person(s, NULL); if (acptr == sptr) continue; if (!acptr) { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, s); continue; } del_dccallow(sptr, acptr); } else if (!didlist && !myncmp(s, "list", 4)) { didanything = didlist = 1; sendto_one(sptr, ":%s %d %s :The following users are on your dcc allow list:", me.name, RPL_DCCINFO, sptr->name); for(lp = sptr->user->dccallow; lp; lp = lp->next) { if (lp->flags == DCC_LINK_REMOTE) continue; sendto_one(sptr, ":%s %d %s :%s (%s@%s)", me.name, RPL_DCCLIST, sptr->name, lp->value.cptr->name, lp->value.cptr->user->username, GetHost(lp->value.cptr)); } sendto_one(sptr, rpl_str(RPL_ENDOFDCCLIST), me.name, sptr->name, s); } else if (!didhelp && !myncmp(s, "help", 4)) { didanything = didhelp = 1; for(ptr = dcc_help; *ptr; ptr++) sendto_one(sptr, ":%s %d %s :%s", me.name, RPL_DCCINFO, sptr->name, *ptr); sendto_one(sptr, rpl_str(RPL_ENDOFDCCLIST), me.name, sptr->name, s); } } if (!didanything) { sendnotice(sptr, "Invalid syntax for DCCALLOW. Type '/DCCALLOW HELP' for more information."); return 0; } return 0; }
/* * do_svssno() * parv[0] - sender * parv[1] - username to change snomask for * parv[2] - snomasks to change * show_change determines whether to show the change to the user */ int do_svssno(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_change) { char *p; aClient *acptr; int what = MODE_ADD, i; if (!IsULine(sptr)) return 0; if (parc < 2) return 0; if (parv[1][0] == '#') return 0; if (!(acptr = find_person(parv[1], NULL))) return 0; if (hunt_server_token(cptr, sptr, show_change ? MSG_SVS2SNO : MSG_SVSSNO, show_change ? TOK_SVS2SNO : TOK_SVSSNO, "%s %s", 1, parc, parv) != HUNTED_ISME) { return 0; } if (MyClient(acptr)) { if (parc == 2) acptr->user->snomask = 0; else { for (p = parv[2]; p && *p; p++) { switch (*p) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; default: for (i = 0; i <= Snomask_highest; i++) { if (!Snomask_Table[i].flag) continue; if (*p == Snomask_Table[i].flag) { if (what == MODE_ADD) acptr->user->snomask |= Snomask_Table[i].mode; else acptr->user->snomask &= ~Snomask_Table[i].mode; } } } } } } if (show_change) sendto_one(acptr, rpl_str(RPL_SNOMASK), me.name, acptr->name, get_sno_str(acptr)); return 0; }
/* * * m_list * parv[0] = sender prefix * parv[1] = channel */ DLLFUNC CMD_FUNC(m_list) { aChannel *chptr; TS currenttime = TStime(); char *name, *p = NULL; LOpts *lopt = NULL; Link *lp; int usermax, usermin, error = 0, doall = 0; TS chantimemin, chantimemax; TS topictimemin, topictimemax; Link *yeslist = NULL, *nolist = NULL; static char *usage[] = { " Usage: /LIST <options>", "", "If you don't include any options, the default is to send you the", "entire unfiltered list of channels. Below are the options you can", "use, and what channels LIST will return when you use them.", ">number List channels with more than <number> people.", "<number List channels with less than <number> people.", "C>number List channels created between now and <number> minutes ago.", "C<number List channels created earlier than <number> minutes ago.", "T>number List channels whose topics are older than <number> minutes", " (Ie, they have not changed in the last <number> minutes.", "T<number List channels whose topics are not older than <number> minutes.", "*mask* List channels that match *mask*", "!*mask* List channels that do not match *mask*", NULL }; /* Some starting san checks -- No interserver lists allowed. */ if (cptr != sptr || !sptr->user) return 0; /* If a /list is in progress, then another one will cancel it */ if ((lopt = sptr->user->lopt) != NULL) { sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]); free_str_list(sptr->user->lopt->yeslist); free_str_list(sptr->user->lopt->nolist); MyFree(sptr->user->lopt); sptr->user->lopt = NULL; return 0; } if (parc < 2 || BadPtr(parv[1])) { sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]); lopt = sptr->user->lopt = (LOpts *) MyMalloc(sizeof(LOpts)); memset(lopt, '\0', sizeof(LOpts)); lopt->showall = 1; if (DBufLength(&cptr->sendQ) < 2048) send_list(cptr, 64); return 0; } if ((parc == 2) && (parv[1][0] == '?') && (parv[1][1] == '\0')) { char **ptr = usage; for (; *ptr; ptr++) sendto_one(sptr, rpl_str(RPL_LISTSYNTAX), me.name, cptr->name, *ptr); return 0; } sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]); chantimemax = topictimemax = currenttime + 86400; chantimemin = topictimemin = 0; usermin = 1; /* Minimum of 1 */ usermax = -1; /* No maximum */ for (name = strtok_r(parv[1], ",", &p); name && !error; name = strtok_r(NULL, ",", &p)) { switch (*name) { case '<': usermax = atoi(name + 1) - 1; doall = 1; break; case '>': usermin = atoi(name + 1) + 1; doall = 1; break; case 'C': case 'c': /* Channel TS time -- creation time? */ ++name; switch (*name++) { case '<': chantimemax = currenttime - 60 * atoi(name); doall = 1; break; case '>': chantimemin = currenttime - 60 * atoi(name); doall = 1; break; default: sendto_one(sptr, err_str(ERR_LISTSYNTAX), me.name, cptr->name); error = 1; } break; #ifdef LIST_USE_T case 'T': case 't': ++name; switch (*name++) { case '<': topictimemax = currenttime - 60 * atoi(name); doall = 1; break; case '>': topictimemin = currenttime - 60 * atoi(name); doall = 1; break; default: sendto_one(sptr, err_str(ERR_LISTSYNTAX), me.name, cptr->name, "Bad list syntax, type /list ?"); error = 1; } break; #endif default: /* A channel, possibly with wildcards. * Thought for the future: Consider turning wildcard * processing on the fly. * new syntax: !channelmask will tell ircd to ignore * any channels matching that mask, and then * channelmask will tell ircd to send us a list of * channels only masking channelmask. Note: Specifying * a channel without wildcards will return that * channel even if any of the !channelmask masks * matches it. */ if (*name == '!') { doall = 1; lp = make_link(); lp->next = nolist; nolist = lp; DupString(lp->value.cp, name + 1); } else if (strchr(name, '*') || strchr(name, '?')) { doall = 1; lp = make_link(); lp->next = yeslist; yeslist = lp; DupString(lp->value.cp, name); } else /* Just a normal channel */ { chptr = find_channel(name, NullChn); if (chptr && (ShowChannel(sptr, chptr) || OPCanSeeSecret(sptr))) { #ifdef LIST_SHOW_MODES modebuf[0] = '['; channel_modes(sptr, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), chptr); if (modebuf[2] == '\0') modebuf[0] = '\0'; else strlcat(modebuf, "]", sizeof modebuf); #endif sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0], name, chptr->users, #ifdef LIST_SHOW_MODES modebuf, #endif (chptr->topic ? chptr->topic : "")); } } } /* switch */ } /* while */ if (doall) { lopt = sptr->user->lopt = (LOpts *) MyMalloc(sizeof(LOpts)); memset(lopt, '\0', sizeof(LOpts)); lopt->usermin = usermin; lopt->usermax = usermax; lopt->topictimemax = topictimemax; lopt->topictimemin = topictimemin; lopt->chantimemax = chantimemax; lopt->chantimemin = chantimemin; lopt->nolist = nolist; lopt->yeslist = yeslist; if (DBufLength(&cptr->sendQ) < 2048) send_list(cptr, 64); return 0; } sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]); return 0; }
void _send_list(aClient *cptr, int numsend) { aChannel *chptr; LOpts *lopt = cptr->user->lopt; unsigned int hashnum; /* Begin of /list? then send official channels. */ if ((lopt->starthash == 0) && conf_offchans) { ConfigItem_offchans *x; for (x = conf_offchans; x; x = (ConfigItem_offchans *)x->next) { if (find_channel(x->chname, (aChannel *)NULL)) continue; /* exists, >0 users.. will be sent later */ sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name, x->chname, 0, #ifdef LIST_SHOW_MODES "", #endif x->topic ? x->topic : ""); } } for (hashnum = lopt->starthash; hashnum < CH_MAX; hashnum++) { if (numsend > 0) for (chptr = (aChannel *)hash_get_chan_bucket(hashnum); chptr; chptr = chptr->hnextch) { if (SecretChannel(chptr) && !IsMember(cptr, chptr) && !OPCanSeeSecret(cptr)) continue; /* Much more readable like this -- codemastr */ if ((!lopt->showall)) { /* User count must be in range */ if ((chptr->users < lopt->usermin) || ((lopt->usermax >= 0) && (chptr->users > lopt->usermax))) continue; /* Creation time must be in range */ if ((chptr->creationtime && (chptr->creationtime < lopt->chantimemin)) || (chptr->creationtime > lopt->chantimemax)) continue; /* Topic time must be in range */ if ((chptr->topic_time < lopt->topictimemin) || (chptr->topic_time > lopt->topictimemax)) continue; /* Must not be on nolist (if it exists) */ if (lopt->nolist && find_str_match_link(lopt->nolist, chptr->chname)) continue; /* Must be on yeslist (if it exists) */ if (lopt->yeslist && !find_str_match_link(lopt->yeslist, chptr->chname)) continue; } #ifdef LIST_SHOW_MODES modebuf[0] = '['; channel_modes(cptr, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), chptr); if (modebuf[2] == '\0') modebuf[0] = '\0'; else strlcat(modebuf, "]", sizeof modebuf); #endif if (!OPCanSeeSecret(cptr)) sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name, ShowChannel(cptr, chptr) ? chptr->chname : "*", chptr->users, #ifdef LIST_SHOW_MODES ShowChannel(cptr, chptr) ? modebuf : "", #endif ShowChannel(cptr, chptr) ? (chptr->topic ? chptr->topic : "") : ""); else sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name, chptr->chname, chptr->users, #ifdef LIST_SHOW_MODES modebuf, #endif (chptr->topic ? chptr->topic : "")); numsend--; } else break; } /* All done */ if (hashnum == CH_MAX) { sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name); free_str_list(cptr->user->lopt->yeslist); free_str_list(cptr->user->lopt->nolist); MyFree(cptr->user->lopt); cptr->user->lopt = NULL; return; } /* * We've exceeded the limit on the number of channels to send back * at once. */ lopt->starthash = hashnum; return; }
static void do_other_who(aClient *sptr, char *mask) { int oper = IsAnOper(sptr); /* wildcard? */ #ifndef NO_FDLIST if (lifesux && !IsOper(sptr) && *mask == '*' && *(mask+1) == 0) { sendto_one(sptr, err_str(ERR_HTMDISABLED), me.name, sptr->name, "/WHO"); return; } #endif if (strchr(mask, '*') || strchr(mask, '?')) { int i = 0; /* go through all users.. */ aClient *acptr; who_flags |= WF_WILDCARD; for (acptr = client; acptr; acptr = acptr->next) { int cansee; char status[20]; char *channel; int flg; if (!IsPerson(acptr)) continue; if (!oper) { /* non-opers can only search on nick here */ if (match(mask, acptr->name)) continue; } else { /* opers can search on name, ident, virthost, ip and realhost. * Yes, I like readable if's -- Syzop. */ if (!match(mask, acptr->name) || !match(mask, acptr->user->realhost) || !match(mask, acptr->user->username)) goto matchok; if (IsHidden(acptr) && !match(mask, acptr->user->virthost)) goto matchok; if (acptr->user->ip_str && !match(mask, acptr->user->ip_str)) goto matchok; /* nothing matched... */ continue; } matchok: if ((cansee = can_see(sptr, acptr, NULL)) & WHO_CANTSEE) continue; if (WHOLIMIT && !IsAnOper(sptr) && ++i > WHOLIMIT) { sendto_one(sptr, rpl_str(ERR_WHOLIMEXCEED), me.name, sptr->name, WHOLIMIT); return; } channel = first_visible_channel(sptr, acptr, &flg); make_who_status(sptr, acptr, NULL, NULL, status, cansee); send_who_reply(sptr, acptr, channel, status, (flg & FVC_HIDDEN) ? "~" : ""); } } else { /* just a single client (no wildcards detected) */ aClient *acptr = find_client(mask, NULL); int cansee; char status[20]; char *channel; int flg; if (!acptr) return; if ((cansee = can_see(sptr, acptr, NULL)) == WHO_CANTSEE) return; channel = first_visible_channel(sptr, acptr, &flg); make_who_status(sptr, acptr, NULL, NULL, status, cansee); send_who_reply(sptr, acptr, channel, status, (flg & FVC_HIDDEN) ? "~" : ""); } }
/* Routine that actually makes a user join the channel * this does no actual checking (banned, etc.) it just adds the user */ DLLFUNC void _join_channel(aChannel *chptr, aClient *cptr, aClient *sptr, int flags) { char *parv[] = { 0, 0 }; /* ** Complete user entry to the new channel (if any) */ add_user_to_channel(chptr, sptr, flags); /* ** notify all other users on the new channel */ if (chptr->mode.mode & MODE_AUDITORIUM) { if (MyClient(sptr)) sendto_one(sptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); sendto_chanops_butone(NULL, chptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); } else sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", sptr->name, chptr->chname); sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, sptr->name, MSG_JOIN, TOK_JOIN, "%s", chptr->chname); #ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN if ((MyClient(sptr) && !(flags & CHFL_CHANOP)) || !MyClient(sptr)) sendto_serv_butone_token_opt(cptr, OPT_SJ3, sptr->name, MSG_JOIN, TOK_JOIN, "%s", chptr->chname); if (flags && !(flags & CHFL_DEOPPED)) { #endif /* I _know_ that the "@%s " look a bit wierd with the space and all .. but its to get around a SJOIN bug --stskeeps */ sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_SJB64, me.name, MSG_SJOIN, TOK_SJOIN, "%B %s :%s%s ", (long)chptr->creationtime, chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name); sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_NOT_SJB64, me.name, MSG_SJOIN, TOK_SJOIN, "%li %s :%s%s ", chptr->creationtime, chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name); #ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN } #endif if (MyClient(sptr)) { /* ** Make a (temporal) creationtime, if someone joins ** during a net.reconnect : between remote join and ** the mode with TS. --Run */ if (chptr->creationtime == 0) { chptr->creationtime = TStime(); sendto_serv_butone_token(cptr, me.name, MSG_MODE, TOK_MODE, "%s + %lu", chptr->chname, chptr->creationtime); } del_invite(sptr, chptr); if (flags && !(flags & CHFL_DEOPPED)) { #ifndef PREFIX_AQ if ((flags & CHFL_CHANOWNER) || (flags & CHFL_CHANPROT)) { /* +ao / +qo for when PREFIX_AQ is off */ sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, me.name, MSG_MODE, TOK_MODE, "%s +o%c %s %s %lu", chptr->chname, chfl_to_chanmode(flags), sptr->name, sptr->name, chptr->creationtime); } else { #endif /* +v/+h/+o (and +a/+q if PREFIX_AQ is on) */ sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, me.name, MSG_MODE, TOK_MODE, "%s +%c %s %lu", chptr->chname, chfl_to_chanmode(flags), sptr->name, chptr->creationtime); #ifndef PREFIX_AQ } #endif } if (chptr->topic) { sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, sptr->name, chptr->chname, chptr->topic); sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, sptr->name, chptr->chname, chptr->topic_nick, chptr->topic_time); } if (chptr->users == 1 && (MODES_ON_JOIN #ifdef EXTCMODE || iConf.modes_on_join.extmodes) #endif ) { #ifdef EXTCMODE int i; chptr->mode.extmode = iConf.modes_on_join.extmodes; /* Param fun */ for (i = 0; i <= Channelmode_highest; i++) { if (!Channelmode_Table[i].flag || !Channelmode_Table[i].paracount) continue; if (chptr->mode.extmode & Channelmode_Table[i].mode) { CmodeParam *p; p = Channelmode_Table[i].put_param(NULL, iConf.modes_on_join.extparams[i]); AddListItem(p, chptr->mode.extmodeparam); } } #endif chptr->mode.mode = MODES_ON_JOIN; #ifdef NEWCHFLOODPROT if (iConf.modes_on_join.floodprot.per) { chptr->mode.floodprot = MyMalloc(sizeof(ChanFloodProt)); memcpy(chptr->mode.floodprot, &iConf.modes_on_join.floodprot, sizeof(ChanFloodProt)); } #else chptr->mode.kmode = iConf.modes_on_join.kmode; chptr->mode.per = iConf.modes_on_join.per; chptr->mode.msgs = iConf.modes_on_join.msgs; #endif *modebuf = *parabuf = 0; channel_modes(sptr, modebuf, parabuf, chptr); /* This should probably be in the SJOIN stuff */ sendto_serv_butone_token(&me, me.name, MSG_MODE, TOK_MODE, "%s %s %s %lu", chptr->chname, modebuf, parabuf, chptr->creationtime); sendto_one(sptr, ":%s MODE %s %s %s", me.name, chptr->chname, modebuf, parabuf); } parv[0] = sptr->name; parv[1] = chptr->chname; do_cmd(cptr, sptr, "NAMES", 2, parv); RunHook4(HOOKTYPE_LOCAL_JOIN, cptr, sptr,chptr,parv); } else { RunHook4(HOOKTYPE_REMOTE_JOIN, cptr, sptr, chptr, parv); /* (rarely used) */ } #ifdef NEWCHFLOODPROT /* I'll explain this only once: * 1. if channel is +f * 2. local client OR synced server * 3. then, increase floodcounter * 4. if we reached the limit AND only if source was a local client.. do the action (+i). * Nr 4 is done because otherwise you would have a noticeflood with 'joinflood detected' * from all servers. */ if (chptr->mode.floodprot && (MyClient(sptr) || sptr->srvptr->serv->flags.synced) && !IsULine(sptr) && do_chanflood(chptr->mode.floodprot, FLD_JOIN) && MyClient(sptr)) { do_chanflood_action(chptr, FLD_JOIN, "join"); } #endif }
/* * m_userip is based on m_userhost * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce * the need for complicated requests like WHOIS. It returns user/host * information only (no spurious AWAY labels or channels). * Re-written by Dianora 1999 */ DLLFUNC CMD_FUNC(m_userip) { char *p; /* scratch end pointer */ char *cn; /* current name */ char *ip, ipbuf[HOSTLEN+1]; struct Client *acptr; char response[5][NICKLEN * 2 + CHANNELLEN + USERLEN + HOSTLEN + 30]; int i; /* loop counter */ if (!MyClient(sptr)) return -1; if (parc < 2) { sendto_one(sptr, rpl_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERIP"); return 0; } /* The idea is to build up the response string out of pieces * none of this strlen() nonsense. * 5 * (NICKLEN*2+CHANNELLEN+USERLEN+HOSTLEN+30) is still << sizeof(buf) * and our ircsprintf() truncates it to fit anyway. There is * no danger of an overflow here. -Dianora */ response[0][0] = response[1][0] = response[2][0] = response[3][0] = response[4][0] = '\0'; cn = parv[1]; for (i = 0; (i < 5) && cn; i++) { if ((p = strchr(cn, ' '))) *p = '\0'; if ((acptr = find_person(cn, NULL))) { if (!(ip = GetIP(acptr))) ip = "<unknown>"; if (sptr != acptr && !IsOper(sptr) && IsHidden(acptr)) { make_virthost(acptr, GetIP(acptr), ipbuf, 0); ip = ipbuf; } ircsprintf(response[i], "%s%s=%c%s@%s", acptr->name, (IsAnOper(acptr) && (!IsHideOper(acptr) || sptr == acptr || IsAnOper(sptr))) ? "*" : "", (acptr->user->away) ? '-' : '+', acptr->user->username, ip); /* add extra fakelag (penalty) because of all the work we need to do: 1s per entry: */ sptr->since += 1; } if (p) p++; cn = p; } sendto_one(sptr, rpl_str(RPL_USERIP), me.name, parv[0], response[0], response[1], response[2], response[3], response[4]); return 0; }