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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

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    
19     #include "common/setup_before.h"
20     #ifdef STDC_HEADERS
21     # include <stdlib.h>
22     #else
23     # ifdef HAVE_MALLOC_H
24     # include <malloc.h>
25     # endif
26     #endif
27     #ifdef HAVE_STRING_H
28     # include <string.h>
29     #else
30     # ifdef HAVE_STRINGS_H
31     # include <strings.h>
32     # endif
33     # ifdef HAVE_MEMORY_H
34     # include <memory.h>
35     # endif
36     #endif
37     #include "compat/strdup.h"
38     #include <errno.h>
39     #include "compat/strerror.h"
40     #ifdef TIME_WITH_SYS_TIME
41     # include <sys/time.h>
42     # include <time.h>
43     #else
44     # ifdef HAVE_SYS_TIME_H
45     # include <sys/time.h>
46     # else
47     # include <time.h>
48     # endif
49     #endif
50     #include "common/irc_protocol.h"
51     #include "common/packet.h"
52     #include "common/eventlog.h"
53     #include "connection.h"
54     #include "common/bn_type.h"
55     #include "common/field_sizes.h"
56     #include "common/addr.h"
57     #include "common/version.h"
58     #include "common/queue.h"
59     #include "common/list.h"
60     #include "common/bnethash.h"
61     #include "common/bnethashconv.h"
62     #include "common/tag.h"
63     #include "message.h"
64     #include "account.h"
65     #include "account_wrap.h"
66     #include "channel.h"
67     #include "irc.h"
68     #include "prefs.h"
69     #include "server.h"
70     #include "tick.h"
71     #include "message.h"
72     #include "command_groups.h"
73     #include "common/util.h"
74     #include "common/xalloc.h"
75     #include "common/setup_after.h"
76    
77     typedef struct {
78     char const * nick;
79     char const * user;
80     char const * host;
81     } t_irc_message_from;
82    
83    
84     static char ** irc_split_elems(char * list, int separator, int ignoreblank);
85     static int irc_unget_elems(char ** elems);
86     static char * irc_message_preformat(t_irc_message_from const * from, char const * command, char const * dest, char const * text);
87    
88     extern int irc_send_cmd(t_connection * conn, char const * command, char const * params)
89     {
90     t_packet * p;
91     char data[MAX_IRC_MESSAGE_LEN+1];
92     int len;
93     char const * ircname = server_get_name();
94     char const * nick;
95    
96     if (!conn) {
97     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
98     return -1;
99     }
100     if (!command) {
101     eventlog(eventlog_level_error,__FUNCTION__,"got NULL command");
102     return -1;
103     }
104     if (!(p = packet_create(packet_class_raw))) {
105     eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
106     return -1;
107     }
108    
109     nick = conn_get_loggeduser(conn);
110     if (!nick)
111     nick = ""; /* FIXME: Is this good? */
112     /* snprintf isn't portable -> check message length first */
113     if (params) {
114     len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+strlen(params)+2;
115     if (len > MAX_IRC_MESSAGE_LEN)
116     {
117     eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
118     return -1;
119     }
120     else
121     sprintf(data,":%s %s %s %s\r\n",ircname,command,nick,params);
122     } else {
123     len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+2;
124     if (len > MAX_IRC_MESSAGE_LEN)
125     {
126     eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
127     return -1;
128     }
129     else
130     sprintf(data,":%s %s %s\r\n",ircname,command,nick);
131     }
132     packet_set_size(p,0);
133     packet_append_data(p,data,len);
134     // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
135     conn_push_outqueue(conn,p);
136     packet_del_ref(p);
137     return 0;
138     }
139    
140     extern int irc_send(t_connection * conn, int code, char const * params)
141     {
142     char temp[4]; /* '000\0' */
143    
144     if (!conn) {
145     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
146     return -1;
147     }
148     if ((code>999)||(code<0)) { /* more than 3 digits or negative */
149     eventlog(eventlog_level_error,__FUNCTION__,"invalid message code (%d)",code);
150     return -1;
151     }
152     sprintf(temp,"%03u",code);
153     return irc_send_cmd(conn,temp,params);
154     }
155    
156     extern int irc_send_cmd2(t_connection * conn, char const * prefix, char const * command, char const * postfix, char const * comment)
157     {
158     t_packet * p;
159     char data[MAX_IRC_MESSAGE_LEN+1];
160     int len;
161    
162     if (!conn) {
163     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
164     return -1;
165     }
166     if (!prefix)
167     {
168     eventlog(eventlog_level_error,__FUNCTION__,"got NULL prefix");
169     return -1;
170     }
171     if (!command) {
172     eventlog(eventlog_level_error,__FUNCTION__,"got NULL command");
173     return -1;
174     }
175     if (!postfix)
176     {
177     eventlog(eventlog_level_error,__FUNCTION__,"got NULL postfix");
178     return -1;
179     }
180    
181     if (!(p = packet_create(packet_class_raw))) {
182     eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
183     return -1;
184     }
185    
186     if (comment) {
187     len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+2+strlen(comment)+1+2;
188     if (len > MAX_IRC_MESSAGE_LEN)
189     {
190     eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
191     return -1;
192     }
193     else
194     sprintf(data,":%s %s %s :%s\r\n",prefix,command,postfix,comment);
195     } else {
196     len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+1+2;
197     if (len > MAX_IRC_MESSAGE_LEN)
198     {
199     eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
200     return -1;
201     }
202     else
203     sprintf(data,":%s %s %s\r\n",prefix,command,postfix);
204     }
205     packet_set_size(p,0);
206     packet_append_data(p,data,len);
207     // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
208     conn_push_outqueue(conn,p);
209     packet_del_ref(p);
210     return 0;
211     }
212    
213     extern int irc_send_ping(t_connection * conn)
214     {
215     t_packet * p;
216     char data[MAX_IRC_MESSAGE_LEN];
217    
218     if (!conn) {
219     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
220     return -1;
221     }
222     if (!(p = packet_create(packet_class_raw))) {
223     eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
224     return -1;
225     }
226     conn_set_ircping(conn,get_ticks());
227     if (conn_get_state(conn)==conn_state_bot_username)
228     sprintf(data,"PING :%u\r\n",conn_get_ircping(conn)); /* Undernet doesn't reveal the servername yet ... so do we */
229     else if ((6+strlen(server_get_name())+2+1)<=MAX_IRC_MESSAGE_LEN)
230     sprintf(data,"PING :%s\r\n",server_get_name());
231     else
232     eventlog(eventlog_level_error,__FUNCTION__,"maximum message length exceeded");
233     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
234     packet_set_size(p,0);
235     packet_append_data(p,data,strlen(data));
236     conn_push_outqueue(conn,p);
237     packet_del_ref(p);
238     return 0;
239     }
240    
241     extern int irc_send_pong(t_connection * conn, char const * params)
242     {
243     t_packet * p;
244     char data[MAX_IRC_MESSAGE_LEN];
245    
246     if (!conn) {
247     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
248     return -1;
249     }
250     if ((1+strlen(server_get_name())+1+4+1+strlen(server_get_name())+((params)?(2+strlen(params)):(0))+2+1) > MAX_IRC_MESSAGE_LEN) {
251     eventlog(eventlog_level_error,__FUNCTION__,"max message length exceeded");
252     return -1;
253     }
254     if (!(p = packet_create(packet_class_raw))) {
255     eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
256     return -1;
257     }
258     if (params)
259     sprintf(data,":%s PONG %s :%s\r\n",server_get_name(),server_get_name(),params);
260     else
261     sprintf(data,":%s PONG %s\r\n",server_get_name(),server_get_name());
262     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
263     packet_set_size(p,0);
264     packet_append_data(p,data,strlen(data));
265     conn_push_outqueue(conn,p);
266     packet_del_ref(p);
267     return 0;
268     }
269    
270     extern int irc_authenticate(t_connection * conn, char const * passhash)
271     {
272     t_hash h1;
273     t_hash h2;
274     t_account * a;
275     char const * temphash;
276     char const * username;
277    
278     if (!conn) {
279     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
280     return 0;
281     }
282     if (!passhash) {
283     eventlog(eventlog_level_error,__FUNCTION__,"got NULL passhash");
284     return 0;
285     }
286     username = conn_get_loggeduser(conn);
287     if (!username) {
288     /* redundant sanity check */
289     eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn->protocol.loggeduser");
290     return 0;
291     }
292     a = accountlist_find_account(username);
293     if (!a) {
294     irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* user does not exist */
295     return 0;
296     }
297    
298     if (connlist_find_connection_by_account(a) && prefs_get_kick_old_login()==0)
299     {
300     irc_send_cmd(conn,"NOTICE",":Authentication rejected (already logged in) ");
301     }
302     else if (account_get_auth_lock(a)==1)
303     {
304     irc_send_cmd(conn,"NOTICE",":Authentication rejected (account is locked) ");
305     }
306     else
307     {
308     hash_set_str(&h1,passhash);
309     temphash = account_get_pass(a);
310     hash_set_str(&h2,temphash);
311     if (hash_eq(h1,h2)) {
312     conn_login(conn,a,username);
313     conn_set_state(conn,conn_state_loggedin);
314     /* FIXME: set clienttag to "ircd" or something (and make an icon) */
315     conn_set_clienttag(conn,CLIENTTAG_BNCHATBOT_UINT); /* CHAT hope here is ok */
316     irc_send_cmd(conn,"NOTICE",":Authentication successful. You are now logged in.");
317     return 1;
318     } else {
319     irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* wrong password */
320     conn_increment_passfail_count(conn);
321     }
322     }
323     return 0;
324     }
325    
326     extern int irc_welcome(t_connection * conn)
327     {
328     char temp[MAX_IRC_MESSAGE_LEN];
329     time_t temptime;
330     char const * tempname;
331     char const * temptimestr;
332     char const * filename;
333     FILE *fp;
334     char * line, * formatted_line;
335     char send_line[MAX_IRC_MESSAGE_LEN];
336     char motd_failed = 0;
337    
338     if (!conn) {
339     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
340     return -1;
341     }
342    
343     tempname = conn_get_loggeduser(conn);
344    
345    
346     if ((34+strlen(tempname)+1)<=MAX_IRC_MESSAGE_LEN)
347     sprintf(temp,":Welcome to the BNETD IRC Network %s",tempname);
348     else
349     sprintf(temp,":Maximum length exceeded");
350     irc_send(conn,RPL_WELCOME,temp);
351    
352     if ((14+strlen(server_get_name())+10+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+1)<=MAX_IRC_MESSAGE_LEN)
353     sprintf(temp,":Your host is %s, running "PVPGN_SOFTWARE" "PVPGN_VERSION,server_get_name());
354     else
355     sprintf(temp,":Maximum length exceeded");
356     irc_send(conn,RPL_YOURHOST,temp);
357    
358     temptime = server_get_starttime(); /* FIXME: This should be build time */
359     temptimestr = ctime(&temptime);
360     if ((25+strlen(temptimestr)+1)<=MAX_IRC_MESSAGE_LEN)
361     sprintf(temp,":This server was created %s",temptimestr); /* FIXME: is ctime() portable? */
362     else
363     sprintf(temp,":Maximum length exceeded");
364     irc_send(conn,RPL_CREATED,temp);
365    
366     if ((strlen(server_get_name())+7+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+9+1)<=MAX_IRC_MESSAGE_LEN)
367     sprintf(temp,"%s "PVPGN_SOFTWARE" "PVPGN_VERSION" aroO Oon",server_get_name()); /* FIXME: be honest about modes :) */
368     else
369     sprintf(temp,":Maximum length exceeded");
370     irc_send(conn,RPL_MYINFO,temp);
371     /* 251 is here */
372     /* 255 is here */
373     /* FIXME: show a real MOTD */
374     if ((3+strlen(server_get_name())+22+1)<=MAX_IRC_MESSAGE_LEN)
375     sprintf(temp,":- %s Message of the day - ",server_get_name());
376     else
377     sprintf(temp,":Maximum length exceeded");
378    
379     irc_send(conn,RPL_MOTDSTART,temp);
380    
381     if ((filename = prefs_get_motdfile()))
382     {
383     if ((fp = fopen(filename,"r")))
384     {
385    
386     while ((line=file_get_line(fp)))
387     {
388    
389     if ((formatted_line = message_format_line(conn,line)))
390     {
391     formatted_line[0]=' ';
392     sprintf(send_line,":-%s",formatted_line);
393     irc_send(conn,RPL_MOTD,send_line);
394     xfree(formatted_line);
395     }
396     }
397    
398     file_get_line(NULL); // clear file_get_line buffer
399     fclose(fp);
400     }
401     else motd_failed = 1;
402     }
403     else
404     motd_failed = 1;
405    
406     if (motd_failed)
407     {
408     irc_send(conn,RPL_MOTD,":- Failed to load motd, sending default motd ");
409     irc_send(conn,RPL_MOTD,":- ====================================================== ");
410     irc_send(conn,RPL_MOTD,":- http://www.pvpgn.org ");
411     irc_send(conn,RPL_MOTD,":- ====================================================== ");
412     }
413     irc_send(conn,RPL_ENDOFMOTD,":End of /MOTD command");
414     irc_send_cmd(conn,"NOTICE",":This is an experimental service.");
415     conn_set_state(conn,conn_state_bot_password);
416     if (connlist_find_connection_by_accountname(conn_get_loggeduser(conn))) {
417     irc_send_cmd(conn,"NOTICE","This account is allready logged in, use another account.");
418     return -1;
419     }
420     if (conn_get_ircpass(conn)) {
421     irc_send_cmd(conn,"NOTICE",":Trying to authenticate with PASS ...");
422     irc_authenticate(conn,conn_get_ircpass(conn));
423     } else {
424     irc_send_cmd(conn,"NOTICE",":No PASS command received. Please identify yourself by /msg NICKSERV identify <password>.");
425     }
426     return 0;
427     }
428    
429     /* Channel name conversion rules: */
430     /* Not allowed in IRC (RFC2812): NUL, BELL, CR, LF, ' ', ':' and ','*/
431     /* ' ' -> '_' */
432     /* '_' -> '%_' */
433     /* '%' -> '%%' */
434     /* '\b' -> '%b' */
435     /* '\n' -> '%n' */
436     /* '\r' -> '%r' */
437     /* ':' -> '%=' */
438     /* ',' -> '%-' */
439     /* In IRC a channel can be specified by '#'+channelname or '!'+channelid */
440    
441     extern char const * irc_convert_channel(t_channel const * channel)
442     {
443     char const * bname;
444     static char out[CHANNEL_NAME_LEN];
445     unsigned int outpos;
446     int i;
447    
448     if (!channel)
449     return "*";
450    
451     memset(out,0,sizeof(out));
452     out[0] = '#';
453     outpos = 1;
454     bname = channel_get_name(channel);
455     for (i=0; bname[i]!='\0'; i++) {
456     if (bname[i]==' ') {
457     out[outpos++] = '_';
458     } else if (bname[i]=='_') {
459     out[outpos++] = '%';
460     out[outpos++] = '_';
461     } else if (bname[i]=='%') {
462     out[outpos++] = '%';
463     out[outpos++] = '%';
464     } else if (bname[i]=='\b') {
465     out[outpos++] = '%';
466     out[outpos++] = 'b';
467     } else if (bname[i]=='\n') {
468     out[outpos++] = '%';
469     out[outpos++] = 'n';
470     } else if (bname[i]=='\r') {
471     out[outpos++] = '%';
472     out[outpos++] = 'r';
473     } else if (bname[i]==':') {
474     out[outpos++] = '%';
475     out[outpos++] = '=';
476     } else if (bname[i]==',') {
477     out[outpos++] = '%';
478     out[outpos++] = '-';
479     } else {
480     out[outpos++] = bname[i];
481     }
482     if ((outpos+2)>=(sizeof(out))) {
483     sprintf(out,"!%u",channel_get_channelid(channel));
484     return out;
485     }
486     }
487     return out;
488     }
489    
490     extern char const * irc_convert_ircname(char const * pircname)
491     {
492     static char out[CHANNEL_NAME_LEN];
493     unsigned int outpos;
494     int special;
495     int i;
496     char const * ircname = pircname + 1;
497    
498     if (!ircname) {
499     eventlog(eventlog_level_error,__FUNCTION__,"got NULL ircname");
500     return NULL;
501     }
502    
503     outpos = 0;
504     memset(out,0,sizeof(out));
505     special = 0;
506     if (pircname[0]=='!') {
507     t_channel * channel;
508    
509     channel = channellist_find_channel_bychannelid(atoi(ircname));
510     if (channel)
511     return channel_get_name(channel);
512     else
513     return NULL;
514     } else if (pircname[0]!='#') {
515     return NULL;
516     }
517     for (i=0; ircname[i]!='\0'; i++) {
518     if (ircname[i]=='_') {
519     out[outpos++] = ' ';
520     } else if (ircname[i]=='%') {
521     if (special) {
522     out[outpos++] = '%';
523     special = 0;
524     } else {
525     special = 1;
526     }
527     } else if (special) {
528     if (ircname[i]=='_') {
529     out[outpos++] = '_';
530     } else if (ircname[i]=='b') {
531     out[outpos++] = '\b';
532     } else if (ircname[i]=='n') {
533     out[outpos++] = '\n';
534     } else if (ircname[i]=='r') {
535     out[outpos++] = '\r';
536     } else if (ircname[i]=='=') {
537     out[outpos++] = ':';
538     } else if (ircname[i]=='-') {
539     out[outpos++] = ',';
540     } else {
541     /* maybe it's just a typo :) */
542     out[outpos++] = '%';
543     out[outpos++] = ircname[i];
544     }
545     } else {
546     out[outpos++] = ircname[i];
547     }
548     if ((outpos+2)>=(sizeof(out))) {
549     return NULL;
550     }
551     }
552     return out;
553     }
554    
555     /* splits an string list into its elements */
556     /* (list will be modified) */
557     static char ** irc_split_elems(char * list, int separator, int ignoreblank)
558     {
559     int i;
560     int count;
561     char ** out;
562    
563     if (!list) {
564     eventlog(eventlog_level_error,__FUNCTION__,"got NULL list");
565     return NULL;
566     }
567    
568     for (count=0,i=0;list[i]!='\0';i++) {
569     if (list[i]==separator) {
570     count++;
571     if (ignoreblank) {
572     /* ignore more than one separators "in a row" */
573     while ((list[i+1]!='\0')&&(list[i]==separator)) i++;
574     }
575     }
576     }
577     count++; /* count separators -> we have one more element ... */
578     /* we also need a terminating element */
579     out = xmalloc((count+1)*sizeof(char *));
580    
581     out[0] = list;
582     if (count>1) {
583     for (i=1;i<count;i++) {
584     out[i] = strchr(out[i-1],separator);
585     if (!out[i]) {
586     eventlog(eventlog_level_error,__FUNCTION__,"BUG: wrong number of separators");
587     xfree(out);
588     return NULL;
589     }
590     if (ignoreblank)
591     while ((*out[i]+1)==separator) out[i]++;
592     *out[i]++ = '\0';
593     }
594     if ((ignoreblank)&&(out[count-1])&&(*out[count-1]=='\0')) {
595     out[count-1] = NULL; /* last element is blank */
596     }
597     } else if ((ignoreblank)&&(*out[0]=='\0')) {
598     out[0] = NULL; /* now we have 2 terminators ... never mind */
599     }
600     out[count] = NULL; /* terminating element */
601     return out;
602     }
603    
604     static int irc_unget_elems(char ** elems)
605     {
606     if (!elems) {
607     eventlog(eventlog_level_error,__FUNCTION__,"got NULL elems");
608     return -1;
609     }
610     xfree(elems);
611     return 0;
612     }
613    
614     extern char ** irc_get_listelems(char * list)
615     {
616     return irc_split_elems(list,',',0);
617     }
618    
619     extern int irc_unget_listelems(char ** elems)
620     {
621     return irc_unget_elems(elems);
622     }
623    
624     extern char ** irc_get_paramelems(char * list)
625     {
626     return irc_split_elems(list,' ',1);
627     }
628    
629     extern int irc_unget_paramelems(char ** elems)
630     {
631     return irc_unget_elems(elems);
632     }
633    
634     static char * irc_message_preformat(t_irc_message_from const * from, char const * command, char const * dest, char const * text)
635     {
636     char * myfrom;
637     char const * mydest = "";
638     char const * mytext = "";
639     int len;
640     char * msg;
641    
642     if (!command) {
643     eventlog(eventlog_level_error,__FUNCTION__,"got NULL command");
644     return NULL;
645     }
646     if (from) {
647     if ((!from->nick)||(!from->user)||(!from->host)) {
648     eventlog(eventlog_level_error,__FUNCTION__,"got malformed from");
649     return NULL;
650     }
651     myfrom = xmalloc(strlen(from->nick)+1+strlen(from->user)+1+strlen(from->host)+1); /* nick + "!" + user + "@" + host + "\0" */
652     sprintf(myfrom,"%s!%s@%s",from->nick,from->user,from->host);
653     } else
654     myfrom = xstrdup(server_get_name());
655     if (dest)
656     mydest = dest;
657     if (text)
658     mytext = text;
659    
660     len = 1+strlen(myfrom)+1+
661     strlen(command)+1+
662     strlen(mydest)+1+
663     1+strlen(mytext)+1;
664    
665    
666     msg = xmalloc(len);
667     sprintf(msg,":%s\n%s\n%s\n%s",myfrom,command,mydest,mytext);
668     xfree(myfrom);
669     return msg;
670     }
671    
672     extern int irc_message_postformat(t_packet * packet, t_connection const * dest)
673     {
674     int len;
675     /* the four elements */
676     char * e1;
677     char * e1_2;
678     char * e2;
679     char * e3;
680     char * e4;
681     char const * tname = NULL;
682     char const * toname = "AUTH"; /* fallback name */
683    
684     if (!packet) {
685     eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
686     return -1;
687     }
688     if (!dest) {
689     eventlog(eventlog_level_error,__FUNCTION__,"got NULL dest");
690     return -1;
691     }
692    
693     e1 = packet_get_raw_data(packet,0);
694     e2 = strchr(e1,'\n');
695     if (!e2) {
696     eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e2 missing)");
697     return -1;
698     }
699     *e2++ = '\0';
700     e3 = strchr(e2,'\n');
701     if (!e3) {
702     eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e3 missing)");
703     return -1;
704     }
705     *e3++ = '\0';
706     e4 = strchr(e3,'\n');
707     if (!e4) {
708     eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e4 missing)");
709     return -1;
710     }
711     *e4++ = '\0';
712    
713     if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(dest)) & command_get_group("/admin-addr")))
714     {
715     e1_2 = strchr(e1,'@');
716     if (e1_2)
717     {
718     *e1_2++ = '\0';
719     }
720     }
721     else
722     e1_2 = NULL;
723    
724     if (e3[0]=='\0') { /* fill in recipient */
725     if ((tname = conn_get_chatname(dest)))
726     toname = tname;
727     } else
728     toname = e3;
729    
730     if (strcmp(toname,"\r")==0) {
731     toname = ""; /* HACK: the target field is really empty */
732     }
733    
734     len = (strlen(e1)+1+strlen(e2)+1+strlen(toname)+1+strlen(e4)+2+1);
735     if (len<=MAX_IRC_MESSAGE_LEN) {
736     char msg[MAX_IRC_MESSAGE_LEN+1];
737    
738     if (e1_2)
739     sprintf(msg,"%s@hidden %s %s %s\r\n",e1,e2,toname,e4);
740     else
741     sprintf(msg,"%s %s %s %s\r\n",e1,e2,toname,e4);
742     eventlog(eventlog_level_debug,__FUNCTION__,"sent \"%s\"",msg);
743     packet_set_size(packet,0);
744     packet_append_data(packet,msg,strlen(msg));
745     if (tname)
746     conn_unget_chatname(dest,tname);
747     return 0;
748     } else {
749     /* FIXME: split up message? */
750     eventlog(eventlog_level_warn,__FUNCTION__,"maximum IRC message length exceeded");
751     if (tname)
752     conn_unget_chatname(dest,tname);
753     return -1;
754     }
755     }
756    
757     extern int irc_message_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags)
758     {
759     char * msg;
760     char const * ctag;
761     t_irc_message_from from;
762    
763     if (!packet)
764     {
765     eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
766     return -1;
767     }
768    
769     msg = NULL;
770     ctag = clienttag_uint_to_str(conn_get_clienttag(me));
771    
772     switch (type)
773     {
774     /* case message_type_adduser: this is sent manually in handle_irc */
775     case message_type_adduser:
776     /* when we do it somewhere else, then we can also make sure to not get our logs spammed */
777     break;
778     case message_type_join:
779     from.nick = conn_get_chatname(me);
780     from.user = ctag;
781     from.host = addr_num_to_ip_str(conn_get_addr(me));
782     msg = irc_message_preformat(&from,"JOIN","\r",irc_convert_channel(conn_get_channel(me)));
783     conn_unget_chatname(me,from.nick);
784     break;
785     case message_type_part:
786     from.nick = conn_get_chatname(me);
787     from.user = ctag;
788     from.host = addr_num_to_ip_str(conn_get_addr(me));
789     msg = irc_message_preformat(&from,"PART","\r",irc_convert_channel(conn_get_channel(me)));
790     conn_unget_chatname(me,from.nick);
791     break;
792     case message_type_talk:
793     case message_type_whisper:
794     {
795     char const * dest;
796     char temp[MAX_IRC_MESSAGE_LEN];
797     from.nick = conn_get_chatname(me);
798     from.user = ctag;
799     from.host = addr_num_to_ip_str(conn_get_addr(me));
800     if (type==message_type_talk)
801     dest = irc_convert_channel(conn_get_channel(me)); /* FIXME: support more channels and choose right one! */
802     else
803     dest = ""; /* will be replaced with username in postformat */
804     sprintf(temp,":%s",text);
805     msg = irc_message_preformat(&from,"PRIVMSG",dest,temp);
806     conn_unget_chatname(me,from.nick);
807     }
808     break;
809     case message_type_emote:
810     {
811     char const * dest;
812     char temp[MAX_IRC_MESSAGE_LEN];
813    
814     /* "\001ACTION " + text + "\001" + \0 */
815     if ((8+strlen(text)+1+1)<=MAX_IRC_MESSAGE_LEN) {
816     sprintf(temp,":\001ACTION %s\001",text);
817     } else {
818     sprintf(temp,":\001ACTION (maximum message length exceeded)\001");
819     }
820     from.nick = conn_get_chatname(me);
821     from.user = ctag;
822     from.host = addr_num_to_ip_str(conn_get_addr(me));
823     /* FIXME: also supports whisper emotes? */
824     dest = irc_convert_channel(conn_get_channel(me)); /* FIXME: support more channels and choose right one! */
825     msg = irc_message_preformat(&from,"PRIVMSG",dest,temp);
826     conn_unget_chatname(me,from.nick);
827     }
828     break;
829     case message_type_broadcast:
830     case message_type_info:
831     case message_type_error:
832     {
833     char temp[MAX_IRC_MESSAGE_LEN];
834     sprintf(temp,":%s",text);
835     msg = irc_message_preformat(NULL,"NOTICE",NULL,temp);
836     }
837     break;
838     case message_type_channel:
839     /* ignore it */
840     break;
841     case message_type_mode:
842     from.nick = conn_get_chatname(me);
843     from.user = ctag;
844     from.host = addr_num_to_ip_str(conn_get_addr(me));
845     msg = irc_message_preformat(&from,"MODE","\r",text);
846     conn_unget_chatname(me,from.nick);
847     break;
848     default:
849     eventlog(eventlog_level_warn,__FUNCTION__,"%d not yet implemented",type);
850     return -1;
851     }
852    
853     if (msg) {
854     packet_append_string(packet,msg);
855     xfree(msg);
856     return 0;
857     }
858     return -1;
859     }
860    
861     extern int irc_send_rpl_namreply(t_connection * c, t_channel const * channel)
862     {
863     char temp[MAX_IRC_MESSAGE_LEN];
864     char const * ircname;
865     int first = 1;
866     t_connection * m;
867    
868     if (!c) {
869     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
870     return -1;
871     }
872     if (!channel) {
873     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
874     return -1;
875     }
876     memset(temp,0,sizeof(temp));
877     ircname = irc_convert_channel(channel);
878     if (!ircname) {
879     eventlog(eventlog_level_error,__FUNCTION__,"channel has NULL ircname");
880     return -1;
881     }
882     /* '@' = secret; '*' = private; '=' = public */
883     if ((1+1+strlen(ircname)+2+1)<=MAX_IRC_MESSAGE_LEN) {
884     sprintf(temp,"%c %s :",((channel_get_permanent(channel))?('='):('*')),ircname);
885     } else {
886     eventlog(eventlog_level_warn,__FUNCTION__,"maximum message length exceeded");
887     return -1;
888     }
889     /* FIXME: Add per user flags (@(op) and +(voice))*/
890     for (m = channel_get_first(channel);m;m = channel_get_next()) {
891     char const * name = conn_get_chatname(m);
892     char flg[5] = "";
893     unsigned int flags;
894    
895     if (!name)
896     continue;
897     flags = conn_get_flags(m);
898     if (flags & MF_BLIZZARD)
899     strcat(flg,"@");
900     else if ((flags & MF_BNET) || (flags & MF_GAVEL))
901     strcat(flg,"%");
902     else if (flags & MF_VOICE)
903     strcat(flg,"+");
904     if ((strlen(temp)+((!first)?(1):(0))+strlen(flg)+strlen(name)+1)<=sizeof(temp)) {
905     if (!first) strcat(temp," ");
906     strcat(temp,flg);
907     strcat(temp,name);
908     first = 0;
909     }
910     conn_unget_chatname(m,name);
911     }
912     irc_send(c,RPL_NAMREPLY,temp);
913     return 0;
914     }
915    
916     static int irc_who_connection(t_connection * dest, t_connection * c)
917     {
918     t_account * a;
919     char const * tempuser;
920     char const * tempowner;
921     char const * tempname;
922     char const * tempip;
923     char const * tempflags = "@"; /* FIXME: that's dumb */
924     char temp[MAX_IRC_MESSAGE_LEN];
925     char const * tempchannel;
926    
927     if (!dest) {
928     eventlog(eventlog_level_error,__FUNCTION__,"got NULL destination");
929     return -1;
930     }
931     if (!c) {
932     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
933     return -1;
934     }
935     a = conn_get_account(c);
936     if (!(tempuser = clienttag_uint_to_str(conn_get_clienttag(c))))
937     {
938     eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag (tempuser)");
939     return -1;
940     }
941     if (!(tempowner = account_get_ll_owner(a)))
942     {
943     eventlog(eventlog_level_error,__FUNCTION__,"got NULL ll_owner (tempowner)");
944     return -1;
945     }
946     if (!(tempname = conn_get_username(c)))
947     {
948     eventlog(eventlog_level_error,__FUNCTION__,"got NULL username (tempname)");
949     return -1;
950     }
951     if (!(tempip = addr_num_to_ip_str(conn_get_addr(c))))
952     {
953     eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr (tempip)");
954     return -1;
955     }
956     if (!(tempchannel = irc_convert_channel(conn_get_channel(c))))
957     {
958     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel (tempchannel)");
959     return -1;
960     }
961     if ((strlen(tempchannel)+1+strlen(tempuser)+1+strlen(tempip)+1+strlen(server_get_name())+1+strlen(tempname)+1+1+strlen(tempflags)+4+strlen(tempowner)+1)>MAX_IRC_MESSAGE_LEN) {
962     eventlog(eventlog_level_info,__FUNCTION__,"WHO reply too long - skip");
963     return -1;
964     } else
965     sprintf(temp,"%s %s %s %s %s %c%s :0 %s",tempchannel,tempuser,tempip,server_get_name(),tempname,'H',tempflags,tempowner);
966     irc_send(dest,RPL_WHOREPLY,temp);
967     return 0;
968     }
969    
970     extern int irc_who(t_connection * c, char const * name)
971     {
972     /* FIXME: support wildcards! */
973    
974     if (!c) {
975     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
976     return -1;
977     }
978     if (!name) {
979     eventlog(eventlog_level_error,__FUNCTION__,"got NULL name");
980     return -1;
981     }
982     if ((name[0]=='#')||(name[0]=='&')||(name[0]=='!')) {
983     /* it's a channel */
984     t_connection * info;
985     t_channel * channel;
986     char const * ircname;
987    
988     ircname = irc_convert_ircname(name);
989     channel = channellist_find_channel_by_name(ircname,NULL,NULL);
990     if (!channel) {
991     char temp[MAX_IRC_MESSAGE_LEN];
992    
993     if ((strlen(":No such channel")+1+strlen(name)+1)<=MAX_IRC_MESSAGE_LEN) {
994     sprintf(temp,":No such channel %s",name);
995     irc_send(c,ERR_NOSUCHCHANNEL,temp);
996     } else {
997     irc_send(c,ERR_NOSUCHCHANNEL,":No such channel");
998     }
999     return 0;
1000     }
1001     for (info = channel_get_first(channel);info;info = channel_get_next()) {
1002     irc_who_connection(c,info);
1003     }
1004     } else {
1005     /* it's just one user */
1006     t_connection * info;
1007    
1008     if ((info = connlist_find_connection_by_accountname(name)))
1009     return irc_who_connection(c,info);
1010     }
1011     return 0;
1012     }
1013    

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