added .gitignore
[NeonServV5.git] / WHOHandler.c
1
2 #include "WHOHandler.h"
3 #include "ChanNode.h"
4 #include "UserNode.h"
5 #include "ChanUser.h"
6 #include "ClientSocket.h"
7
8 #define WHOQUEUETYPE_ISONQUEUE 0x01
9 #define WHOQUEUETYPE_USERLIST  0x02
10
11 struct WHOQueueEntry {
12     char type;
13     struct ClientSocket *client;
14     struct ChanNode *chan;
15     struct UserNode *user;
16     struct WHOQueueEntry *next;
17     userlist_callback_t *callback;
18     void *data;
19 };
20
21 static struct WHOQueueEntry *first_entry = NULL, *last_entry = NULL;
22
23 static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
24     struct WHOQueueEntry *entry = malloc(sizeof(*entry));
25     if (!entry)
26     {
27         perror("malloc() failed");
28         return NULL;
29     }
30     entry->next = NULL;
31     entry->client = client;
32     if(last_entry)
33         last_entry->next = entry;
34     if(!first_entry)
35         first_entry = entry;
36     return entry;
37 }
38
39 static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, int freeEntry) {
40     if(!first_entry) return NULL;
41     struct WHOQueueEntry *entry;
42     for(entry = first_entry; entry; entry = entry->next) {
43         if(entry->client == client)
44             break;
45     }
46     if(entry == NULL) return NULL;
47     if(freeEntry) {
48         first_entry = first_entry->next;
49         if(last_entry == first_entry)
50             last_entry = NULL;
51     }
52     return entry;
53 }
54
55 void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) {
56     struct ClientSocket *bot;
57     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
58         if(isUserOnChan(bot->user, chan))
59             break;
60     }
61     if(bot == NULL) return;
62     struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
63     entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
64     entry->chan = chan;
65     entry->callback = callback;
66     entry->data = data;
67     //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
68     putsock(bot, "WHO %s,%d %%tuhnaf,%d", chan->name, entry->type, entry->type);
69 }
70
71 void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc) {
72     int i;
73     if(argc < 2) return;
74     int type = atoi(argv[1]);
75     if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
76     struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 0);
77     if(entry == NULL || entry->type != type) return;
78     if(type & WHOQUEUETYPE_USERLIST) {
79         if(argc < 7) return;
80         //:OGN2.OnlineGamesNet.net 354 skynet 1 pk910 2001:41d0:2:1d3b::babe skynet H@ pk910
81         struct ChanNode *chan = entry->chan;
82         //add the user toe the channel if he isn't added, yet and update its user data
83         struct UserNode *user = getUserByNick(argv[4]);
84         if(user == NULL) {
85             user = addUser(argv[4]);
86         }
87         //parse flags
88         int userflags = 0;
89         int chanuserflags = 0;
90         for(i = 0; i < strlen(argv[5]); i++) {
91             switch (argv[5][i]) {
92                 case '@':
93                     chanuserflags |= CHANUSERFLAG_OPPED;
94                     break;
95                 case '+':
96                     chanuserflags |= CHANUSERFLAG_VOICED;
97                     break;
98                 case '*':
99                     userflags |= USERFLAG_ISIRCOP;
100                     break;
101                 default:
102                     break;
103             }
104         }
105         user->flags = (user->flags & ~USERFLAG_ISIRCOP) | userflags;
106         if(!isUserOnChan(user, chan)) {
107             struct ChanUser *chanuser = addChanUser(chan, user);
108             chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
109         }
110         if(!*user->ident)
111             strcpy(user->ident, argv[2]);
112         if(!*user->host)
113             strcpy(user->host, argv[3]);
114         if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[6], "0")) {
115             strcpy(user->auth, argv[6]);
116             user->flags |= USERFLAG_ISAUTHED;
117         }
118     }
119 }
120
121 void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc) {
122     if(argc < 2) return;
123     char *typestr = strstr(argv[1], ",") + 1;
124     int type = atoi(typestr);
125     if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
126     struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 1);
127     if(entry == NULL || entry->type != type) return;
128     if(type & WHOQUEUETYPE_USERLIST) {
129         //:OGN2.OnlineGamesNet.net 315 skynet #pk910,1 :End of /WHO list.
130         entry->chan->flags |= CHANFLAG_RECEIVED_USERLIST;
131         entry->callback(client, entry->chan, entry->data);
132     }
133     free(entry);
134 }
135
136 void free_whoqueue() {
137     struct WHOQueueEntry *entry, *next;
138     for(entry = first_entry; entry; entry = next) {
139         next = entry->next;
140         free(entry);
141     }
142     first_entry = NULL;
143     last_entry = NULL;
144 }