struct userNode *
AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *userinfo, time_t timestamp, irc_in_addr_t realip, const char *stamp) {
struct userNode *uNode, *oldUser;
- unsigned int nn;
+ unsigned int nn, dummy;
if (!uplink) {
log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server does not exist!", uplink, nick);
return NULL;
}
- if (!is_valid_nick(nick)) {
+ dummy = modes && modes[0] == '*';
+ if (dummy) {
+ ++modes;
+ } else if (!is_valid_nick(nick)) {
log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): invalid nickname detected.", uplink, nick);
return NULL;
}
}
mod_usermode(uNode, modes);
+ if (dummy) uNode->modes |= FLAGS_DUMMY;
if (stamp) call_account_func(uNode, stamp);
if (IsLocal(uNode)) irc_user(uNode);
for (nn=0; nn<nuf_used; nn++) {
irc_kill(killer, user, why);
}
}
+ dict_remove(service_msginfo_dict, user->nick);
modeList_clean(&user->channels);
user->dead = 1;
if (dead_users.size) {
irc_user(struct userNode *user) {
char modes[32];
int modelen = 0;
+ if (!user || user->nick[0] != ' ') return;
if (IsOper(user)) modes[modelen++] = 'o';
if (IsInvisible(user)) modes[modelen++] = 'i';
if (IsWallOp(user)) modes[modelen++] = 'w';
if (IsService(user)) modes[modelen++] = 'k';
- if (IsServNotice(user)) modes[modelen++] = 's';
if (IsDeaf(user)) modes[modelen++] = 'd';
if (IsReggedNick(user)) modes[modelen++] = 'r';
if (IsGlobal(user)) modes[modelen++] = 'g';
}
}
+static int
+deliver_to_dummy(struct userNode *source, struct userNode *dest, const char *message, int type)
+{
+ struct service_message_info *smi;
+
+ if (!dest || !IsDummy(dest) || !IsLocal(dest))
+ return 0;
+ smi = dict_find(service_msginfo_dict, dest->nick, NULL);
+ switch (type) {
+ default:
+ if (smi && smi->on_privmsg)
+ {
+ smi->on_privmsg(source, dest, message, 0);
+ return 1;
+ }
+ break;
+ case 1:
+ if (smi && smi->on_notice)
+ {
+ smi->on_notice(source, dest, message, 0);
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
void
irc_privmsg(struct userNode *from, const char *to, const char *message) {
- putsock(":%s PRIVMSG %s :%s", from->nick, to, message);
+ if (!deliver_to_dummy(from, GetUserH(to), message, 1))
+ putsock(":%s PRIVMSG %s :%s", from->nick, to, message);
}
void
irc_notice(struct userNode *from, const char *to, const char *message) {
- putsock(":%s NOTICE %s :%s", from->nick, to, message);
+ if (!deliver_to_dummy(from, GetUserH(to), message, 0))
+ putsock(":%s NOTICE %s :%s", from->nick, to, message);
}
void
irc_notice_user(struct userNode *from, struct userNode *to, const char *message) {
- putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
+ if (!deliver_to_dummy(from, to, message, 0))
+ putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
}
void
irc_svsmode(struct userNode *target, char *modes, unsigned long stamp) {
extern struct userNode *nickserv;
if (stamp) {
- putsock(":%s SVSMODE %s "FMT_TIME_T" %s %lu", nickserv->nick, target->nick, target->timestamp, modes, stamp);
+ putsock(":%s SVSMODE %s "FMT_TIME_T" %s %lu", nickserv->nick, target->nick, target->timestamp, modes, stamp);
} else {
- putsock(":%s SVSMODE %s "FMT_TIME_T" %s", nickserv->nick, target->nick, target->timestamp, modes);
+ putsock(":%s SVSMODE %s "FMT_TIME_T" %s", nickserv->nick, target->nick, target->timestamp, modes);
}
}
parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data) {
char *j, old;
do {
- j = target_list;
- while (*j != 0 && *j != ',') j++;
- old = *j;
+ j = target_list;
+ while (*j != 0 && *j != ',') j++;
+ old = *j;
*j = 0;
- if (IsChannelName(target_list)) {
- struct chanNode *chan = GetChannel(target_list);
+ if (IsChannelName(target_list)) {
+ struct chanNode *chan = GetChannel(target_list);
if (chan) {
if (cf) cf(chan, data);
} else {
if (nc) nc(target_list, data);
}
- } else {
- struct userNode *user;
+ } else {
+ struct userNode *user;
struct privmsg_desc *pd = data;
pd->is_qualified = 0;
if (*target_list == '@') {
user = NULL;
} else if (strchr(target_list, '@')) {
- struct server *server;
+ struct server *server;
pd->is_qualified = 1;
- user = GetUserH(strtok(target_list, "@"));
- server = GetServerH(strtok(NULL, "@"));
-
- if (user && (user->uplink != server)) {
- /* Don't attempt to index into any arrays
- using a user's numeric on another server. */
- user = NULL;
- }
- } else {
- user = GetUserH(target_list);
- }
+ user = GetUserH(strtok(target_list, "@"));
+ server = GetServerH(strtok(NULL, "@"));
+
+ if (user && (user->uplink != server)) {
+ /* Don't attempt to index into any arrays
+ using a user's numeric on another server. */
+ user = NULL;
+ }
+ } else {
+ user = GetUserH(target_list);
+ }
if (user) {
if (uf) uf(user, data);
} else {
if (nu) nu(target_list, data);
}
- }
- target_list = j+1;
+ }
+ target_list = j+1;
} while (old == ',');
}
{
if (argc < 3) return 0;
if (!strcmp(argv[2], self->name)) {
- timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
- timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
- timeq_add(now + ping_freq, timed_send_ping, 0);
- received_ping();
+ timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
+ timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
+ timeq_add(now + ping_freq, timed_send_ping, 0);
+ received_ping();
}
return 1;
}
res = 0;
}
if (!res) {
- log_module(MAIN_LOG, LOG_ERROR, "PARSE ERROR on line: %s", unsplit_string(argv, argc, NULL));
+ log_module(MAIN_LOG, LOG_ERROR, "PARSE ERROR on line: %s", unsplit_string(argv, argc, NULL));
} else if (!recursive) {
unsigned int i;
for (i=0; i<dead_users.used; i++) {
info->on_privmsg = handler;
}
+void
+unreg_privmsg_func(struct userNode *user) {
+ struct service_message_info *info;
+ info = dict_find(service_msginfo_dict, user->nick, NULL);
+ if (info) {
+ info->on_privmsg = NULL;
+ if (info->on_notice == NULL) {
+ dict_remove(service_msginfo_dict, user->nick);
+ }
+ }
+}
+
void
reg_notice_func(struct userNode *user, privmsg_func_t handler) {
struct service_message_info *info = dict_find(service_msginfo_dict, user->nick, NULL);
info->on_notice = handler;
}
+void
+unreg_notice_func(struct userNode *user) {
+ struct service_message_info *info;
+ info = dict_find(service_msginfo_dict, user->nick, NULL);
+ if (info) {
+ info->on_notice = NULL;
+ if (info->on_privmsg == NULL) {
+ dict_remove(service_msginfo_dict, user->nick);
+ }
+ }
+}
+
void
reg_oper_func(oper_func_t handler)
{
if (of_used == of_size) {
- if (of_size) {
- of_size <<= 1;
- of_list = realloc(of_list, of_size*sizeof(oper_func_t));
- } else {
- of_size = 8;
- of_list = malloc(of_size*sizeof(oper_func_t));
- }
+ if (of_size) {
+ of_size <<= 1;
+ of_list = realloc(of_list, of_size*sizeof(oper_func_t));
+ } else {
+ of_size = 8;
+ of_list = malloc(of_size*sizeof(oper_func_t));
+ }
}
of_list[of_used++] = handler;
}
if (IsLocal(user)) return;
for (n=0; n<of_used; n++)
{
- of_list[n](user);
+ of_list[n](user);
}
}
if (!user || !mode_change) return;
while (1) {
#define do_user_mode(FLAG) do { if (add) user->modes |= FLAG; else user->modes &= ~FLAG; } while (0)
- switch (*mode_change++) {
- case 0: return;
- case '+': add = 1; break;
- case '-': add = 0; break;
- case 'o':
- do_user_mode(FLAGS_OPER);
- if (add) {
- userList_append(&curr_opers, user);
- call_oper_funcs(user);
- } else {
- userList_remove(&curr_opers, user);
- }
- break;
- case 'O': do_user_mode(FLAGS_LOCOP); break;
- case 'i': do_user_mode(FLAGS_INVISIBLE);
- if (add) invis_clients++; else invis_clients--;
- break;
- case 'w': do_user_mode(FLAGS_WALLOP); break;
- case 's': do_user_mode(FLAGS_SERVNOTICE); break;
- case 'd': do_user_mode(FLAGS_DEAF); break;
- case 'r': do_user_mode(FLAGS_REGNICK); break;
- case 'k': do_user_mode(FLAGS_SERVICE); break;
- case 'g': do_user_mode(FLAGS_GLOBAL); break;
- case 'h': do_user_mode(FLAGS_HELPER); break;
- }
+ switch (*mode_change++) {
+ case 0: return;
+ case '+': add = 1; break;
+ case '-': add = 0; break;
+ case 'o':
+ do_user_mode(FLAGS_OPER);
+ if (add) {
+ userList_append(&curr_opers, user);
+ call_oper_funcs(user);
+ } else {
+ userList_remove(&curr_opers, user);
+ }
+ break;
+ case 'i': do_user_mode(FLAGS_INVISIBLE);
+ if (add) invis_clients++; else invis_clients--;
+ break;
+ case 'w': do_user_mode(FLAGS_WALLOP); break;
+ case 'd': do_user_mode(FLAGS_DEAF); break;
+ case 'r': do_user_mode(FLAGS_REGNICK); break;
+ case 'k': do_user_mode(FLAGS_SERVICE); break;
+ case 'g': do_user_mode(FLAGS_GLOBAL); break;
+ }
#undef do_user_mode
}
}
case 'p': do_chan_mode(MODE_PRIVATE); break;
case 's': do_chan_mode(MODE_SECRET); break;
case 't': do_chan_mode(MODE_TOPICLIMIT); break;
- case 'r':
- if (!(flags & MCP_REGISTERED)) {
- do_chan_mode(MODE_REGISTERED);
- } else {
- mod_chanmode_free(change);
- return NULL;
- }
- break;
+ case 'r':
+ if (!(flags & MCP_REGISTERED)) {
+ do_chan_mode(MODE_REGISTERED);
+ } else {
+ mod_chanmode_free(change);
+ return NULL;
+ }
+ break;
#undef do_chan_mode
case 'l':
if (add) {