2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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.
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
18 * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
19 * based on Dante source code
20 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
21 * Inferno Nettverk A/S, Norway. All rights reserved.
24 /*#define DEBUG_MSPROXY*/
55 #include "proto-irc.h"
60 #include <openssl/ssl.h> /* SSL_() */
61 #include <openssl/err.h> /* ERR_() */
78 extern SSL_CTX
*ctx
; /* xchat.c */
80 static struct session
*g_sess
= NULL
;
83 static GSList
*away_list
= NULL
;
84 GSList
*serv_list
= NULL
;
86 static void auto_reconnect (server
*serv
, int send_quit
, int err
);
87 static void server_disconnect (session
* sess
, int sendquit
, int err
);
88 static int server_cleanup (server
* serv
);
89 static void server_connect (server
*serv
, char *hostname
, int port
, int no_login
);
92 extern pxProxyFactory
*libproxy_factory
;
95 /* actually send to the socket. This might do a character translation or
96 send via SSL. server/dcc both use this function. */
99 tcp_send_real (void *ssl
, int sok
, char *encoding
, int using_irc
, char *buf
, int len
)
105 if (encoding
== NULL
) /* system */
108 if (!prefs
.utf8_locale
)
110 const gchar
*charset
;
112 g_get_charset (&charset
);
113 locale
= g_convert_with_fallback (buf
, len
, charset
, "UTF-8",
114 "?", 0, &loc_len
, 0);
118 if (using_irc
) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
119 /* if all chars fit inside CP1252, use that. Otherwise this
120 returns NULL and we send UTF-8. */
121 locale
= g_convert (buf
, len
, "CP1252", "UTF-8", 0, &loc_len
, 0);
123 locale
= g_convert_with_fallback (buf
, len
, encoding
, "UTF-8",
124 "?", 0, &loc_len
, 0);
132 ret
= send (sok
, locale
, len
, 0);
134 ret
= _SSL_send (ssl
, locale
, len
);
136 ret
= send (sok
, locale
, len
, 0);
143 ret
= send (sok
, buf
, len
, 0);
145 ret
= _SSL_send (ssl
, buf
, len
);
147 ret
= send (sok
, buf
, len
, 0);
155 server_send_real (server
*serv
, char *buf
, int len
)
157 fe_add_rawlog (serv
, buf
, len
, TRUE
);
159 return tcp_send_real (serv
->ssl
, serv
->sok
, serv
->encoding
, serv
->using_irc
,
163 /* new throttling system, uses the same method as the Undernet
164 ircu2.10 server; under test, a 200-line paste didn't flood
168 tcp_send_queue (server
*serv
)
173 time_t now
= time (0);
175 /* did the server close since the timeout was added? */
176 if (!is_server (serv
))
179 /* try priority 2,1,0 */
183 list
= serv
->outbound_queue
;
186 buf
= (char *) list
->data
;
189 buf
++; /* skip the priority byte */
192 if (serv
->next_send
< now
)
193 serv
->next_send
= now
;
194 if (serv
->next_send
- now
>= 10)
196 /* check for clock skew */
197 if (now
>= serv
->prev_now
)
198 return 1; /* don't remove the timeout handler */
199 /* it is skewed, reset to something sane */
200 serv
->next_send
= now
;
203 for (p
= buf
, i
= len
; i
&& *p
!= ' '; p
++, i
--);
204 serv
->next_send
+= (2 + i
/ 120);
205 serv
->sendq_len
-= len
;
206 serv
->prev_now
= now
;
207 fe_set_throttle (serv
);
209 server_send_real (serv
, buf
, len
);
212 serv
->outbound_queue
= g_slist_remove (serv
->outbound_queue
, buf
);
214 list
= serv
->outbound_queue
;
223 return 0; /* remove the timeout handler */
227 tcp_send_len (server
*serv
, char *buf
, int len
)
230 int noqueue
= !serv
->outbound_queue
;
233 return server_send_real (serv
, buf
, len
);
235 dbuf
= malloc (len
+ 2); /* first byte is the priority */
236 dbuf
[0] = 2; /* pri 2 for most things */
237 memcpy (dbuf
+ 1, buf
, len
);
240 /* privmsg and notice get a lower priority */
241 if (strncasecmp (dbuf
+ 1, "PRIVMSG", 7) == 0 ||
242 strncasecmp (dbuf
+ 1, "NOTICE", 6) == 0)
248 /* WHO/MODE get the lowest priority */
249 if (strncasecmp (dbuf
+ 1, "WHO ", 4) == 0 ||
250 /* but only MODE queries, not changes */
251 (strncasecmp (dbuf
+ 1, "MODE", 4) == 0 &&
252 strchr (dbuf
, '-') == NULL
&&
253 strchr (dbuf
, '+') == NULL
))
257 serv
->outbound_queue
= g_slist_append (serv
->outbound_queue
, dbuf
);
258 serv
->sendq_len
+= len
; /* tcp_send_queue uses strlen */
260 if (tcp_send_queue (serv
) && noqueue
)
261 fe_timeout_add (500, tcp_send_queue
, serv
);
267 tcp_send (server *serv, char *buf)
269 return tcp_send_len (serv, buf, strlen (buf));
273 tcp_sendf (server
*serv
, char *fmt
, ...)
276 /* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
277 string shorter, so allow alot more than 512 for now. */
278 static char send_buf
[1540]; /* good code hey (no it's not overflowable) */
281 va_start (args
, fmt
);
282 len
= vsnprintf (send_buf
, sizeof (send_buf
) - 1, fmt
, args
);
285 send_buf
[sizeof (send_buf
) - 1] = '\0';
286 if (len
< 0 || len
> (sizeof (send_buf
) - 1))
287 len
= strlen (send_buf
);
289 tcp_send_len (serv
, send_buf
, len
);
293 close_socket_cb (gpointer sok
)
295 closesocket (GPOINTER_TO_INT (sok
));
300 close_socket (int sok
)
302 /* close the socket in 5 seconds so the QUIT message is not lost */
303 fe_timeout_add (5000, close_socket_cb
, GINT_TO_POINTER (sok
));
306 /* handle 1 line of text received from the server */
309 server_inline (server
*serv
, char *line
, int len
)
311 char *utf_line_allocated
= NULL
;
313 /* Checks whether we're set to use UTF-8 charset */
314 if (serv
->using_irc
|| /* 1. using CP1252/UTF-8 Hybrid */
315 (serv
->encoding
== NULL
&& prefs
.utf8_locale
) || /* OR 2. using system default->UTF-8 */
316 (serv
->encoding
!= NULL
&& /* OR 3. explicitly set to UTF-8 */
317 (strcasecmp (serv
->encoding
, "UTF8") == 0 ||
318 strcasecmp (serv
->encoding
, "UTF-8") == 0)))
320 /* The user has the UTF-8 charset set, either via /charset
321 command or from his UTF-8 locale. Thus, we first try the
322 UTF-8 charset, and if we fail to convert, we assume
323 it to be ISO-8859-1 (see text_validate). */
325 utf_line_allocated
= text_validate (&line
, &len
);
329 /* Since the user has an explicit charset set, either
330 via /charset command or from his non-UTF8 locale,
331 we don't fallback to ISO-8859-1 and instead try to remove
332 errnoeous octets till the string is convertable in the
335 const char *encoding
= NULL
;
337 if (serv
->encoding
!= NULL
)
338 encoding
= serv
->encoding
;
340 g_get_charset (&encoding
);
342 if (encoding
!= NULL
)
344 char *conv_line
; /* holds a copy of the original string */
345 int conv_len
; /* tells g_convert how much of line to convert */
351 conv_line
= g_malloc (len
+ 1);
352 memcpy (conv_line
, line
, len
);
356 /* if CP1255, convert it with the NUL terminator.
357 Works around SF bug #1122089 */
358 if (serv
->using_cp1255
)
365 utf_line_allocated
= g_convert_with_fallback (conv_line
, conv_len
, "UTF-8", encoding
, "?", &read_len
, &utf_len
, &err
);
368 if (err
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
&& conv_len
> (read_len
+ 1))
370 /* Make our best bet by removing the erroneous char.
371 This will work for casual 8-bit strings with non-standard chars. */
372 memmove (conv_line
+ read_len
, conv_line
+ read_len
+ 1, conv_len
- read_len
-1);
382 /* If any conversion has occured at all. Conversion might fail
383 due to errors other than invalid sequences, e.g. unknown charset. */
384 if (utf_line_allocated
!= NULL
)
386 line
= utf_line_allocated
;
388 if (serv
->using_cp1255
&& len
> 0)
393 /* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
394 utf_line_allocated
= text_validate (&line
, &len
);
399 fe_add_rawlog (serv
, line
, len
, FALSE
);
401 /* let proto-irc.c handle it */
402 serv
->p_inline (serv
, line
, len
);
404 if (utf_line_allocated
!= NULL
) /* only if a special copy was allocated */
405 g_free (utf_line_allocated
);
408 /* read data from socket */
411 server_read (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
422 len
= recv (sok
, lbuf
, sizeof (lbuf
) - 2, 0);
425 len
= _SSL_recv (serv
->ssl
, lbuf
, sizeof (lbuf
) - 2);
434 error
= sock_error ();
436 if (!serv
->end_of_motd
)
438 server_disconnect (serv
->server_session
, FALSE
, error
);
439 if (!servlist_cycle (serv
))
441 if (prefs
.autoreconnect
)
442 auto_reconnect (serv
, FALSE
, error
);
446 if (prefs
.autoreconnect
)
447 auto_reconnect (serv
, FALSE
, error
);
449 server_disconnect (serv
->server_session
, FALSE
, error
);
466 serv
->linebuf
[serv
->pos
] = 0;
467 server_inline (serv
, serv
->linebuf
, serv
->pos
);
472 serv
->linebuf
[serv
->pos
] = lbuf
[i
];
473 if (serv
->pos
>= (sizeof (serv
->linebuf
) - 1))
475 "*** XCHAT WARNING: Buffer overflow - shit server!\n");
485 server_connected (server
* serv
)
487 prefs
.wait_on_exit
= TRUE
;
488 serv
->ping_recv
= time (0);
489 serv
->connected
= TRUE
;
490 set_nonblocking (serv
->sok
);
491 serv
->iotag
= fe_input_add (serv
->sok
, FIA_READ
|FIA_EX
, server_read
, serv
);
494 EMIT_SIGNAL (XP_TE_CONNECTED
, serv
->server_session
, NULL
, NULL
, NULL
,
499 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
500 (((ircnet
*)serv
->network
)->user
)) ?
501 (((ircnet
*)serv
->network
)->user
) :
503 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
504 (((ircnet
*)serv
->network
)->real
)) ?
505 (((ircnet
*)serv
->network
)->real
) :
509 serv
->p_login (serv
, prefs
.username
, prefs
.realname
);
513 EMIT_SIGNAL (XP_TE_SERVERCONNECTED
, serv
->server_session
, NULL
, NULL
,
517 server_set_name (serv
, serv
->servername
);
518 fe_server_event (serv
, FE_SE_CONNECT
, 0);
524 server_close_pipe (int *pipefd
) /* see comments below */
526 close (pipefd
[0]); /* close WRITE end first to cause an EOF on READ */
527 close (pipefd
[1]); /* in giowin32, and end that thread. */
535 server_stopconnecting (server
* serv
)
539 fe_input_remove (serv
->iotag
);
543 if (serv
->joindelay_tag
)
545 fe_timeout_remove (serv
->joindelay_tag
);
546 serv
->joindelay_tag
= 0;
550 /* kill the child process trying to connect */
551 kill (serv
->childpid
, SIGKILL
);
552 waitpid (serv
->childpid
, NULL
, 0);
554 close (serv
->childwrite
);
555 close (serv
->childread
);
557 PostThreadMessage (serv
->childpid
, WM_QUIT
, 0, 0);
560 /* if we close the pipe now, giowin32 will crash. */
561 int *pipefd
= malloc (sizeof (int) * 2);
562 pipefd
[0] = serv
->childwrite
;
563 pipefd
[1] = serv
->childread
;
564 g_idle_add ((GSourceFunc
)server_close_pipe
, pipefd
);
569 if (serv
->ssl_do_connect_tag
)
571 fe_timeout_remove (serv
->ssl_do_connect_tag
);
572 serv
->ssl_do_connect_tag
= 0;
576 fe_progressbar_end (serv
);
578 serv
->connecting
= FALSE
;
579 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
583 #define SSLTMOUT 90 /* seconds */
585 ssl_cb_info (SSL
* s
, int where
, int ret
)
590 return; /* FIXME: make debug level adjustable in serverlist or settings */
592 /* snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
594 EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
596 fprintf (stderr, "%s\n", buf);*/
600 ssl_cb_verify (int ok
, X509_STORE_CTX
* ctx
)
607 X509_NAME_oneline (X509_get_subject_name (ctx
->current_cert
), subject
,
609 X509_NAME_oneline (X509_get_issuer_name (ctx
->current_cert
), issuer
,
612 snprintf (buf
, sizeof (buf
), "* Subject: %s", subject
);
613 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
614 snprintf (buf
, sizeof (buf
), "* Issuer: %s", issuer
);
615 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
617 return (TRUE
); /* always ok */
621 ssl_do_connect (server
* serv
)
625 g_sess
= serv
->server_session
;
626 if (SSL_connect (serv
->ssl
) <= 0)
632 if ((err
= ERR_get_error ()) > 0)
634 ERR_error_string (err
, err_buf
);
635 snprintf (buf
, sizeof (buf
), "(%d) %s", err
, err_buf
);
636 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
639 if (ERR_GET_REASON (err
) == SSL_R_WRONG_VERSION_NUMBER
)
640 PrintText (serv
->server_session
, _("Are you sure this is a SSL capable server and port?\n"));
642 server_cleanup (serv
);
644 if (prefs
.autoreconnectonfail
)
645 auto_reconnect (serv
, FALSE
, -1);
647 return (0); /* remove it (0) */
652 if (SSL_is_init_finished (serv
->ssl
))
654 struct cert_info cert_info
;
655 struct chiper_info
*chiper_info
;
659 if (!_SSL_get_cert_info (&cert_info
, serv
->ssl
))
661 snprintf (buf
, sizeof (buf
), "* Certification info:");
662 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
664 snprintf (buf
, sizeof (buf
), " Subject:");
665 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
667 for (i
= 0; cert_info
.subject_word
[i
]; i
++)
669 snprintf (buf
, sizeof (buf
), " %s", cert_info
.subject_word
[i
]);
670 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
673 snprintf (buf
, sizeof (buf
), " Issuer:");
674 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
676 for (i
= 0; cert_info
.issuer_word
[i
]; i
++)
678 snprintf (buf
, sizeof (buf
), " %s", cert_info
.issuer_word
[i
]);
679 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
682 snprintf (buf
, sizeof (buf
), " Public key algorithm: %s (%d bits)",
683 cert_info
.algorithm
, cert_info
.algorithm_bits
);
684 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
686 /*if (cert_info.rsa_tmp_bits)
688 snprintf (buf, sizeof (buf),
689 " Public key algorithm uses ephemeral key with %d bits",
690 cert_info.rsa_tmp_bits);
691 EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
694 snprintf (buf
, sizeof (buf
), " Sign algorithm %s",
695 cert_info
.sign_algorithm
/*, cert_info.sign_algorithm_bits*/);
696 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
698 snprintf (buf
, sizeof (buf
), " Valid since %s to %s",
699 cert_info
.notbefore
, cert_info
.notafter
);
700 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
704 snprintf (buf
, sizeof (buf
), " * No Certificate");
705 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
709 chiper_info
= _SSL_get_cipher_info (serv
->ssl
); /* static buffer */
710 snprintf (buf
, sizeof (buf
), "* Cipher info:");
711 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
713 snprintf (buf
, sizeof (buf
), " Version: %s, cipher %s (%u bits)",
714 chiper_info
->version
, chiper_info
->chiper
,
715 chiper_info
->chiper_bits
);
716 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
719 verify_error
= SSL_get_verify_result (serv
->ssl
);
720 switch (verify_error
)
723 /* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
724 /* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
726 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
727 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
:
728 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
729 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
730 case X509_V_ERR_CERT_HAS_EXPIRED
:
731 case X509_V_ERR_CERT_UNTRUSTED
:
732 if (serv
->accept_invalid_cert
)
734 snprintf (buf
, sizeof (buf
), "* Verify E: %s.? (%d) -- Ignored",
735 X509_verify_cert_error_string (verify_error
),
737 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
742 snprintf (buf
, sizeof (buf
), "%s.? (%d)",
743 X509_verify_cert_error_string (verify_error
),
745 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
, NULL
,
748 server_cleanup (serv
);
753 server_stopconnecting (serv
);
755 /* activate gtk poll */
756 server_connected (serv
);
758 return (0); /* remove it (0) */
761 if (serv
->ssl
->session
&& serv
->ssl
->session
->time
+ SSLTMOUT
< time (NULL
))
763 snprintf (buf
, sizeof (buf
), "SSL handshake timed out");
764 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
766 server_cleanup (serv
); /* ->connecting = FALSE */
768 if (prefs
.autoreconnectonfail
)
769 auto_reconnect (serv
, FALSE
, -1);
771 return (0); /* remove it (0) */
774 return (1); /* call it more (1) */
780 timeout_auto_reconnect (server
*serv
)
782 if (is_server (serv
)) /* make sure it hasnt been closed during the delay */
784 serv
->recondelay_tag
= 0;
785 if (!serv
->connected
&& !serv
->connecting
&& serv
->server_session
)
787 server_connect (serv
, serv
->hostname
, serv
->port
, FALSE
);
790 return 0; /* returning 0 should remove the timeout handler */
794 auto_reconnect (server
*serv
, int send_quit
, int err
)
800 if (serv
->server_session
== NULL
)
804 while (list
) /* make sure auto rejoin can work */
807 if (s
->type
== SESS_CHANNEL
&& s
->channel
[0])
809 strcpy (s
->waitchannel
, s
->channel
);
810 strcpy (s
->willjoinchannel
, s
->channel
);
816 server_disconnect (serv
->server_session
, send_quit
, err
);
818 del
= prefs
.recon_delay
* 1000;
820 del
= 500; /* so it doesn't block the gui */
823 if (err
== -1 || err
== 0 || err
== ECONNRESET
|| err
== ETIMEDOUT
)
825 if (err
== -1 || err
== 0 || err
== WSAECONNRESET
|| err
== WSAETIMEDOUT
)
827 serv
->reconnect_away
= serv
->is_away
;
829 /* is this server in a reconnect delay? remove it! */
830 if (serv
->recondelay_tag
)
832 fe_timeout_remove (serv
->recondelay_tag
);
833 serv
->recondelay_tag
= 0;
836 serv
->recondelay_tag
= fe_timeout_add (del
, timeout_auto_reconnect
, serv
);
837 fe_server_event (serv
, FE_SE_RECONDELAY
, del
);
841 server_flush_queue (server
*serv
)
843 list_free (&serv
->outbound_queue
);
845 fe_set_throttle (serv
);
848 #define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
850 /* connect() successed */
853 server_connect_success (server
*serv
)
856 #define SSLDOCONNTMOUT 300
861 /* it'll be a memory leak, if connection isn't terminated by
863 serv
->ssl
= _SSL_socket (ctx
, serv
->sok
);
864 if ((err
= _SSL_set_verify (ctx
, ssl_cb_verify
, NULL
)) && !serv
->accept_invalid_cert
)
866 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, err
, NULL
,
868 server_cleanup (serv
); /* ->connecting = FALSE */
871 /* FIXME: it'll be needed by new servers */
872 /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
873 set_nonblocking (serv
->sok
);
874 serv
->ssl_do_connect_tag
= fe_timeout_add (SSLDOCONNTMOUT
,
875 ssl_do_connect
, serv
);
881 server_stopconnecting (serv
); /* ->connecting = FALSE */
882 /* activate glib poll */
883 server_connected (serv
);
886 /* receive info from the child-process about connection progress */
889 server_read_child (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
891 session
*sess
= serv
->server_session
;
898 waitline2 (source
, tbuf
, sizeof tbuf
);
902 case '0': /* print some text */
903 waitline2 (source
, tbuf
, sizeof tbuf
);
904 PrintText (serv
->server_session
, tbuf
);
906 case '1': /* unknown host */
907 server_stopconnecting (serv
);
908 closesocket (serv
->sok4
);
909 if (serv
->proxy_sok4
!= -1)
910 closesocket (serv
->proxy_sok4
);
912 if (serv
->sok6
!= -1)
913 closesocket (serv
->sok6
);
914 if (serv
->proxy_sok6
!= -1)
915 closesocket (serv
->proxy_sok6
);
917 EMIT_SIGNAL (XP_TE_UKNHOST
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
918 if (!servlist_cycle (serv
))
919 if (prefs
.autoreconnectonfail
)
920 auto_reconnect (serv
, FALSE
, -1);
922 case '2': /* connection failed */
923 waitline2 (source
, tbuf
, sizeof tbuf
);
924 server_stopconnecting (serv
);
925 closesocket (serv
->sok4
);
926 if (serv
->proxy_sok4
!= -1)
927 closesocket (serv
->proxy_sok4
);
929 if (serv
->sok6
!= -1)
930 closesocket (serv
->sok6
);
931 if (serv
->proxy_sok6
!= -1)
932 closesocket (serv
->proxy_sok6
);
934 EMIT_SIGNAL (XP_TE_CONNFAIL
, sess
, errorstring (atoi (tbuf
)), NULL
,
936 if (!servlist_cycle (serv
))
937 if (prefs
.autoreconnectonfail
)
938 auto_reconnect (serv
, FALSE
, -1);
940 case '3': /* gethostbyname finished */
941 waitline2 (source
, host
, sizeof host
);
942 waitline2 (source
, ip
, sizeof ip
);
943 waitline2 (source
, outbuf
, sizeof outbuf
);
944 EMIT_SIGNAL (XP_TE_CONNECT
, sess
, host
, ip
, outbuf
, NULL
, 0);
949 identd_start ((((ircnet
*)serv
->network
)->user
) ?
950 (((ircnet
*)serv
->network
)->user
) :
953 identd_start (prefs
.username
);
956 snprintf (outbuf
, sizeof (outbuf
), "%s/auth/xchat_auth",
958 if (access (outbuf
, X_OK
) == 0)
960 snprintf (outbuf
, sizeof (outbuf
), "exec -d %s/auth/xchat_auth %s",
961 g_get_home_dir (), prefs
.username
);
962 handle_command (serv
->server_session
, outbuf
, FALSE
);
966 case '4': /* success */
967 waitline2 (source
, tbuf
, sizeof (tbuf
));
969 serv
->sok
= strtol (tbuf
, &p
, 10);
972 serv
->proxy_sok
= strtol (p
, &p
, 10);
973 serv
->msp_state
.clientid
= strtol (++p
, &p
, 10);
974 serv
->msp_state
.serverid
= strtol (++p
, &p
, 10);
975 serv
->msp_state
.seq_sent
= atoi (++p
);
977 serv
->proxy_sok
= -1;
979 printf ("Parent got main socket: %d, proxy socket: %d\n", serv
->sok
, serv
->proxy_sok
);
980 printf ("Client ID 0x%08x server ID 0x%08x seq_sent %d\n", serv
->msp_state
.clientid
, serv
->msp_state
.serverid
, serv
->msp_state
.seq_sent
);
983 serv
->sok
= atoi (tbuf
);
986 /* close the one we didn't end up using */
987 if (serv
->sok
== serv
->sok4
)
988 closesocket (serv
->sok6
);
990 closesocket (serv
->sok4
);
991 if (serv
->proxy_sok
!= -1)
993 if (serv
->proxy_sok
== serv
->proxy_sok4
)
994 closesocket (serv
->proxy_sok6
);
996 closesocket (serv
->proxy_sok4
);
999 server_connect_success (serv
);
1001 case '5': /* prefs ip discovered */
1002 waitline2 (source
, tbuf
, sizeof tbuf
);
1003 prefs
.local_ip
= inet_addr (tbuf
);
1005 case '7': /* gethostbyname (prefs.hostname) failed */
1007 _("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
1009 PrintText (sess
, outbuf
);
1012 PrintText (sess
, _("Proxy traversal failed.\n"));
1013 server_disconnect (sess
, FALSE
, -1);
1016 waitline2 (source
, tbuf
, sizeof tbuf
);
1017 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
1024 /* kill all sockets & iotags of a server. Stop a connection attempt, or
1025 disconnect if already connected. */
1028 server_cleanup (server
* serv
)
1030 fe_set_lag (serv
, 0.0);
1034 fe_input_remove (serv
->iotag
);
1038 if (serv
->joindelay_tag
)
1040 fe_timeout_remove (serv
->joindelay_tag
);
1041 serv
->joindelay_tag
= 0;
1047 _SSL_close (serv
->ssl
);
1052 if (serv
->connecting
)
1054 server_stopconnecting (serv
);
1055 closesocket (serv
->sok4
);
1056 if (serv
->proxy_sok4
!= -1)
1057 closesocket (serv
->proxy_sok4
);
1058 if (serv
->sok6
!= -1)
1059 closesocket (serv
->sok6
);
1060 if (serv
->proxy_sok6
!= -1)
1061 closesocket (serv
->proxy_sok6
);
1065 if (serv
->connected
)
1067 close_socket (serv
->sok
);
1068 if (serv
->proxy_sok
)
1069 close_socket (serv
->proxy_sok
);
1070 serv
->connected
= FALSE
;
1071 serv
->end_of_motd
= FALSE
;
1075 /* is this server in a reconnect delay? remove it! */
1076 if (serv
->recondelay_tag
)
1078 fe_timeout_remove (serv
->recondelay_tag
);
1079 serv
->recondelay_tag
= 0;
1087 server_disconnect (session
* sess
, int sendquit
, int err
)
1089 server
*serv
= sess
->server
;
1092 gboolean shutup
= FALSE
;
1094 /* send our QUIT reason */
1095 if (sendquit
&& serv
->connected
)
1097 server_sendquit (sess
);
1100 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
1102 /* close all sockets & io tags */
1103 switch (server_cleanup (serv
))
1105 case 0: /* it wasn't even connected! */
1108 case 1: /* it was in the process of connecting */
1109 sprintf (tbuf
, "%d", sess
->server
->childpid
);
1110 EMIT_SIGNAL (XP_TE_STOPCONNECT
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
1113 shutup
= TRUE
; /* won't print "disconnected" in channels */
1116 server_flush_queue (serv
);
1121 sess
= (struct session
*) list
->data
;
1122 if (sess
->server
== serv
)
1124 if (!shutup
|| sess
->type
== SESS_SERVER
)
1125 /* print "Disconnected" to each window using this server */
1126 EMIT_SIGNAL (XP_TE_DISCON
, sess
, errorstring (err
), NULL
, NULL
, NULL
, 0);
1128 if (!sess
->channel
[0] || sess
->type
== SESS_CHANNEL
)
1129 clear_channel (sess
);
1135 serv
->motd_skipped
= FALSE
;
1136 serv
->no_login
= FALSE
;
1137 serv
->servername
[0] = 0;
1143 /* send a "print text" command to the parent process - MUST END IN \n! */
1146 proxy_error (int fd
, char *msg
)
1148 write (fd
, "0\n", 2);
1149 write (fd
, msg
, strlen (msg
));
1161 /* traverse_socks() returns:
1163 * 1 socks traversal failed */
1166 traverse_socks (int print_fd
, int sok
, char *serverAddr
, int port
)
1168 struct sock_connect sc
;
1169 unsigned char buf
[256];
1173 sc
.port
= htons (port
);
1174 sc
.address
= inet_addr (serverAddr
);
1175 strncpy (sc
.username
, prefs
.username
, 9);
1177 send (sok
, (char *) &sc
, 8 + strlen (sc
.username
) + 1, 0);
1179 recv (sok
, buf
, 10, 0);
1183 snprintf (buf
, sizeof (buf
), "SOCKS\tServer reported error %d,%d.\n", buf
[0], buf
[1]);
1184 proxy_error (print_fd
, buf
);
1188 struct sock5_connect1
1196 traverse_socks5 (int print_fd
, int sok
, char *serverAddr
, int port
)
1198 struct sock5_connect1 sc1
;
1200 unsigned int packetlen
, addrlen
;
1201 unsigned char buf
[260];
1202 int auth
= prefs
.proxy_auth
&& prefs
.proxy_user
[0] && prefs
.proxy_pass
[0];
1207 sc1
.method
= 2; /* Username/Password Authentication (UPA) */
1209 sc1
.method
= 0; /* NO Authentication */
1210 send (sok
, (char *) &sc1
, 3, 0);
1211 if (recv (sok
, buf
, 2, 0) != 2)
1216 proxy_error (print_fd
, "SOCKS\tServer is not socks version 5.\n");
1220 /* did the server say no auth required? */
1226 int len_u
=0, len_p
=0;
1228 /* authentication sub-negotiation (RFC1929) */
1229 if (buf
[1] != 2) /* UPA not supported by server */
1231 proxy_error (print_fd
, "SOCKS\tServer doesn't support UPA authentication.\n");
1235 memset (buf
, 0, sizeof(buf
));
1237 /* form the UPA request */
1238 len_u
= strlen (prefs
.proxy_user
);
1239 len_p
= strlen (prefs
.proxy_pass
);
1242 memcpy (buf
+ 2, prefs
.proxy_user
, len_u
);
1243 buf
[2 + len_u
] = len_p
;
1244 memcpy (buf
+ 3 + len_u
, prefs
.proxy_pass
, len_p
);
1246 send (sok
, buf
, 3 + len_u
+ len_p
, 0);
1247 if ( recv (sok
, buf
, 2, 0) != 2 )
1251 proxy_error (print_fd
, "SOCKS\tAuthentication failed. "
1252 "Is username and password correct?\n");
1253 return 1; /* UPA failed! */
1260 proxy_error (print_fd
, "SOCKS\tAuthentication required but disabled in settings.\n");
1265 addrlen
= strlen (serverAddr
);
1266 packetlen
= 4 + 1 + addrlen
+ 2;
1267 sc2
= malloc (packetlen
);
1268 sc2
[0] = 5; /* version */
1269 sc2
[1] = 1; /* command */
1270 sc2
[2] = 0; /* reserved */
1271 sc2
[3] = 3; /* address type */
1272 sc2
[4] = (unsigned char) addrlen
; /* hostname length */
1273 memcpy (sc2
+ 5, serverAddr
, addrlen
);
1274 *((unsigned short *) (sc2
+ 5 + addrlen
)) = htons (port
);
1275 send (sok
, sc2
, packetlen
, 0);
1278 /* consume all of the reply */
1279 if (recv (sok
, buf
, 4, 0) != 4)
1281 if (buf
[0] != 5 || buf
[1] != 0)
1284 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy refused to connect to host (not allowed).\n");
1286 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy failed to connect to host (error %d).\n", buf
[1]);
1287 proxy_error (print_fd
, buf
);
1290 if (buf
[3] == 1) /* IPV4 32bit address */
1292 if (recv (sok
, buf
, 6, 0) != 6)
1294 } else if (buf
[3] == 4) /* IPV6 128bit address */
1296 if (recv (sok
, buf
, 18, 0) != 18)
1298 } else if (buf
[3] == 3) /* string, 1st byte is size */
1300 if (recv (sok
, buf
, 1, 0) != 1) /* read the string size */
1302 packetlen
= buf
[0] + 2; /* can't exceed 260 */
1303 if (recv (sok
, buf
, packetlen
, 0) != packetlen
)
1307 return 0; /* success */
1310 proxy_error (print_fd
, "SOCKS\tRead error from server.\n");
1315 traverse_wingate (int print_fd
, int sok
, char *serverAddr
, int port
)
1319 snprintf (buf
, sizeof (buf
), "%s %d\r\n", serverAddr
, port
);
1320 send (sok
, buf
, strlen (buf
), 0);
1325 /* stuff for HTTP auth is here */
1328 three_to_four (char *from
, char *to
)
1330 static const char tab64
[64]=
1332 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1333 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1334 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1335 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1338 to
[0] = tab64
[ (from
[0] >> 2) & 63 ];
1339 to
[1] = tab64
[ ((from
[0] << 4) | (from
[1] >> 4)) & 63 ];
1340 to
[2] = tab64
[ ((from
[1] << 2) | (from
[2] >> 6)) & 63 ];
1341 to
[3] = tab64
[ from
[2] & 63 ];
1345 base64_encode (char *to
, char *from
, unsigned int len
)
1349 three_to_four (from
, to
);
1356 char three
[3]={0,0,0};
1360 three_to_four (three
, to
);
1362 to
[2] = to
[3] = '=';
1371 http_read_line (int print_fd
, int sok
, char *buf
, int len
)
1374 /* make sure waitline() uses recv() or it'll fail on win32 */
1375 len
= waitline (sok
, buf
, len
, FALSE
);
1377 len
= waitline (sok
, buf
, len
, TRUE
);
1381 /* print the message out (send it to the parent process) */
1382 write (print_fd
, "0\n", 2);
1384 if (buf
[len
-1] == '\r')
1387 write (print_fd
, buf
, len
);
1390 write (print_fd
, buf
, len
);
1391 write (print_fd
, "\n", 1);
1399 traverse_http (int print_fd
, int sok
, char *serverAddr
, int port
)
1402 char auth_data
[256];
1403 char auth_data2
[252];
1406 n
= snprintf (buf
, sizeof (buf
), "CONNECT %s:%d HTTP/1.0\r\n",
1408 if (prefs
.proxy_auth
)
1410 n2
= snprintf (auth_data2
, sizeof (auth_data2
), "%s:%s",
1411 prefs
.proxy_user
, prefs
.proxy_pass
);
1412 base64_encode (auth_data
, auth_data2
, n2
);
1413 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "Proxy-Authorization: Basic %s\r\n", auth_data
);
1415 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "\r\n");
1416 send (sok
, buf
, n
, 0);
1418 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1419 /* "HTTP/1.0 200 OK" */
1422 if (memcmp (buf
, "HTTP/", 5) || memcmp (buf
+ 9, "200", 3))
1426 /* read until blank line */
1427 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1428 if (n
< 1 || (n
== 1 && buf
[0] == '\n'))
1435 traverse_proxy (int proxy_type
, int print_fd
, int sok
, char *ip
, int port
, struct msproxy_state_t
*state
, netstore
*ns_proxy
, int csok4
, int csok6
, int *csok
, char bound
)
1440 return traverse_wingate (print_fd
, sok
, ip
, port
);
1442 return traverse_socks (print_fd
, sok
, ip
, port
);
1444 return traverse_socks5 (print_fd
, sok
, ip
, port
);
1446 return traverse_http (print_fd
, sok
, ip
, port
);
1449 return traverse_msproxy (sok
, ip
, port
, state
, ns_proxy
, csok4
, csok6
, csok
, bound
);
1456 /* this is the child process making the connection attempt */
1459 server_child (server
* serv
)
1461 netstore
*ns_server
;
1462 netstore
*ns_proxy
= NULL
;
1464 int port
= serv
->port
;
1467 char *hostname
= serv
->hostname
;
1468 char *real_hostname
= NULL
;
1470 char *proxy_ip
= NULL
;
1476 char *proxy_host
= NULL
;
1479 ns_server
= net_store_new ();
1481 /* is a hostname set? - bind to it */
1482 if (prefs
.hostname
[0])
1484 ns_local
= net_store_new ();
1485 local_ip
= net_resolve (ns_local
, prefs
.hostname
, 0, &real_hostname
);
1486 if (local_ip
!= NULL
)
1488 snprintf (buf
, sizeof (buf
), "5\n%s\n", local_ip
);
1489 write (serv
->childwrite
, buf
, strlen (buf
));
1490 net_bind (ns_local
, serv
->sok4
, serv
->sok6
);
1494 write (serv
->childwrite
, "7\n", 2);
1496 net_store_destroy (ns_local
);
1499 if (!serv
->dont_use_proxy
) /* blocked in serverlist? */
1504 else if (prefs
.proxy_type
== 5)
1509 url
= g_strdup_printf ("irc://%s:%d", hostname
, port
);
1510 proxy_list
= px_proxy_factory_get_proxies (libproxy_factory
, url
);
1513 /* can use only one */
1514 proxy
= proxy_list
[0];
1515 if (!strncmp (proxy
, "direct", 6))
1517 else if (!strncmp (proxy
, "http", 4))
1519 else if (!strncmp (proxy
, "socks5", 6))
1521 else if (!strncmp (proxy
, "socks", 5))
1527 c
= strchr (proxy
, ':') + 3;
1528 proxy_host
= strdup (c
);
1529 c
= strchr (proxy_host
, ':');
1531 proxy_port
= atoi (c
+ 1);
1534 g_strfreev (proxy_list
);
1538 else if (prefs
.proxy_host
[0] &&
1539 prefs
.proxy_type
> 0 &&
1540 prefs
.proxy_use
!= 2) /* proxy is NOT dcc-only */
1542 proxy_type
= prefs
.proxy_type
;
1543 proxy_host
= strdup (prefs
.proxy_host
);
1544 proxy_port
= prefs
.proxy_port
;
1548 serv
->proxy_type
= proxy_type
;
1550 /* first resolve where we want to connect to */
1553 snprintf (buf
, sizeof (buf
), "9\n%s\n", proxy_host
);
1554 write (serv
->childwrite
, buf
, strlen (buf
));
1555 ip
= net_resolve (ns_server
, proxy_host
, proxy_port
, &real_hostname
);
1559 write (serv
->childwrite
, "1\n", 2);
1562 connect_port
= proxy_port
;
1564 /* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
1565 if ((proxy_type
== 2) || (proxy_type
== 5))
1567 ns_proxy
= net_store_new ();
1568 proxy_ip
= net_resolve (ns_proxy
, hostname
, port
, &real_hostname
);
1571 write (serv
->childwrite
, "1\n", 2);
1574 } else /* otherwise we can just use the hostname */
1575 proxy_ip
= strdup (hostname
);
1578 ip
= net_resolve (ns_server
, hostname
, port
, &real_hostname
);
1581 write (serv
->childwrite
, "1\n", 2);
1584 connect_port
= port
;
1587 snprintf (buf
, sizeof (buf
), "3\n%s\n%s\n%d\n",
1588 real_hostname
, ip
, connect_port
);
1589 write (serv
->childwrite
, buf
, strlen (buf
));
1591 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1592 error
= net_connect (ns_server
, serv
->proxy_sok4
, serv
->proxy_sok6
, &psok
);
1595 error
= net_connect (ns_server
, serv
->sok4
, serv
->sok6
, &sok
);
1601 snprintf (buf
, sizeof (buf
), "2\n%d\n", sock_error ());
1602 write (serv
->childwrite
, buf
, strlen (buf
));
1605 /* connect succeeded */
1608 switch (traverse_proxy (proxy_type
, serv
->childwrite
, psok
, proxy_ip
, port
, &serv
->msp_state
, ns_proxy
, serv
->sok4
, serv
->sok6
, &sok
, bound
))
1610 case 0: /* success */
1612 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1613 snprintf (buf
, sizeof (buf
), "4\n%d %d %d %d %d\n", sok
, psok
, serv
->msp_state
.clientid
, serv
->msp_state
.serverid
,
1614 serv
->msp_state
.seq_sent
);
1617 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1618 write (serv
->childwrite
, buf
, strlen (buf
));
1620 case 1: /* socks traversal failed */
1621 write (serv
->childwrite
, "8\n", 2);
1626 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1627 write (serv
->childwrite
, buf
, strlen (buf
));
1633 #if defined (USE_IPV6) || defined (WIN32)
1634 /* this is probably not needed */
1635 net_store_destroy (ns_server
);
1637 net_store_destroy (ns_proxy
);
1640 /* no need to free ip/real_hostname, this process is exiting */
1642 /* under win32 we use a thread -> shared memory, must free! */
1648 free (real_hostname
);
1655 server_connect (server
*serv
, char *hostname
, int port
, int no_login
)
1657 int pid
, read_des
[2];
1658 session
*sess
= serv
->server_session
;
1661 if (!ctx
&& serv
->use_ssl
)
1663 if (!(ctx
= _SSL_context_init (ssl_cb_info
, FALSE
)))
1665 fprintf (stderr
, "_SSL_context_init failed\n");
1676 /* use default port for this server type */
1683 port
&= 0xffff; /* wrap around */
1685 if (serv
->connected
|| serv
->connecting
|| serv
->recondelay_tag
)
1686 server_disconnect (sess
, TRUE
, -1);
1688 fe_progressbar_start (sess
);
1690 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, hostname
, NULL
, NULL
, NULL
, 0);
1692 safe_strcpy (serv
->servername
, hostname
, sizeof (serv
->servername
));
1693 /* overlap illegal in strncpy */
1694 if (hostname
!= serv
->hostname
)
1695 safe_strcpy (serv
->hostname
, hostname
, sizeof (serv
->hostname
));
1700 char cert_file
[256];
1702 /* first try network specific cert/key */
1703 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1704 get_xdir_fs (), server_get_network (serv
, TRUE
));
1705 if (SSL_CTX_use_certificate_file (ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1706 SSL_CTX_use_PrivateKey_file (ctx
, cert_file
, SSL_FILETYPE_PEM
);
1709 /* if that doesn't exist, try ~/.xchat2/client.pem */
1710 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1711 get_xdir_fs (), "client");
1712 if (SSL_CTX_use_certificate_file (ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1713 SSL_CTX_use_PrivateKey_file (ctx
, cert_file
, SSL_FILETYPE_PEM
);
1718 server_set_defaults (serv
);
1719 serv
->connecting
= TRUE
;
1721 serv
->no_login
= no_login
;
1723 fe_server_event (serv
, FE_SE_CONNECTING
, 0);
1725 server_flush_queue (serv
);
1728 if (_pipe (read_des
, 4096, _O_BINARY
) < 0)
1730 if (pipe (read_des
) < 0)
1733 #ifdef __EMX__ /* os/2 */
1734 setmode (read_des
[0], O_BINARY
);
1735 setmode (read_des
[1], O_BINARY
);
1737 serv
->childread
= read_des
[0];
1738 serv
->childwrite
= read_des
[1];
1740 /* create both sockets now, drop one later */
1741 net_sockets (&serv
->sok4
, &serv
->sok6
);
1743 /* In case of MS Proxy we have a separate UDP control connection */
1744 if (!serv
->dont_use_proxy
&& (serv
->proxy_type
== 5))
1745 udp_sockets (&serv
->proxy_sok4
, &serv
->proxy_sok6
);
1749 serv
->proxy_sok4
= -1;
1750 serv
->proxy_sok6
= -1;
1754 CloseHandle (CreateThread (NULL
, 0,
1755 (LPTHREAD_START_ROUTINE
)server_child
,
1756 serv
, 0, (DWORD
*)&pid
));
1759 rand(); /* CL: net_resolve calls rand() when LOOKUPD is set, so prepare a different seed for each child. This method giver a bigger variation in seed values than calling srand(time(0)) in the child itself. */
1761 switch (pid
= fork ())
1767 /* this is the child */
1769 server_child (serv
);
1773 serv
->childpid
= pid
;
1774 serv
->iotag
= fe_input_add (serv
->childread
, FIA_READ
, server_read_child
,
1779 server_fill_her_up (server
*serv
)
1781 serv
->connect
= server_connect
;
1782 serv
->disconnect
= server_disconnect
;
1783 serv
->cleanup
= server_cleanup
;
1784 serv
->flush_queue
= server_flush_queue
;
1785 serv
->auto_reconnect
= auto_reconnect
;
1787 proto_fill_her_up (serv
);
1791 server_set_encoding (server
*serv
, char *new_encoding
)
1797 free (serv
->encoding
);
1798 /* can be left as NULL to indicate system encoding */
1799 serv
->encoding
= NULL
;
1800 serv
->using_cp1255
= FALSE
;
1801 serv
->using_irc
= FALSE
;
1806 serv
->encoding
= strdup (new_encoding
);
1807 /* the serverlist GUI might have added a space
1808 and short description - remove it. */
1809 space
= strchr (serv
->encoding
, ' ');
1813 /* server_inline() uses these flags */
1814 if (!strcasecmp (serv
->encoding
, "CP1255") ||
1815 !strcasecmp (serv
->encoding
, "WINDOWS-1255"))
1816 serv
->using_cp1255
= TRUE
;
1817 else if (!strcasecmp (serv
->encoding
, "IRC"))
1818 serv
->using_irc
= TRUE
;
1828 serv
= malloc (sizeof (struct server
));
1829 memset (serv
, 0, sizeof (struct server
));
1831 /* use server.c and proto-irc.c functions */
1832 server_fill_her_up (serv
);
1836 strcpy (serv
->nick
, prefs
.nick1
);
1837 server_set_defaults (serv
);
1839 serv_list
= g_slist_prepend (serv_list
, serv
);
1841 fe_new_server (serv
);
1847 is_server (server
*serv
)
1849 return g_slist_find (serv_list
, serv
) ? 1 : 0;
1853 server_set_defaults (server
*serv
)
1855 if (serv
->chantypes
)
1856 free (serv
->chantypes
);
1857 if (serv
->chanmodes
)
1858 free (serv
->chanmodes
);
1859 if (serv
->nick_prefixes
)
1860 free (serv
->nick_prefixes
);
1861 if (serv
->nick_modes
)
1862 free (serv
->nick_modes
);
1864 serv
->chantypes
= strdup ("#&!+");
1865 serv
->chanmodes
= strdup ("beI,k,l");
1866 serv
->nick_prefixes
= strdup ("@%+");
1867 serv
->nick_modes
= strdup ("ohv");
1869 serv
->nickcount
= 1;
1870 serv
->nickservtype
= 1;
1871 serv
->end_of_motd
= FALSE
;
1872 serv
->is_away
= FALSE
;
1873 serv
->supports_watch
= FALSE
;
1874 serv
->bad_prefix
= FALSE
;
1875 serv
->use_who
= TRUE
;
1876 serv
->have_namesx
= FALSE
;
1877 serv
->have_uhnames
= FALSE
;
1878 serv
->have_whox
= FALSE
;
1879 serv
->have_capab
= FALSE
;
1880 serv
->have_idmsg
= FALSE
;
1881 serv
->have_except
= FALSE
;
1885 server_get_network (server
*serv
, gboolean fallback
)
1888 return ((ircnet
*)serv
->network
)->name
;
1891 return serv
->servername
;
1897 server_set_name (server
*serv
, char *name
)
1899 GSList
*list
= sess_list
;
1903 name
= serv
->hostname
;
1905 /* strncpy parameters must NOT overlap */
1906 if (name
!= serv
->servername
)
1908 safe_strcpy (serv
->servername
, name
, sizeof (serv
->servername
));
1913 sess
= (session
*) list
->data
;
1914 if (sess
->server
== serv
)
1915 fe_set_title (sess
);
1919 if (serv
->server_session
->type
== SESS_SERVER
)
1923 safe_strcpy (serv
->server_session
->channel
, ((ircnet
*)serv
->network
)->name
, CHANLEN
);
1926 safe_strcpy (serv
->server_session
->channel
, name
, CHANLEN
);
1928 fe_set_channel (serv
->server_session
);
1933 server_away_find_message (server
*serv
, char *nick
)
1935 struct away_msg
*away
;
1936 GSList
*list
= away_list
;
1939 away
= (struct away_msg
*) list
->data
;
1940 if (away
->server
== serv
&& !serv
->p_cmp (nick
, away
->nick
))
1948 server_away_free_messages (server
*serv
)
1950 GSList
*list
, *next
;
1951 struct away_msg
*away
;
1958 if (away
->server
== serv
)
1960 away_list
= g_slist_remove (away_list
, away
);
1962 free (away
->message
);
1971 server_away_save_message (server
*serv
, char *nick
, char *msg
)
1973 struct away_msg
*away
= server_away_find_message (serv
, nick
);
1975 if (away
) /* Change message for known user */
1978 free (away
->message
);
1979 away
->message
= strdup (msg
);
1981 /* Create brand new entry */
1983 away
= malloc (sizeof (struct away_msg
));
1986 away
->server
= serv
;
1987 safe_strcpy (away
->nick
, nick
, sizeof (away
->nick
));
1988 away
->message
= strdup (msg
);
1989 away_list
= g_slist_prepend (away_list
, away
);
1995 server_free (server
*serv
)
1997 serv
->cleanup (serv
);
1999 serv_list
= g_slist_remove (serv_list
, serv
);
2001 dcc_notify_kill (serv
);
2002 serv
->flush_queue (serv
);
2003 server_away_free_messages (serv
);
2005 free (serv
->nick_modes
);
2006 free (serv
->nick_prefixes
);
2007 free (serv
->chanmodes
);
2008 free (serv
->chantypes
);
2009 if (serv
->bad_nick_prefixes
)
2010 free (serv
->bad_nick_prefixes
);
2011 if (serv
->last_away_reason
)
2012 free (serv
->last_away_reason
);
2014 free (serv
->encoding
);
2016 free (serv
->autojoin
);
2018 fe_server_callback (serv
);