source: roaraudio/plugins/roard/protocol-irc.c @ 5424:535acd76cf85

Last change on this file since 5424:535acd76cf85 was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

File size: 20.5 KB
Line 
1//irc.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2012
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include <roard/include/roard.h>
27#include <ctype.h>
28
29#define MAX_CHANNELS 8
30
31static int on_nick(int client, const char * cmd, char * args, char * text);
32static int on_user(int client, const char * cmd, char * args, char * text);
33static int on_quit(int client, const char * cmd, char * args, char * text);
34static int on_ping(int client, const char * cmd, char * args, char * text);
35static int on_lusers(int client, const char * cmd, char * args, char * text);
36static int on_whois(int client, const char * cmd, char * args, char * text);
37static int on_privmsg(int client, const char * cmd, char * args, char * text);
38
39static int on_list(int client, const char * cmd, char * args, char * text);
40static int on_join(int client, const char * cmd, char * args, char * text);
41static int on_part(int client, const char * cmd, char * args, char * text);
42static int on_names(int client, const char * cmd, char * args, char * text);
43
44static int on_topic(int client, const char * cmd, char * args, char * text);
45
46static int do_join(int client, const char * channel);
47static int do_part(int client, const char * channel);
48static int do_names(int client, const char * channel);
49
50static void cb_client_delete(struct roar_notify_core * core, struct roar_event * event, void * userdata);
51
52static struct roar_subscriber * subscription_client_delete = NULL;
53
54static char * server_name     = "irc.roard";
55static char * server_fullname = "RoarAudio roard IRC Server plugin";
56
57static char * quit_msg = NULL;
58
59static struct channel {
60 char * name;
61 struct {
62  char * text;
63  char * user;
64  time_t ts;
65 } topic;
66 size_t client_count;
67 int clients[ROAR_CLIENTS_MAX];
68} g_channels[MAX_CHANNELS];
69
70static struct command {
71 const char * name;
72 int (*func)(int client, const char * cmd, char * args, char * text);
73} g_commands[] = {
74 {"NICK", on_nick},
75 {"USER", on_user},
76 {"QUIT", on_quit},
77 {"PING", on_ping},
78 {"LUSERS", on_lusers},
79 {"WHOIS", on_whois},
80 {"PRIVMSG", on_privmsg},
81 {"NOTICE", on_privmsg},
82 {"LIST", on_list},
83 {"JOIN", on_join},
84 {"PART", on_part},
85 {"NAMES", on_names},
86 {"TOPIC", on_topic},
87 {NULL, NULL}
88};
89
90static void init(void) {
91 struct roar_event event;
92
93 memset(&event, 0, sizeof(event));
94
95 event.event = ROAR_OE_BASICS_DELETE;
96
97 event.emitter = -1;
98 event.target = -1;
99 event.target_type = ROAR_OT_CLIENT;
100
101 memset(g_channels, 0, sizeof(g_channels));
102
103 subscription_client_delete = roar_notify_core_subscribe(NULL, &event, cb_client_delete, NULL);
104}
105
106static int is_valid_name (const char * name) {
107 register char c;
108
109 for (; (c = *name) != 0; name++) {
110  if ( !(isalnum(c) || c == '-' || c == '_') )
111   return 0;
112 }
113
114 return 1;
115}
116
117static void strip_nl(char * str) {
118 register char c;
119
120 for (; (c = *str) != 0; str++) {
121  if ( c == '\r' || c == '\n' ) {
122   *str = 0;
123   return;
124  }
125 }
126}
127
128static char * get_nick(int client) {
129 struct roar_client * c;
130 clients_get(client, &c);
131 return c->name;
132}
133
134static const char * get_ident(int client) {
135 static char buf[80];
136 struct roar_client * c;
137 clients_get(client, &c);
138
139 if ( c->uid == -1 ) {
140  buf[0] = '~';
141  buf[1] = 0;
142 } else {
143  snprintf(buf, sizeof(buf)-1, "uid%i~", c->uid);
144  buf[sizeof(buf)-1] = 0;
145 }
146
147 return buf;
148}
149
150static const char * get_node(int client) {
151 struct roar_client * c;
152 static char buf_nnode[80];
153 char * nnode;
154
155 clients_get(client, &c);
156
157 roar_nnode_to_str(&(c->nnode), buf_nnode, sizeof(buf_nnode));
158
159 nnode  = strstr(buf_nnode, ": ");
160 if ( nnode == NULL ) {
161  nnode  = "unknown~";
162 } else {
163  nnode += 2;
164 }
165
166 return nnode;
167}
168
169static const char * get_ufull(int client) {
170 struct roar_client * c;
171 static char buf[80];
172 const char * ident = get_ident(client);
173 const char * nnode = get_node(client);
174
175 clients_get(client, &c);
176
177 snprintf(buf, sizeof(buf)-1, "%s!%s@%s", c->name, ident, nnode);
178
179 buf[sizeof(buf)-1] = 0;
180
181 return buf;
182}
183
184static const char * get_realname(int client) {
185 (void)client;
186 return "(no realname)";
187}
188
189static int get_client_by_nick(const char * nick) {
190 struct roar_client * c;
191 int i;
192
193 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
194  if ( clients_get(i, &c) != 0 )
195   continue;
196
197  if ( !!strcasecmp(c->name, nick) )
198   continue;
199
200  return i;
201 }
202
203 return -1;
204}
205
206static struct channel * get_channel(const char * name) {
207 struct channel * c;
208 size_t i;
209
210 for (i = 0; i < MAX_CHANNELS; i++) {
211  c = &(g_channels[i]);
212
213  if ( !c->client_count )
214   continue;
215
216  if ( !!strcasecmp(c->name, name) )
217   continue;
218
219  return c;
220 }
221
222 return NULL;
223}
224
225static size_t get_listener_list(int client, const char * channel, int ** listener) {
226 struct channel * c;
227 static int clients[ROAR_CLIENTS_MAX];
228 size_t ret = 0;
229 size_t i, k;
230 int j;
231 int found;
232
233 for (i = 0; i < MAX_CHANNELS; i++) {
234  c = &(g_channels[i]);
235
236  if ( !c->client_count )
237   continue;
238
239  if ( c->clients[client] < 1 )
240   continue;
241
242  if ( channel != NULL && !!strcasecmp(c->name, channel) )
243   continue;
244
245  for (j = 0; j < ROAR_CLIENTS_MAX; j++) {
246   if ( c->clients[j] > 0 ) {
247    found = 0;
248    for (k = 0; k < ret; k++) {
249     if ( clients[k] == j ) {
250      found = 1;
251     }
252    }
253    if ( !found ) {
254     clients[ret] = j;
255     ret++;
256    }
257   }
258  }
259 }
260
261 *listener = clients;
262
263 return ret;
264}
265
266static void put_printf(int client, const char *format, ...) {
267 va_list ap;
268 struct roar_buffer * buf;
269 size_t len = 2048;
270 void * data;
271 int ret;
272
273 if ( roar_buffer_new_data(&buf, len, &data) == -1 )
274  return;
275
276 va_start(ap, format);
277 ret = vsnprintf(data, len-1, format, ap);
278 va_end(ap);
279
280 if ( roar_buffer_set_len(buf, strlen(data)) == -1 ) {
281  roar_buffer_free(buf);
282  return;
283 }
284
285 clients_add_output(client, &buf);
286}
287
288static int do_join(int client, const char * channel) {
289 struct channel * c = NULL;
290 size_t i;
291
292 if ( channel[0] != '#' )
293  return -1;
294
295 if ( !is_valid_name(channel+1) )
296  return -1;
297
298 for (i = 0; i < MAX_CHANNELS; i++) {
299  if ( !g_channels[i].client_count )
300   continue;
301
302  if ( !!strcasecmp(g_channels[i].name, channel) )
303   continue;
304
305  c = &(g_channels[i]);
306  break;
307 }
308
309 if ( c == NULL ) {
310  for (i = 0; i < MAX_CHANNELS; i++) {
311   if ( g_channels[i].client_count )
312    continue;
313
314   c = &(g_channels[i]);
315   break;
316  }
317
318  if ( c == NULL )
319   return -1;
320
321  memset(c, 0, sizeof(*c));
322
323  c->name = roar_mm_strdup(channel);
324 }
325
326 if ( c->clients[client] )
327  return -1;
328
329 c->clients[client] = 1;
330 c->client_count++;
331
332 return 0;
333}
334
335static int do_part(int client, const char * channel) {
336 struct channel * c = NULL;
337 size_t i;
338
339 for (i = 0; i < MAX_CHANNELS; i++) {
340  if ( !g_channels[i].client_count )
341   continue;
342
343  if ( !!strcasecmp(g_channels[i].name, channel) )
344   continue;
345
346  if ( !g_channels[i].clients[client] )
347   return -1;
348
349  c = &(g_channels[i]);
350  break;
351 }
352
353 c->clients[client] = 0;
354 c->client_count--;
355
356 if ( !c->client_count ) {
357  roar_mm_free(c->name);
358
359  if ( c->topic.text != NULL )
360   roar_mm_free(c->topic.text);
361  if ( c->topic.user != NULL )
362   roar_mm_free(c->topic.user);
363 }
364
365 return 0;
366}
367
368static int do_names(int client, const char * channel) {
369 const char * nick = get_nick(client);
370 size_t i;
371 char buf[256];
372 size_t len, offset;
373 char * c_nick;
374 int j;
375
376 for (i = 0; i < MAX_CHANNELS; i++) {
377  if ( !g_channels[i].client_count )
378   continue;
379
380  if ( !!strcasecmp(g_channels[i].name, channel) )
381   continue;
382
383  offset = 0;
384
385  for (j = 0; j < ROAR_CLIENTS_MAX; j++) {
386   if ( g_channels[i].clients[j] == 0 )
387    continue;
388
389   c_nick = get_nick(j);
390   len = strlen(c_nick);
391   if ( (offset + len + 3) > sizeof(buf) ) {
392    buf[offset] = 0;
393    put_printf(client, ":%s 353 %s = %s :%s\n", server_name, nick, channel, buf);
394    offset = 0;
395   }
396
397   memcpy(buf + offset, c_nick, len);
398   offset += len;
399   buf[offset] = ' ';
400   offset++;
401   buf[offset] = 0;
402  }
403
404  if ( offset ) {
405   buf[offset] = 0;
406   put_printf(client, ":%s 353 %s = %s :%s\n", server_name, nick, channel, buf);
407  }
408  put_printf(client, ":%s 366 %s %s :End of /NAMES list.\n", server_name, nick, channel);
409
410  return 0;
411 }
412
413 return -1;
414}
415
416static void cb_client_delete(struct roar_notify_core * core, struct roar_event * event, void * userdata) {
417 int * listener;
418 size_t count;
419 struct channel * c;
420 char * text = quit_msg;
421 int client = event->target;
422 const char * ufull = get_ufull(client);
423 size_t i;
424
425 (void)core, (void)userdata;
426
427 if ( text == NULL ) {
428  text = "Client deleted. Died, kicked or internal error.";
429 }
430
431 put_printf(client, "ERROR :Closing Link: %s (Quit: %s)\n", ufull, text);
432
433  count = get_listener_list(client, NULL, &listener);
434  for (; count; count--, listener++)
435   put_printf(*listener, ":%s QUIT :Quit: %s\n", ufull, text);
436
437 for (i = 0; i < MAX_CHANNELS; i++) {
438  c = &(g_channels[i]);
439
440  if ( !c->client_count )
441   continue;
442
443  if ( !c->clients[client] )
444   continue;
445
446  c->clients[client] = 0;
447  c->client_count--;
448
449  if ( !c->client_count ) {
450   roar_mm_free(c->name);
451
452   if ( c->topic.text != NULL )
453    roar_mm_free(c->topic.text);
454   if ( c->topic.user != NULL )
455    roar_mm_free(c->topic.user);
456  }
457 }
458
459 clients_flush(client);
460}
461
462static int new_client(int client, struct roar_vio_calls * vio, struct roard_listen * lsock) {
463 struct roar_client_server * cs;
464 char * name;
465
466 (void)client, (void)vio, (void)lsock;
467
468 clients_get_server(client, &cs);
469
470 name = ROAR_CLIENT(cs)->name;
471 snprintf(name, sizeof(ROAR_CLIENT(cs)->name), "Client%i~", client);
472
473/*
474:ph7.ph.sft NOTICE AUTH :*** Looking up your hostname...
475:ph7.ph.sft NOTICE AUTH :*** Couldn't resolve your hostname; using your IP address instead
476NICK nick
477USER A B C D
478:ph7.ph.sft NOTICE AUTH :*** Couldn't resolve your hostname; using your IP address instead
479:ph7.ph.sft 002 nick :Your host is ph7.ph.sft, running version Unreal3.2.7
480:ph7.ph.sft 003 nick :This server was created Tue Aug 28 2007 at 10:02:00 CEST
481:ph7.ph.sft 004 nick ph7.ph.sft Unreal3.2.7 iowghraAsORTVSxNCWqBzvdHtGp lvhopsmntikrRcaqOALQbSeIKVfMCuzNTGj
482:ph7.ph.sft 005 nick NAMESX SAFELIST HCN MAXCHANNELS=10 CHANLIMIT=#:10 MAXLIST=b:60,e:60,I:60 NICKLEN=30 CHANNELLEN=32 TOPICLEN=307 KICKLEN=307 AWAYLEN=307 MAXTARGETS=20 WALLCHOPS :are supported by this server
483:ph7.ph.sft 005 nick WATCH=128 SILENCE=15 MODES=12 CHANTYPES=# PREFIX=(ohv)@%+ CHANMODES=beIqa,kfL,lj,psmntirRcOAQKVCuzNSMTG NETWORK=PH2 CASEMAPPING=ascii EXTBAN=~,cqnr ELIST=MNUCT STATUSMSG=@%+ EXCEPTS INVEX :are supported by this server
484:ph7.ph.sft 005 nick CMDS=KNOCK,MAP,DCCALLOW,USERIP :are supported by this server
485*/
486
487 put_printf(client,
488      ":%s 001 %s :Welcome to the roard based IRC server.\n"
489      ":%s 375 %s :- %s Message of the Day -\n"
490      ":%s 372 %s :- MotD goes here...\n"
491      ":%s 376 %s :End of /MOTD command.\n",
492   server_name, name,
493   server_name, name, server_name,
494   server_name, name,
495   server_name, name
496 );
497
498 on_lusers(client, NULL, NULL, NULL);
499
500 return 0;
501}
502
503static int check_client(int client, struct roar_vio_calls * vio) {
504 struct roar_vio_calls     rvio;
505 char cmd[1024*2];
506 char * args;
507 char * text;
508 ssize_t len;
509 size_t i;
510 int found = 0;
511
512 if ( vio == NULL ) {
513  vio = &rvio;
514  roar_vio_open_fh_socket(vio, clients_get_fh(client));
515 }
516
517 len = roar_vio_read(vio, cmd, sizeof(cmd)-1);
518 if ( len < 1 ) {
519  clients_delete(client);
520  return -1;
521 }
522
523 cmd[len] = 0;
524
525 strip_nl(cmd);
526
527 ROAR_DBG("check_client(client=%i, vio=?): cmd=\"%s\"", client, cmd);
528
529 if ( cmd[0] == 0 )
530  return 0;
531
532 args = strstr(cmd, " ");
533
534 if ( args != NULL ) {
535  *args = 0;
536  args++;
537  if ( *args == ':' ) {
538   text = args + 1;
539   args = NULL;
540  } else {
541   text = strstr(args, " :");
542   if ( text != NULL ) {
543    *text = 0;
544    text += 2;
545   }
546  }
547 } else {
548  text = NULL;
549 }
550
551 for (i = 0; g_commands[i].name != NULL; i++) {
552  if ( !strcasecmp(g_commands[i].name, cmd) ) {
553   found = 1;
554   g_commands[i].func(client, cmd, args, text);
555  }
556 }
557
558 if ( !found ) {
559  put_printf(client, ":%s 421 %s %s :Unknown command\n", server_name, get_nick(client), cmd);
560 }
561
562 return 0;
563}
564
565// commands:
566static int on_nick(int client, const char * cmd, char * args, char * text) {
567 char * nick = get_nick(client);
568 int * listener;
569 size_t count;
570 const char * ufull;
571
572 (void)cmd, (void)text;
573
574 if ( args != NULL && args[0] != 0 && is_valid_name(args) && strlen(args) < ROAR_BUFFER_NAME ) {
575  if ( get_client_by_nick(args) != -1 ) {
576   put_printf(client, ":%s 433 %s %s :Nickname is already in use.\n", server_name, nick, args);
577  } else {
578   ufull = get_ufull(client);
579   put_printf(client, ":%s NICK :%s\n", ufull, args);
580   count = get_listener_list(client, NULL, &listener);
581   for (; count; count--, listener++)
582    if ( *listener != client )
583     put_printf(*listener, ":%s NICK :%s\n", ufull, args);
584
585   strcpy(nick, args);
586  }
587 } else {
588  put_printf(client, ":%s 432 %s %s :Erroneous Nickname: Illegal characters\n", server_name, nick, args);
589 }
590
591 return 0;
592}
593
594static int on_user(int client, const char * cmd, char * args, char * text) {
595 (void)client, (void)cmd, (void)args, (void)text;
596 return 0;
597}
598
599static int on_quit(int client, const char * cmd, char * args, char * text) {
600 int ret;
601
602 (void)cmd, (void)args;
603
604 if ( text == NULL )
605  text = "... have a cuddle ...";
606
607 quit_msg = text;
608 ret = clients_delete(client);
609 quit_msg = NULL;
610
611 return ret;
612}
613
614static int on_ping(int client, const char * cmd, char * args, char * text) {
615 (void)cmd, (void)args;
616
617 put_printf(client, "PONG :%s\n", text);
618
619 return 0;
620}
621
622static int on_lusers(int client, const char * cmd, char * args, char * text) {
623 const char * clientnick = get_nick(client);
624 size_t i;
625 size_t numchans = 0;
626
627 (void)cmd, (void)args, (void)text;
628
629/*
630:v0.fellig.org 251 nick :There are 9 users and 11 invisible on 1 servers
631
632:v0.fellig.org 252 nick 1 :operator(s) online
633
634:v0.fellig.org 254 nick 16 :channels formed
635:v0.fellig.org 255 nick :I have 20 clients and 0 servers
636:v0.fellig.org 265 nick :Current Local Users: 20  Max: 52
637:v0.fellig.org 266 nick :Current Global Users: 20  Max: 22
638*/
639
640 for (i = 0; i < MAX_CHANNELS; i++) {
641  if ( !g_channels[i].client_count )
642   continue;
643  numchans++;
644 }
645
646 put_printf(client, ":%s 251 %s :There are %zu users and 0 invisible on 1 servers\n",
647            server_name, clientnick, counters_get(cur, clients));
648 put_printf(client, ":%s 254 %s %zu :channels formed\n",
649            server_name, clientnick, numchans);
650 put_printf(client, ":%s 255 %s :I have %zu clients and 0 servers\n",
651            server_name, clientnick, counters_get(cur, clients));
652 put_printf(client, ":%s 265 %s :Current Local Users: %zu  Max: <unknown>\n",
653            server_name, clientnick, counters_get(cur, clients));
654 put_printf(client, ":%s 266 %s :Current Global Users: %zu  Max: <unknown>\n",
655            server_name, clientnick, counters_get(cur, clients));
656
657 return 0;
658}
659
660static int on_whois(int client, const char * cmd, char * args, char * text) {
661 const char * clientnick = get_nick(client);
662 const char * tnick = args;
663 int tclient;
664
665 (void)cmd, (void)text;
666
667/*
668:ph7.ph.sft 317 nick phi 131 1322456381 :seconds idle, signon time
669*/
670
671 if ( (tclient = get_client_by_nick(tnick)) == -1 ) {
672  put_printf(client, ":%s 401 %s %s :No such nick/channel\n", server_name, clientnick, tnick);
673 } else {
674  put_printf(client, ":%s 311 %s %s %s %s * :%s\n", server_name, clientnick, tnick,
675             get_ident(tclient), get_node(tclient), get_realname(tclient));
676  put_printf(client, ":%s 312 %s %s %s :%s\n", server_name, clientnick, tnick, server_name, server_fullname);
677 }
678 put_printf(client, ":%s 318 %s %s :End of /WHOIS list.\n", server_name, clientnick, tnick);
679
680 return 0;
681}
682
683static int on_privmsg(int client, const char * cmd, char * args, char * text) {
684 const char * ufull = get_ufull(client);
685 int * listener;
686 size_t count;
687 char * next;
688 int tmp;
689
690 if ( args == NULL || text == NULL )
691  return -1;
692
693 if ( text[0] == 0 )
694  return 0;
695
696 while (args != NULL) {
697  next = strstr(args, ",");
698  if ( next != NULL ) {
699   *next = 0;
700   next++;
701  }
702
703  if ( args[0] == '#' ) {
704   count = get_listener_list(client, args, &listener);
705   for (; count; count--, listener++)
706    if ( *listener != client )
707     put_printf(*listener, ":%s %s %s :%s\n", ufull, cmd, args, text);
708  } else {
709   if ( (tmp = get_client_by_nick(args)) == -1 ) {
710    put_printf(client, ":%s 401 %s %s :No such nick/channel\n", server_name, get_nick(client), args);
711   } else {
712    put_printf(tmp, ":%s %s %s :%s\n", ufull, cmd, args, text);
713   }
714  }
715
716  args = next;
717 }
718
719 return 0;
720}
721
722
723static int on_list(int client, const char * cmd, char * args, char * text) {
724 const char * clientnick = get_nick(client);
725 struct channel * c;
726 size_t i;
727
728 (void)cmd, (void)args, (void)text;
729
730 put_printf(client, ":%s 321 %s Channel :Users  Name\n", server_name, clientnick);
731
732 for (i = 0; i < MAX_CHANNELS; i++) {
733  c = &(g_channels[i]);
734  if ( !c->client_count )
735   continue;
736
737  put_printf(client, ":%s 322 %s %s %zu :[+] %s\n",
738             server_name, clientnick, c->name, c->client_count, c->topic.text == NULL ? "" : c->topic.text);
739 }
740
741 put_printf(client, ":%s 323 %s :End of /LIST\n", server_name, clientnick);
742
743 return 0;
744}
745
746static int on_join(int client, const char * cmd, char * args, char * text) {
747 struct channel * c;
748 const char * ufull = get_ufull(client);
749 int * listener;
750 size_t count;
751 const char * nick;
752
753 (void)cmd, (void)text;
754
755 if ( args == NULL )
756  return -1;
757
758 if ( do_join(client, args) != 0 ) {
759  return -1;
760 }
761
762 count = get_listener_list(client, args, &listener);
763 for (; count; count--, listener++)
764  put_printf(*listener, ":%s JOIN :%s\n", ufull, args);
765
766 c = get_channel(args);
767
768 if ( c->topic.text != NULL ) {
769  nick = get_nick(client);
770  put_printf(client, ":%s 332 %s %s :%s\n"
771                     ":%s 333 %s %s %s %li\n",
772         server_name, nick, c->name, c->topic.text,
773         server_name, nick, c->name, c->topic.user, (long int)c->topic.ts
774  );
775 }
776
777 do_names(client, args);
778
779 return 0;
780}
781
782static int on_part(int client, const char * cmd, char * args, char * text) {
783 const char * ufull = get_ufull(client);
784 int * listener;
785 size_t count;
786
787 (void)cmd;
788
789 if ( args == NULL )
790  return -1;
791
792 if ( text == NULL )
793  text = "Dejoined.";
794
795 count = get_listener_list(client, args, &listener);
796 for (; count; count--, listener++)
797  put_printf(*listener, ":%s PART %s :%s\n", ufull, args, text);
798
799 do_part(client, args);
800
801 return 0;
802}
803
804static int on_names(int client, const char * cmd, char * args, char * text) {
805 (void)cmd, (void)text;
806
807 if ( args == NULL )
808  return -1;
809
810 return do_names(client, args);
811}
812
813static int on_topic(int client, const char * cmd, char * args, char * text) {
814 struct channel * c;
815 const char * ufull = get_ufull(client);
816 int * listener;
817 size_t count;
818 char * nick = get_nick(client);
819
820 (void)cmd;
821
822 if ( args == NULL )
823  return -1;
824
825 c = get_channel(args);
826
827 if ( c == NULL )
828  return -1;
829
830 if ( !c->clients[client] ) {
831  return -1;
832 }
833
834 if ( c->topic.text != NULL )
835  roar_mm_free(c->topic.text);
836 if ( c->topic.user != NULL )
837  roar_mm_free(c->topic.user);
838
839 c->topic.text = NULL;
840 c->topic.user = roar_mm_strdup(nick);
841 c->topic.ts   = time(NULL);
842
843 if ( text != NULL )
844  c->topic.text = roar_mm_strdup(text);
845
846 if ( text == NULL )
847  text = "";
848
849 count = get_listener_list(client, c->name, &listener);
850 for (; count; count--, listener++)
851  put_printf(*listener, ":%s TOPIC %s :%s\n", ufull, c->name, text);
852
853 return 0;
854}
855
856// plugin handling suff:
857
858static int unload(struct roar_dl_librarypara * para, struct roar_dl_libraryinst * lib) {
859 (void)para, (void)lib;
860
861 roar_notify_core_unsubscribe(NULL, subscription_client_delete);
862
863 return 0;
864}
865
866static struct roard_proto proto[1] = {
867 {ROAR_PROTO_IRC, ROAR_SUBSYS_NONE, "Internet Relay Chat", NULL, new_client, check_client, NULL, NULL}
868};
869
870ROARD_DL_REG_PROTO(proto)
871
872ROAR_DL_PLUGIN_START(roard_irc_protocol) {
873 ROARD_DL_CHECK_VERSIONS();
874
875 ROAR_DL_PLUGIN_META_PRODUCT_NIV("roard-irc-protocol", ROAR_VID_ROARAUDIO, ROAR_VNAME_ROARAUDIO);
876 ROAR_DL_PLUGIN_META_VERSION(ROAR_VERSION_STRING);
877 ROAR_DL_PLUGIN_META_LICENSE_TAG(GPLv3_0);
878 ROAR_DL_PLUGIN_META_CONTACT_FLNE("Philipp", "Schafft", "ph3-der-loewe", "lion@lion.leolix.org");
879 ROAR_DL_PLUGIN_META_DESC("Implementation of the Internet Relay Chat (IRC)");
880
881 ROAR_DL_PLUGIN_REG_UNLOAD(unload);
882 ROARD_DL_REGFN_PROTO();
883 init();
884} ROAR_DL_PLUGIN_END
885
886//ll
Note: See TracBrowser for help on using the repository browser.