c194935eab2c4906e7de94904e8e626a58bd4137
[NeonServV5.git] / src / HandleInfoHandler.c
1 /* HandleInfoHandler.c - NeonServ v5.3
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "HandleInfoHandler.h"
19 #include "ClientSocket.h"
20 #include "UserNode.h"
21 #include "IRCEvents.h"
22 #include "tools.h"
23
24 #define AUTHSERV_NICK "AuthServ"
25
26 #define MAXCALLBACKS 3
27
28 struct HandleInfoQueueEntry {
29     char *auth;
30     void *callback[MAXCALLBACKS];
31     void *data[MAXCALLBACKS];
32     
33     struct HandleInfoQueueEntry *next;
34 };
35
36 static struct HandleInfoQueueEntry* addHandleInfoQueueEntry(struct ClientSocket *client) {
37     struct HandleInfoQueueEntry *entry = malloc(sizeof(*entry));
38     if (!entry)
39     {
40         perror("malloc() failed");
41         return NULL;
42     }
43     entry->next = NULL;
44     if(client->handleinfo_last)
45         client->handleinfo_last->next = entry;
46     else
47         client->handleinfo_first = entry;
48     client->handleinfo_last = entry;
49     return entry;
50 }
51
52 static struct HandleInfoQueueEntry* getNextHandleInfoQueueEntry(struct ClientSocket *client, int freeEntry) {
53     if(!client->handleinfo_first) return NULL;
54     struct HandleInfoQueueEntry *entry = client->handleinfo_first;
55     if(freeEntry) {
56         client->handleinfo_first = entry->next;
57         if(entry == client->handleinfo_last) {
58             client->handleinfo_last = NULL;
59         }
60     }
61     return entry;
62 }
63
64 void clear_handleinfoqueue(struct ClientSocket *client) {
65     if(!client->handleinfo_first) return;
66     struct HandleInfoQueueEntry *entry, *next;
67     for(entry = client->handleinfo_first; entry; entry = next) {
68         next = entry->next;
69         free(entry);
70     }
71     client->handleinfo_last = NULL;
72     client->handleinfo_first = NULL;
73 }
74
75 void lookup_authname(char *auth, authlookup_callback_t callback, void *data) {
76     struct ClientSocket *bot;
77     struct HandleInfoQueueEntry* entry;
78     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
79         for(entry = bot->handleinfo_first; entry; entry = entry->next) {
80             if(!stricmp(entry->auth, auth)) {
81                 int i = 0;
82                 for(i = 1; i < MAXCALLBACKS; i++) {
83                     if(!entry->callback[i]) {
84                         entry->callback[i] = callback;
85                         entry->data[i] = data;
86                         return;
87                     }
88                 }
89             }
90         }
91         if(bot->flags & SOCKET_FLAG_PREFERRED)
92             break;
93     }
94     if(bot == NULL) return;
95     entry = addHandleInfoQueueEntry(bot);
96     int i;
97     entry->auth = strdup(auth);
98     entry->callback[0] = callback;
99     for(i = 1; i < MAXCALLBACKS; i++)
100         entry->callback[i] = NULL;
101     entry->data[0] = data;
102     for(i = 1; i < MAXCALLBACKS; i++)
103         entry->data[i] = NULL;
104     putsock(bot, "PRIVMSG " AUTHSERV_NICK " :ACCOUNTINFO *%s", auth);
105 }
106
107 static void recv_notice(struct UserNode *user, struct UserNode *target, char *message) {
108     if(stricmp(user->nick, AUTHSERV_NICK)) return;
109     struct ClientSocket *bot;
110     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
111         if(bot->user == target) break;
112     }
113     if(!bot) return;
114     char *auth = NULL;
115     int do_match = 0, exists = 0;
116     char *tmp;
117     //messages to parse:
118     //  Account * has not been registered.
119     //  Account information for Skynet:
120     if(!match("Account * has not been registered.", message)) {
121         do_match = 1;
122         tmp = strstr(message, "\002");
123         auth = tmp+1;
124         tmp = strstr(auth, "\002");
125         *tmp = '\0';
126     }
127     if(!match("Account information for *", message)) {
128         do_match = 1;
129         exists = 1;
130         tmp = strstr(message, "\002");
131         auth = tmp+1;
132         tmp = strstr(auth, "\002");
133         *tmp = '\0';
134     }
135     if(do_match) {
136         struct HandleInfoQueueEntry* entry = getNextHandleInfoQueueEntry(bot, 1);
137         if(entry) {
138             authlookup_callback_t *callback;
139             int i;
140             for(i = 0; i < MAXCALLBACKS; i++) {
141                 callback = entry->callback[i];
142                 if(!callback) break;
143                 callback(auth, exists, entry->data[i]);
144             }
145             free(entry->auth);
146             free(entry);
147         }
148     }
149 }
150
151 void init_handleinfohandler() {
152     bind_privnotice(recv_notice);
153 }
154
155 void free_handleinfohandler() {
156     
157 }