4 #include "../core/hooks.h"
5 #include "../lib/splitline.h"
6 #include "../core/config.h"
7 #include "../irc/irc.h"
8 #include "../lib/array.h"
9 #include "../lib/base64.h"
10 #include "../lib/irc_string.h"
11 #include "../core/error.h"
12 #include "../localuser/localuser.h"
13 #include "../lib/strlfunc.h"
14 #include "../lib/sha1.h"
15 #include "../irc/irc.h"
16 #include "../lib/hmac.h"
17 #include "../core/schedule.h"
20 static const char *DEFAULT_SERVICE_MASKS
[] = { "services*.*.quakenet.org", (char *)0 };
22 static array defaultservicemasks_a
;
23 static sstring
**defaultservicemasks
;
25 static void handlemaskprivmsg(int, void *);
26 static CommandTree
*cmds
;
29 struct messagequeue
*next
;
34 struct messagequeue
*head
, *tail
;
37 static void *xsbnicksched
;
39 static void handler(nick
*target
, int messagetype
, void **args
);
40 static void flushqueue(void);
42 static char *servicenick(char *server
) {
43 static char nickbuf
[NICKLEN
+1];
44 char digest
[SHA1_DIGESTSIZE
*2+1];
45 unsigned char digestbuf
[SHA1_DIGESTSIZE
];
49 SHA1Update(&s
, (unsigned char *)server
, strlen(server
));
50 SHA1Final(digestbuf
, &s
);
52 snprintf(nickbuf
, sizeof(nickbuf
), "XSB1-%s", hmac_printhex(digestbuf
, digest
, SHA1_DIGESTSIZE
));
57 static void setuplocaluser(void *arg
) {
60 xsbnick
= registerlocaluser(servicenick(myserver
->content
), "xsb", "xsb.quakenet.org", "eXtended service broadcast localuser (v1)", NULL
, UMODE_OPER
| UMODE_SERVICE
| UMODE_INV
, handler
);
62 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);
72 cmds
= newcommandtree();
76 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);
78 registerhook(HOOK_NICK_MASKPRIVMSG
, &handlemaskprivmsg
);
80 array_init(&defaultservicemasks_a
, sizeof(sstring
*));
82 for(p
=DEFAULT_SERVICE_MASKS
;*p
;p
++) {
83 int i
= array_getfreeslot(&defaultservicemasks_a
);
84 defaultservicemasks
= (sstring
**)defaultservicemasks_a
.content
;
86 defaultservicemasks
[i
] = getsstring(*p
, strlen(*p
));
89 servicemasks
= getconfigitems("xsb", "servicemask");
90 if(!servicemasks
|| !servicemasks
->cursi
)
91 Error("xsb", ERR_WARNING
, "No service masks in config file (xsb/servicemask), using defaults.");
96 struct messagequeue
*q
, *nq
;
99 deregisterlocaluser(xsbnick
, NULL
);
102 deleteschedule(xsbnicksched
, setuplocaluser
, NULL
);
107 destroycommandtree(cmds
);
109 deregisterhook(HOOK_NICK_MASKPRIVMSG
, &handlemaskprivmsg
);
111 for(i
=0;i
<defaultservicemasks_a
.cursi
;i
++)
112 freesstring(defaultservicemasks
[i
]);
113 array_free(&defaultservicemasks_a
);
124 void xsb_addcommand(const char *name
, const int maxparams
, CommandHandler handler
) {
125 addcommandtotree(cmds
, name
, 0, maxparams
, handler
);
128 void xsb_delcommand(const char *name
, CommandHandler handler
) {
129 deletecommandfromtree(cmds
, name
, handler
);
132 static void handlemaskprivmsg(int hooknum
, void *args
) {
133 void **hargs
= (void **)args
;
134 nick
*source
= hargs
[0];
135 char *message
= hargs
[2];
144 if(!IsOper(source
) || !IsService(source
))
147 cargc
= splitline(message
, cargv
, 50, 0);
151 if(strcmp(cargv
[0], "XSB1"))
154 s
= &serverlist
[homeserver(source
->numeric
)];
155 if(s
->linkstate
!= LS_LINKED
) {
156 Error("xsb", ERR_WARNING
, "Got XSB message from unlinked server (%s): %s", s
->name
->content
, source
->nick
);
161 if(!(s
->flags
& SMODE_SERVICE
)) {
162 Error("xsb", ERR_WARNING
, "Got XSB message from non-service server (%s): %s", s
->name
->content
, source
->nick
);
167 cmd
= findcommandintree(cmds
, cargv
[1], 1);
171 if(cmd
->maxparams
< (cargc
- 2)) {
172 rejoinline(cargv
[cmd
->maxparams
], cargc
- (cmd
->maxparams
));
173 cargc
= (cmd
->maxparams
) + 2;
176 (cmd
->handler
)(source
, cargc
- 2, &cargv
[2]);
179 static void directsend(struct messagequeue
*q
) {
180 nick
*np
= getnickbynumeric(q
->numeric
);
181 if(!np
|| !IsOper(np
) || !IsService(np
))
185 if(!(serverlist
[homeserver(np
->numeric
)].flags
& SMODE_SERVICE
))
189 sendmessagetouser(xsbnick
, np
, "XSB1 %s", q
->buf
);
192 static void flushqueue(void) {
193 struct messagequeue
*q
, *nq
;
205 static int getservicemasks(sstring
***masks
) {
206 array
*aservicemasks
= getconfigitems("xsb", "servicemask");
207 if(!aservicemasks
|| !aservicemasks
->cursi
)
208 aservicemasks
= &defaultservicemasks_a
;
210 *masks
= (sstring
**)aservicemasks
->content
;
212 return aservicemasks
->cursi
;
215 static void xsb_send(nick
*target
, const char *format
, ...) {
219 struct messagequeue
*q
;
221 va_start(va
, format
);
222 len
= vsnprintf(buf
, sizeof(buf
), format
, va
);
224 if(len
>= sizeof(buf
))
228 q
= (struct messagequeue
*)malloc(sizeof(struct messagequeue
) + len
+ 5);
229 q
->numeric
= target
->numeric
;
230 strlcpy(q
->buf
, buf
, len
+ 2);
246 void xsb_broadcast(const char *command
, server
*service
, const char *format
, ...) {
249 sstring
**servicemasks
;
254 va_start(va
, format
);
255 vsnprintf(buf
, sizeof(buf
), format
, va
);
259 np
= getnickbynick(servicenick(service
->name
->content
));
263 xsb_send(np
, "%s %s", command
, buf
);
267 marker
= nextservermarker();
269 for(i
=getservicemasks(&servicemasks
)-1;i
>=0;i
--) {
270 char *mask
= servicemasks
[i
]->content
;
271 for(j
=0;j
<MAXSERVERS
;j
++) {
272 if(!serverlist
[j
].name
|| serverlist
[j
].marker
== marker
)
275 if(!match(mask
, serverlist
[j
].name
->content
)) {
276 serverlist
[j
].marker
= marker
;
278 np
= getnickbynick(servicenick(serverlist
[j
].name
->content
));
280 xsb_send(np
, "%s %s", command
, buf
);
286 void xsb_unicast(const char *command
, nick
*np
, const char *format
, ...) {
290 va_start(va
, format
);
291 vsnprintf(buf
, sizeof(buf
), format
, va
);
294 xsb_send(np
, "%s %s", command
, buf
);
297 int xsb_isservice(server
*service
) {
299 sstring
**servicemasks
;
300 char *name
= service
->name
->content
;
302 if(!(service
->flags
& SMODE_SERVICE
))
305 for(i
=getservicemasks(&servicemasks
)-1;i
>=0;i
--)
306 if(match2strings(servicemasks
[i
]->content
, name
))
312 static void handler(nick
*target
, int messagetype
, void **args
) {
313 switch(messagetype
) {
316 nick
*sender
= args
[0];
317 char *cargv
= args
[1];
323 handlemaskprivmsg(0, newargs
);
328 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);