changed Makefile; build all commands as an own file
[NeonServV5.git] / ModeNode.c
index cf9901f6c35b646d22a3f7e002a22af93c2927f4..0afe6f2aa700b962fd5aeeed0af7f65fc114f788 100644 (file)
@@ -4,27 +4,13 @@
 #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,
@@ -53,6 +39,7 @@ void init_ModeNode() {
     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;
@@ -62,6 +49,7 @@ void init_ModeNode() {
             mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
             modes_with_intarg++;
         }
+        modes_count++;
         mode[0] = flag;
         flag = flag << 1;
     }
@@ -76,6 +64,7 @@ struct ModeNode *createModeNode(struct ChanNode *chan) {
     }
     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;
@@ -106,6 +95,11 @@ int isModeSet(struct ModeNode* modes, char modeChar) {
     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);
@@ -117,6 +111,14 @@ void* getModeValue(struct ModeNode* modes, char 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);
@@ -187,8 +189,10 @@ void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
                     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) {
@@ -205,6 +209,72 @@ void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
     #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)
@@ -231,3 +301,42 @@ void getModeString(struct ModeNode* modes, char *modesStr) {
     #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
+}