]> jfr.im git - irc/quakenet/newserv.git/blame - whowas/whowas.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / whowas / whowas.c
CommitLineData
fa6819a7 1#include <string.h>
0eb4cbd3 2#include <stdio.h>
fa6819a7
GB
3#include "../core/hooks.h"
4#include "../control/control.h"
5#include "../irc/irc.h"
6#include "../lib/irc_string.h"
363e3ed0 7#include "../lib/version.h"
291fdf5f 8#include "../core/config.h"
fa6819a7
GB
9#include "whowas.h"
10
363e3ed0 11MODULE_VERSION("");
fa6819a7 12
291fdf5f 13whowas *whowasrecs;
0495c1d1 14int whowasoffset = 0;
291fdf5f 15int whowasmax;
d6385de2 16
0495c1d1 17whowas *whowas_fromnick(nick *np, int standalone) {
fa6819a7 18 whowas *ww;
0eb4cbd3
GB
19 nick *wnp;
20 struct irc_in_addr ipaddress_canonical;
dd33b9ca 21 void *args[2];
fa6819a7
GB
22
23 /* Create a new record. */
0495c1d1
GB
24 if (standalone)
25 ww = malloc(sizeof(whowas));
26 else {
27 ww = &whowasrecs[whowasoffset];
28 whowas_clean(ww);
291fdf5f 29 whowasoffset = (whowasoffset + 1) % whowasmax;
0495c1d1
GB
30 }
31
4030a47e 32 memset(ww, 0, sizeof(whowas));
0eb4cbd3 33
0495c1d1 34 wnp = &ww->nick;
0eb4cbd3
GB
35 memset(wnp, 0, sizeof(nick));
36 strncpy(wnp->nick, np->nick, NICKLEN + 1);
37 wnp->numeric = np->numeric;
38 strncpy(wnp->ident, np->ident, USERLEN + 1);
39
40 wnp->host = newhost();
41 memset(wnp->host, 0, sizeof(host));
42 wnp->host->name = getsstring(np->host->name->content, HOSTLEN);
43
44 wnp->realname = newrealname();
45 memset(wnp->realname, 0, sizeof(realname));
46 wnp->realname->name = getsstring(np->realname->name->content, REALLEN);
81e02f8e
GB
47 wnp->shident = np->shident ? getsstring(np->shident->content, 512) : NULL;
48 wnp->sethost = np->sethost ? getsstring(np->sethost->content, 512) : NULL;
49 wnp->opername = np->opername ? getsstring(np->opername->content, 512) : NULL;
0eb4cbd3
GB
50 wnp->umodes = np->umodes;
51 if (np->auth) {
52 wnp->auth = newauthname();
53 memset(wnp->auth, 0, sizeof(authname));
54 wnp->auth->userid = np->auth->userid;
55 strncpy(wnp->auth->name, np->auth->name, ACCOUNTLEN + 1);
b965fa47 56 wnp->authname = wnp->auth->name;
0eb4cbd3 57 }
0eb4cbd3
GB
58 wnp->timestamp = np->timestamp;
59 wnp->accountts = np->accountts;
60 wnp->away = np->away ? getsstring(np->away->content, 512) : NULL;
61
62 memcpy(&wnp->ipaddress, &np->ipaddress, sizeof(struct irc_in_addr));
63
64 ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
65 wnp->ipnode = refnode(iptree, &ipaddress_canonical, PATRICIA_MAXBITS);
66
67 wnp->next = (nick *)ww; /* Yuck. */
68
0eb4cbd3 69 ww->timestamp = getnettime();
a45da344 70 ww->type = WHOWAS_USED;
fa6819a7 71
dd33b9ca
GB
72 args[0] = ww;
73 args[1] = np;
74 triggerhook(HOOK_WHOWAS_NEWRECORD, args);
75
4030a47e
GB
76 return ww;
77}
d6385de2 78
0495c1d1 79void whowas_clean(whowas *ww) {
0eb4cbd3
GB
80 nick *np;
81
0495c1d1 82 if (!ww || ww->type == WHOWAS_UNUSED)
accce086
GB
83 return;
84
dd33b9ca
GB
85 triggerhook(HOOK_WHOWAS_LOSTRECORD, ww);
86
0495c1d1 87 np = &ww->nick;
0eb4cbd3
GB
88 freesstring(np->host->name);
89 freehost(np->host);
90 freesstring(np->realname->name);
91 freerealname(np->realname);
92 freesstring(np->shident);
93 freesstring(np->sethost);
94 freesstring(np->opername);
95 freeauthname(np->auth);
96 freesstring(np->away);
291fdf5f 97 derefnode(iptree, np->ipnode);
accce086 98 freesstring(ww->reason);
291fdf5f 99 freesstring(ww->newnick);
0495c1d1 100 ww->type = WHOWAS_UNUSED;
accce086
GB
101}
102
0495c1d1
GB
103void whowas_free(whowas *ww) {
104 whowas_clean(ww);
105 free(ww);
fa6819a7 106}
4030a47e
GB
107
108static void whowas_handlequitorkill(int hooknum, void *arg) {
109 void **args = arg;
110 nick *np = args[0];
111 char *reason = args[1];
112 char *rreason;
113 char resbuf[512];
114 whowas *ww;
115
4030a47e 116 /* Create a new record. */
0495c1d1 117 ww = whowas_fromnick(np, 0);
4030a47e
GB
118
119 if (hooknum == HOOK_NICK_KILL) {
120 if ((rreason = strchr(reason, ' '))) {
121 sprintf(resbuf, "Killed%s", rreason);
122 reason = resbuf;
123 }
124
125 ww->type = WHOWAS_KILL;
98005421
GB
126 } else {
127 if (strncmp(reason, "G-lined", 7) == 0)
128 ww->type = WHOWAS_KILL;
129 else
130 ww->type = WHOWAS_QUIT;
131 }
4030a47e
GB
132
133 ww->reason = getsstring(reason, WW_REASONLEN);
4030a47e
GB
134}
135
136static void whowas_handlerename(int hooknum, void *arg) {
137 void **args = arg;
138 nick *np = args[0];
139 char *oldnick = args[1];
140 whowas *ww;
0eb4cbd3 141 nick *wnp;
4030a47e 142
0495c1d1 143 ww = whowas_fromnick(np, 0);
4030a47e 144 ww->type = WHOWAS_RENAME;
0495c1d1 145 wnp = &ww->nick;
0eb4cbd3
GB
146 ww->newnick = getsstring(wnp->nick, NICKLEN);
147 strncpy(wnp->nick, oldnick, NICKLEN + 1);
4030a47e
GB
148}
149
0495c1d1 150whowas *whowas_chase(const char *target, int maxage) {
56cab147 151 whowas *ww;
0495c1d1 152 nick *wnp;
56cab147 153 time_t now;
0495c1d1 154 int i;
56cab147
GB
155
156 now = getnettime();
157
291fdf5f
CP
158 for (i = whowasoffset + whowasmax - 1; i >= whowasoffset; i--) {
159 ww = &whowasrecs[i % whowasmax];
0495c1d1
GB
160
161 if (ww->type == WHOWAS_UNUSED)
162 continue;
163
164 wnp = &ww->nick;
165
0eb4cbd3 166 if (ww->timestamp < now - maxage)
56cab147
GB
167 break; /* records are in timestamp order, we're done */
168
0495c1d1 169 if (ircd_strcmp(wnp->nick, target) == 0)
56cab147
GB
170 return ww;
171 }
172
173 return NULL;
174}
175
0eb4cbd3 176const char *whowas_format(whowas *ww) {
0495c1d1 177 nick *np = &ww->nick;
0eb4cbd3 178 static char buf[512];
accce086 179 char timebuf[30];
0eb4cbd3 180 char hostmask[512];
accce086 181
432206be 182 snprintf(hostmask, sizeof(hostmask), "%s!%s@%s%s%s [%s] (%s)",
0eb4cbd3
GB
183 np->nick, np->ident, np->host->name->content,
184 np->auth ? "/" : "", np->auth ? np->authname : "",
fdcb5d66 185 IPtostr(np->ipaddress),
432206be 186 printflags(np->umodes, umodeflags));
0eb4cbd3 187 strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&(ww->timestamp)));
accce086
GB
188
189 if (ww->type == WHOWAS_RENAME)
0eb4cbd3 190 snprintf(buf, sizeof(buf), "[%s] NICK %s r(%s) -> %s", timebuf, hostmask, np->realname->name->content, ww->newnick->content);
accce086 191 else
0eb4cbd3
GB
192 snprintf(buf, sizeof(buf), "[%s] %s %s r(%s): %s", timebuf, (ww->type == WHOWAS_QUIT) ? "QUIT" : "KILL", hostmask, np->realname->name->content, ww->reason->content);
193
194 return buf;
195}
196
dd33b9ca
GB
197const char *whowas_formatchannels(whowas *ww) {
198 static char buf[512];
199 int i, first = 1;
200
201 strcpy(buf, "Channels: ");
202
203 for (i = 0; i < WW_MAXCHANNELS; i++) {
204 if (!ww->channels[i])
205 break;
206
207 if (!first)
208 strncat(buf, ", ", sizeof(buf));
209 else
210 first = 0;
211
212 strncat(buf, ww->channels[i]->name->content, sizeof(buf));
213 }
214
215 if (!ww->channels[0])
216 strncat(buf, "(No channels.)", sizeof(buf));
217
218 buf[sizeof(buf) - 1] = '\0';
219
220 return buf;
221}
222
0eb4cbd3
GB
223unsigned int nextwhowasmarker() {
224 whowas *ww;
0495c1d1 225 int i;
0eb4cbd3
GB
226 static unsigned int whowasmarker=0;
227
228 whowasmarker++;
229
230 if (!whowasmarker) {
231 /* If we wrapped to zero, zap the marker on all records */
291fdf5f
CP
232 for (i = 0; i < whowasmax; i++) {
233 ww = &whowasrecs[i % whowasmax];
0495c1d1
GB
234 ww->marker=0;
235 }
236
0eb4cbd3
GB
237 whowasmarker++;
238 }
239
240 return whowasmarker;
accce086
GB
241}
242
4030a47e 243void _init(void) {
291fdf5f
CP
244 {
245 sstring *temp = getcopyconfigitem("whowas", "maxentries", XStringify(WW_DEFAULT_MAXENTRIES), 10);
246 whowasmax = atoi(temp->content);
247 freesstring(temp);
248 }
249 whowasrecs = calloc(whowasmax, sizeof(whowas));
8bf19136 250
4030a47e
GB
251 registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
252 registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
253 registerhook(HOOK_NICK_RENAME, whowas_handlerename);
254}
255
256void _fini(void) {
0495c1d1
GB
257 int i;
258 whowas *ww;
259
4030a47e
GB
260 deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
261 deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
262 deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
263
291fdf5f 264 for (i = 0; i < whowasmax; i++) {
96fa425f 265 ww = &whowasrecs[i];
0495c1d1
GB
266 whowas_clean(ww);
267 }
291fdf5f
CP
268
269 free(whowasrecs);
4030a47e 270}