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"
18 #include "../lib/version.h"
23 static const char *DEFAULT_SERVICE_MASKS
[] = { "services*.*.quakenet.org", (char *)0 };
25 static array defaultservicemasks_a
;
26 static sstring
**defaultservicemasks
;
28 static void handlemaskprivmsg(int, void *);
29 static CommandTree
*cmds
;
32 struct messagequeue
*next
;
37 struct messagequeue
*head
, *tail
;
40 static void *xsbnicksched
;
42 static void handler(nick
*target
, int messagetype
, void **args
);
43 static void flushqueue(void);
45 static char *servicenick(char *server
) {
46 static char nickbuf
[NICKLEN
+1];
47 char digest
[SHA1_DIGESTSIZE
*2+1];
48 unsigned char digestbuf
[SHA1_DIGESTSIZE
];
52 SHA1Update(&s
, (unsigned char *)server
, strlen(server
));
53 SHA1Final(digestbuf
, &s
);
55 snprintf(nickbuf
, sizeof(nickbuf
), "XSB1-%s", hmac_printhex(digestbuf
, digest
, SHA1_DIGESTSIZE
));
60 static void setuplocaluser(void *arg
) {
63 xsbnick
= registerlocaluser(servicenick(myserver
->content
), "xsb", "xsb.quakenet.org", "eXtended service broadcast localuser (v1)", NULL
, UMODE_OPER
| UMODE_SERVICE
| UMODE_INV
, handler
);
65 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);
75 cmds
= newcommandtree();
79 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);
81 registerhook(HOOK_NICK_MASKPRIVMSG
, &handlemaskprivmsg
);
83 array_init(&defaultservicemasks_a
, sizeof(sstring
*));
85 for(p
=DEFAULT_SERVICE_MASKS
;*p
;p
++) {
86 int i
= array_getfreeslot(&defaultservicemasks_a
);
87 defaultservicemasks
= (sstring
**)defaultservicemasks_a
.content
;
89 defaultservicemasks
[i
] = getsstring(*p
, strlen(*p
));
92 servicemasks
= getconfigitems("xsb", "servicemask");
93 if(!servicemasks
|| !servicemasks
->cursi
)
94 Error("xsb", ERR_WARNING
, "No service masks in config file (xsb/servicemask), using defaults.");
99 struct messagequeue
*q
, *nq
;
102 deregisterlocaluser(xsbnick
, NULL
);
105 deleteschedule(xsbnicksched
, setuplocaluser
, NULL
);
110 destroycommandtree(cmds
);
112 deregisterhook(HOOK_NICK_MASKPRIVMSG
, &handlemaskprivmsg
);
114 for(i
=0;i
<defaultservicemasks_a
.cursi
;i
++)
115 freesstring(defaultservicemasks
[i
]);
116 array_free(&defaultservicemasks_a
);
127 void xsb_addcommand(const char *name
, const int maxparams
, CommandHandler handler
) {
128 addcommandtotree(cmds
, name
, 0, maxparams
, handler
);
131 void xsb_delcommand(const char *name
, CommandHandler handler
) {
132 deletecommandfromtree(cmds
, name
, handler
);
135 static void handlemaskprivmsg(int hooknum
, void *args
) {
136 void **hargs
= (void **)args
;
137 nick
*source
= hargs
[0];
138 char *message
= hargs
[2];
147 if(!IsOper(source
) || !IsService(source
))
150 cargc
= splitline(message
, cargv
, 50, 0);
154 if(strcmp(cargv
[0], "XSB1"))
157 s
= &serverlist
[homeserver(source
->numeric
)];
158 if(s
->linkstate
!= LS_LINKED
) {
159 Error("xsb", ERR_WARNING
, "Got XSB message from unlinked server (%s): %s", s
->name
->content
, source
->nick
);
164 if(!(s
->flags
& SMODE_SERVICE
)) {
165 Error("xsb", ERR_WARNING
, "Got XSB message from non-service server (%s): %s", s
->name
->content
, source
->nick
);
170 cmd
= findcommandintree(cmds
, cargv
[1], 1);
174 if(cmd
->maxparams
< (cargc
- 2)) {
175 rejoinline(cargv
[cmd
->maxparams
], cargc
- (cmd
->maxparams
));
176 cargc
= (cmd
->maxparams
) + 2;
179 (cmd
->handler
)(source
, cargc
- 2, &cargv
[2]);
182 static void directsend(struct messagequeue
*q
) {
183 nick
*np
= getnickbynumeric(q
->numeric
);
184 if(!np
|| !IsOper(np
) || !IsService(np
))
188 if(!(serverlist
[homeserver(np
->numeric
)].flags
& SMODE_SERVICE
))
192 sendmessagetouser(xsbnick
, np
, "XSB1 %s", q
->buf
);
195 static void flushqueue(void) {
196 struct messagequeue
*q
, *nq
;
208 static int getservicemasks(sstring
***masks
) {
209 array
*aservicemasks
= getconfigitems("xsb", "servicemask");
210 if(!aservicemasks
|| !aservicemasks
->cursi
)
211 aservicemasks
= &defaultservicemasks_a
;
213 *masks
= (sstring
**)aservicemasks
->content
;
215 return aservicemasks
->cursi
;
218 static void xsb_send(nick
*target
, const char *format
, ...) {
222 struct messagequeue
*q
;
224 va_start(va
, format
);
225 len
= vsnprintf(buf
, sizeof(buf
), format
, va
);
227 if(len
>= sizeof(buf
))
231 q
= (struct messagequeue
*)malloc(sizeof(struct messagequeue
) + len
+ 5);
232 q
->numeric
= target
->numeric
;
233 strlcpy(q
->buf
, buf
, len
+ 2);
249 void xsb_broadcast(const char *command
, server
*service
, const char *format
, ...) {
252 sstring
**servicemasks
;
257 va_start(va
, format
);
258 vsnprintf(buf
, sizeof(buf
), format
, va
);
262 np
= getnickbynick(servicenick(service
->name
->content
));
266 xsb_send(np
, "%s %s", command
, buf
);
270 marker
= nextservermarker();
272 for(i
=getservicemasks(&servicemasks
)-1;i
>=0;i
--) {
273 char *mask
= servicemasks
[i
]->content
;
274 for(j
=0;j
<MAXSERVERS
;j
++) {
275 if(!serverlist
[j
].name
|| serverlist
[j
].marker
== marker
)
278 if(!match(mask
, serverlist
[j
].name
->content
)) {
279 serverlist
[j
].marker
= marker
;
281 np
= getnickbynick(servicenick(serverlist
[j
].name
->content
));
283 xsb_send(np
, "%s %s", command
, buf
);
289 void xsb_unicast(const char *command
, nick
*np
, const char *format
, ...) {
293 va_start(va
, format
);
294 vsnprintf(buf
, sizeof(buf
), format
, va
);
297 xsb_send(np
, "%s %s", command
, buf
);
300 int xsb_isservice(server
*service
) {
302 sstring
**servicemasks
;
303 char *name
= service
->name
->content
;
305 if(!(service
->flags
& SMODE_SERVICE
))
308 for(i
=getservicemasks(&servicemasks
)-1;i
>=0;i
--)
309 if(match2strings(servicemasks
[i
]->content
, name
))
315 static void handler(nick
*target
, int messagetype
, void **args
) {
316 switch(messagetype
) {
319 nick
*sender
= args
[0];
320 char *cargv
= args
[1];
326 handlemaskprivmsg(0, newargs
);
331 xsbnicksched
= scheduleoneshot(time(NULL
)+1, setuplocaluser
, NULL
);