From: Michael Poole Date: Sat, 8 Oct 2005 14:56:31 +0000 (+0000) Subject: Initial oplevel support. X-Git-Tag: v1.4.0-rc1~163 X-Git-Url: http://git.pk910.de/?p=srvx.git;a=commitdiff_plain;h=a8ad571a6043b23bced98d1a950defe6326a19cb Initial oplevel support. src/proto-p10.c: Fix a few bugs and compile errors in oplevel code. Patches applied: * sp@gamesurge.net--2005/srvx--sp--1.3--patch-1 Oplevel support * sp@gamesurge.net--2005/srvx--sp--1.3--patch-2 Oplevel support (part 2) git-archimport-id: srvx@srvx.net--2005-srvx/srvx--devo--1.3--patch-29 --- diff --git a/ChangeLog b/ChangeLog index e9a3926..11f4bf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,32 @@ # arch-tag: automatic-ChangeLog--srvx@srvx.net--2005-srvx/srvx--devo--1.3 # +2005-10-08 14:56:31 GMT Michael Poole patch-29 + + Summary: + Initial oplevel support. + Revision: + srvx--devo--1.3--patch-29 + + src/proto-p10.c: Fix a few bugs and compile errors in oplevel code. + + Patches applied: + + * sp@gamesurge.net--2005/srvx--sp--1.3--patch-1 + Oplevel support + + * sp@gamesurge.net--2005/srvx--sp--1.3--patch-2 + Oplevel support (part 2) + + modified files: + ChangeLog src/hash.c src/hash.h src/opserv.c + src/proto-common.c src/proto-p10.c src/proto.h + + new patches: + sp@gamesurge.net--2005/srvx--sp--1.3--patch-1 + sp@gamesurge.net--2005/srvx--sp--1.3--patch-2 + + 2005-10-08 14:33:12 GMT Michael Poole patch-28 Summary: diff --git a/src/hash.c b/src/hash.c index c60ec57..eff19d1 100644 --- a/src/hash.c +++ b/src/hash.c @@ -289,6 +289,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned unsigned int orig_limit; chan_mode_t orig_modes; char orig_key[KEYLEN+1]; + char orig_apass[KEYLEN+1]; + char orig_upass[KEYLEN+1]; unsigned int nn, argc; /* nuke old topic */ @@ -300,6 +302,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned orig_modes = cNode->modes; orig_limit = cNode->limit; strcpy(orig_key, cNode->key); + strcpy(orig_upass, cNode->upass); + strcpy(orig_apass, cNode->apass); cNode->modes = 0; mod_chanmode(NULL, cNode, modes, modec, 0); cNode->timestamp = new_time; @@ -323,6 +327,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned change->modes_set = orig_modes; change->new_limit = orig_limit; strcpy(change->new_key, orig_key); + strcpy(change->new_upass, orig_upass); + strcpy(change->new_apass, orig_apass); for (nn = argc = 0; nn < cNode->members.used; ++nn) { struct modeNode *mn = cNode->members.list[nn]; if ((mn->modes & MODE_CHANOP) && IsService(mn->user) && IsLocal(mn->user)) { @@ -475,7 +481,8 @@ AddChannelUser(struct userNode *user, struct chanNode* channel) modeList_append(&user->channels, mNode); if (channel->members.used == 1 - && !(channel->modes & MODE_REGISTERED)) + && !(channel->modes & MODE_REGISTERED) + && !(channel->modes & MODE_APASS)) mNode->modes |= MODE_CHANOP; for (n=0; nmembers.used && !channel->locks && !(channel->modes & MODE_REGISTERED)) + /* A single check for APASS only should be enough here */ + if (!deleting && !channel->members.used && !channel->locks + && !(channel->modes & MODE_REGISTERED) && !(channel->modes & MODE_APASS)) DelChannel(channel); } diff --git a/src/hash.h b/src/hash.h index 975ccf4..2ecd749 100644 --- a/src/hash.h +++ b/src/hash.h @@ -41,6 +41,8 @@ #define MODE_NOCOLORS 0x2000 /* +c */ #define MODE_NOCTCPS 0x4000 /* +C */ #define MODE_REGISTERED 0x8000 /* Bahamut +r */ +#define MODE_APASS 0x10000 /* +A adminpass */ +#define MODE_UPASS 0x20000 /* +U userpass */ #define MODE_REMOVE 0x80000000 #define FLAGS_OPER 0x0001 /* Operator +O */ @@ -125,6 +127,8 @@ struct chanNode { chan_mode_t modes; unsigned int limit, locks; char key[KEYLEN + 1]; + char upass[KEYLEN + 1]; + char apass[KEYLEN + 1]; time_t timestamp; /* creation time */ char topic[TOPICLEN + 1]; @@ -152,6 +156,7 @@ struct modeNode { struct chanNode *channel; struct userNode *user; long modes; + int oplevel; time_t idle_since; }; diff --git a/src/opserv.c b/src/opserv.c index 35ead4a..7aed110 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -457,9 +457,16 @@ static MODCMD_FUNC(cmd_chaninfo) } reply("OSMSG_CHANINFO_USER_COUNT", channel->members.used); for (n=0; nmembers.used; n++) { - moden = channel->members.list[n]; - if (moden->modes & MODE_CHANOP) - send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname); + moden = channel->members.list[n]; + if (moden->modes & MODE_CHANOP) + { + if (moden->oplevel >= 0) + { + send_message_type(4, user, cmd->parent->bot, " (%d)@%s (%s@%s)", moden->oplevel, moden->user->nick, moden->user->ident, moden->user->hostname); + } else { + send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname); + } + } } for (n=0; nmembers.used; n++) { moden = channel->members.list[n]; diff --git a/src/proto-common.c b/src/proto-common.c index b5e5118..b7b9bc2 100644 --- a/src/proto-common.c +++ b/src/proto-common.c @@ -543,6 +543,8 @@ mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra) res->modes_clear = orig->modes_clear; res->new_limit = orig->new_limit; memcpy(res->new_key, orig->new_key, sizeof(res->new_key)); + memcpy(res->new_upass, orig->new_upass, sizeof(res->new_upass)); + memcpy(res->new_apass, orig->new_apass, sizeof(res->new_apass)); res->argc = orig->argc; memcpy(res->args, orig->args, orig->argc*sizeof(orig->args[0])); } @@ -561,6 +563,10 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch channel->limit = change->new_limit; if (change->modes_set & MODE_KEY) strcpy(channel->key, change->new_key); + if (change->modes_set & MODE_UPASS) + strcpy(channel->upass, change->new_upass); + if (change->modes_set & MODE_APASS) + strcpy(channel->apass, change->new_apass); for (ii = 0; ii < change->argc; ++ii) { switch (change->args[ii].mode) { case MODE_BAN: @@ -648,6 +654,8 @@ irc_make_chanmode(struct chanNode *chan, char *out) change.modes_set = chan->modes; change.new_limit = chan->limit; safestrncpy(change.new_key, chan->key, sizeof(change.new_key)); + safestrncpy(change.new_upass, chan->upass, sizeof(change.new_upass)); + safestrncpy(change.new_apass, chan->apass, sizeof(change.new_apass)); return strlen(mod_chanmode_format(&change, out)); } diff --git a/src/proto-p10.c b/src/proto-p10.c index cf9b076..ec34a8d 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -296,6 +296,8 @@ static struct userNode *AddUser(struct server* uplink, const char *nick, const c extern int off_channel; +static int parse_oplevel(char *str); + /* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the * server and Y's indentifying the client on that server. */ struct server* @@ -981,6 +983,7 @@ static CMD_FUNC(cmd_error_nick) struct create_desc { struct userNode *user; + int oplevel; time_t when; }; @@ -988,7 +991,12 @@ static void join_helper(struct chanNode *chan, void *data) { struct create_desc *cd = data; - AddChannelUser(cd->user, chan); + struct modeNode *mNode; + + mNode = AddChannelUser(cd->user, chan); + mNode->oplevel = cd->oplevel; + if (mNode->oplevel >= 0) + mNode->modes |= MODE_CHANOP; } static void @@ -1105,6 +1113,7 @@ static CMD_FUNC(cmd_burst) struct userNode *un; struct modeNode *mNode; long mode; + int oplevel = -1; char *user, *end, sep; time_t in_timestamp; @@ -1117,7 +1126,8 @@ static CMD_FUNC(cmd_burst) const char *pos; int n_modes; for (pos=argv[next], n_modes = 1; *pos; pos++) - if ((*pos == 'k') || (*pos == 'l')) + if ((*pos == 'k') || (*pos == 'l') || (*pos == 'A') + || (*pos == 'U')) n_modes++; unsplit_string(argv+next, n_modes, modes); next += n_modes; @@ -1143,12 +1153,18 @@ static CMD_FUNC(cmd_burst) if (sep == ':') { mode = 0; while ((sep = *end++)) { - if (sep == 'o') + if (sep == 'o') { mode |= MODE_CHANOP; - else if (sep == 'v') + oplevel = -1; + } else if (sep == 'v') { mode |= MODE_VOICE; - else if (isdigit(sep)) { + oplevel = -1; + } else if (isdigit(sep)) { mode |= MODE_CHANOP; + if (oplevel >= 0) + oplevel += parse_oplevel(end); + else + oplevel = parse_oplevel(end); while (isdigit(*end)) end++; } else break; @@ -1160,8 +1176,10 @@ static CMD_FUNC(cmd_burst) res = 0; continue; } - if ((mNode = AddChannelUser(un, cNode))) + if ((mNode = AddChannelUser(un, cNode))) { mNode->modes = mode; + mNode->oplevel = oplevel; + } } return res; @@ -1710,15 +1728,38 @@ static void parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data) { char *j, old; + char *cPos, *hPos; + int oplevel; + do { j = target_list; while (*j != 0 && *j != ',') j++; old = *j; *j = 0; + + hPos = strchr(target_list,'#'); + cPos = strchr(target_list,':'); + + /* + * Check if both a '#' and a ':' is in the target's name + * and if cPos < hPos. + * If that's the case, voila, we've found a join with an oplevel + */ + if (hPos && cPos && (cPos < hPos)) + { + oplevel = parse_oplevel(target_list); + target_list = hPos + 1; + } + else + oplevel = -1; + if (IsChannelName(target_list) || (target_list[0] == '0' && target_list[1] == '\0')) { struct chanNode *chan = GetChannel(target_list); + struct create_desc *cd = (struct create_desc*) data; + + cd->oplevel = oplevel; if (chan) { if (cf) cf(chan, data); @@ -2193,6 +2234,37 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un } } break; + case 'U': + if (add) + { + if (in_arg >= argc) + goto error; + change->modes_set |= MODE_UPASS; + safestrncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass)); + } else { + change->modes_clear |= MODE_UPASS; + if (!(flags & MCP_UPASS_FREE)) { + if (in_arg >= argc) + goto error; + in_arg++; + } + } + break; + case 'A': + if (add) { + if (in_arg >= argc) + goto error; + change->modes_set |= MODE_APASS; + safestrncpy(change->new_apass, modes[in_arg++], sizeof(change->new_apass)); + } else { + change->modes_clear |= MODE_APASS; + if (!(flags & MCP_APASS_FREE)) { + if (in_arg >= argc) + goto error; + in_arg++; + } + } + break; case 'b': if (!(flags & MCP_ALLOW_OVB)) goto error; @@ -2206,6 +2278,25 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un case 'o': case 'v': { struct userNode *victim; + char *oplevel_str; + int oplevel; + + oplevel_str = strchr(modes[in_arg], ':'); + + /* XXYYY M #channel +o XXYYY: */ + if (oplevel_str) + { + oplevel = parse_oplevel(oplevel_str+1); + *oplevel_str = 0; + } + else if (channel->modes & MODE_UPASS) + { + /* TODO: need to set oplevel based on issuer's oplevel */ + oplevel = -1; + } + else + oplevel = -1; + if (!(flags & MCP_ALLOW_OVB)) goto error; if (in_arg >= argc) @@ -2220,7 +2311,11 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un if (!victim) continue; if ((change->args[ch_arg].u.member = GetUserMode(channel, victim))) + { + /* Apply the oplevel change */ + change->args[ch_arg].u.member->oplevel = oplevel; ch_arg++; + } break; } default: @@ -2313,6 +2408,10 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod #undef DO_MODE_CHAR if (change->modes_clear & channel->modes & MODE_KEY) mod_chanmode_append(&chbuf, 'k', channel->key); + if (change->modes_clear & channel->modes & MODE_UPASS) + mod_chanmode_append(&chbuf, 'U', channel->upass); + if (change->modes_clear * channel->modes & MODE_APASS) + mod_chanmode_append(&chbuf, 'A', channel->apass); } for (arg = 0; arg < change->argc; ++arg) { if (!(change->args[arg].mode & MODE_REMOVE)) @@ -2352,6 +2451,10 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod #undef DO_MODE_CHAR if(change->modes_set & MODE_KEY) mod_chanmode_append(&chbuf, 'k', change->new_key); + if (change->modes_set & MODE_UPASS) + mod_chanmode_append(&chbuf, 'U', change->new_upass); + if (change->modes_set & MODE_APASS) + mod_chanmode_append(&chbuf, 'A', change->new_apass); if(change->modes_set & MODE_LIMIT) { sprintf(int_buff, "%d", change->new_limit); mod_chanmode_append(&chbuf, 'l', int_buff); @@ -2400,6 +2503,8 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff) DO_MODE_CHAR(NOPRIVMSGS, 'n'); DO_MODE_CHAR(LIMIT, 'l'); DO_MODE_CHAR(KEY, 'k'); + DO_MODE_CHAR(UPASS, 'U'); + DO_MODE_CHAR(APASS, 'A'); DO_MODE_CHAR(DELAYJOINS, 'D'); DO_MODE_CHAR(REGONLY, 'r'); DO_MODE_CHAR(NOCOLORS, 'c'); @@ -2422,10 +2527,51 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff) DO_MODE_CHAR(NOCTCPS, 'C'); DO_MODE_CHAR(REGISTERED, 'z'); #undef DO_MODE_CHAR - switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) { + switch (change->modes_set & (MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS)) { + /* Doing this implementation has been a pain in the arse, I hope I didn't forget a possible combination */ + case MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS: + used += sprintf(outbuff+used, "lkAU %d %s %s %s", change->new_limit, change->new_key, change->new_apass, change->new_upass); + break; + + case MODE_KEY|MODE_LIMIT|MODE_APASS: + used += sprintf(outbuff+used, "lkA %d %s %s", change->new_limit, change->new_key, change->new_apass); + break; + case MODE_KEY|MODE_LIMIT|MODE_UPASS: + used += sprintf(outbuff+used, "lkU %d %s %s", change->new_limit, change->new_key, change->new_upass); + break; + case MODE_KEY|MODE_APASS|MODE_UPASS: + used += sprintf(outbuff+used, "kAU %s %s %s", change->new_key, change->new_apass, change->new_upass); + break; + + case MODE_KEY|MODE_APASS: + used += sprintf(outbuff+used, "kA %s %s", change->new_key, change->new_apass); + break; + case MODE_KEY|MODE_UPASS: + used += sprintf(outbuff+used, "kU %s %s", change->new_key, change->new_upass); + break; case MODE_KEY|MODE_LIMIT: used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key); break; + case MODE_LIMIT|MODE_UPASS: + used += sprintf(outbuff+used, "lU %d %s", change->new_limit, change->new_upass); + break; + case MODE_LIMIT|MODE_APASS: + used += sprintf(outbuff+used, "lA %d %s", change->new_limit, change->new_apass); + break; + case MODE_APASS|MODE_UPASS: + used += sprintf(outbuff+used, "AU %s %s", change->new_apass, change->new_upass); + break; + + case MODE_LIMIT|MODE_APASS|MODE_UPASS: + used += sprintf(outbuff+used, "lAU %d %s %s", change->new_limit, change->new_apass, change->new_upass); + break; + + case MODE_APASS: + used += sprintf(outbuff+used, "A %s", change->new_apass); + break; + case MODE_UPASS: + used += sprintf(outbuff+used, "U %s", change->new_upass); + break; case MODE_KEY: used += sprintf(outbuff+used, "k %s", change->new_key); break; @@ -2457,6 +2603,14 @@ clear_chanmode(struct chanNode *channel, const char *modes) remove |= MODE_KEY; channel->key[0] = '\0'; break; + case 'A': + remove |= MODE_APASS; + channel->apass[0] = '\0'; + break; + case 'U': + remove |= MODE_UPASS; + channel->upass[0] = '\0'; + break; case 'l': remove |= MODE_LIMIT; channel->limit = 0; @@ -2616,3 +2770,15 @@ send_burst(void) for (it = dict_first(channels); it; it = iter_next(it)) dict_insert(unbursted_channels, iter_key(it), iter_data(it)); } + +/* + * Oplevel parsing + */ +static int +parse_oplevel(char *str) +{ + int oplevel = 0; + while (isdigit(*str)) + oplevel = oplevel * 10 + *str++ - '0'; + return oplevel; +} diff --git a/src/proto.h b/src/proto.h index 71e5564..9f0f77a 100644 --- a/src/proto.h +++ b/src/proto.h @@ -192,6 +192,8 @@ struct mod_chanmode { unsigned int alloc_argc; #endif char new_key[KEYLEN + 1]; + char new_upass[KEYLEN + 1]; + char new_apass[KEYLEN + 1]; struct { unsigned int mode; union { @@ -204,6 +206,8 @@ struct mod_chanmode { #define MCP_FROM_SERVER 0x0002 /* parse as from a server */ #define MCP_KEY_FREE 0x0004 /* -k without a key argument */ #define MCP_REGISTERED 0x0008 /* chan is already registered; do not allow changes to MODE_REGISTERED */ +#define MCP_UPASS_FREE 0x0010 /* -U without a key argument */ +#define MCP_APASS_FREE 0x0020 /* -A without a key argument */ #define MC_ANNOUNCE 0x0100 /* send a mod_chanmode() change out */ #define MC_NOTIFY 0x0200 /* make local callbacks to announce */ #ifdef NDEBUG