dict_t clients;
dict_t servers;
unsigned int max_clients, invis_clients;
-time_t max_clients_time;
+unsigned long max_clients_time;
struct userList curr_opers;
static void hash_cleanup(void);
#endif
/* Make callbacks for nick changes. Do this with new nick in
- * place because that is slightly more useful.
+ * place because that is slightly more useful. Stop if the user
+ * gets killed by any of the hooks, so that later hooks do not get
+ * confused by the user having disappeared.
*/
- for (nn=0; nn<ncf2_used; nn++)
+ for (nn=0; (nn<ncf2_used) && !user->dead; nn++)
ncf2_list[nn](user, old_nick);
user->timestamp = now;
if (IsLocal(user) && !no_announce)
}
void
-call_account_func(struct userNode *user, const char *stamp)
+call_account_func(struct userNode *user, const char *stamp, unsigned long timestamp, unsigned long serial)
{
/* We've received an account stamp for a user; notify
NickServ, which registers the sole account_func
P10 Protocol violation if (user->modes & FLAGS_STAMPED) here.
*/
if (account_func)
- account_func(user, stamp);
+ account_func(user, stamp, timestamp, serial);
#ifdef WITH_PROTOCOL_P10
/* Mark the user so we don't stamp it again. */
}
void
-StampUser(struct userNode *user, const char *stamp)
+StampUser(struct userNode *user, const char *stamp, unsigned long timestamp, unsigned long serial)
{
#ifdef WITH_PROTOCOL_P10
/* The P10 protocol says we can't stamp users who already
return;
#endif
- irc_account(user, stamp);
+ irc_account(user, stamp, timestamp, serial);
user->modes |= FLAGS_STAMPED;
}
void
-assign_fakehost(struct userNode *user, const char *host, int announce)
+assign_fakehost(struct userNode *user, const char *host, const char *ident, int force, int announce)
{
- safestrncpy(user->fakehost, host, sizeof(user->fakehost));
+ if (host)
+ safestrncpy(user->fakehost, host, sizeof(user->fakehost));
+ if (ident)
+ safestrncpy(user->fakeident, ident, sizeof(user->ident));
if (announce)
- irc_fakehost(user, host);
+ irc_fakehost(user, host, ident, force);
}
static new_channel_func_t *ncf_list;
int rel_age;
static void
-wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned int modec) {
+wipeout_channel(struct chanNode *cNode, unsigned long new_time, char **modes, unsigned int modec) {
unsigned int orig_limit;
chan_mode_t orig_modes;
char orig_key[KEYLEN+1];
}
struct chanNode *
-AddChannel(const char *name, time_t time_, const char *modes, char *banlist)
+AddChannel(const char *name, unsigned long time_, const char *modes, char *banlist)
{
struct chanNode *cNode;
char new_modes[MAXLEN], *argv[MAXNUMPARAMS];
strcpy(cNode->name, name);
banList_init(&cNode->banlist);
modeList_init(&cNode->members);
+ userList_init(&cNode->invited);
mod_chanmode(NULL, cNode, argv, nn, MCP_FROM_SERVER);
dict_insert(channels, cNode->name, cNode);
cNode->timestamp = time_;
modeList_clean(&channel->members);
banList_clean(&channel->banlist);
+ userList_clean(&channel->invited);
free(channel);
}
mNode->channel = channel;
mNode->user = user;
mNode->modes = 0;
- mNode->oplevel = -1;
+ mNode->oplevel = MAXOPLEVEL;
mNode->idle_since = now;
/* Add modeNode to channel and to user.
&& !(channel->modes & MODE_APASS))
mNode->modes |= MODE_CHANOP;
- for (n=0; n<jf_used; n++) {
+ if (IsLocal(user)) {
+ irc_join(user, channel);
+ }
+
+ for (n=0; (n<jf_used) && !user->dead; n++) {
/* Callbacks return true if they kick or kill the user,
* and we can continue without removing mNode. */
if (jf_list[n](mNode))
return NULL;
}
- if (IsLocal(user))
- irc_join(user, channel);
-
return mNode;
}
+/* Return negative if *(struct modeNode**)pa is "less than" pb,
+ * positive if pa is "larger than" pb. Comparison is based on sorting
+ * so that non-voiced/non-opped users are first, voiced-only users are
+ * next, and the "strongest" oplevels are before "weaker" oplevels.
+ * Within those sets, ordering is arbitrary.
+ */
+int
+modeNode_sort(const void *pa, const void *pb)
+{
+ struct modeNode *a = *(struct modeNode**)pa;
+ struct modeNode *b = *(struct modeNode**)pb;
+
+ if (a->modes & MODE_CHANOP) {
+ if (!(b->modes & MODE_CHANOP))
+ return -1;
+ else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+ return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+ else if (a->oplevel != b->oplevel)
+ return a->oplevel - b->oplevel;
+ } else if (b->modes & MODE_CHANOP)
+ return 1;
+ else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+ return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+
+ return irccasecmp(a->user->nick, b->user->nick);
+}
+
static part_func_t *pf_list;
static unsigned int pf_size = 0, pf_used = 0;
unsigned int n;
struct modeNode *mn;
- if (!victim || !channel || IsService(victim) || !GetUserMode(channel, victim))
+ if (!victim || !channel || !GetUserMode(channel, victim))
return;
-
+
/* Update the kicker's idle time (kicker may be null if it was a server) */
if (kicker && (mn = GetUserMode(channel, kicker)))
mn->idle_since = now;
irc_topic(user, channel, topic);
} else {
for (n=0; n<tf_used; n++)
+ /* A topic change handler can return non-zero to indicate
+ * that it has reverted the topic change, and that further
+ * hooks should not be called.
+ */
if (tf_list[n](user, channel, old_topic))
break;
}