X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fhash.c;h=a55ad9ba92568bc06f6e3b031953a41bce38f273;hb=HEAD;hp=4fa1e913f11e93826aaddf309516464bf8b011a9;hpb=4a2c9aa9ab119a212d78c6a3a73261de56800251;p=srvx.git diff --git a/src/hash.c b/src/hash.c index 4fa1e91..a55ad9b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -191,9 +191,11 @@ NickChange(struct userNode* user, const char *new_nick, int no_announce) #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; nndead; nn++) ncf2_list[nn](user, old_nick); user->timestamp = now; if (IsLocal(user) && !no_announce) @@ -219,7 +221,7 @@ reg_account_func(account_func_t handler) } 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 @@ -228,7 +230,7 @@ call_account_func(struct userNode *user, const char *stamp) 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. */ @@ -237,7 +239,7 @@ call_account_func(struct userNode *user, const char *stamp) } 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 @@ -246,16 +248,19 @@ StampUser(struct userNode *user, const char *stamp) 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; @@ -377,6 +382,7 @@ AddChannel(const char *name, unsigned long time_, const char *modes, char *banli 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_; @@ -464,6 +470,7 @@ DelChannel(struct chanNode *channel) modeList_clean(&channel->members); banList_clean(&channel->banlist); + userList_clean(&channel->invited); free(channel); } @@ -483,7 +490,7 @@ AddChannelUser(struct userNode *user, struct chanNode* 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. @@ -498,19 +505,47 @@ AddChannelUser(struct userNode *user, struct chanNode* channel) && !(channel->modes & MODE_APASS)) mNode->modes |= MODE_CHANOP; - for (n=0; ndead; 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; @@ -630,9 +665,9 @@ ChannelUserKicked(struct userNode* kicker, struct userNode* victim, struct chanN 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; @@ -699,6 +734,10 @@ SetChannelTopic(struct chanNode *channel, struct userNode *user, const char *top irc_topic(user, channel, topic); } else { for (n=0; n