#include "UserNode.h"
#include "BanNode.h"
-static int modes_with_strarg, modes_with_intarg;
+static int modes_with_strarg, modes_with_intarg, modes_count;
-//Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
-#define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
-#define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
-#define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
-#define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
-#define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
-
-#define CHANNEL_MODE_VALUE_STRING 0x10
-#define CHANNEL_MODE_VALUE_INTEGER 0x20
-#define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
-
-#define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
-#define CHANNEL_MODE_VALUE_INDEX_MASK (0xff << CHANNEL_MODE_VALUE_INDEX_SHIFT) /* this "bitrange" is reserved for storing the array indexes of the mode values */
-
-static unsigned int valid_modes[] = { /* Thats our mode list :P */
+unsigned int valid_modes[] = { /* Thats our mode list :P */
1, 'b', CHANNEL_MODE_TYPE_A,
2, 'o', CHANNEL_MODE_TYPE_A,
3, 'v', CHANNEL_MODE_TYPE_A,
- 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING,
+ 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING | CHANNEL_MODE_KEY,
5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
unsigned int *mode, flag = 1;
modes_with_strarg = 0;
modes_with_intarg = 0;
+ modes_count = 0;
for (mode = valid_modes; mode[1]; mode += 3) {
if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
modes_with_intarg++;
}
+ modes_count++;
mode[0] = flag;
flag = flag << 1;
}
}
modes->chan = chan;
modes->modes = 0;
+ modes->allmodes = 0;
modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
return modes;
return (modes->modes & modeOpt[0]);
}
+int isModeAffected(struct ModeNode* modes, char modeChar) {
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ return (modes->allmodes & modeOpt[0]);
+}
+
void* getModeValue(struct ModeNode* modes, char modeChar) {
#define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
unsigned int *modeOpt = getModeOptions(modeChar);
#undef MODE_VALUE_INDEX
}
+unsigned int getModeType(struct ModeNode* modes, char modeChar) {
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ if(!modeOpt) return 0;
+ return modeOpt[2];
+ #undef MODE_VALUE_INDEX
+}
+
static void parseModesUserPriv(struct ModeNode* modes, unsigned char flag, int add, char *nick) {
if(modes->chan == NULL) return;
struct UserNode *user = getUserByNick(nick);
argpos++; //we simply don't know what to do with the argument...
}
modes->modes |= modeOpt[0];
+ modes->allmodes |= modeOpt[0];
} else {
modes->modes &= ~modeOpt[0];
+ modes->allmodes |= modeOpt[0];
if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
if(argpos == argc) continue;
if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
#undef MODE_VALUE_INDEX
}
+void parseModeString(struct ModeNode* modes, char *modeStr) {
+ int argc = 0;
+ char *args[modes_count+1];
+ char *a, *b = modeStr;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ args[argc++] = b;
+ if(a) b = a+1;
+ } while(a);
+ parseModes(modes, args[0], args+1, argc-1);
+}
+
+int parseMode(struct ModeNode* modes, int add, char mode, char *param) {
+ #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt = getModeOptions(mode);
+ if(!modeOpt) return 0;
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
+ if(!param) return 0;
+ //special mode ;)
+ switch(mode) {
+ case 'o':
+ parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
+ break;
+ case 'v':
+ parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
+ break;
+ case 'b':
+ parseModesBan(modes, add, param);
+ break;
+ default:
+ return 0; //we have an unknown TYPE_A mode???
+ }
+ }
+ if(add) {
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
+ if(!param) return 0;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ if(modes->mode_str_args[MODE_VALUE_INDEX])
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = strdup(param);
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = atoi(param);
+ }
+ modes->modes |= modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ } else {
+ modes->modes &= ~modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
+ if(!param) return 0;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = 0;
+ }
+ }
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+ return 1;
+}
+
void getModeString(struct ModeNode* modes, char *modesStr) {
#define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
#define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
#undef MODE_VALUE
#undef MODE_VALUE_INDEX
}
+
+void getFullModeString(struct ModeNode* modes, char *modesStr) {
+ #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ char addMode[modes_count+1];
+ int addModePos = 0;
+ char addParams[MAXLEN];
+ addParams[0] = '\0';
+ int addParamsPos = 0;
+ char delMode[modes_count+1];
+ int delModePos = 0;
+ unsigned int *mode;
+ for (mode = valid_modes; mode[1]; mode += 3) {
+ if(modes->allmodes & mode[0]) {
+ if(modes->modes & mode[0]) {
+ addMode[addModePos++] = (char) mode[1];
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
+ addParamsPos += sprintf(addParams + addParamsPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
+ else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ addParamsPos += sprintf(addParams + addParamsPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
+ }
+ } else {
+ delMode[delModePos++] = (char) mode[1];
+ }
+ }
+ }
+ addMode[addModePos] = '\0';
+ delMode[delModePos] = '\0';
+ addParams[addParamsPos] = '\0';
+ sprintf(modesStr, "%s%s%s%s%s", (addModePos ? "+" : ""), addMode, (delModePos ? "-" : ""), delMode, addParams);
+ if(*modesStr == '\0') {
+ sprintf(modesStr, "+");
+ }
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+}