changed Makefile; build all commands as an own file
[NeonServV5.git] / ChanNode.c
1 #include "ChanNode.h"
2 #include "ChanUser.h"
3 #include "UserNode.h"
4 #include "BanNode.h"
5 #include "modcmd.h"
6 #include "ModeNode.h"
7
8 static struct ChanNode **chanList;
9
10 void init_ChanNode() {
11     /*
12      len pos chars 
13      26  0   a-z
14      10  26  0-9
15      10  36  {|}~[\]^_`
16      1   46  *everything else*
17      ---------------------------
18      = 47
19     */
20     #define CHANNEL_LIST_SIZE 47
21     chanList = calloc(CHANNEL_LIST_SIZE, sizeof(*chanList));
22 }
23
24 void free_ChanNode() {
25     //kamikaze free all channels and chanusers
26     int i;
27     struct ChanNode *chan, *next;
28     struct ChanUser *chanuser, *next_chanuser;
29     for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
30         for(chan = chanList[i]; chan; chan = next) {
31             next = chan->next;
32             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next_chanuser) {
33                 next_chanuser = getChannelUsers(chan, chanuser);
34                 free(chanuser);
35             }
36             freeChanNode(chan);
37         }
38     }
39     free(chanList);
40 }
41
42 int is_valid_chan(const char *name) {
43     unsigned int ii;
44     if (*name !='#')
45         return 0;
46     for (ii=1; name[ii]; ++ii) {
47         if ((name[ii] > 0) && (name[ii] <= 32))
48             return 0;
49         if (name[ii] == ',')
50             return 0;
51         if (name[ii] == '\xa0')
52             return 0;
53     }
54     return 1;
55 }
56
57 static int get_chanlist_entry(int name) {
58     if((name > 0 && name <= 32) || name == ',' || name == '\xa0') return -1; //invalid name
59     if(tolower(name) >= 97 && tolower(name) <= 122) {
60         return (tolower(name) - 97);
61     }
62     if(tolower(name) >= 48 && tolower(name) <= 57) {
63         return (tolower(name) - 48 + 26);
64     }
65     /* {|}~[\]^_` */
66     if(name == '{') return 36;
67     if(name == '|') return 37;
68     if(name == '}') return 38;
69     if(name == '~') return 39;
70     if(name == '[') return 40;
71     if(name == '\\') return 41;
72     if(name == ']') return 42;
73     if(name == '^') return 43;
74     if(name == '_') return 44;
75     if(name == '`') return 45;
76     return 46;
77 }
78
79 struct ChanNode* getChanByName(const char *name) { //case insensitive
80     int chanListIndex = get_chanlist_entry(name[1]);
81     if(chanListIndex == -1 || chanList[chanListIndex] == NULL)
82         return NULL;
83     struct ChanNode *chan;
84     for(chan = chanList[chanListIndex]; chan; chan = chan->next) {
85         if(!stricmp(name, chan->name))
86             return chan;
87     }
88     return NULL;
89 }
90
91 struct ChanNode* addChannel(const char *name) {
92     int chanListIndex = get_chanlist_entry(name[1]);
93     if(chanListIndex == -1 || !is_valid_chan(name))
94         return NULL;
95     struct ChanNode *chan = malloc(sizeof(*chan));
96     if (!chan)
97     {
98         perror("malloc() failed");
99         return NULL;
100     }
101     strcpy(chan->name, name);
102     chan->user = NULL;
103     chan->bans = NULL;
104     chan->usercount = 0;
105     chan->chanbot = NULL;
106     chan->topic[0] = 0;
107     chan->flags = 0;
108     /* mode lists */
109     chan->modes = createModeNode(chan);
110     chan->trigger = NULL;
111     
112     chan->next = chanList[chanListIndex];
113     chanList[chanListIndex] = chan;
114     return chan;
115 }
116
117 int getChannelCount() {
118     int i, count = 0;
119     struct ChanNode *chan;
120     for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
121         for(chan = chanList[i]; chan; chan = chan->next) {
122             count++;
123         }
124     }
125     return count;
126 }
127
128 int getChanUserCount() {
129     int i, count = 0;
130     struct ChanNode *chan;
131     for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
132         for(chan = chanList[i]; chan; chan = chan->next) {
133             count += chan->usercount;
134         }
135     }
136     return count;
137 }
138
139 int getChanBanCount() {
140     int i, count = 0;
141     struct ChanNode *chan;
142     struct BanNode *ban;
143     for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
144         for(chan = chanList[i]; chan; chan = chan->next) {
145             for(ban = chan->bans; ban; ban = ban->next)
146                 count ++;
147         }
148     }
149     return count;
150 }
151
152 void delChannel(struct ChanNode* chan, int freeChan) {
153     int chanListIndex = get_chanlist_entry(chan->name[1]);
154     if(chanListIndex == -1) return;
155     struct ChanNode *cchan, *last_chan = NULL;
156     for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) {
157         if(cchan == chan) {
158             if(last_chan)
159                 last_chan->next = chan->next;
160             else
161                 chanList[chanListIndex] = chan->next;
162             break;
163         } else
164             last_chan = cchan;
165     }
166     if(chan->user) {
167         //free all chanusers
168         struct ChanUser *chanuser, *next;
169         for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
170             next = getChannelUsers(chan, chanuser);
171             removeChanUserFromLists(chanuser, 0, 1, 1);
172         }
173     }
174     if(freeChan)
175         freeChanNode(chan);
176     else
177         chan->next = NULL;
178 }
179
180 void freeChanNode(struct ChanNode* chan) {
181     if(chan->trigger) {
182         struct trigger_cache *trigger, *next_trigger;
183         for(trigger = chan->trigger; trigger; trigger = next_trigger) {
184             next_trigger = trigger->next;
185             free(trigger->trigger);
186             free(trigger);
187         }
188     }
189     freeModeNode(chan->modes);
190     if(chan->bans)
191         removeChannelBans(chan);
192     free(chan);
193 }
194
195 void checkChannelVisibility(struct ChanNode* chan) {
196     struct ChanUser *chanuser, *next;
197     for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
198         if(chanuser->user->flags & USERFLAG_ISBOT) {
199             chan->chanbot = chanuser->user;
200             return;
201         }
202     }
203     //free the channel...
204     for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
205         next = getChannelUsers(chan, chanuser);
206         //remove the channel from the user's channel-list
207         removeChanUserFromLists(chanuser, 0, 1, 0);
208         if(!chanuser->user->channel) {
209             //free the user (no more channels)
210             delUser(chanuser->user, 1);
211         }
212         free(chanuser);
213     }
214     chan->user = NULL;
215     delChannel(chan, 1);
216 }