]> jfr.im git - irc/quakenet/newserv.git/blob - nick/nick.c
Sigh
[irc/quakenet/newserv.git] / nick / nick.c
1 /* nick.c */
2
3 #include "nick.h"
4 #include "../lib/flags.h"
5 #include "../lib/irc_string.h"
6 #include "../lib/base64.h"
7 #include "../irc/irc.h"
8 #include "../irc/irc_config.h"
9 #include "../core/error.h"
10 #include "../core/hooks.h"
11 #include "../lib/sstring.h"
12 #include "../server/server.h"
13 #include "../parser/parser.h"
14 #include "../lib/version.h"
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdio.h>
18
19 MODULE_VERSION("$Id: nick.c 663 2006-05-16 17:27:36Z newserv $")
20
21 const flag umodeflags[] = {
22 { 'i', UMODE_INV },
23 { 'w', UMODE_WALLOPS },
24 { 'g', UMODE_DEBUG },
25 { 'o', UMODE_OPER },
26 { 'k', UMODE_SERVICE },
27 { 'X', UMODE_XOPER },
28 { 'd', UMODE_DEAF },
29 { 'r', UMODE_ACCOUNT },
30 { 'n', UMODE_HIDECHAN },
31 { 'x', UMODE_HIDEHOST },
32 { 'h', UMODE_SETHOST },
33 { 'R', UMODE_REGPRIV },
34 { 'I', UMODE_HIDEIDLE },
35 { '\0', 0 } };
36
37 #define nickhash(x) ((crc32i(x))%NICKHASHSIZE)
38
39 nick *nicktable[NICKHASHSIZE];
40 nick **servernicks[MAXSERVERS];
41
42 sstring *nickextnames[MAXNICKEXTS];
43
44 void nickstats(int hooknum, void *arg);
45
46 void _init() {
47 initnickalloc();
48 initnickhelpers();
49 memset(nicktable,0,sizeof(nicktable));
50 memset(servernicks,0,sizeof(servernicks));
51
52 /* Register our hooks */
53 registerhook(HOOK_SERVER_NEWSERVER,&handleserverchange);
54 registerhook(HOOK_SERVER_LOSTSERVER,&handleserverchange);
55 registerhook(HOOK_CORE_STATSREQUEST,&nickstats);
56
57 /* And our server handlers */
58 registerserverhandler("N",&handlenickmsg,10);
59 registerserverhandler("D",&handlekillmsg,2);
60 registerserverhandler("Q",&handlequitmsg,1);
61 registerserverhandler("M",&handleusermodemsg,3);
62 registerserverhandler("W",&handlewhoismsg,2);
63 registerserverhandler("AC",&handleaccountmsg,2);
64 registerserverhandler("R",&handlestatsmsg,2);
65
66 /* Fake the addition of our own server */
67 handleserverchange(HOOK_SERVER_NEWSERVER,(void *)numerictolong(mynumeric->content,2));
68 }
69
70 /*
71 * This function handles servers appearing and disappearing.
72 * For a new server, the client table is allocated.
73 * For a disappearing server, all it's clients are killed and the client table is freed.
74 */
75
76 void handleserverchange(int hooknum, void *arg) {
77 int servernum;
78 int i;
79
80 servernum=(int)arg;
81
82 switch(hooknum) {
83 case HOOK_SERVER_NEWSERVER:
84 servernicks[servernum]=(nick **)malloc((serverlist[servernum].maxusernum+1)*sizeof(nick **));
85 memset(servernicks[servernum],0,(serverlist[servernum].maxusernum+1)*sizeof(nick **));
86 break;
87
88 case HOOK_SERVER_LOSTSERVER:
89 for (i=0;i<=serverlist[servernum].maxusernum;i++) {
90 if (servernicks[servernum][i]!=NULL) {
91 deletenick(servernicks[servernum][i]);
92 }
93 }
94 free(servernicks[servernum]);
95 break;
96 }
97 }
98
99 /*
100 * deletenick:
101 *
102 * This function handles the removal of a nick from the network
103 */
104
105 void deletenick(nick *np) {
106 nick **nh;
107
108 /* Fire the hook. This will deal with removal from channels etc. */
109 triggerhook(HOOK_NICK_LOSTNICK, np);
110
111 /* Release the realname and hostname parts */
112
113 for (nh=&(np->realname->nicks);*nh;nh=&((*nh)->nextbyrealname)) {
114 if (*nh==np) {
115 *nh=np->nextbyrealname;
116 break;
117 }
118 }
119
120 for (nh=&(np->host->nicks);*nh;nh=&((*nh)->nextbyhost)) {
121 if (*nh==np) {
122 *nh=np->nextbyhost;
123 break;
124 }
125 }
126
127 releaserealname(np->realname);
128 releasehost(np->host);
129
130 freesstring(np->shident); /* freesstring(NULL) is OK */
131 freesstring(np->sethost);
132
133 /* Delete the nick from the servernick table */
134 *(gethandlebynumericunsafe(np->numeric))=NULL;
135
136 /* Remove the nick from the hash table */
137 removenickfromhash(np);
138
139 freenick(np);
140 }
141
142 void addnicktohash(nick *np) {
143 np->next=nicktable[nickhash(np->nick)];
144 nicktable[nickhash(np->nick)]=np;
145 }
146
147 void removenickfromhash(nick *np) {
148 nick **nh;
149
150 for (nh=&(nicktable[nickhash(np->nick)]);*nh;nh=&((*nh)->next)) {
151 if ((*nh)==np) {
152 (*nh)=np->next;
153 break;
154 }
155 }
156 }
157
158 nick *getnickbynick(const char *name) {
159 nick *np;
160
161 for (np=nicktable[nickhash(name)];np;np=np->next) {
162 if (!ircd_strcmp(np->nick,name))
163 return np;
164 }
165
166 return NULL;
167 }
168
169 void nickstats(int hooknum, void *arg) {
170 int total,maxchain,curchain,i,buckets;
171 nick *np;
172 char buf[200];
173
174 /* Get nick stats */
175 buckets=total=maxchain=curchain=0;
176 for (i=0;i<NICKHASHSIZE;i++,curchain=0) {
177 np=nicktable[i];
178 if (np!=NULL) {
179 buckets++;
180 for (;np;np=np->next) {
181 total++;
182 curchain++;
183 }
184 }
185 if (curchain>maxchain) {
186 maxchain=curchain;
187 }
188 }
189
190 if ((int)arg>5) {
191 /* Full stats */
192 sprintf(buf,"Nick : %6d nicks (HASH: %6d/%6d, chain %3d)",total,buckets,NICKHASHSIZE,maxchain);
193 } else if ((int)arg>2) {
194 sprintf(buf,"Nick : %6d users on network.",total);
195 }
196
197 if ((int)arg>2) {
198 triggerhook(HOOK_CORE_STATSREPLY,buf);
199 }
200 }
201
202 int registernickext(const char *name) {
203 int i;
204
205 if (findnickext(name)!=-1) {
206 Error("nick",ERR_WARNING,"Tried to register duplicate nick extension %s",name);
207 return -1;
208 }
209
210 for (i=0;i<MAXNICKEXTS;i++) {
211 if (nickextnames[i]==NULL) {
212 nickextnames[i]=getsstring(name,100);
213 return i;
214 }
215 }
216
217 Error("channel",ERR_WARNING,"Tried to register too many extensions: %s",name);
218 return -1;
219 }
220
221 int findnickext(const char *name) {
222 int i;
223
224 for (i=0;i<MAXNICKEXTS;i++) {
225 if (nickextnames[i]!=NULL && !ircd_strcmp(name,nickextnames[i]->content)) {
226 return i;
227 }
228 }
229
230 return -1;
231 }
232
233 void releasenickext(int index) {
234 int i;
235 nick *np;
236
237 freesstring(nickextnames[index]);
238 nickextnames[index]=NULL;
239
240 for (i=0;i<NICKHASHSIZE;i++) {
241 for (np=nicktable[i];np;np=np->next) {
242 np->exts[index]=NULL;
243 }
244 }
245 }
246
247 /* visiblehostmask
248 * Produces the "apparent" hostmask as seen by network users.
249 */
250
251 char *visiblehostmask(nick *np, char *buf) {
252 char hostbuf[HOSTLEN+1];
253 char *ident, *host;
254
255 ident=np->ident;
256 host=np->host->name->content;
257
258 if (IsSetHost(np)) {
259 if (np->shident) {
260 ident=np->shident->content;
261 }
262 if (np->sethost) {
263 host=np->sethost->content;
264 }
265 } else if (IsAccount(np) && IsHideHost(np)) {
266 sprintf(hostbuf,"%s.%s", np->authname, HIS_HIDDENHOST);
267 host=hostbuf;
268 }
269
270 sprintf(buf,"%s!%s@%s",np->nick,ident,host);
271
272 return buf;
273 }
274
275 #if 0
276
277 /*
278 * gethandlebynumeric:
279 * Given a numeric, gives the location in the servernicks table
280 * where it should be. Does not check that the nick currently found
281 * there (if any) has the correct numeric; this is left to the
282 * calling function to figure out.
283 */
284
285 nick **gethandlebynumeric(long numeric) {
286 int servernum;
287 int maskednum;
288 server *serv;
289
290 /* Shift off the client identifier part of the numeric to get the server ID */
291 servernum=(numeric>>18);
292
293 if ((serv=getserverdata(servernum))==NULL) {
294 Error("nick",ERR_WARNING,"Numeric %ld refers to non-existent server %d",numeric,servernum);
295 return NULL;
296 }
297
298 /* Compute the masked numeric */
299 maskednum=numeric&(serv->maxusernum);
300
301 return (servernicks[servernum])+maskednum;
302 }
303
304 /*
305 * getnickbynumeric[str]()
306 * These functions retrieve a nick based on it's numeric on the network
307 * Use the approriate function depending on how your numeric is expressed..
308 */
309
310 nick *getnickbynumeric(long numeric) {
311 nick **nh;
312
313 nh=gethandlebynumeric(numeric);
314
315 if ((*nh) && ((*nh)->numeric!=numeric)) {
316 /* We found a masked numeric match, but the actual numeric
317 * is different. This counts as a miss. */
318 return NULL;
319 }
320
321 return (*nh);
322 }
323
324 nick *getnickbynumericstr(char *numericstr) {
325 return getnickbynumeric(numerictolong(numericstr,5));
326 }
327
328 #endif