+int ss_check_user_level(struct chanNode *channel, struct userNode *user, unsigned int minimum, int allow_override, int exempt_owner)
+{
+ struct userData *uData;
+ struct chanData *cData = channel->channel_info;
+ if(!minimum)
+ return 1;
+ uData = _GetChannelUser(cData, user->handle_info, allow_override, 0);
+ if(!uData)
+ return 0;
+ if(minimum <= uData->access)
+ return 1;
+ if((minimum > UL_OWNER) && (uData->access == UL_OWNER) && exempt_owner)
+ return 1;
+ return 0;
+}
+
+
+static int
+channel_except_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptlevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptlevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTLEVEL", cInfo->exceptlevel);
+ return 0;
+}
+
+static int
+channel_except_adv_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptadvlevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptadvlevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTADVLEVEL", cInfo->exceptadvlevel);
+ return 0;
+}
+
+static int
+channel_except_badword_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptbadwordlevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptbadwordlevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTBADWORDLEVEL", cInfo->exceptbadwordlevel);
+ return 0;
+}
+
+static int
+channel_except_caps_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptcapslevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptcapslevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTCAPSLEVEL", cInfo->exceptcapslevel);
+ return 0;
+}
+
+static int
+channel_except_flood_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptfloodlevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptfloodlevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTFLOODLEVEL", cInfo->exceptfloodlevel);
+ return 0;
+}
+
+static int
+channel_except_spam_level(struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
+{
+ struct chanData *cData = channel->channel_info;
+ struct chanInfo *cInfo;
+ struct userData *uData;
+ unsigned short value;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ if(!ss_check_user_level(channel, user, cInfo->exceptspamlevel, 1, 1))
+ {
+ reply("SSMSG_CANNOT_SET");
+ return 0;
+ }
+ value = user_level_from_name(argv[1], UL_OWNER+1);
+ if(!value && strcmp(argv[1], "0"))
+ {
+ reply("SSMSG_INVALID_ACCESS", argv[1]);
+ return 0;
+ }
+ uData = GetChannelUser(cData, user->handle_info);
+ if(!uData || ((uData->access < UL_OWNER) && (value > uData->access)))
+ {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ cInfo->exceptspamlevel = value;
+ }
+ reply("SSMSG_SET_EXCEPTSPAMLEVEL", cInfo->exceptspamlevel);
+ return 0;
+}
+
+static
+SPAMSERV_FUNC(opt_capsmin)
+{
+ struct chanInfo *cInfo;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ char *mask = strdup(argv[1]);
+ unsigned int old = cInfo->capsmin;
+
+ if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
+ cInfo->capsmin = mask ? strtoul(mask, NULL, 0) : 10;
+
+ if (cInfo->capsmin < 0) {
+ cInfo->capsmin = old;
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ } else {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ }
+ reply("SSMSG_SET_CAPSMIN", cInfo->capsmin);
+ return 0;
+}
+
+static
+SPAMSERV_FUNC(opt_capspercent)
+{
+ struct chanInfo *cInfo;
+
+ cInfo = get_chanInfo(channel->name);
+
+ if(argc > 1)
+ {
+ char *mask = strdup(argv[1]);
+ unsigned int old = cInfo->capspercent;
+
+ if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
+ cInfo->capspercent = mask ? strtoul(mask, NULL, 0) : 10;
+
+ if ((cInfo->capspercent < 0) || (cInfo->capspercent > 100)) {
+ cInfo->capspercent = old;
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ } else {
+ reply("SSMSG_BAD_SETLEVEL");
+ return 0;
+ }
+ }
+ reply("SSMSG_SET_CAPSPERCENT", cInfo->capspercent);
+ return 0;
+}
+
+static
+SPAMSERV_FUNC(opt_exceptlevel)
+{
+ return channel_except_level(SSFUNC_ARGS);
+}
+
+static
+SPAMSERV_FUNC(opt_exceptadvlevel)
+{
+ return channel_except_adv_level(SSFUNC_ARGS);
+}
+
+static
+SPAMSERV_FUNC(opt_exceptbadwordlevel)
+{
+ return channel_except_badword_level(SSFUNC_ARGS);
+}
+
+static
+SPAMSERV_FUNC(opt_exceptcapslevel)
+{
+ return channel_except_caps_level(SSFUNC_ARGS);
+}
+
+static
+SPAMSERV_FUNC(opt_exceptfloodlevel)
+{
+ return channel_except_flood_level(SSFUNC_ARGS);
+}
+
+static
+SPAMSERV_FUNC(opt_exceptspamlevel)
+{
+ return channel_except_spam_level(SSFUNC_ARGS);
+}
+