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*/
51 #include "proto-irc.h"
56 #include <openssl/ssl.h> /* SSL_() */
57 #include <openssl/err.h> /* ERR_() */
70 extern SSL_CTX
*ctx
; /* xchat.c */
72 static struct session
*g_sess
= NULL
;
75 static GSList
*away_list
= NULL
;
76 GSList
*serv_list
= NULL
;
78 static void auto_reconnect (server
*serv
, int send_quit
, int err
);
79 static void server_disconnect (session
* sess
, int sendquit
, int err
);
80 static int server_cleanup (server
* serv
);
81 static void server_connect (server
*serv
, char *hostname
, int port
, int no_login
);
84 extern pxProxyFactory
*libproxy_factory
;
87 /* actually send to the socket. This might do a character translation or
88 send via SSL. server/dcc both use this function. */
91 tcp_send_real (void *ssl
, int sok
, char *encoding
, int using_irc
, char *buf
, int len
)
97 if (encoding
== NULL
) /* system */
100 if (!prefs
.utf8_locale
)
102 const gchar
*charset
;
104 g_get_charset (&charset
);
105 locale
= g_convert_with_fallback (buf
, len
, charset
, "UTF-8",
106 "?", 0, &loc_len
, 0);
110 if (using_irc
) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
111 /* if all chars fit inside CP1252, use that. Otherwise this
112 returns NULL and we send UTF-8. */
113 locale
= g_convert (buf
, len
, "CP1252", "UTF-8", 0, &loc_len
, 0);
115 locale
= g_convert_with_fallback (buf
, len
, encoding
, "UTF-8",
116 "?", 0, &loc_len
, 0);
124 ret
= send (sok
, locale
, len
, 0);
126 ret
= _SSL_send (ssl
, locale
, len
);
128 ret
= send (sok
, locale
, len
, 0);
135 ret
= send (sok
, buf
, len
, 0);
137 ret
= _SSL_send (ssl
, buf
, len
);
139 ret
= send (sok
, buf
, len
, 0);
147 server_send_real (server
*serv
, char *buf
, int len
)
149 fe_add_rawlog (serv
, buf
, len
, TRUE
);
151 return tcp_send_real (serv
->ssl
, serv
->sok
, serv
->encoding
, serv
->using_irc
,
155 /* new throttling system, uses the same method as the Undernet
156 ircu2.10 server; under test, a 200-line paste didn't flood
160 tcp_send_queue (server
*serv
)
165 time_t now
= time (0);
167 /* did the server close since the timeout was added? */
168 if (!is_server (serv
))
171 /* try priority 2,1,0 */
175 list
= serv
->outbound_queue
;
178 buf
= (char *) list
->data
;
181 buf
++; /* skip the priority byte */
184 if (serv
->next_send
< now
)
185 serv
->next_send
= now
;
186 if (serv
->next_send
- now
>= 10)
188 /* check for clock skew */
189 if (now
>= serv
->prev_now
)
190 return 1; /* don't remove the timeout handler */
191 /* it is skewed, reset to something sane */
192 serv
->next_send
= now
;
195 for (p
= buf
, i
= len
; i
&& *p
!= ' '; p
++, i
--);
196 serv
->next_send
+= (2 + i
/ 120);
197 serv
->sendq_len
-= len
;
198 serv
->prev_now
= now
;
199 fe_set_throttle (serv
);
201 server_send_real (serv
, buf
, len
);
204 serv
->outbound_queue
= g_slist_remove (serv
->outbound_queue
, buf
);
206 list
= serv
->outbound_queue
;
215 return 0; /* remove the timeout handler */
219 tcp_send_len (server
*serv
, char *buf
, int len
)
222 int noqueue
= !serv
->outbound_queue
;
225 return server_send_real (serv
, buf
, len
);
227 dbuf
= malloc (len
+ 2); /* first byte is the priority */
228 dbuf
[0] = 2; /* pri 2 for most things */
229 memcpy (dbuf
+ 1, buf
, len
);
232 /* privmsg and notice get a lower priority */
233 if (strncasecmp (dbuf
+ 1, "PRIVMSG", 7) == 0 ||
234 strncasecmp (dbuf
+ 1, "NOTICE", 6) == 0)
240 /* WHO/MODE get the lowest priority */
241 if (strncasecmp (dbuf
+ 1, "WHO ", 4) == 0 ||
242 /* but only MODE queries, not changes */
243 (strncasecmp (dbuf
+ 1, "MODE", 4) == 0 &&
244 strchr (dbuf
, '-') == NULL
&&
245 strchr (dbuf
, '+') == NULL
))
249 serv
->outbound_queue
= g_slist_append (serv
->outbound_queue
, dbuf
);
250 serv
->sendq_len
+= len
; /* tcp_send_queue uses strlen */
252 if (tcp_send_queue (serv
) && noqueue
)
253 fe_timeout_add (500, tcp_send_queue
, serv
);
259 tcp_send (server *serv, char *buf)
261 return tcp_send_len (serv, buf, strlen (buf));
265 tcp_sendf (server
*serv
, char *fmt
, ...)
268 /* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
269 string shorter, so allow alot more than 512 for now. */
270 static char send_buf
[1540]; /* good code hey (no it's not overflowable) */
273 va_start (args
, fmt
);
274 len
= vsnprintf (send_buf
, sizeof (send_buf
) - 1, fmt
, args
);
277 send_buf
[sizeof (send_buf
) - 1] = '\0';
278 if (len
< 0 || len
> (sizeof (send_buf
) - 1))
279 len
= strlen (send_buf
);
281 tcp_send_len (serv
, send_buf
, len
);
285 close_socket_cb (gpointer sok
)
287 closesocket (GPOINTER_TO_INT (sok
));
292 close_socket (int sok
)
294 /* close the socket in 5 seconds so the QUIT message is not lost */
295 fe_timeout_add (5000, close_socket_cb
, GINT_TO_POINTER (sok
));
298 /* handle 1 line of text received from the server */
301 server_inline (server
*serv
, char *line
, int len
)
303 char *utf_line_allocated
= NULL
;
305 /* Checks whether we're set to use UTF-8 charset */
306 if (serv
->using_irc
|| /* 1. using CP1252/UTF-8 Hybrid */
307 (serv
->encoding
== NULL
&& prefs
.utf8_locale
) || /* OR 2. using system default->UTF-8 */
308 (serv
->encoding
!= NULL
&& /* OR 3. explicitly set to UTF-8 */
309 (strcasecmp (serv
->encoding
, "UTF8") == 0 ||
310 strcasecmp (serv
->encoding
, "UTF-8") == 0)))
312 /* The user has the UTF-8 charset set, either via /charset
313 command or from his UTF-8 locale. Thus, we first try the
314 UTF-8 charset, and if we fail to convert, we assume
315 it to be ISO-8859-1 (see text_validate). */
317 utf_line_allocated
= text_validate (&line
, &len
);
321 /* Since the user has an explicit charset set, either
322 via /charset command or from his non-UTF8 locale,
323 we don't fallback to ISO-8859-1 and instead try to remove
324 errnoeous octets till the string is convertable in the
327 const char *encoding
= NULL
;
329 if (serv
->encoding
!= NULL
)
330 encoding
= serv
->encoding
;
332 g_get_charset (&encoding
);
334 if (encoding
!= NULL
)
336 char *conv_line
; /* holds a copy of the original string */
337 int conv_len
; /* tells g_convert how much of line to convert */
343 conv_line
= g_malloc (len
+ 1);
344 memcpy (conv_line
, line
, len
);
348 /* if CP1255, convert it with the NUL terminator.
349 Works around SF bug #1122089 */
350 if (serv
->using_cp1255
)
357 utf_line_allocated
= g_convert_with_fallback (conv_line
, conv_len
, "UTF-8", encoding
, "?", &read_len
, &utf_len
, &err
);
360 if (err
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
&& conv_len
> (read_len
+ 1))
362 /* Make our best bet by removing the erroneous char.
363 This will work for casual 8-bit strings with non-standard chars. */
364 memmove (conv_line
+ read_len
, conv_line
+ read_len
+ 1, conv_len
- read_len
-1);
374 /* If any conversion has occured at all. Conversion might fail
375 due to errors other than invalid sequences, e.g. unknown charset. */
376 if (utf_line_allocated
!= NULL
)
378 line
= utf_line_allocated
;
380 if (serv
->using_cp1255
&& len
> 0)
385 /* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
386 utf_line_allocated
= text_validate (&line
, &len
);
391 fe_add_rawlog (serv
, line
, len
, FALSE
);
393 /* let proto-irc.c handle it */
394 serv
->p_inline (serv
, line
, len
);
396 if (utf_line_allocated
!= NULL
) /* only if a special copy was allocated */
397 g_free (utf_line_allocated
);
400 /* read data from socket */
403 server_read (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
414 len
= recv (sok
, lbuf
, sizeof (lbuf
) - 2, 0);
417 len
= _SSL_recv (serv
->ssl
, lbuf
, sizeof (lbuf
) - 2);
426 error
= sock_error ();
428 if (!serv
->end_of_motd
)
430 server_disconnect (serv
->server_session
, FALSE
, error
);
431 if (!servlist_cycle (serv
))
433 if (prefs
.autoreconnect
)
434 auto_reconnect (serv
, FALSE
, error
);
438 if (prefs
.autoreconnect
)
439 auto_reconnect (serv
, FALSE
, error
);
441 server_disconnect (serv
->server_session
, FALSE
, error
);
458 serv
->linebuf
[serv
->pos
] = 0;
459 server_inline (serv
, serv
->linebuf
, serv
->pos
);
464 serv
->linebuf
[serv
->pos
] = lbuf
[i
];
465 if (serv
->pos
>= (sizeof (serv
->linebuf
) - 1))
467 "*** XCHAT WARNING: Buffer overflow - shit server!\n");
477 server_connected (server
* serv
)
479 prefs
.wait_on_exit
= TRUE
;
480 serv
->ping_recv
= time (0);
481 serv
->connected
= TRUE
;
482 set_nonblocking (serv
->sok
);
483 serv
->iotag
= fe_input_add (serv
->sok
, FIA_READ
|FIA_EX
, server_read
, serv
);
486 EMIT_SIGNAL (XP_TE_CONNECTED
, serv
->server_session
, NULL
, NULL
, NULL
,
491 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
492 (((ircnet
*)serv
->network
)->user
)) ?
493 (((ircnet
*)serv
->network
)->user
) :
495 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
496 (((ircnet
*)serv
->network
)->real
)) ?
497 (((ircnet
*)serv
->network
)->real
) :
501 serv
->p_login (serv
, prefs
.username
, prefs
.realname
);
505 EMIT_SIGNAL (XP_TE_SERVERCONNECTED
, serv
->server_session
, NULL
, NULL
,
509 server_set_name (serv
, serv
->servername
);
510 fe_server_event (serv
, FE_SE_CONNECT
, 0);
515 server_stopconnecting (server
* serv
)
519 fe_input_remove (serv
->iotag
);
523 if (serv
->joindelay_tag
)
525 fe_timeout_remove (serv
->joindelay_tag
);
526 serv
->joindelay_tag
= 0;
529 /* kill the child process trying to connect */
530 kill (serv
->childpid
, SIGKILL
);
531 waitpid (serv
->childpid
, NULL
, 0);
533 close (serv
->childwrite
);
534 close (serv
->childread
);
537 if (serv
->ssl_do_connect_tag
)
539 fe_timeout_remove (serv
->ssl_do_connect_tag
);
540 serv
->ssl_do_connect_tag
= 0;
544 fe_progressbar_end (serv
);
546 serv
->connecting
= FALSE
;
547 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
551 #define SSLTMOUT 90 /* seconds */
553 ssl_cb_info (SSL
* s
, int where
, int ret
)
558 return; /* FIXME: make debug level adjustable in serverlist or settings */
560 /* snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
562 EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
564 fprintf (stderr, "%s\n", buf);*/
568 ssl_cb_verify (int ok
, X509_STORE_CTX
* ctx
)
575 X509_NAME_oneline (X509_get_subject_name (ctx
->current_cert
), subject
,
577 X509_NAME_oneline (X509_get_issuer_name (ctx
->current_cert
), issuer
,
580 snprintf (buf
, sizeof (buf
), "* Subject: %s", subject
);
581 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
582 snprintf (buf
, sizeof (buf
), "* Issuer: %s", issuer
);
583 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
585 return (TRUE
); /* always ok */
589 ssl_do_connect (server
* serv
)
593 g_sess
= serv
->server_session
;
594 if (SSL_connect (serv
->ssl
) <= 0)
600 if ((err
= ERR_get_error ()) > 0)
602 ERR_error_string (err
, err_buf
);
603 snprintf (buf
, sizeof (buf
), "(%d) %s", err
, err_buf
);
604 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
607 if (ERR_GET_REASON (err
) == SSL_R_WRONG_VERSION_NUMBER
)
608 PrintText (serv
->server_session
, _("Are you sure this is a SSL capable server and port?\n"));
610 server_cleanup (serv
);
612 if (prefs
.autoreconnect
) {
613 auto_reconnect (serv
, FALSE
, -1);
617 return (0); /* remove it (0) */
622 if (SSL_is_init_finished (serv
->ssl
))
624 struct cert_info cert_info
;
625 struct chiper_info
*chiper_info
;
629 if (!_SSL_get_cert_info (&cert_info
, serv
->ssl
))
631 snprintf (buf
, sizeof (buf
), "* Certification info:");
632 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
634 snprintf (buf
, sizeof (buf
), " Subject:");
635 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
637 for (i
= 0; cert_info
.subject_word
[i
]; i
++)
639 snprintf (buf
, sizeof (buf
), " %s", cert_info
.subject_word
[i
]);
640 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
643 snprintf (buf
, sizeof (buf
), " Issuer:");
644 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
646 for (i
= 0; cert_info
.issuer_word
[i
]; i
++)
648 snprintf (buf
, sizeof (buf
), " %s", cert_info
.issuer_word
[i
]);
649 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
652 snprintf (buf
, sizeof (buf
), " Public key algorithm: %s (%d bits)",
653 cert_info
.algorithm
, cert_info
.algorithm_bits
);
654 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
656 /*if (cert_info.rsa_tmp_bits)
658 snprintf (buf, sizeof (buf),
659 " Public key algorithm uses ephemeral key with %d bits",
660 cert_info.rsa_tmp_bits);
661 EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
664 snprintf (buf
, sizeof (buf
), " Sign algorithm %s",
665 cert_info
.sign_algorithm
/*, cert_info.sign_algorithm_bits*/);
666 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
668 snprintf (buf
, sizeof (buf
), " Valid since %s to %s",
669 cert_info
.notbefore
, cert_info
.notafter
);
670 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
674 snprintf (buf
, sizeof (buf
), " * No Certificate");
675 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
679 chiper_info
= _SSL_get_cipher_info (serv
->ssl
); /* static buffer */
680 snprintf (buf
, sizeof (buf
), "* Cipher info:");
681 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
683 snprintf (buf
, sizeof (buf
), " Version: %s, cipher %s (%u bits)",
684 chiper_info
->version
, chiper_info
->chiper
,
685 chiper_info
->chiper_bits
);
686 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
689 verify_error
= SSL_get_verify_result (serv
->ssl
);
690 switch (verify_error
)
693 /* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
694 /* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
696 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
697 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
:
698 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
699 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
700 case X509_V_ERR_CERT_HAS_EXPIRED
:
701 case X509_V_ERR_CERT_UNTRUSTED
:
702 if (serv
->accept_invalid_cert
)
704 snprintf (buf
, sizeof (buf
), "* Verify E: %s.? (%d) -- Ignored",
705 X509_verify_cert_error_string (verify_error
),
707 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
712 snprintf (buf
, sizeof (buf
), "%s.? (%d)",
713 X509_verify_cert_error_string (verify_error
),
715 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
, NULL
,
718 server_cleanup (serv
);
723 server_stopconnecting (serv
);
725 /* activate gtk poll */
726 server_connected (serv
);
728 return (0); /* remove it (0) */
731 if (serv
->ssl
->session
&& serv
->ssl
->session
->time
+ SSLTMOUT
< time (NULL
))
733 snprintf (buf
, sizeof (buf
), "SSL handshake timed out");
734 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
736 server_cleanup (serv
); /* ->connecting = FALSE */
738 if (prefs
.autoreconnect
) {
739 auto_reconnect (serv
, FALSE
, -1);
743 return (0); /* remove it (0) */
746 return (1); /* call it more (1) */
752 timeout_auto_reconnect (server
*serv
)
754 if (is_server (serv
)) /* make sure it hasnt been closed during the delay */
756 serv
->recondelay_tag
= 0;
757 if (!serv
->connected
&& !serv
->connecting
&& serv
->server_session
)
759 server_connect (serv
, serv
->hostname
, serv
->port
, FALSE
);
762 return 0; /* returning 0 should remove the timeout handler */
766 auto_reconnect (server
*serv
, int send_quit
, int err
)
772 if (serv
->server_session
== NULL
)
776 while (list
) /* make sure auto rejoin can work */
779 if (s
->type
== SESS_CHANNEL
&& s
->channel
[0])
781 strcpy (s
->waitchannel
, s
->channel
);
782 strcpy (s
->willjoinchannel
, s
->channel
);
788 server_disconnect (serv
->server_session
, send_quit
, err
);
790 del
= prefs
.recon_delay
* 1000;
792 del
= 500; /* so it doesn't block the gui */
794 if (err
== -1 || err
== 0 || err
== ECONNRESET
|| err
== ETIMEDOUT
)
795 serv
->reconnect_away
= serv
->is_away
;
797 /* is this server in a reconnect delay? remove it! */
798 if (serv
->recondelay_tag
)
800 fe_timeout_remove (serv
->recondelay_tag
);
801 serv
->recondelay_tag
= 0;
804 serv
->recondelay_tag
= fe_timeout_add (del
, timeout_auto_reconnect
, serv
);
805 fe_server_event (serv
, FE_SE_RECONDELAY
, del
);
809 server_flush_queue (server
*serv
)
811 list_free (&serv
->outbound_queue
);
813 fe_set_throttle (serv
);
816 #define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
818 /* connect() successed */
821 server_connect_success (server
*serv
)
824 #define SSLDOCONNTMOUT 300
829 /* it'll be a memory leak, if connection isn't terminated by
831 serv
->ssl
= _SSL_socket (ctx
, serv
->sok
);
832 if ((err
= _SSL_set_verify (ctx
, ssl_cb_verify
, NULL
)) && !serv
->accept_invalid_cert
)
834 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, err
, NULL
,
836 server_cleanup (serv
); /* ->connecting = FALSE */
839 /* FIXME: it'll be needed by new servers */
840 /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
841 set_nonblocking (serv
->sok
);
842 serv
->ssl_do_connect_tag
= fe_timeout_add (SSLDOCONNTMOUT
,
843 ssl_do_connect
, serv
);
849 server_stopconnecting (serv
); /* ->connecting = FALSE */
850 /* activate glib poll */
851 server_connected (serv
);
854 /* receive info from the child-process about connection progress */
857 server_read_child (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
859 session
*sess
= serv
->server_session
;
866 waitline2 (source
, tbuf
, sizeof tbuf
);
870 case '0': /* print some text */
871 waitline2 (source
, tbuf
, sizeof tbuf
);
872 PrintText (serv
->server_session
, tbuf
);
874 case '1': /* unknown host */
875 server_stopconnecting (serv
);
876 closesocket (serv
->sok4
);
877 if (serv
->proxy_sok4
!= -1)
878 closesocket (serv
->proxy_sok4
);
880 if (serv
->sok6
!= -1)
881 closesocket (serv
->sok6
);
882 if (serv
->proxy_sok6
!= -1)
883 closesocket (serv
->proxy_sok6
);
885 EMIT_SIGNAL (XP_TE_UKNHOST
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
886 if (!servlist_cycle (serv
))
887 if (prefs
.autoreconnect
)
888 auto_reconnect (serv
, FALSE
, -1);
890 case '2': /* connection failed */
891 waitline2 (source
, tbuf
, sizeof tbuf
);
892 server_stopconnecting (serv
);
893 closesocket (serv
->sok4
);
894 if (serv
->proxy_sok4
!= -1)
895 closesocket (serv
->proxy_sok4
);
897 if (serv
->sok6
!= -1)
898 closesocket (serv
->sok6
);
899 if (serv
->proxy_sok6
!= -1)
900 closesocket (serv
->proxy_sok6
);
902 EMIT_SIGNAL (XP_TE_CONNFAIL
, sess
, errorstring (atoi (tbuf
)), NULL
,
904 if (!servlist_cycle (serv
))
905 if (prefs
.autoreconnect
)
906 auto_reconnect (serv
, FALSE
, -1);
908 case '3': /* gethostbyname finished */
909 waitline2 (source
, host
, sizeof host
);
910 waitline2 (source
, ip
, sizeof ip
);
911 waitline2 (source
, outbuf
, sizeof outbuf
);
912 EMIT_SIGNAL (XP_TE_CONNECT
, sess
, host
, ip
, outbuf
, NULL
, 0);
913 snprintf (outbuf
, sizeof (outbuf
), "%s/auth/xchat_auth",
915 if (access (outbuf
, X_OK
) == 0)
917 snprintf (outbuf
, sizeof (outbuf
), "exec -d %s/auth/xchat_auth %s",
918 g_get_home_dir (), prefs
.username
);
919 handle_command (serv
->server_session
, outbuf
, FALSE
);
922 case '4': /* success */
923 waitline2 (source
, tbuf
, sizeof (tbuf
));
925 serv
->sok
= strtol (tbuf
, &p
, 10);
928 serv
->proxy_sok
= strtol (p
, &p
, 10);
929 serv
->msp_state
.clientid
= strtol (++p
, &p
, 10);
930 serv
->msp_state
.serverid
= strtol (++p
, &p
, 10);
931 serv
->msp_state
.seq_sent
= atoi (++p
);
933 serv
->proxy_sok
= -1;
935 printf ("Parent got main socket: %d, proxy socket: %d\n", serv
->sok
, serv
->proxy_sok
);
936 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
);
939 serv
->sok
= atoi (tbuf
);
942 /* close the one we didn't end up using */
943 if (serv
->sok
== serv
->sok4
)
944 closesocket (serv
->sok6
);
946 closesocket (serv
->sok4
);
947 if (serv
->proxy_sok
!= -1)
949 if (serv
->proxy_sok
== serv
->proxy_sok4
)
950 closesocket (serv
->proxy_sok6
);
952 closesocket (serv
->proxy_sok4
);
955 server_connect_success (serv
);
957 case '5': /* prefs ip discovered */
958 waitline2 (source
, tbuf
, sizeof tbuf
);
959 prefs
.local_ip
= inet_addr (tbuf
);
961 case '7': /* gethostbyname (prefs.hostname) failed */
963 _("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
965 PrintText (sess
, outbuf
);
968 PrintText (sess
, _("Proxy traversal failed.\n"));
969 server_disconnect (sess
, FALSE
, -1);
970 if (prefs
.autoreconnect
)
971 auto_reconnect (serv
, FALSE
, -1);
974 waitline2 (source
, tbuf
, sizeof tbuf
);
975 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
982 /* kill all sockets & iotags of a server. Stop a connection attempt, or
983 disconnect if already connected. */
986 server_cleanup (server
* serv
)
988 fe_set_lag (serv
, 0.0);
992 fe_input_remove (serv
->iotag
);
996 if (serv
->joindelay_tag
)
998 fe_timeout_remove (serv
->joindelay_tag
);
999 serv
->joindelay_tag
= 0;
1005 _SSL_close (serv
->ssl
);
1010 if (serv
->connecting
)
1012 server_stopconnecting (serv
);
1013 closesocket (serv
->sok4
);
1014 if (serv
->proxy_sok4
!= -1)
1015 closesocket (serv
->proxy_sok4
);
1016 if (serv
->sok6
!= -1)
1017 closesocket (serv
->sok6
);
1018 if (serv
->proxy_sok6
!= -1)
1019 closesocket (serv
->proxy_sok6
);
1023 if (serv
->connected
)
1025 close_socket (serv
->sok
);
1026 if (serv
->proxy_sok
)
1027 close_socket (serv
->proxy_sok
);
1028 serv
->connected
= FALSE
;
1029 serv
->end_of_motd
= FALSE
;
1033 /* is this server in a reconnect delay? remove it! */
1034 if (serv
->recondelay_tag
)
1036 fe_timeout_remove (serv
->recondelay_tag
);
1037 serv
->recondelay_tag
= 0;
1045 server_disconnect (session
* sess
, int sendquit
, int err
)
1047 server
*serv
= sess
->server
;
1050 gboolean shutup
= FALSE
;
1052 /* send our QUIT reason */
1053 if (sendquit
&& serv
->connected
)
1055 server_sendquit (sess
);
1058 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
1060 /* close all sockets & io tags */
1061 switch (server_cleanup (serv
))
1063 case 0: /* it wasn't even connected! */
1066 case 1: /* it was in the process of connecting */
1067 sprintf (tbuf
, "%d", sess
->server
->childpid
);
1068 EMIT_SIGNAL (XP_TE_STOPCONNECT
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
1071 shutup
= TRUE
; /* won't print "disconnected" in channels */
1074 server_flush_queue (serv
);
1079 sess
= (struct session
*) list
->data
;
1080 if (sess
->server
== serv
)
1082 if (!shutup
|| sess
->type
== SESS_SERVER
)
1083 /* print "Disconnected" to each window using this server */
1084 EMIT_SIGNAL (XP_TE_DISCON
, sess
, errorstring (err
), NULL
, NULL
, NULL
, 0);
1086 if (!sess
->channel
[0] || sess
->type
== SESS_CHANNEL
)
1087 clear_channel (sess
);
1093 serv
->motd_skipped
= FALSE
;
1094 serv
->no_login
= FALSE
;
1095 serv
->servername
[0] = 0;
1101 /* send a "print text" command to the parent process - MUST END IN \n! */
1104 proxy_error (int fd
, char *msg
)
1106 write (fd
, "0\n", 2);
1107 write (fd
, msg
, strlen (msg
));
1119 /* traverse_socks() returns:
1121 * 1 socks traversal failed */
1124 traverse_socks (int print_fd
, int sok
, char *serverAddr
, int port
)
1126 struct sock_connect sc
;
1127 unsigned char buf
[256];
1131 sc
.port
= htons (port
);
1132 sc
.address
= inet_addr (serverAddr
);
1133 strncpy (sc
.username
, prefs
.username
, 9);
1135 send (sok
, (char *) &sc
, 8 + strlen (sc
.username
) + 1, 0);
1137 recv (sok
, buf
, 10, 0);
1141 snprintf (buf
, sizeof (buf
), "SOCKS\tServer reported error %d,%d.\n", buf
[0], buf
[1]);
1142 proxy_error (print_fd
, buf
);
1146 struct sock5_connect1
1154 traverse_socks5 (int print_fd
, int sok
, char *serverAddr
, int port
)
1156 struct sock5_connect1 sc1
;
1158 unsigned int packetlen
, addrlen
;
1159 unsigned char buf
[260];
1160 int auth
= prefs
.proxy_auth
&& prefs
.proxy_user
[0] && prefs
.proxy_pass
[0];
1165 sc1
.method
= 2; /* Username/Password Authentication (UPA) */
1167 sc1
.method
= 0; /* NO Authentication */
1168 send (sok
, (char *) &sc1
, 3, 0);
1169 if (recv (sok
, buf
, 2, 0) != 2)
1174 proxy_error (print_fd
, "SOCKS\tServer is not socks version 5.\n");
1178 /* did the server say no auth required? */
1184 int len_u
=0, len_p
=0;
1186 /* authentication sub-negotiation (RFC1929) */
1187 if (buf
[1] != 2) /* UPA not supported by server */
1189 proxy_error (print_fd
, "SOCKS\tServer doesn't support UPA authentication.\n");
1193 memset (buf
, 0, sizeof(buf
));
1195 /* form the UPA request */
1196 len_u
= strlen (prefs
.proxy_user
);
1197 len_p
= strlen (prefs
.proxy_pass
);
1200 memcpy (buf
+ 2, prefs
.proxy_user
, len_u
);
1201 buf
[2 + len_u
] = len_p
;
1202 memcpy (buf
+ 3 + len_u
, prefs
.proxy_pass
, len_p
);
1204 send (sok
, buf
, 3 + len_u
+ len_p
, 0);
1205 if ( recv (sok
, buf
, 2, 0) != 2 )
1209 proxy_error (print_fd
, "SOCKS\tAuthentication failed. "
1210 "Is username and password correct?\n");
1211 return 1; /* UPA failed! */
1218 proxy_error (print_fd
, "SOCKS\tAuthentication required but disabled in settings.\n");
1223 addrlen
= strlen (serverAddr
);
1224 packetlen
= 4 + 1 + addrlen
+ 2;
1225 sc2
= malloc (packetlen
);
1226 sc2
[0] = 5; /* version */
1227 sc2
[1] = 1; /* command */
1228 sc2
[2] = 0; /* reserved */
1229 sc2
[3] = 3; /* address type */
1230 sc2
[4] = (unsigned char) addrlen
; /* hostname length */
1231 memcpy (sc2
+ 5, serverAddr
, addrlen
);
1232 *((unsigned short *) (sc2
+ 5 + addrlen
)) = htons (port
);
1233 send (sok
, sc2
, packetlen
, 0);
1236 /* consume all of the reply */
1237 if (recv (sok
, buf
, 4, 0) != 4)
1239 if (buf
[0] != 5 || buf
[1] != 0)
1242 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy refused to connect to host (not allowed).\n");
1244 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy failed to connect to host (error %d).\n", buf
[1]);
1245 proxy_error (print_fd
, buf
);
1248 if (buf
[3] == 1) /* IPV4 32bit address */
1250 if (recv (sok
, buf
, 6, 0) != 6)
1252 } else if (buf
[3] == 4) /* IPV6 128bit address */
1254 if (recv (sok
, buf
, 18, 0) != 18)
1256 } else if (buf
[3] == 3) /* string, 1st byte is size */
1258 if (recv (sok
, buf
, 1, 0) != 1) /* read the string size */
1260 packetlen
= buf
[0] + 2; /* can't exceed 260 */
1261 if (recv (sok
, buf
, packetlen
, 0) != packetlen
)
1265 return 0; /* success */
1268 proxy_error (print_fd
, "SOCKS\tRead error from server.\n");
1273 traverse_wingate (int print_fd
, int sok
, char *serverAddr
, int port
)
1277 snprintf (buf
, sizeof (buf
), "%s %d\r\n", serverAddr
, port
);
1278 send (sok
, buf
, strlen (buf
), 0);
1283 /* stuff for HTTP auth is here */
1286 three_to_four (char *from
, char *to
)
1288 static const char tab64
[64]=
1290 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1291 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1292 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1293 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1296 to
[0] = tab64
[ (from
[0] >> 2) & 63 ];
1297 to
[1] = tab64
[ ((from
[0] << 4) | (from
[1] >> 4)) & 63 ];
1298 to
[2] = tab64
[ ((from
[1] << 2) | (from
[2] >> 6)) & 63 ];
1299 to
[3] = tab64
[ from
[2] & 63 ];
1303 base64_encode (char *to
, char *from
, unsigned int len
)
1307 three_to_four (from
, to
);
1314 char three
[3]={0,0,0};
1318 three_to_four (three
, to
);
1320 to
[2] = to
[3] = '=';
1329 http_read_line (int print_fd
, int sok
, char *buf
, int len
)
1331 len
= waitline (sok
, buf
, len
, TRUE
);
1334 /* print the message out (send it to the parent process) */
1335 write (print_fd
, "0\n", 2);
1337 if (buf
[len
-1] == '\r')
1340 write (print_fd
, buf
, len
);
1343 write (print_fd
, buf
, len
);
1344 write (print_fd
, "\n", 1);
1352 traverse_http (int print_fd
, int sok
, char *serverAddr
, int port
)
1355 char auth_data
[256];
1356 char auth_data2
[252];
1359 n
= snprintf (buf
, sizeof (buf
), "CONNECT %s:%d HTTP/1.0\r\n",
1361 if (prefs
.proxy_auth
)
1363 n2
= snprintf (auth_data2
, sizeof (auth_data2
), "%s:%s",
1364 prefs
.proxy_user
, prefs
.proxy_pass
);
1365 base64_encode (auth_data
, auth_data2
, n2
);
1366 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "Proxy-Authorization: Basic %s\r\n", auth_data
);
1368 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "\r\n");
1369 send (sok
, buf
, n
, 0);
1371 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1372 /* "HTTP/1.0 200 OK" */
1375 if (memcmp (buf
, "HTTP/", 5) || memcmp (buf
+ 9, "200", 3))
1379 /* read until blank line */
1380 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1381 if (n
< 1 || (n
== 1 && buf
[0] == '\n'))
1388 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
)
1393 return traverse_wingate (print_fd
, sok
, ip
, port
);
1395 return traverse_socks (print_fd
, sok
, ip
, port
);
1397 return traverse_socks5 (print_fd
, sok
, ip
, port
);
1399 return traverse_http (print_fd
, sok
, ip
, port
);
1402 return traverse_msproxy (sok
, ip
, port
, state
, ns_proxy
, csok4
, csok6
, csok
, bound
);
1409 /* this is the child process making the connection attempt */
1412 server_child (server
* serv
)
1414 netstore
*ns_server
;
1415 netstore
*ns_proxy
= NULL
;
1417 int port
= serv
->port
;
1420 char *hostname
= serv
->hostname
;
1421 char *real_hostname
= NULL
;
1423 char *proxy_ip
= NULL
;
1429 char *proxy_host
= NULL
;
1432 ns_server
= net_store_new ();
1434 /* is a hostname set? - bind to it */
1435 if (prefs
.hostname
[0])
1437 ns_local
= net_store_new ();
1438 local_ip
= net_resolve (ns_local
, prefs
.hostname
, 0, &real_hostname
);
1439 if (local_ip
!= NULL
)
1441 snprintf (buf
, sizeof (buf
), "5\n%s\n", local_ip
);
1442 write (serv
->childwrite
, buf
, strlen (buf
));
1443 net_bind (ns_local
, serv
->sok4
, serv
->sok6
);
1447 write (serv
->childwrite
, "7\n", 2);
1449 net_store_destroy (ns_local
);
1452 if (!serv
->dont_use_proxy
) /* blocked in serverlist? */
1457 else if (prefs
.proxy_type
== 5)
1462 url
= g_strdup_printf ("irc://%s:%d", hostname
, port
);
1463 proxy_list
= px_proxy_factory_get_proxies (libproxy_factory
, url
);
1466 /* can use only one */
1467 proxy
= proxy_list
[0];
1468 if (!strncmp (proxy
, "direct", 6))
1470 else if (!strncmp (proxy
, "http", 4))
1472 else if (!strncmp (proxy
, "socks5", 6))
1474 else if (!strncmp (proxy
, "socks", 5))
1480 c
= strchr (proxy
, ':') + 3;
1481 proxy_host
= strdup (c
);
1482 c
= strchr (proxy_host
, ':');
1484 proxy_port
= atoi (c
+ 1);
1487 g_strfreev (proxy_list
);
1491 else if (prefs
.proxy_host
[0] &&
1492 prefs
.proxy_type
> 0 &&
1493 prefs
.proxy_use
!= 2) /* proxy is NOT dcc-only */
1495 proxy_type
= prefs
.proxy_type
;
1496 proxy_host
= strdup (prefs
.proxy_host
);
1497 proxy_port
= prefs
.proxy_port
;
1501 serv
->proxy_type
= proxy_type
;
1503 /* first resolve where we want to connect to */
1506 snprintf (buf
, sizeof (buf
), "9\n%s\n", proxy_host
);
1507 write (serv
->childwrite
, buf
, strlen (buf
));
1508 ip
= net_resolve (ns_server
, proxy_host
, proxy_port
, &real_hostname
);
1512 write (serv
->childwrite
, "1\n", 2);
1515 connect_port
= proxy_port
;
1517 /* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
1518 if ((proxy_type
== 2) || (proxy_type
== 5))
1520 ns_proxy
= net_store_new ();
1521 proxy_ip
= net_resolve (ns_proxy
, hostname
, port
, &real_hostname
);
1524 write (serv
->childwrite
, "1\n", 2);
1527 } else /* otherwise we can just use the hostname */
1528 proxy_ip
= strdup (hostname
);
1531 ip
= net_resolve (ns_server
, hostname
, port
, &real_hostname
);
1534 write (serv
->childwrite
, "1\n", 2);
1537 connect_port
= port
;
1540 snprintf (buf
, sizeof (buf
), "3\n%s\n%s\n%d\n",
1541 real_hostname
, ip
, connect_port
);
1542 write (serv
->childwrite
, buf
, strlen (buf
));
1544 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1545 error
= net_connect (ns_server
, serv
->proxy_sok4
, serv
->proxy_sok6
, &psok
);
1548 error
= net_connect (ns_server
, serv
->sok4
, serv
->sok6
, &sok
);
1554 snprintf (buf
, sizeof (buf
), "2\n%d\n", sock_error ());
1555 write (serv
->childwrite
, buf
, strlen (buf
));
1558 /* connect succeeded */
1561 switch (traverse_proxy (proxy_type
, serv
->childwrite
, psok
, proxy_ip
, port
, &serv
->msp_state
, ns_proxy
, serv
->sok4
, serv
->sok6
, &sok
, bound
))
1563 case 0: /* success */
1565 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1566 snprintf (buf
, sizeof (buf
), "4\n%d %d %d %d %d\n", sok
, psok
, serv
->msp_state
.clientid
, serv
->msp_state
.serverid
,
1567 serv
->msp_state
.seq_sent
);
1570 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1571 write (serv
->childwrite
, buf
, strlen (buf
));
1573 case 1: /* socks traversal failed */
1574 write (serv
->childwrite
, "8\n", 2);
1579 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1580 write (serv
->childwrite
, buf
, strlen (buf
));
1586 #if defined (USE_IPV6)
1587 /* this is probably not needed */
1588 net_store_destroy (ns_server
);
1590 net_store_destroy (ns_proxy
);
1593 /* no need to free ip/real_hostname, this process is exiting */
1599 server_connect (server
*serv
, char *hostname
, int port
, int no_login
)
1601 int pid
, read_des
[2];
1602 session
*sess
= serv
->server_session
;
1605 if (!ctx
&& serv
->use_ssl
)
1607 if (!(ctx
= _SSL_context_init (ssl_cb_info
, FALSE
)))
1609 fprintf (stderr
, "_SSL_context_init failed\n");
1620 /* use default port for this server type */
1627 port
&= 0xffff; /* wrap around */
1629 if (serv
->connected
|| serv
->connecting
|| serv
->recondelay_tag
)
1630 server_disconnect (sess
, TRUE
, -1);
1632 fe_progressbar_start (sess
);
1634 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, hostname
, NULL
, NULL
, NULL
, 0);
1636 safe_strcpy (serv
->servername
, hostname
, sizeof (serv
->servername
));
1637 /* overlap illegal in strncpy */
1638 if (hostname
!= serv
->hostname
)
1639 safe_strcpy (serv
->hostname
, hostname
, sizeof (serv
->hostname
));
1644 char cert_file
[256];
1646 /* first try network specific cert/key */
1647 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1648 get_xdir_fs (), server_get_network (serv
, TRUE
));
1649 if (SSL_CTX_use_certificate_file (ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1650 SSL_CTX_use_PrivateKey_file (ctx
, cert_file
, SSL_FILETYPE_PEM
);
1653 /* if that doesn't exist, try ~/.xchat2/client.pem */
1654 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1655 get_xdir_fs (), "client");
1656 if (SSL_CTX_use_certificate_file (ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1657 SSL_CTX_use_PrivateKey_file (ctx
, cert_file
, SSL_FILETYPE_PEM
);
1662 server_set_defaults (serv
);
1663 serv
->connecting
= TRUE
;
1665 serv
->no_login
= no_login
;
1667 fe_server_event (serv
, FE_SE_CONNECTING
, 0);
1669 server_flush_queue (serv
);
1671 if (pipe (read_des
) < 0)
1673 serv
->childread
= read_des
[0];
1674 serv
->childwrite
= read_des
[1];
1676 /* create both sockets now, drop one later */
1677 net_sockets (&serv
->sok4
, &serv
->sok6
);
1679 /* In case of MS Proxy we have a separate UDP control connection */
1680 if (!serv
->dont_use_proxy
&& (serv
->proxy_type
== 5))
1681 udp_sockets (&serv
->proxy_sok4
, &serv
->proxy_sok6
);
1685 serv
->proxy_sok4
= -1;
1686 serv
->proxy_sok6
= -1;
1690 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. */
1692 switch (pid
= fork ())
1698 /* this is the child */
1700 server_child (serv
);
1703 serv
->childpid
= pid
;
1704 serv
->iotag
= fe_input_add (serv
->childread
, FIA_READ
, server_read_child
,
1709 server_fill_her_up (server
*serv
)
1711 serv
->connect
= server_connect
;
1712 serv
->disconnect
= server_disconnect
;
1713 serv
->cleanup
= server_cleanup
;
1714 serv
->flush_queue
= server_flush_queue
;
1715 serv
->auto_reconnect
= auto_reconnect
;
1717 proto_fill_her_up (serv
);
1721 server_set_encoding (server
*serv
, char *new_encoding
)
1727 free (serv
->encoding
);
1728 /* can be left as NULL to indicate system encoding */
1729 serv
->encoding
= NULL
;
1730 serv
->using_cp1255
= FALSE
;
1731 serv
->using_irc
= FALSE
;
1736 serv
->encoding
= strdup (new_encoding
);
1737 /* the serverlist GUI might have added a space
1738 and short description - remove it. */
1739 space
= strchr (serv
->encoding
, ' ');
1743 /* server_inline() uses these flags */
1744 if (!strcasecmp (serv
->encoding
, "CP1255") ||
1745 !strcasecmp (serv
->encoding
, "WINDOWS-1255"))
1746 serv
->using_cp1255
= TRUE
;
1747 else if (!strcasecmp (serv
->encoding
, "IRC"))
1748 serv
->using_irc
= TRUE
;
1758 serv
= malloc (sizeof (struct server
));
1759 memset (serv
, 0, sizeof (struct server
));
1761 /* use server.c and proto-irc.c functions */
1762 server_fill_her_up (serv
);
1766 strcpy (serv
->nick
, prefs
.nick1
);
1767 server_set_defaults (serv
);
1769 serv_list
= g_slist_prepend (serv_list
, serv
);
1771 fe_new_server (serv
);
1777 is_server (server
*serv
)
1779 return g_slist_find (serv_list
, serv
) ? 1 : 0;
1783 server_set_defaults (server
*serv
)
1785 if (serv
->chantypes
)
1786 free (serv
->chantypes
);
1787 if (serv
->chanmodes
)
1788 free (serv
->chanmodes
);
1789 if (serv
->nick_prefixes
)
1790 free (serv
->nick_prefixes
);
1791 if (serv
->nick_modes
)
1792 free (serv
->nick_modes
);
1794 serv
->chantypes
= strdup ("#&!+");
1795 serv
->chanmodes
= strdup ("beI,k,l");
1796 serv
->nick_prefixes
= strdup ("@%+");
1797 serv
->nick_modes
= strdup ("ohv");
1799 serv
->nickcount
= 1;
1800 serv
->end_of_motd
= FALSE
;
1801 serv
->is_away
= FALSE
;
1802 serv
->supports_watch
= FALSE
;
1803 serv
->supports_monitor
= FALSE
;
1804 serv
->bad_prefix
= FALSE
;
1805 serv
->use_who
= TRUE
;
1806 serv
->have_namesx
= FALSE
;
1807 serv
->have_awaynotify
= FALSE
;
1808 serv
->have_uhnames
= FALSE
;
1809 serv
->have_whox
= FALSE
;
1810 serv
->have_idmsg
= FALSE
;
1811 serv
->have_accnotify
= FALSE
;
1812 serv
->have_extjoin
= FALSE
;
1813 serv
->have_sasl
= FALSE
;
1814 serv
->have_except
= FALSE
;
1818 server_get_network (server
*serv
, gboolean fallback
)
1821 return ((ircnet
*)serv
->network
)->name
;
1824 return serv
->servername
;
1830 server_set_name (server
*serv
, char *name
)
1832 GSList
*list
= sess_list
;
1836 name
= serv
->hostname
;
1838 /* strncpy parameters must NOT overlap */
1839 if (name
!= serv
->servername
)
1841 safe_strcpy (serv
->servername
, name
, sizeof (serv
->servername
));
1846 sess
= (session
*) list
->data
;
1847 if (sess
->server
== serv
)
1848 fe_set_title (sess
);
1852 if (serv
->server_session
->type
== SESS_SERVER
)
1856 safe_strcpy (serv
->server_session
->channel
, ((ircnet
*)serv
->network
)->name
, CHANLEN
);
1859 safe_strcpy (serv
->server_session
->channel
, name
, CHANLEN
);
1861 fe_set_channel (serv
->server_session
);
1866 server_away_find_message (server
*serv
, char *nick
)
1868 struct away_msg
*away
;
1869 GSList
*list
= away_list
;
1872 away
= (struct away_msg
*) list
->data
;
1873 if (away
->server
== serv
&& !serv
->p_cmp (nick
, away
->nick
))
1881 server_away_free_messages (server
*serv
)
1883 GSList
*list
, *next
;
1884 struct away_msg
*away
;
1891 if (away
->server
== serv
)
1893 away_list
= g_slist_remove (away_list
, away
);
1895 free (away
->message
);
1904 server_away_save_message (server
*serv
, char *nick
, char *msg
)
1906 struct away_msg
*away
= server_away_find_message (serv
, nick
);
1908 if (away
) /* Change message for known user */
1911 free (away
->message
);
1912 away
->message
= strdup (msg
);
1914 /* Create brand new entry */
1916 away
= malloc (sizeof (struct away_msg
));
1919 away
->server
= serv
;
1920 safe_strcpy (away
->nick
, nick
, sizeof (away
->nick
));
1921 away
->message
= strdup (msg
);
1922 away_list
= g_slist_prepend (away_list
, away
);
1928 server_free (server
*serv
)
1930 serv
->cleanup (serv
);
1932 serv_list
= g_slist_remove (serv_list
, serv
);
1934 dcc_notify_kill (serv
);
1935 serv
->flush_queue (serv
);
1936 server_away_free_messages (serv
);
1938 free (serv
->nick_modes
);
1939 free (serv
->nick_prefixes
);
1940 free (serv
->chanmodes
);
1941 free (serv
->chantypes
);
1942 if (serv
->bad_nick_prefixes
)
1943 free (serv
->bad_nick_prefixes
);
1944 if (serv
->last_away_reason
)
1945 free (serv
->last_away_reason
);
1947 free (serv
->encoding
);
1949 free (serv
->autojoin
);
1951 fe_server_callback (serv
);