/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/handle_irc.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/handle_irc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 sysadm 1.1 /*
2     * Copyright (C) 2001 Marco Ziech (mmz@gmx.net)
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the Free Software
16     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17     */
18     #define CONNECTION_INTERNAL_ACCESS
19     #include "common/setup_before.h"
20     #include "common/util.h" //amadeo: needed for strstart
21     #ifdef STDC_HEADERS
22     # include <stdlib.h>
23     #else
24     # ifdef HAVE_MALLOC_H
25     # include <malloc.h>
26     # endif
27     #endif
28     #ifdef HAVE_STRING_H
29     # include <string.h>
30     #else
31     # ifdef HAVE_STRINGS_H
32     # include <strings.h>
33     # endif
34     # ifdef HAVE_MEMORY_H
35     # include <memory.h>
36     # endif
37     #endif
38     #include "compat/strdup.h"
39     #include "compat/strcasecmp.h"
40     #include <errno.h>
41     #include "compat/strerror.h"
42     #include "common/irc_protocol.h"
43     #include "common/packet.h"
44     #include "common/eventlog.h"
45     #include "connection.h"
46     #include "common/bn_type.h"
47     #include "common/field_sizes.h"
48     #include "common/addr.h"
49     #include "common/version.h"
50     #include "common/queue.h"
51     #include "common/list.h"
52     #include "common/bnethash.h"
53     #include "common/bnethashconv.h"
54     #include "message.h"
55     #include "account.h"
56     #include "account_wrap.h"
57     #include "channel.h"
58     #include "irc.h"
59     #include "prefs.h"
60     #include "tick.h"
61     #include "timer.h"
62     #include "server.h"
63     #include "command.h"
64     #include "handle_irc.h"
65     #include "topic.h"
66     #include "command_groups.h"
67     #include "common/tag.h"
68     #include "common/xalloc.h"
69     #include "ctype.h"
70     #include "common/setup_after.h"
71    
72     typedef int (* t_irc_command)(t_connection * conn, int numparams, char ** params, char * text);
73    
74     typedef struct {
75     const char * irc_command_string;
76     t_irc_command irc_command_handler;
77     } t_irc_command_table_row;
78    
79     static int _handle_nick_command(t_connection * conn, int numparams, char ** params, char * text);
80     static int _handle_user_command(t_connection * conn, int numparams, char ** params, char * text);
81     static int _handle_ping_command(t_connection * conn, int numparams, char ** params, char * text);
82     static int _handle_pong_command(t_connection * conn, int numparams, char ** params, char * text);
83     static int _handle_pass_command(t_connection * conn, int numparams, char ** params, char * text);
84     static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text);
85     static int _handle_notice_command(t_connection * conn, int numparams, char ** params, char * text);
86     static int _handle_quit_command(t_connection * conn, int numparams, char ** params, char * text);
87    
88    
89     static int _handle_who_command(t_connection * conn, int numparams, char ** params, char * text);
90     static int _handle_list_command(t_connection * conn, int numparams, char ** params, char * text);
91     static int _handle_topic_command(t_connection * conn, int numparams, char ** params, char * text);
92     static int _handle_join_command(t_connection * conn, int numparams, char ** params, char * text);
93     static int _handle_names_command(t_connection * conn, int numparams, char ** params, char * text);
94     static int _handle_mode_command(t_connection * conn, int numparams, char ** params, char * text);
95     static int _handle_userhost_command(t_connection * conn, int numparams, char ** params, char * text);
96     static int _handle_ison_command(t_connection * conn, int numparams, char ** params, char * text);
97     static int _handle_whois_command(t_connection * conn, int numparams, char ** params, char * text);
98    
99    
100     /* state connected handlers */
101     static const t_irc_command_table_row irc_con_command_table[] =
102     {
103     { "NICK" , _handle_nick_command },
104     { "USER" , _handle_user_command },
105     { "PING" , _handle_ping_command },
106     { "PONG" , _handle_pong_command },
107     { "PASS" , _handle_pass_command },
108     { "PRIVMSG" , _handle_privmsg_command },
109     { "NOTICE" , _handle_notice_command },
110     { "QUIT" , _handle_quit_command },
111     { NULL , NULL }
112     };
113    
114     /* state log'ed in handlers */
115    
116     static const t_irc_command_table_row irc_log_command_table[] =
117     {
118     { "WHO" , _handle_who_command },
119     { "LIST" , _handle_list_command },
120     { "TOPIC" , _handle_topic_command },
121     { "JOIN" , _handle_join_command },
122     { "NAMES" , _handle_names_command },
123     { "MODE" , _handle_mode_command },
124     { "USERHOST" , _handle_userhost_command },
125     { "ISON" , _handle_ison_command },
126     { "WHOIS" , _handle_whois_command },
127     { NULL , NULL }
128     };
129    
130    
131     static int handle_irc_con_command(t_connection * conn, char const * command, int numparams, char ** params, char * text)
132     {
133     t_irc_command_table_row const *p;
134    
135     for (p = irc_con_command_table; p->irc_command_string != NULL; p++)
136     {
137     if (strcasecmp(command, p->irc_command_string)==0)
138     {
139     if (p->irc_command_handler != NULL) return ((p->irc_command_handler)(conn,numparams,params,text));
140     }
141     }
142     return -1;
143     }
144    
145     static int handle_irc_log_command(t_connection * conn, char const * command, int numparams, char ** params, char * text)
146     {
147     t_irc_command_table_row const *p;
148    
149     for (p = irc_log_command_table; p->irc_command_string != NULL; p++)
150     {
151     if (strcasecmp(command, p->irc_command_string)==0)
152     {
153     if (p->irc_command_handler != NULL) return ((p->irc_command_handler)(conn,numparams,params,text));
154     }
155     }
156     return -1;
157     }
158    
159     static int handle_irc_line(t_connection * conn, char const * ircline)
160     { /* [:prefix] <command> [[param1] [param2] ... [paramN]] [:<text>]*/
161     char * line; /* copy of ircline */
162     char * prefix = NULL; /* optional; mostly NULL */
163     char * command; /* mandatory */
164     char ** params = NULL; /* optional (array of params) */
165     char * text = NULL; /* optional */
166     char * bnet_command = NULL; //amadeo: used for battle.net.commands
167     int unrecognized_before = 0;
168     int linelen; //amadeo: counter for stringlenghts
169    
170     int numparams = 0;
171     char * tempparams;
172    
173     if (!conn) {
174     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
175     return -1;
176     }
177     if (!ircline) {
178     eventlog(eventlog_level_error,__FUNCTION__,"got NULL ircline");
179     return -1;
180     }
181     if (ircline[0] == '\0') {
182     eventlog(eventlog_level_error,__FUNCTION__,"got empty ircline");
183     return -1;
184     }
185     //amadeo: code was sent by some unknown fellow of pvpgn, prevents buffer-overflow for
186     // too long irc-lines
187    
188     if (strlen(ircline)>254) {
189     char * tmp = (char *)ircline;
190     eventlog(eventlog_level_warn,__FUNCTION__,"line to long, truncation...");
191     tmp[254]='\0';
192     }
193    
194     line = xstrdup(ircline);
195    
196     /* split the message */
197     if (line[0] == ':') {
198     /* The prefix is optional and is rarely provided */
199     prefix = line;
200     if (!(command = strchr(line,' '))) {
201     eventlog(eventlog_level_warn,__FUNCTION__,"got malformed line (missing command)");
202     /* FIXME: send message instead of eventlog? */
203     xfree(line);
204     return -1;
205     }
206     *command++ = '\0';
207     } else {
208     /* In most cases command is the first thing on the line */
209     command = line;
210     }
211    
212     tempparams = strchr(command,' ');
213     if (tempparams) {
214     int i;
215    
216     *tempparams++ = '\0';
217     if (tempparams[0]==':') {
218     text = tempparams+1; /* theres just text, no params. skip the colon */
219     } else {
220     for (i=0;tempparams[i]!='\0';i++) {
221     if ((tempparams[i]==' ')&&(tempparams[i+1]==':')) {
222     text = tempparams+i;
223     *text++ = '\0';
224     text++; /* skip the colon */
225     break; /* text found, stop search */
226     }
227     }
228     params = irc_get_paramelems(tempparams);
229     }
230     }
231    
232     if (params) {
233     /* count parameters */
234     for (numparams=0;params[numparams];numparams++);
235     }
236    
237     {
238     int i;
239     char paramtemp[MAX_IRC_MESSAGE_LEN*2];
240     int first = 1;
241    
242     memset(paramtemp,0,sizeof(paramtemp));
243     for (i=0;((numparams>0)&&(params[i]));i++) {
244     if (!first) strcat(paramtemp," ");
245     strcat(paramtemp,"\"");
246     strcat(paramtemp,params[i]);
247     strcat(paramtemp,"\"");
248     first = 0;
249     }
250     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] got \"%s\" \"%s\" [%s] \"%s\"",conn_get_socket(conn),((prefix)?(prefix):("")),command,paramtemp,((text)?(text):("")));
251     }
252    
253     if (conn_get_state(conn)==conn_state_connected) {
254     t_timer_data temp;
255    
256     conn_set_state(conn,conn_state_bot_username);
257     temp.n = prefs_get_irc_latency();
258     conn_test_latency(conn,time(NULL),temp);
259     }
260    
261     if (handle_irc_con_command(conn, command, numparams, params, text)!=-1) {}
262     else if (conn_get_state(conn)!=conn_state_loggedin) {
263     char temp[MAX_IRC_MESSAGE_LEN+1];
264    
265     if ((38+strlen(command)+16+1)<sizeof(temp)) {
266     sprintf(temp,":Unrecognized command \"%s\" (before login)",command);
267     irc_send(conn,ERR_UNKNOWNCOMMAND,temp);
268     } else {
269     irc_send(conn,ERR_UNKNOWNCOMMAND,":Unrecognized command (before login)");
270     }
271     } else {
272     /* command is handled later */
273     unrecognized_before = 1;
274     }
275     /* --- The following should only be executable after login --- */
276     if ((conn_get_state(conn)==conn_state_loggedin)&&(unrecognized_before)) {
277    
278     if (handle_irc_log_command(conn, command, numparams, params, text)!=-1) {}
279     else if ((strstart(command,"LAG")!=0)&&(strstart(command,"JOIN")!=0)){
280     linelen = strlen (ircline);
281     bnet_command = xmalloc(linelen + 2);
282     bnet_command[0]='/';
283     strcpy(bnet_command + 1, ircline);
284     handle_command(conn,bnet_command);
285     xfree((void*)bnet_command);
286     }
287     } /* loggedin */
288     if (params)
289     irc_unget_paramelems(params);
290     xfree(line);
291     return 0;
292     }
293    
294     extern int handle_irc_packet(t_connection * conn, t_packet const * const packet)
295     {
296     unsigned int i;
297     char ircline[MAX_IRC_MESSAGE_LEN];
298     int ircpos;
299     char const * data;
300    
301     if (!packet) {
302     eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
303     return -1;
304     }
305     if (conn_get_class(conn) != conn_class_irc ) {
306     eventlog(eventlog_level_error,__FUNCTION__,"FIXME: handle_irc_packet without any reason (conn->class != conn_class_irc)");
307     return -1;
308     }
309    
310     /* eventlog(eventlog_level_debug,__FUNCTION__,"got \"%s\"",packet_get_raw_data_const(packet,0)); */
311    
312     memset(ircline,0,sizeof(ircline));
313     data = conn_get_ircline(conn); /* fetch current status */
314     if (data)
315     strcpy(ircline,data);
316     ircpos = strlen(ircline);
317     data = packet_get_raw_data_const(packet,0);
318     for (i=0; i < packet_get_size(packet); i++) {
319     if ((data[i] == '\r')||(data[i] == '\0')) {
320     /* kindly ignore \r and NUL ... */
321     } else if (data[i] == '\n') {
322     /* end of line */
323     handle_irc_line(conn,ircline);
324     memset(ircline,0,sizeof(ircline));
325     ircpos = 0;
326     } else {
327     if (ircpos < MAX_IRC_MESSAGE_LEN-1)
328     ircline[ircpos++] = data[i];
329     else {
330     ircpos++; /* for the statistic :) */
331     eventlog(eventlog_level_warn,__FUNCTION__,"[%d] client exceeded maximum allowed message length by %d characters",conn_get_socket(conn),ircpos-MAX_IRC_MESSAGE_LEN);
332     if ((ircpos-MAX_IRC_MESSAGE_LEN)>100) {
333     /* automatic flood protection */
334     eventlog(eventlog_level_error,__FUNCTION__,"[%d] excess flood",conn_get_socket(conn));
335     return -1;
336     }
337     }
338     }
339     }
340     conn_set_ircline(conn,ircline); /* write back current status */
341     return 0;
342     }
343    
344     static int _handle_nick_command(t_connection * conn, int numparams, char ** params, char * text)
345     {
346     /* FIXME: more strict param checking */
347    
348     if ((conn_get_loggeduser(conn))&&
349     (conn_get_state(conn)!=conn_state_bot_password &&
350     conn_get_state(conn)!=conn_state_bot_username))
351     {
352     irc_send(conn,ERR_RESTRICTED,":You can't change your nick after login");
353     }
354     else
355     {
356     if ((params)&&(params[0]))
357     {
358     if (conn_get_loggeduser(conn))
359     irc_send_cmd2(conn,conn_get_loggeduser(conn),"NICK","",params[0]);
360     conn_set_loggeduser(conn,params[0]);
361     }
362     else if (text)
363     {
364     if (conn_get_loggeduser(conn))
365     irc_send_cmd2(conn,conn_get_loggeduser(conn),"NICK","",text);
366     conn_set_loggeduser(conn,text);
367     }
368     else
369     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to NICK");
370     if ((conn_get_user(conn))&&(conn_get_loggeduser(conn)))
371     irc_welcome(conn); /* only send the welcome if we have USER and NICK */
372     }
373     return 0;
374     }
375    
376     static int _handle_user_command(t_connection * conn, int numparams, char ** params, char * text)
377     {
378     /* RFC 2812 says: */
379     /* <user> <mode> <unused> :<realname>*/
380     /* ircII and X-Chat say: */
381     /* mz SHODAN localhost :Marco Ziech */
382     /* BitchX says: */
383     /* mz +iws mz :Marco Ziech */
384     /* What does this tell us? Ditch mode and unused, they don't contain what they should. */
385     char * user = NULL;
386     char * mode = NULL;
387     char * unused = NULL;
388     char * realname = NULL;
389    
390     if ((numparams>=3)&&(params[0])&&(params[1])&&(params[2])&&(text))
391     {
392     user = params[0];
393     mode = params[1];
394     unused = params[2];
395     realname = text;
396     if (conn_get_user(conn))
397     {
398     irc_send(conn,ERR_ALREADYREGISTRED,":You are already registred");
399     }
400     else
401     {
402     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] got USER: user=\"%s\" mode=\"%s\" unused=\"%s\" realname=\"%s\"",conn_get_socket(conn),user,mode,unused,realname);
403     conn_set_user(conn,user);
404     conn_set_owner(conn,realname);
405     if (conn_get_loggeduser(conn))
406     irc_welcome(conn); /* only send the welcome if we have USER and NICK */
407     }
408     }
409     else
410     {
411     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to USER");
412     }
413     return 0;
414     }
415    
416     static int _handle_ping_command(t_connection * conn, int numparams, char ** params, char * text)
417     {
418     /* Dizzy: just ignore this because RFC says we should not reply client PINGs
419     * NOTE: RFC2812 doesn't seem to be very expressive about this ... */
420     if (numparams)
421     irc_send_pong(conn,params[0]);
422     else
423     irc_send_pong(conn,text);
424     return 0;
425     }
426    
427     static int _handle_pong_command(t_connection * conn, int numparams, char ** params, char * text)
428     {
429    
430     /* NOTE: RFC2812 doesn't seem to be very expressive about this ... */
431     if (conn_get_ircping(conn)==0)
432     {
433     eventlog(eventlog_level_warn,__FUNCTION__,"[%d] PONG without PING",conn_get_socket(conn));
434     }
435     else
436     {
437     unsigned int val = 0;
438     char * sname;
439    
440     if (numparams>=1)
441     {
442     val = atoi(params[0]);
443     sname = params[0];
444     }
445     else if (text)
446     {
447     val = atoi(text);
448     sname = text;
449     }
450     else
451     {
452     val = 0;
453     sname = 0;
454     }
455    
456     if (conn_get_ircping(conn) != val)
457     {
458     if ((!(sname)) || (strcmp(sname,server_get_name())!=0))
459     {
460     /* Actually the servername should not be always accepted but we aren't that pedantic :) */
461     eventlog(eventlog_level_warn,__FUNCTION__,"[%d] got bad PONG (%u!=%u && %s!=%s)",conn_get_socket(conn),val,conn_get_ircping(conn),sname,server_get_name());
462     return -1;
463     }
464     }
465     conn_set_latency(conn,get_ticks()-conn_get_ircping(conn));
466     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] latency is now %d (%u-%u)",conn_get_socket(conn),get_ticks()-conn_get_ircping(conn),get_ticks(),conn_get_ircping(conn));
467     conn_set_ircping(conn,0);
468     }
469     return 0;
470     }
471    
472     static int _handle_pass_command(t_connection * conn, int numparams, char ** params, char * text)
473     {
474     if ((!conn_get_ircpass(conn))&&(conn_get_state(conn)==conn_state_bot_username))
475     {
476     t_hash h;
477    
478     if (numparams>=1)
479     {
480     bnet_hash(&h,strlen(params[0]),params[0]);
481     conn_set_ircpass(conn,hash_get_str(h));
482     }
483     else
484     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PASS");
485     }
486     else
487     {
488     eventlog(eventlog_level_warn,__FUNCTION__,"[%d] client tried to set password twice with PASS",conn_get_socket(conn));
489     }
490     return 0;
491     }
492    
493     static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text)
494     {
495     if ((numparams>=1)&&(text))
496     {
497     int i;
498     char ** e;
499    
500     e = irc_get_listelems(params[0]);
501     /* FIXME: support wildcards! */
502    
503     //start amadeo: code was sent by some unkown fellow of pvpgn(maybe u wanna give us your name
504     // for any credits), it adds nick-registration,i changed some things here and there...
505     for (i=0;((e)&&(e[i]));i++)
506     {
507     if (strcasecmp(e[i],"NICKSERV")==0)
508     {
509     char * pass;
510     char * p;
511    
512     pass = strchr(text,' ');
513     if (pass)
514     *pass++ = '\0';
515    
516     if (strcasecmp(text,"identify")==0)
517     {
518     switch (conn_get_state(conn))
519     {
520     case conn_state_bot_password:
521     {
522     if (pass)
523     {
524     t_hash h;
525    
526     for (p = pass; *p; p++)
527     if (isupper((int)*p)) *p = tolower(*p);
528     bnet_hash(&h,strlen(pass),pass);
529     irc_authenticate(conn,hash_get_str(h));
530     }
531     else
532     {
533     irc_send_cmd(conn,"NOTICE",":Syntax: IDENTIFY password(max 16 characters)");
534     }
535     break;
536     }
537     case conn_state_loggedin:
538     {
539     irc_send_cmd(conn,"NOTICE",":You don't need to IDENTIFY");
540     break;
541     }
542     default: ;
543     eventlog(eventlog_level_trace,__FUNCTION__,"got /msg in unexpected connection state (%s)",conn_state_get_str(conn_get_state(conn)));
544     }
545     }
546     else if (strcasecmp(text,"register")==0)
547     {
548     unsigned int j;
549     t_hash passhash;
550     t_account * temp;
551     char msgtemp[MAX_MESSAGE_LEN];
552     char * username=(char *)conn_get_loggeduser(conn);
553    
554     if (account_check_name(username)<0)
555     {
556     message_send_text(conn,message_type_error,conn,"Account name contains invalid symbol!");
557     break;
558     }
559    
560     if (!pass || pass[0]=='\0' || (strlen(pass)>16) )
561     {
562     message_send_text(conn,message_type_error,conn,":Syntax: REGISTER password(max 16 characters)");
563     break;
564     }
565    
566    
567     for (j=0; j<strlen(pass); j++)
568     if (isupper((int)pass[j])) pass[j] = tolower((int)pass[j]);
569    
570     bnet_hash(&passhash,strlen(pass),pass);
571    
572     sprintf(msgtemp,"Trying to create account \"%s\" with password \"%s\"",username,pass);
573     message_send_text(conn,message_type_info,conn,msgtemp);
574    
575     temp = accountlist_create_account(username,hash_get_str(passhash));
576     if (!temp) {
577     message_send_text(conn,message_type_error,conn,"Failed to create account!");
578     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" not created (failed)",conn_get_socket(conn),username);
579     conn_unget_chatname(conn,username);
580     break;
581     }
582    
583     sprintf(msgtemp,"Account "UID_FORMAT" created.",account_get_uid(temp));
584     message_send_text(conn,message_type_info,conn,msgtemp);
585     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" created",conn_get_socket(conn),username);
586     conn_unget_chatname(conn,username);
587     }
588     else
589     {
590     char tmp[MAX_IRC_MESSAGE_LEN+1];
591    
592     irc_send_cmd(conn,"NOTICE",":Invalid arguments for NICKSERV");
593     sprintf(tmp,":Unrecognized command \"%s\"",text);
594     irc_send_cmd(conn,"NOTICE",tmp);
595     }
596     }
597    
598     else if (conn_get_state(conn)==conn_state_loggedin)
599     {
600     if (e[i][0]=='#')
601     {
602     /* channel message */
603     t_channel * channel;
604    
605     if ((channel = channellist_find_channel_by_name(irc_convert_ircname(e[i]),NULL,NULL)))
606     {
607     if ((strlen(text)>=9)&&(strncmp(text,"\001ACTION ",8)==0)&&(text[strlen(text)-1]=='\001'))
608     { /* at least "\001ACTION \001" */
609     /* it's a CTCP ACTION message */
610     text = text + 8;
611     text[strlen(text)-1] = '\0';
612     channel_message_send(channel,message_type_emote,conn,text);
613     }
614     else
615     channel_message_send(channel,message_type_talk,conn,text);
616     }
617     else
618     {
619     irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel");
620     }
621     }
622     else
623     {
624     /* whisper */
625     t_connection * user;
626    
627     if ((user = connlist_find_connection_by_accountname(e[i])))
628     {
629     message_send_text(user,message_type_whisper,conn,text);
630     }
631     else
632     {
633     irc_send(conn,ERR_NOSUCHNICK,":No such user");
634     }
635     }
636     }
637     }
638     if (e)
639     irc_unget_listelems(e);
640     }
641     else
642     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PRIVMSG");
643     return 0;
644     }
645    
646     static int _handle_notice_command(t_connection * conn, int numparams, char ** params, char * text)
647     {
648     if ((numparams>=1)&&(text))
649     {
650     int i;
651     char ** e;
652    
653     e = irc_get_listelems(params[0]);
654     /* FIXME: support wildcards! */
655    
656     for (i=0;((e)&&(e[i]));i++)
657     {
658     if (conn_get_state(conn)==conn_state_loggedin)
659     {
660     t_connection * user;
661    
662     if ((user = connlist_find_connection_by_accountname(e[i])))
663     {
664     irc_send_cmd2(user,conn_get_loggeduser(conn),"NOTICE",conn_get_loggeduser(user),text);
665     }
666     else
667     {
668     irc_send(conn,ERR_NOSUCHNICK,":No such user");
669     }
670     }
671     }
672     if (e)
673     irc_unget_listelems(e);
674     }
675     else
676     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PRIVMSG");
677     return 0;
678     }
679    
680     static int _handle_who_command(t_connection * conn, int numparams, char ** params, char * text)
681     {
682     if (numparams>=1)
683     {
684     int i;
685     char ** e;
686    
687     e = irc_get_listelems(params[0]);
688     for (i=0; ((e)&&(e[i]));i++)
689     {
690     irc_who(conn,e[i]);
691     }
692     irc_send(conn,RPL_ENDOFWHO,":End of WHO list"); /* RFC2812 only requires this to be sent if a list of names was given. Undernet seems to always send it, so do we :) */
693     if (e)
694     irc_unget_listelems(e);
695     }
696     else
697     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to WHO");
698     return 0;
699     }
700    
701     static int _handle_list_command(t_connection * conn, int numparams, char ** params, char * text)
702     {
703     char temp[MAX_IRC_MESSAGE_LEN];
704    
705     irc_send(conn,RPL_LISTSTART,"Channel :Users Name"); /* backward compatibility */
706     if (numparams==0)
707     {
708     t_elem const * curr;
709    
710     LIST_TRAVERSE_CONST(channellist(),curr)
711     {
712     t_channel const * channel = elem_get_data(curr);
713     char const * tempname;
714     char const * notopic = "No topic is set";
715     char * topic = channel_get_topic(channel_get_name(channel));
716    
717     tempname = irc_convert_channel(channel);
718    
719     //FIXME: AARON: only list channels like in /channels command
720    
721     if (topic)
722     {
723     if (strlen(tempname)+1+20+1+1+strlen(topic)<MAX_IRC_MESSAGE_LEN)
724     sprintf(temp,"%s %u :%s",tempname,channel_get_length(channel),topic);
725     else
726     eventlog(eventlog_level_warn,__FUNCTION__,"LISTREPLY length exceeded");
727     }
728     else
729     {
730     if (strlen(tempname)+1+20+1+1+strlen(notopic)<MAX_IRC_MESSAGE_LEN)
731     sprintf(temp,"%s %u :%s",tempname,channel_get_length(channel),notopic);
732     else
733     eventlog(eventlog_level_warn,__FUNCTION__,"LISTREPLY length exceeded");
734     }
735     irc_send(conn,RPL_LIST,temp);
736     }
737     }
738     else if (numparams>=1)
739     {
740     int i;
741     char ** e;
742    
743     /* FIXME: support wildcards! */
744     e = irc_get_listelems(params[0]);
745     for (i=0;((e)&&(e[i]));i++)
746     {
747     t_channel const * channel;
748     char const * verytemp; /* another good example for creative naming conventions :) */
749     char const * tempname;
750     char const * notopic = "No topic is set";
751     char * topic;
752    
753     verytemp = irc_convert_ircname(e[i]);
754     if (!verytemp)
755     continue; /* something is wrong with the name ... */
756     channel = channellist_find_channel_by_name(verytemp,NULL,NULL);
757     if (!channel)
758     continue; /* channel doesn't exist */
759    
760     topic = channel_get_topic(channel_get_name(channel));
761     tempname = irc_convert_channel(channel);
762    
763     if (topic)
764     {
765     if (strlen(tempname)+1+20+1+1+strlen(topic)<MAX_IRC_MESSAGE_LEN)
766     sprintf(temp,"%s %u :%s",tempname,channel_get_length(channel),topic);
767     else
768     eventlog(eventlog_level_warn,__FUNCTION__,"LISTREPLY length exceeded");
769     }
770     else
771     {
772     if (strlen(tempname)+1+20+1+1+strlen(notopic)<MAX_IRC_MESSAGE_LEN)
773     sprintf(temp,"%s %u :%s",tempname,channel_get_length(channel),notopic);
774     else
775     eventlog(eventlog_level_warn,__FUNCTION__,"LISTREPLY length exceeded");
776     }
777     irc_send(conn,RPL_LIST,temp);
778     }
779     if (e)
780     irc_unget_listelems(e);
781     }
782     irc_send(conn,RPL_LISTEND,":End of LIST command");
783     return 0;
784     }
785    
786     static int _handle_topic_command(t_connection * conn, int numparams, char ** params, char * text)
787     {
788     char ** e = NULL;
789    
790     if (params!=NULL) e = irc_get_listelems(params[0]);
791    
792     if ((e)&&(e[0]))
793     {
794     t_channel *channel = conn_get_channel(conn);
795    
796     if (channel)
797     {
798     char * topic;
799     char temp[MAX_IRC_MESSAGE_LEN];
800     char const * ircname = irc_convert_ircname(e[0]);
801    
802     if ((ircname) && (strcasecmp(channel_get_name(channel),ircname)==0))
803     {
804     if ((topic = channel_get_topic(channel_get_name(channel))))
805     {
806     sprintf(temp,"%s :%s",ircname,topic);
807     irc_send(conn,RPL_TOPIC,temp);
808     }
809     else
810     irc_send(conn,RPL_NOTOPIC,":No topic is set");
811     }
812     else
813     irc_send(conn,ERR_NOTONCHANNEL,":You are not on that channel");
814     }
815     else
816     {
817     irc_send(conn,ERR_NOTONCHANNEL,":You're not on a channel");
818     }
819     irc_unget_listelems(e);
820     }
821     else
822     irc_send(conn,ERR_NEEDMOREPARAMS,":too few arguments to TOPIC");
823     return 0;
824     }
825    
826     static int _handle_join_command(t_connection * conn, int numparams, char ** params, char * text)
827     {
828     if (numparams>=1)
829     {
830     char ** e;
831    
832     e = irc_get_listelems(params[0]);
833     if ((e)&&(e[0]))
834     {
835     char const * ircname = irc_convert_ircname(e[0]);
836     char * old_channel_name = NULL;
837     t_channel * old_channel = conn_get_channel(conn);
838    
839     if (old_channel)
840     old_channel_name = xstrdup(irc_convert_channel(old_channel));
841    
842     if ((!(ircname)) || (conn_set_channel(conn,ircname)<0))
843     {
844     irc_send(conn,ERR_NOSUCHCHANNEL,":JOIN failed"); /* FIXME: be more precise; what is the real error code for that? */
845     }
846     else
847     {
848     t_channel * channel;
849    
850    
851    
852     channel = conn_get_channel(conn);
853     if (channel!=old_channel)
854     {
855     char temp[MAX_IRC_MESSAGE_LEN];
856     char * topic;
857    
858     channel_set_userflags(conn);
859     message_send_text(conn,message_type_join,conn,NULL); /* we have to send the JOIN acknowledgement */
860     ircname=irc_convert_channel(channel);
861    
862     if ((topic = channel_get_topic(channel_get_name(channel))))
863     {
864    
865     if ((strlen(ircname)+1+1+strlen(topic)+1)<MAX_IRC_MESSAGE_LEN)
866     {
867     sprintf(temp,"%s :%s",ircname,topic);
868     irc_send(conn,RPL_TOPIC,temp);
869     }
870    
871     if ((strlen(ircname)+1+strlen("FIXME 0")+1)<MAX_IRC_MESSAGE_LEN)
872     {
873     sprintf(temp,"%s FIXME 0",ircname);
874     irc_send(conn,RPL_TOPICWHOTIME,temp); /* FIXME: this in an undernet extension but other servers support it too */
875     }
876     }
877     else
878     irc_send(conn,RPL_NOTOPIC,":No topic is set");
879    
880     irc_send_rpl_namreply(conn,channel);
881     irc_send(conn,RPL_ENDOFNAMES,":End of NAMES list");
882    
883     if (old_channel_name)
884     {
885     irc_send_cmd2(conn,conn_get_loggeduser(conn),"PART",old_channel_name,"only one channel at once");
886     }
887     }
888     }
889     if (old_channel_name) xfree((void *)old_channel_name);
890     }
891     if (e)
892     irc_unget_listelems(e);
893     }
894     else
895     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to JOIN");
896     return 0;
897     }
898    
899     static int _handle_names_command(t_connection * conn, int numparams, char ** params, char * text)
900     {
901     t_channel * channel;
902    
903     if (numparams>=1)
904     {
905     char ** e;
906     char const * ircname;
907     char const * verytemp;
908     char temp[MAX_IRC_MESSAGE_LEN];
909     int i;
910    
911     e = irc_get_listelems(params[0]);
912     for (i=0;((e)&&(e[i]));i++)
913     {
914     verytemp = irc_convert_ircname(e[i]);
915    
916     if (!verytemp)
917     continue; /* something is wrong with the name ... */
918     channel = channellist_find_channel_by_name(verytemp,NULL,NULL);
919     if (!channel)
920     continue; /* channel doesn't exist */
921     irc_send_rpl_namreply(conn,channel);
922     ircname=irc_convert_channel(channel);
923     if ((strlen(ircname)+1+strlen(":End of NAMES list")+1)<MAX_IRC_MESSAGE_LEN)
924     {
925     sprintf(temp,"%s :End of NAMES list",ircname);
926     irc_send(conn,RPL_ENDOFNAMES,temp);
927     }
928     else
929     irc_send(conn,RPL_ENDOFNAMES,":End of NAMES list");
930     }
931     if (e)
932     irc_unget_listelems(e);
933     }
934     else if (numparams==0)
935     {
936     t_elem const * curr;
937     LIST_TRAVERSE_CONST(channellist(),curr)
938     {
939     channel = elem_get_data(curr);
940     irc_send_rpl_namreply(conn,channel);
941     }
942     irc_send(conn,RPL_ENDOFNAMES,"* :End of NAMES list");
943     }
944     return 0;
945     }
946    
947     static int _handle_mode_command(t_connection * conn, int numparams, char ** params, char * text)
948     {
949     /* FIXME: Not yet implemented */
950     return 0;
951     }
952    
953     static int _handle_userhost_command(t_connection * conn, int numparams, char ** params, char * text)
954     {
955     /* FIXME: Send RPL_USERHOST */
956     return 0;
957     }
958    
959     static int _handle_quit_command(t_connection * conn, int numparams, char ** params, char * text)
960     {
961     conn_set_channel(conn, NULL);
962     conn_set_state(conn, conn_state_destroy);
963     return 0;
964     }
965    
966     static int _handle_ison_command(t_connection * conn, int numparams, char ** params, char * text)
967     {
968     char temp[MAX_IRC_MESSAGE_LEN];
969     char first = 1;
970    
971     if (numparams>=1)
972     {
973     int i;
974    
975     temp[0]='\0';
976     for (i=0; (i<numparams && (params) && (params[i]));i++)
977     {
978     if (connlist_find_connection_by_accountname(params[i]))
979     {
980     if (first)
981     strcat(temp,":");
982     else
983     strcat(temp," ");
984     strcat(temp,params[i]);
985     first = 0;
986     }
987     }
988     irc_send(conn,RPL_ISON,temp);
989     }
990     else
991     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to ISON");
992     return 0;
993     }
994    
995     static int _handle_whois_command(t_connection * conn, int numparams, char ** params, char * text)
996     {
997     char temp[MAX_IRC_MESSAGE_LEN];
998     char temp2[MAX_IRC_MESSAGE_LEN];
999     if (numparams>=1)
1000     {
1001     int i;
1002     char ** e;
1003     t_connection * c;
1004     t_channel * chan;
1005    
1006     temp[0]='\0';
1007     temp2[0]='\0';
1008     e = irc_get_listelems(params[0]);
1009     for (i=0; ((e)&&(e[i]));i++)
1010     {
1011     if ((c = connlist_find_connection_by_accountname(e[i])))
1012     {
1013     if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(conn)) & command_get_group("/admin-addr")))
1014     sprintf(temp,"%s %s hidden * :%s",e[i],clienttag_uint_to_str(conn_get_clienttag(c)),"PvPGN user");
1015     else
1016     sprintf(temp,"%s %s %s * :%s",e[i],clienttag_uint_to_str(conn_get_clienttag(c)),addr_num_to_ip_str(conn_get_addr(c)),"PvPGN user");
1017     irc_send(conn,RPL_WHOISUSER,temp);
1018    
1019     if ((chan=conn_get_channel(conn)))
1020     {
1021     char flg;
1022     unsigned int flags;
1023    
1024     flags = conn_get_flags(c);
1025    
1026     if (flags & MF_BLIZZARD)
1027     flg='@';
1028     else if ((flags & MF_BNET) || (flags & MF_GAVEL))
1029     flg='%';
1030     else if (flags & MF_VOICE)
1031     flg='+';
1032     else flg = ' ';
1033     sprintf(temp2,"%s :%c%s",e[i],flg,irc_convert_channel(chan));
1034     irc_send(conn,RPL_WHOISCHANNELS,temp2);
1035     }
1036    
1037     }
1038     else
1039     irc_send(conn,ERR_NOSUCHNICK,":No such nick/channel");
1040    
1041     }
1042     irc_send(conn,RPL_ENDOFWHOIS,":End of /WHOIS list");
1043     if (e)
1044     irc_unget_listelems(e);
1045     }
1046     else
1047     irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to WHOIS");
1048     return 0;
1049     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1