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