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_() */
71 static struct session
*g_sess
= NULL
;
74 static GSList
*away_list
= NULL
;
75 GSList
*serv_list
= NULL
;
77 static void auto_reconnect (server
*serv
, int send_quit
, int err
);
78 static void server_disconnect (session
* sess
, int sendquit
, int err
);
79 static int server_cleanup (server
* serv
);
80 static void server_connect (server
*serv
, char *hostname
, int port
, int no_login
);
83 extern pxProxyFactory
*libproxy_factory
;
86 /* actually send to the socket. This might do a character translation or
87 send via SSL. server/dcc both use this function. */
90 tcp_send_real (void *ssl
, int sok
, char *encoding
, int using_irc
, char *buf
, int len
)
96 if (encoding
== NULL
) /* system */
99 if (!prefs
.utf8_locale
)
101 const gchar
*charset
;
103 g_get_charset (&charset
);
104 locale
= g_convert_with_fallback (buf
, len
, charset
, "UTF-8",
105 "?", 0, &loc_len
, 0);
109 if (using_irc
) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
110 /* if all chars fit inside CP1252, use that. Otherwise this
111 returns NULL and we send UTF-8. */
112 locale
= g_convert (buf
, len
, "CP1252", "UTF-8", 0, &loc_len
, 0);
114 locale
= g_convert_with_fallback (buf
, len
, encoding
, "UTF-8",
115 "?", 0, &loc_len
, 0);
123 ret
= send (sok
, locale
, len
, 0);
125 ret
= _SSL_send (ssl
, locale
, len
);
127 ret
= send (sok
, locale
, len
, 0);
134 ret
= send (sok
, buf
, len
, 0);
136 ret
= _SSL_send (ssl
, buf
, len
);
138 ret
= send (sok
, buf
, len
, 0);
146 server_send_real (server
*serv
, char *buf
, int len
)
148 fe_add_rawlog (serv
, buf
, len
, TRUE
);
150 return tcp_send_real (serv
->ssl
, serv
->sok
, serv
->encoding
, serv
->using_irc
,
154 /* new throttling system, uses the same method as the Undernet
155 ircu2.10 server; under test, a 200-line paste didn't flood
159 tcp_send_queue (server
*serv
)
164 time_t now
= time (0);
166 /* did the server close since the timeout was added? */
167 if (!is_server (serv
))
170 /* try priority 2,1,0 */
174 list
= serv
->outbound_queue
;
177 buf
= (char *) list
->data
;
180 buf
++; /* skip the priority byte */
183 if (serv
->next_send
< now
)
184 serv
->next_send
= now
;
185 if (serv
->next_send
- now
>= 10)
187 /* check for clock skew */
188 if (now
>= serv
->prev_now
)
189 return 1; /* don't remove the timeout handler */
190 /* it is skewed, reset to something sane */
191 serv
->next_send
= now
;
194 for (p
= buf
, i
= len
; i
&& *p
!= ' '; p
++, i
--);
195 serv
->next_send
+= (2 + i
/ 120);
196 serv
->sendq_len
-= len
;
197 serv
->prev_now
= now
;
198 fe_set_throttle (serv
);
200 server_send_real (serv
, buf
, len
);
203 serv
->outbound_queue
= g_slist_remove (serv
->outbound_queue
, buf
);
205 list
= serv
->outbound_queue
;
214 return 0; /* remove the timeout handler */
218 tcp_send_len (server
*serv
, char *buf
, int len
)
221 int noqueue
= !serv
->outbound_queue
;
224 return server_send_real (serv
, buf
, len
);
226 dbuf
= malloc (len
+ 2); /* first byte is the priority */
227 dbuf
[0] = 2; /* pri 2 for most things */
228 memcpy (dbuf
+ 1, buf
, len
);
231 /* privmsg and notice get a lower priority */
232 if (strncasecmp (dbuf
+ 1, "PRIVMSG", 7) == 0 ||
233 strncasecmp (dbuf
+ 1, "NOTICE", 6) == 0)
239 /* WHO/MODE get the lowest priority */
240 if (strncasecmp (dbuf
+ 1, "WHO ", 4) == 0 ||
241 /* but only MODE queries, not changes */
242 (strncasecmp (dbuf
+ 1, "MODE", 4) == 0 &&
243 strchr (dbuf
, '-') == NULL
&&
244 strchr (dbuf
, '+') == NULL
))
248 serv
->outbound_queue
= g_slist_append (serv
->outbound_queue
, dbuf
);
249 serv
->sendq_len
+= len
; /* tcp_send_queue uses strlen */
251 if (tcp_send_queue (serv
) && noqueue
)
252 fe_timeout_add (500, tcp_send_queue
, serv
);
258 tcp_send (server *serv, char *buf)
260 return tcp_send_len (serv, buf, strlen (buf));
264 tcp_sendf (server
*serv
, char *fmt
, ...)
267 /* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
268 string shorter, so allow alot more than 512 for now. */
269 static char send_buf
[1540]; /* good code hey (no it's not overflowable) */
272 va_start (args
, fmt
);
273 len
= vsnprintf (send_buf
, sizeof (send_buf
) - 1, fmt
, args
);
276 send_buf
[sizeof (send_buf
) - 1] = '\0';
277 if (len
< 0 || len
> (sizeof (send_buf
) - 1))
278 len
= strlen (send_buf
);
280 tcp_send_len (serv
, send_buf
, len
);
284 close_socket_cb (gpointer sok
)
286 closesocket (GPOINTER_TO_INT (sok
));
291 close_socket (int sok
)
293 /* close the socket in 5 seconds so the QUIT message is not lost */
294 fe_timeout_add (5000, close_socket_cb
, GINT_TO_POINTER (sok
));
297 /* handle 1 line of text received from the server */
300 server_inline (server
*serv
, char *line
, int len
)
302 char *utf_line_allocated
= NULL
;
304 /* Checks whether we're set to use UTF-8 charset */
305 if (serv
->using_irc
|| /* 1. using CP1252/UTF-8 Hybrid */
306 (serv
->encoding
== NULL
&& prefs
.utf8_locale
) || /* OR 2. using system default->UTF-8 */
307 (serv
->encoding
!= NULL
&& /* OR 3. explicitly set to UTF-8 */
308 (strcasecmp (serv
->encoding
, "UTF8") == 0 ||
309 strcasecmp (serv
->encoding
, "UTF-8") == 0)))
311 /* The user has the UTF-8 charset set, either via /charset
312 command or from his UTF-8 locale. Thus, we first try the
313 UTF-8 charset, and if we fail to convert, we assume
314 it to be ISO-8859-1 (see text_validate). */
316 utf_line_allocated
= text_validate (&line
, &len
);
320 /* Since the user has an explicit charset set, either
321 via /charset command or from his non-UTF8 locale,
322 we don't fallback to ISO-8859-1 and instead try to remove
323 errnoeous octets till the string is convertable in the
326 const char *encoding
= NULL
;
328 if (serv
->encoding
!= NULL
)
329 encoding
= serv
->encoding
;
331 g_get_charset (&encoding
);
333 if (encoding
!= NULL
)
335 char *conv_line
; /* holds a copy of the original string */
336 int conv_len
; /* tells g_convert how much of line to convert */
342 conv_line
= g_malloc (len
+ 1);
343 memcpy (conv_line
, line
, len
);
347 /* if CP1255, convert it with the NUL terminator.
348 Works around SF bug #1122089 */
349 if (serv
->using_cp1255
)
356 utf_line_allocated
= g_convert_with_fallback (conv_line
, conv_len
, "UTF-8", encoding
, "?", &read_len
, &utf_len
, &err
);
359 if (err
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
&& conv_len
> (read_len
+ 1))
361 /* Make our best bet by removing the erroneous char.
362 This will work for casual 8-bit strings with non-standard chars. */
363 memmove (conv_line
+ read_len
, conv_line
+ read_len
+ 1, conv_len
- read_len
-1);
373 /* If any conversion has occured at all. Conversion might fail
374 due to errors other than invalid sequences, e.g. unknown charset. */
375 if (utf_line_allocated
!= NULL
)
377 line
= utf_line_allocated
;
379 if (serv
->using_cp1255
&& len
> 0)
384 /* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
385 utf_line_allocated
= text_validate (&line
, &len
);
390 fe_add_rawlog (serv
, line
, len
, FALSE
);
392 /* let proto-irc.c handle it */
393 serv
->p_inline (serv
, line
, len
);
395 if (utf_line_allocated
!= NULL
) /* only if a special copy was allocated */
396 g_free (utf_line_allocated
);
399 /* read data from socket */
402 server_read (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
413 len
= recv (sok
, lbuf
, sizeof (lbuf
) - 2, 0);
416 len
= _SSL_recv (serv
->ssl
, lbuf
, sizeof (lbuf
) - 2);
425 error
= sock_error ();
427 if (!serv
->end_of_motd
)
429 server_disconnect (serv
->server_session
, FALSE
, error
);
430 if (!servlist_cycle (serv
))
432 if (prefs
.autoreconnect
)
433 auto_reconnect (serv
, FALSE
, error
);
437 if (prefs
.autoreconnect
)
438 auto_reconnect (serv
, FALSE
, error
);
440 server_disconnect (serv
->server_session
, FALSE
, error
);
457 serv
->linebuf
[serv
->pos
] = 0;
458 server_inline (serv
, serv
->linebuf
, serv
->pos
);
463 serv
->linebuf
[serv
->pos
] = lbuf
[i
];
464 if (serv
->pos
>= (sizeof (serv
->linebuf
) - 1))
466 "*** XCHAT WARNING: Buffer overflow - shit server!\n");
476 server_connected (server
* serv
)
478 prefs
.wait_on_exit
= TRUE
;
479 serv
->ping_recv
= time (0);
480 serv
->connected
= TRUE
;
481 set_nonblocking (serv
->sok
);
482 serv
->iotag
= fe_input_add (serv
->sok
, FIA_READ
|FIA_EX
, server_read
, serv
);
485 EMIT_SIGNAL (XP_TE_CONNECTED
, serv
->server_session
, NULL
, NULL
, NULL
,
490 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
491 (((ircnet
*)serv
->network
)->user
)) ?
492 (((ircnet
*)serv
->network
)->user
) :
494 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
495 (((ircnet
*)serv
->network
)->real
)) ?
496 (((ircnet
*)serv
->network
)->real
) :
500 serv
->p_login (serv
, prefs
.username
, prefs
.realname
);
504 EMIT_SIGNAL (XP_TE_SERVERCONNECTED
, serv
->server_session
, NULL
, NULL
,
508 server_set_name (serv
, serv
->servername
);
509 fe_server_event (serv
, FE_SE_CONNECT
, 0);
514 server_stopconnecting (server
* serv
)
518 fe_input_remove (serv
->iotag
);
522 if (serv
->joindelay_tag
)
524 fe_timeout_remove (serv
->joindelay_tag
);
525 serv
->joindelay_tag
= 0;
528 /* kill the child process trying to connect */
529 kill (serv
->childpid
, SIGKILL
);
530 waitpid (serv
->childpid
, NULL
, 0);
532 close (serv
->childwrite
);
533 close (serv
->childread
);
536 if (serv
->ssl_do_connect_tag
)
538 fe_timeout_remove (serv
->ssl_do_connect_tag
);
539 serv
->ssl_do_connect_tag
= 0;
543 fe_progressbar_end (serv
);
545 serv
->connecting
= FALSE
;
546 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
550 #define SSLTMOUT 90 /* seconds */
552 ssl_cb_info (SSL
* s
, int where
, int ret
)
557 return; /* FIXME: make debug level adjustable in serverlist or settings */
559 /* snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
561 EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
563 fprintf (stderr, "%s\n", buf);*/
567 ssl_cb_verify (int ok
, X509_STORE_CTX
* ctx
)
575 current_cert
= X509_STORE_CTX_get_current_cert (ctx
);
576 X509_NAME_oneline (X509_get_subject_name (current_cert
), subject
,
578 X509_NAME_oneline (X509_get_issuer_name (current_cert
), issuer
,
581 snprintf (buf
, sizeof (buf
), "* Subject: %s", subject
);
582 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
583 snprintf (buf
, sizeof (buf
), "* Issuer: %s", issuer
);
584 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
586 return (TRUE
); /* always ok */
590 ssl_do_connect (server
* serv
)
594 g_sess
= serv
->server_session
;
595 if (SSL_connect (serv
->ssl
) <= 0)
601 if ((err
= ERR_get_error ()) > 0)
603 ERR_error_string (err
, err_buf
);
604 snprintf (buf
, sizeof (buf
), "(%d) %s", err
, err_buf
);
605 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
608 if (ERR_GET_REASON (err
) == SSL_R_WRONG_VERSION_NUMBER
)
609 PrintText (serv
->server_session
, _("Are you sure this is a SSL capable server and port?\n"));
611 server_cleanup (serv
);
613 if (prefs
.autoreconnect
) {
614 auto_reconnect (serv
, FALSE
, -1);
618 return (0); /* remove it (0) */
623 if (SSL_is_init_finished (serv
->ssl
))
625 struct cert_info cert_info
;
626 struct chiper_info
*chiper_info
;
630 if (!_SSL_get_cert_info (&cert_info
, serv
->ssl
))
632 snprintf (buf
, sizeof (buf
), "* Certification info:");
633 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
635 snprintf (buf
, sizeof (buf
), " Subject:");
636 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
638 for (i
= 0; cert_info
.subject_word
[i
]; i
++)
640 snprintf (buf
, sizeof (buf
), " %s", cert_info
.subject_word
[i
]);
641 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
644 snprintf (buf
, sizeof (buf
), " Issuer:");
645 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
647 for (i
= 0; cert_info
.issuer_word
[i
]; i
++)
649 snprintf (buf
, sizeof (buf
), " %s", cert_info
.issuer_word
[i
]);
650 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
653 snprintf (buf
, sizeof (buf
), " Public key algorithm: %s (%d bits)",
654 cert_info
.algorithm
, cert_info
.algorithm_bits
);
655 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
657 /*if (cert_info.rsa_tmp_bits)
659 snprintf (buf, sizeof (buf),
660 " Public key algorithm uses ephemeral key with %d bits",
661 cert_info.rsa_tmp_bits);
662 EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
665 snprintf (buf
, sizeof (buf
), " Sign algorithm %s",
666 cert_info
.sign_algorithm
/*, cert_info.sign_algorithm_bits*/);
667 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
669 snprintf (buf
, sizeof (buf
), " Valid since %s to %s",
670 cert_info
.notbefore
, cert_info
.notafter
);
671 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
675 snprintf (buf
, sizeof (buf
), " * No Certificate");
676 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
680 chiper_info
= _SSL_get_cipher_info (serv
->ssl
); /* static buffer */
681 snprintf (buf
, sizeof (buf
), "* Cipher info:");
682 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
684 snprintf (buf
, sizeof (buf
), " Version: %s, cipher %s (%u bits)",
685 chiper_info
->version
, chiper_info
->chiper
,
686 chiper_info
->chiper_bits
);
687 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
690 verify_error
= SSL_get_verify_result (serv
->ssl
);
691 switch (verify_error
)
694 /* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
695 /* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
697 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
698 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
:
699 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
700 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
701 case X509_V_ERR_CERT_HAS_EXPIRED
:
702 case X509_V_ERR_CERT_UNTRUSTED
:
703 if (serv
->accept_invalid_cert
)
705 snprintf (buf
, sizeof (buf
), "* Verify E: %s.? (%d) -- Ignored",
706 X509_verify_cert_error_string (verify_error
),
708 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
713 snprintf (buf
, sizeof (buf
), "%s.? (%d)",
714 X509_verify_cert_error_string (verify_error
),
716 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
, NULL
,
719 server_cleanup (serv
);
724 server_stopconnecting (serv
);
726 /* activate gtk poll */
727 server_connected (serv
);
729 return (0); /* remove it (0) */
732 SSL_SESSION
*session
;
735 session
= SSL_get_session (serv
->ssl
);
736 session_time
= SSL_SESSION_get_time (session
);
737 if (session
&& session_time
+ SSLTMOUT
< time (NULL
))
739 snprintf (buf
, sizeof (buf
), "SSL handshake timed out");
740 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
742 server_cleanup (serv
); /* ->connecting = FALSE */
744 if (prefs
.autoreconnect
) {
745 auto_reconnect (serv
, FALSE
, -1);
749 return (0); /* remove it (0) */
752 return (1); /* call it more (1) */
758 timeout_auto_reconnect (server
*serv
)
760 if (is_server (serv
)) /* make sure it hasnt been closed during the delay */
762 serv
->recondelay_tag
= 0;
763 if (!serv
->connected
&& !serv
->connecting
&& serv
->server_session
)
765 server_connect (serv
, serv
->hostname
, serv
->port
, FALSE
);
768 return 0; /* returning 0 should remove the timeout handler */
772 auto_reconnect (server
*serv
, int send_quit
, int err
)
778 if (serv
->server_session
== NULL
)
782 while (list
) /* make sure auto rejoin can work */
785 if (s
->type
== SESS_CHANNEL
&& s
->channel
[0])
787 strcpy (s
->waitchannel
, s
->channel
);
788 strcpy (s
->willjoinchannel
, s
->channel
);
794 server_disconnect (serv
->server_session
, send_quit
, err
);
796 del
= prefs
.recon_delay
* 1000;
798 del
= 500; /* so it doesn't block the gui */
800 if (err
== -1 || err
== 0 || err
== ECONNRESET
|| err
== ETIMEDOUT
)
801 serv
->reconnect_away
= serv
->is_away
;
803 /* is this server in a reconnect delay? remove it! */
804 if (serv
->recondelay_tag
)
806 fe_timeout_remove (serv
->recondelay_tag
);
807 serv
->recondelay_tag
= 0;
810 serv
->recondelay_tag
= fe_timeout_add (del
, timeout_auto_reconnect
, serv
);
811 fe_server_event (serv
, FE_SE_RECONDELAY
, del
);
815 server_flush_queue (server
*serv
)
817 list_free (&serv
->outbound_queue
);
819 fe_set_throttle (serv
);
822 #define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
824 /* connect() successed */
827 server_connect_success (server
*serv
)
830 #define SSLDOCONNTMOUT 300
835 /* it'll be a memory leak, if connection isn't terminated by
837 serv
->ssl
= _SSL_socket (serv
->ctx
, serv
->sok
);
838 if ((err
= _SSL_set_verify (serv
->ctx
, ssl_cb_verify
, NULL
)))
840 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, err
, NULL
,
842 server_cleanup (serv
); /* ->connecting = FALSE */
845 /* FIXME: it'll be needed by new servers */
846 /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
847 set_nonblocking (serv
->sok
);
848 serv
->ssl_do_connect_tag
= fe_timeout_add (SSLDOCONNTMOUT
,
849 ssl_do_connect
, serv
);
855 server_stopconnecting (serv
); /* ->connecting = FALSE */
856 /* activate glib poll */
857 server_connected (serv
);
860 /* receive info from the child-process about connection progress */
863 server_read_child (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
865 session
*sess
= serv
->server_session
;
872 waitline2 (source
, tbuf
, sizeof tbuf
);
876 case '0': /* print some text */
877 waitline2 (source
, tbuf
, sizeof tbuf
);
878 PrintText (serv
->server_session
, tbuf
);
880 case '1': /* unknown host */
881 server_stopconnecting (serv
);
882 closesocket (serv
->sok4
);
883 if (serv
->proxy_sok4
!= -1)
884 closesocket (serv
->proxy_sok4
);
886 if (serv
->sok6
!= -1)
887 closesocket (serv
->sok6
);
888 if (serv
->proxy_sok6
!= -1)
889 closesocket (serv
->proxy_sok6
);
891 EMIT_SIGNAL (XP_TE_UKNHOST
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
892 if (!servlist_cycle (serv
))
893 if (prefs
.autoreconnect
)
894 auto_reconnect (serv
, FALSE
, -1);
896 case '2': /* connection failed */
897 waitline2 (source
, tbuf
, sizeof tbuf
);
898 server_stopconnecting (serv
);
899 closesocket (serv
->sok4
);
900 if (serv
->proxy_sok4
!= -1)
901 closesocket (serv
->proxy_sok4
);
903 if (serv
->sok6
!= -1)
904 closesocket (serv
->sok6
);
905 if (serv
->proxy_sok6
!= -1)
906 closesocket (serv
->proxy_sok6
);
908 EMIT_SIGNAL (XP_TE_CONNFAIL
, sess
, errorstring (atoi (tbuf
)), NULL
,
910 if (!servlist_cycle (serv
))
911 if (prefs
.autoreconnect
)
912 auto_reconnect (serv
, FALSE
, -1);
914 case '3': /* gethostbyname finished */
915 waitline2 (source
, host
, sizeof host
);
916 waitline2 (source
, ip
, sizeof ip
);
917 waitline2 (source
, outbuf
, sizeof outbuf
);
918 EMIT_SIGNAL (XP_TE_CONNECT
, sess
, host
, ip
, outbuf
, NULL
, 0);
919 snprintf (outbuf
, sizeof (outbuf
), "%s/auth/xchat_auth",
921 if (access (outbuf
, X_OK
) == 0)
923 snprintf (outbuf
, sizeof (outbuf
), "exec -d %s/auth/xchat_auth %s",
924 g_get_home_dir (), prefs
.username
);
925 handle_command (serv
->server_session
, outbuf
, FALSE
);
928 case '4': /* success */
929 waitline2 (source
, tbuf
, sizeof (tbuf
));
931 serv
->sok
= strtol (tbuf
, &p
, 10);
934 serv
->proxy_sok
= strtol (p
, &p
, 10);
935 serv
->msp_state
.clientid
= strtol (++p
, &p
, 10);
936 serv
->msp_state
.serverid
= strtol (++p
, &p
, 10);
937 serv
->msp_state
.seq_sent
= atoi (++p
);
939 serv
->proxy_sok
= -1;
941 printf ("Parent got main socket: %d, proxy socket: %d\n", serv
->sok
, serv
->proxy_sok
);
942 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
);
945 serv
->sok
= atoi (tbuf
);
948 /* close the one we didn't end up using */
949 if (serv
->sok
== serv
->sok4
)
950 closesocket (serv
->sok6
);
952 closesocket (serv
->sok4
);
953 if (serv
->proxy_sok
!= -1)
955 if (serv
->proxy_sok
== serv
->proxy_sok4
)
956 closesocket (serv
->proxy_sok6
);
958 closesocket (serv
->proxy_sok4
);
961 server_connect_success (serv
);
963 case '5': /* prefs ip discovered */
964 waitline2 (source
, tbuf
, sizeof tbuf
);
965 prefs
.local_ip
= inet_addr (tbuf
);
967 case '7': /* gethostbyname (prefs.hostname) failed */
969 _("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
971 PrintText (sess
, outbuf
);
974 PrintText (sess
, _("Proxy traversal failed.\n"));
975 server_disconnect (sess
, FALSE
, -1);
976 if (prefs
.autoreconnect
)
977 auto_reconnect (serv
, FALSE
, -1);
980 waitline2 (source
, tbuf
, sizeof tbuf
);
981 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
988 /* kill all sockets & iotags of a server. Stop a connection attempt, or
989 disconnect if already connected. */
992 server_cleanup (server
* serv
)
994 fe_set_lag (serv
, 0.0);
998 fe_input_remove (serv
->iotag
);
1002 if (serv
->joindelay_tag
)
1004 fe_timeout_remove (serv
->joindelay_tag
);
1005 serv
->joindelay_tag
= 0;
1011 SSL_shutdown (serv
->ssl
);
1012 SSL_free (serv
->ssl
);
1017 if (serv
->connecting
)
1019 server_stopconnecting (serv
);
1020 closesocket (serv
->sok4
);
1021 if (serv
->proxy_sok4
!= -1)
1022 closesocket (serv
->proxy_sok4
);
1023 if (serv
->sok6
!= -1)
1024 closesocket (serv
->sok6
);
1025 if (serv
->proxy_sok6
!= -1)
1026 closesocket (serv
->proxy_sok6
);
1030 if (serv
->connected
)
1032 close_socket (serv
->sok
);
1033 if (serv
->proxy_sok
)
1034 close_socket (serv
->proxy_sok
);
1035 serv
->connected
= FALSE
;
1036 serv
->end_of_motd
= FALSE
;
1040 /* is this server in a reconnect delay? remove it! */
1041 if (serv
->recondelay_tag
)
1043 fe_timeout_remove (serv
->recondelay_tag
);
1044 serv
->recondelay_tag
= 0;
1052 server_disconnect (session
* sess
, int sendquit
, int err
)
1054 server
*serv
= sess
->server
;
1057 gboolean shutup
= FALSE
;
1059 /* send our QUIT reason */
1060 if (sendquit
&& serv
->connected
)
1062 server_sendquit (sess
);
1065 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
1067 /* close all sockets & io tags */
1068 switch (server_cleanup (serv
))
1070 case 0: /* it wasn't even connected! */
1073 case 1: /* it was in the process of connecting */
1074 sprintf (tbuf
, "%d", sess
->server
->childpid
);
1075 EMIT_SIGNAL (XP_TE_STOPCONNECT
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
1078 shutup
= TRUE
; /* won't print "disconnected" in channels */
1081 server_flush_queue (serv
);
1086 sess
= (struct session
*) list
->data
;
1087 if (sess
->server
== serv
)
1089 if (!shutup
|| sess
->type
== SESS_SERVER
)
1090 /* print "Disconnected" to each window using this server */
1091 EMIT_SIGNAL (XP_TE_DISCON
, sess
, errorstring (err
), NULL
, NULL
, NULL
, 0);
1093 if (!sess
->channel
[0] || sess
->type
== SESS_CHANNEL
)
1094 clear_channel (sess
);
1100 serv
->motd_skipped
= FALSE
;
1101 serv
->no_login
= FALSE
;
1102 serv
->servername
[0] = 0;
1108 /* send a "print text" command to the parent process - MUST END IN \n! */
1111 proxy_error (int fd
, char *msg
)
1113 write (fd
, "0\n", 2);
1114 write (fd
, msg
, strlen (msg
));
1126 /* traverse_socks() returns:
1128 * 1 socks traversal failed */
1131 traverse_socks (int print_fd
, int sok
, char *serverAddr
, int port
)
1133 struct sock_connect sc
;
1134 unsigned char buf
[256];
1138 sc
.port
= htons (port
);
1139 sc
.address
= inet_addr (serverAddr
);
1140 strncpy (sc
.username
, prefs
.username
, 9);
1142 send (sok
, (char *) &sc
, 8 + strlen (sc
.username
) + 1, 0);
1144 recv (sok
, buf
, 10, 0);
1148 snprintf (buf
, sizeof (buf
), "SOCKS\tServer reported error %d,%d.\n", buf
[0], buf
[1]);
1149 proxy_error (print_fd
, buf
);
1153 struct sock5_connect1
1161 traverse_socks5 (int print_fd
, int sok
, char *serverAddr
, int port
)
1163 struct sock5_connect1 sc1
;
1165 unsigned int packetlen
, addrlen
;
1166 unsigned char buf
[260];
1167 int auth
= prefs
.proxy_auth
&& prefs
.proxy_user
[0] && prefs
.proxy_pass
[0];
1172 sc1
.method
= 2; /* Username/Password Authentication (UPA) */
1174 sc1
.method
= 0; /* NO Authentication */
1175 send (sok
, (char *) &sc1
, 3, 0);
1176 if (recv (sok
, buf
, 2, 0) != 2)
1181 proxy_error (print_fd
, "SOCKS\tServer is not socks version 5.\n");
1185 /* did the server say no auth required? */
1191 int len_u
=0, len_p
=0;
1193 /* authentication sub-negotiation (RFC1929) */
1194 if (buf
[1] != 2) /* UPA not supported by server */
1196 proxy_error (print_fd
, "SOCKS\tServer doesn't support UPA authentication.\n");
1200 memset (buf
, 0, sizeof(buf
));
1202 /* form the UPA request */
1203 len_u
= strlen (prefs
.proxy_user
);
1204 len_p
= strlen (prefs
.proxy_pass
);
1207 memcpy (buf
+ 2, prefs
.proxy_user
, len_u
);
1208 buf
[2 + len_u
] = len_p
;
1209 memcpy (buf
+ 3 + len_u
, prefs
.proxy_pass
, len_p
);
1211 send (sok
, buf
, 3 + len_u
+ len_p
, 0);
1212 if ( recv (sok
, buf
, 2, 0) != 2 )
1216 proxy_error (print_fd
, "SOCKS\tAuthentication failed. "
1217 "Is username and password correct?\n");
1218 return 1; /* UPA failed! */
1225 proxy_error (print_fd
, "SOCKS\tAuthentication required but disabled in settings.\n");
1230 addrlen
= strlen (serverAddr
);
1231 packetlen
= 4 + 1 + addrlen
+ 2;
1232 sc2
= malloc (packetlen
);
1233 sc2
[0] = 5; /* version */
1234 sc2
[1] = 1; /* command */
1235 sc2
[2] = 0; /* reserved */
1236 sc2
[3] = 3; /* address type */
1237 sc2
[4] = (unsigned char) addrlen
; /* hostname length */
1238 memcpy (sc2
+ 5, serverAddr
, addrlen
);
1239 *((unsigned short *) (sc2
+ 5 + addrlen
)) = htons (port
);
1240 send (sok
, sc2
, packetlen
, 0);
1243 /* consume all of the reply */
1244 if (recv (sok
, buf
, 4, 0) != 4)
1246 if (buf
[0] != 5 || buf
[1] != 0)
1249 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy refused to connect to host (not allowed).\n");
1251 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy failed to connect to host (error %d).\n", buf
[1]);
1252 proxy_error (print_fd
, buf
);
1255 if (buf
[3] == 1) /* IPV4 32bit address */
1257 if (recv (sok
, buf
, 6, 0) != 6)
1259 } else if (buf
[3] == 4) /* IPV6 128bit address */
1261 if (recv (sok
, buf
, 18, 0) != 18)
1263 } else if (buf
[3] == 3) /* string, 1st byte is size */
1265 if (recv (sok
, buf
, 1, 0) != 1) /* read the string size */
1267 packetlen
= buf
[0] + 2; /* can't exceed 260 */
1268 if (recv (sok
, buf
, packetlen
, 0) != packetlen
)
1272 return 0; /* success */
1275 proxy_error (print_fd
, "SOCKS\tRead error from server.\n");
1280 traverse_wingate (int print_fd
, int sok
, char *serverAddr
, int port
)
1284 snprintf (buf
, sizeof (buf
), "%s %d\r\n", serverAddr
, port
);
1285 send (sok
, buf
, strlen (buf
), 0);
1290 /* stuff for HTTP auth is here */
1293 three_to_four (char *from
, char *to
)
1295 static const char tab64
[64]=
1297 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1298 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1299 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1300 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1303 to
[0] = tab64
[ (from
[0] >> 2) & 63 ];
1304 to
[1] = tab64
[ ((from
[0] << 4) | (from
[1] >> 4)) & 63 ];
1305 to
[2] = tab64
[ ((from
[1] << 2) | (from
[2] >> 6)) & 63 ];
1306 to
[3] = tab64
[ from
[2] & 63 ];
1310 base64_encode (char *to
, char *from
, unsigned int len
)
1314 three_to_four (from
, to
);
1321 char three
[3]={0,0,0};
1325 three_to_four (three
, to
);
1327 to
[2] = to
[3] = '=';
1336 http_read_line (int print_fd
, int sok
, char *buf
, int len
)
1338 len
= waitline (sok
, buf
, len
, TRUE
);
1341 /* print the message out (send it to the parent process) */
1342 write (print_fd
, "0\n", 2);
1344 if (buf
[len
-1] == '\r')
1347 write (print_fd
, buf
, len
);
1350 write (print_fd
, buf
, len
);
1351 write (print_fd
, "\n", 1);
1359 traverse_http (int print_fd
, int sok
, char *serverAddr
, int port
)
1362 char auth_data
[256];
1363 char auth_data2
[252];
1366 n
= snprintf (buf
, sizeof (buf
), "CONNECT %s:%d HTTP/1.0\r\n",
1368 if (prefs
.proxy_auth
)
1370 n2
= snprintf (auth_data2
, sizeof (auth_data2
), "%s:%s",
1371 prefs
.proxy_user
, prefs
.proxy_pass
);
1372 base64_encode (auth_data
, auth_data2
, n2
);
1373 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "Proxy-Authorization: Basic %s\r\n", auth_data
);
1375 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "\r\n");
1376 send (sok
, buf
, n
, 0);
1378 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1379 /* "HTTP/1.0 200 OK" */
1382 if (memcmp (buf
, "HTTP/", 5) || memcmp (buf
+ 9, "200", 3))
1386 /* read until blank line */
1387 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1388 if (n
< 1 || (n
== 1 && buf
[0] == '\n'))
1395 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
)
1400 return traverse_wingate (print_fd
, sok
, ip
, port
);
1402 return traverse_socks (print_fd
, sok
, ip
, port
);
1404 return traverse_socks5 (print_fd
, sok
, ip
, port
);
1406 return traverse_http (print_fd
, sok
, ip
, port
);
1409 return traverse_msproxy (sok
, ip
, port
, state
, ns_proxy
, csok4
, csok6
, csok
, bound
);
1416 /* this is the child process making the connection attempt */
1419 server_child (server
* serv
)
1421 netstore
*ns_server
;
1422 netstore
*ns_proxy
= NULL
;
1424 int port
= serv
->port
;
1427 char *hostname
= serv
->hostname
;
1428 char *real_hostname
= NULL
;
1430 char *proxy_ip
= NULL
;
1436 char *proxy_host
= NULL
;
1439 ns_server
= net_store_new ();
1441 /* is a hostname set? - bind to it */
1442 if (prefs
.hostname
[0])
1444 ns_local
= net_store_new ();
1445 local_ip
= net_resolve (ns_local
, prefs
.hostname
, 0, &real_hostname
);
1446 if (local_ip
!= NULL
)
1448 snprintf (buf
, sizeof (buf
), "5\n%s\n", local_ip
);
1449 write (serv
->childwrite
, buf
, strlen (buf
));
1450 net_bind (ns_local
, serv
->sok4
, serv
->sok6
);
1454 write (serv
->childwrite
, "7\n", 2);
1456 net_store_destroy (ns_local
);
1459 if (!serv
->dont_use_proxy
) /* blocked in serverlist? */
1464 else if (prefs
.proxy_type
== 5)
1469 url
= g_strdup_printf ("irc://%s:%d", hostname
, port
);
1470 proxy_list
= px_proxy_factory_get_proxies (libproxy_factory
, url
);
1473 /* can use only one */
1474 proxy
= proxy_list
[0];
1475 if (!strncmp (proxy
, "direct", 6))
1477 else if (!strncmp (proxy
, "http", 4))
1479 else if (!strncmp (proxy
, "socks5", 6))
1481 else if (!strncmp (proxy
, "socks", 5))
1487 c
= strchr (proxy
, ':') + 3;
1488 proxy_host
= strdup (c
);
1489 c
= strchr (proxy_host
, ':');
1491 proxy_port
= atoi (c
+ 1);
1494 g_strfreev (proxy_list
);
1498 else if (prefs
.proxy_host
[0] &&
1499 prefs
.proxy_type
> 0 &&
1500 prefs
.proxy_use
!= 2) /* proxy is NOT dcc-only */
1502 proxy_type
= prefs
.proxy_type
;
1503 proxy_host
= strdup (prefs
.proxy_host
);
1504 proxy_port
= prefs
.proxy_port
;
1508 serv
->proxy_type
= proxy_type
;
1510 /* first resolve where we want to connect to */
1513 snprintf (buf
, sizeof (buf
), "9\n%s\n", proxy_host
);
1514 write (serv
->childwrite
, buf
, strlen (buf
));
1515 ip
= net_resolve (ns_server
, proxy_host
, proxy_port
, &real_hostname
);
1519 write (serv
->childwrite
, "1\n", 2);
1522 connect_port
= proxy_port
;
1524 /* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
1525 if ((proxy_type
== 2) || (proxy_type
== 5))
1527 ns_proxy
= net_store_new ();
1528 proxy_ip
= net_resolve (ns_proxy
, hostname
, port
, &real_hostname
);
1531 write (serv
->childwrite
, "1\n", 2);
1534 } else /* otherwise we can just use the hostname */
1535 proxy_ip
= strdup (hostname
);
1538 ip
= net_resolve (ns_server
, hostname
, port
, &real_hostname
);
1541 write (serv
->childwrite
, "1\n", 2);
1544 connect_port
= port
;
1547 snprintf (buf
, sizeof (buf
), "3\n%s\n%s\n%d\n",
1548 real_hostname
, ip
, connect_port
);
1549 write (serv
->childwrite
, buf
, strlen (buf
));
1551 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1552 error
= net_connect (ns_server
, serv
->proxy_sok4
, serv
->proxy_sok6
, &psok
);
1555 error
= net_connect (ns_server
, serv
->sok4
, serv
->sok6
, &sok
);
1561 snprintf (buf
, sizeof (buf
), "2\n%d\n", sock_error ());
1562 write (serv
->childwrite
, buf
, strlen (buf
));
1565 /* connect succeeded */
1568 switch (traverse_proxy (proxy_type
, serv
->childwrite
, psok
, proxy_ip
, port
, &serv
->msp_state
, ns_proxy
, serv
->sok4
, serv
->sok6
, &sok
, bound
))
1570 case 0: /* success */
1572 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1573 snprintf (buf
, sizeof (buf
), "4\n%d %d %d %d %d\n", sok
, psok
, serv
->msp_state
.clientid
, serv
->msp_state
.serverid
,
1574 serv
->msp_state
.seq_sent
);
1577 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1578 write (serv
->childwrite
, buf
, strlen (buf
));
1580 case 1: /* socks traversal failed */
1581 write (serv
->childwrite
, "8\n", 2);
1586 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1587 write (serv
->childwrite
, buf
, strlen (buf
));
1593 #if defined (USE_IPV6)
1594 /* this is probably not needed */
1595 net_store_destroy (ns_server
);
1597 net_store_destroy (ns_proxy
);
1600 /* no need to free ip/real_hostname, this process is exiting */
1606 server_connect (server
*serv
, char *hostname
, int port
, int no_login
)
1608 int pid
, read_des
[2];
1609 session
*sess
= serv
->server_session
;
1612 if (!serv
->ctx
&& serv
->use_ssl
)
1614 if (!(serv
->ctx
= _SSL_context_init (ssl_cb_info
)))
1616 fprintf (stderr
, "_SSL_context_init failed\n");
1627 /* use default port for this server type */
1634 port
&= 0xffff; /* wrap around */
1636 if (serv
->connected
|| serv
->connecting
|| serv
->recondelay_tag
)
1637 server_disconnect (sess
, TRUE
, -1);
1639 fe_progressbar_start (sess
);
1641 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, hostname
, NULL
, NULL
, NULL
, 0);
1643 safe_strcpy (serv
->servername
, hostname
, sizeof (serv
->servername
));
1644 /* overlap illegal in strncpy */
1645 if (hostname
!= serv
->hostname
)
1646 safe_strcpy (serv
->hostname
, hostname
, sizeof (serv
->hostname
));
1651 char cert_file
[256];
1652 serv
->have_cert
= FALSE
;
1654 /* first try network specific cert/key */
1655 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1656 get_xdir_fs (), server_get_network (serv
, TRUE
));
1657 if (SSL_CTX_use_certificate_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1659 if (SSL_CTX_use_PrivateKey_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1660 serv
->have_cert
= TRUE
;
1664 /* if that doesn't exist, try ~/.xchat2/client.pem */
1665 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1666 get_xdir_fs (), "client");
1667 if (SSL_CTX_use_certificate_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1669 if (SSL_CTX_use_PrivateKey_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1670 serv
->have_cert
= TRUE
;
1676 server_set_defaults (serv
);
1677 serv
->connecting
= TRUE
;
1679 serv
->no_login
= no_login
;
1681 fe_server_event (serv
, FE_SE_CONNECTING
, 0);
1683 server_flush_queue (serv
);
1685 if (pipe (read_des
) < 0)
1687 serv
->childread
= read_des
[0];
1688 serv
->childwrite
= read_des
[1];
1690 /* create both sockets now, drop one later */
1691 net_sockets (&serv
->sok4
, &serv
->sok6
);
1693 /* In case of MS Proxy we have a separate UDP control connection */
1694 if (!serv
->dont_use_proxy
&& (serv
->proxy_type
== 5))
1695 udp_sockets (&serv
->proxy_sok4
, &serv
->proxy_sok6
);
1699 serv
->proxy_sok4
= -1;
1700 serv
->proxy_sok6
= -1;
1704 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. */
1706 switch (pid
= fork ())
1712 /* this is the child */
1714 server_child (serv
);
1717 serv
->childpid
= pid
;
1718 serv
->iotag
= fe_input_add (serv
->childread
, FIA_READ
, server_read_child
,
1723 server_fill_her_up (server
*serv
)
1725 serv
->connect
= server_connect
;
1726 serv
->disconnect
= server_disconnect
;
1727 serv
->cleanup
= server_cleanup
;
1728 serv
->flush_queue
= server_flush_queue
;
1729 serv
->auto_reconnect
= auto_reconnect
;
1731 proto_fill_her_up (serv
);
1735 server_set_encoding (server
*serv
, char *new_encoding
)
1741 free (serv
->encoding
);
1742 /* can be left as NULL to indicate system encoding */
1743 serv
->encoding
= NULL
;
1744 serv
->using_cp1255
= FALSE
;
1745 serv
->using_irc
= FALSE
;
1750 serv
->encoding
= strdup (new_encoding
);
1751 /* the serverlist GUI might have added a space
1752 and short description - remove it. */
1753 space
= strchr (serv
->encoding
, ' ');
1757 /* server_inline() uses these flags */
1758 if (!strcasecmp (serv
->encoding
, "CP1255") ||
1759 !strcasecmp (serv
->encoding
, "WINDOWS-1255"))
1760 serv
->using_cp1255
= TRUE
;
1761 else if (!strcasecmp (serv
->encoding
, "IRC"))
1762 serv
->using_irc
= TRUE
;
1772 serv
= malloc (sizeof (struct server
));
1773 memset (serv
, 0, sizeof (struct server
));
1775 /* use server.c and proto-irc.c functions */
1776 server_fill_her_up (serv
);
1780 strcpy (serv
->nick
, prefs
.nick1
);
1781 server_set_defaults (serv
);
1783 serv_list
= g_slist_prepend (serv_list
, serv
);
1785 fe_new_server (serv
);
1791 is_server (server
*serv
)
1793 return g_slist_find (serv_list
, serv
) ? 1 : 0;
1797 server_set_defaults (server
*serv
)
1799 if (serv
->chantypes
)
1800 free (serv
->chantypes
);
1801 if (serv
->chanmodes
)
1802 free (serv
->chanmodes
);
1803 if (serv
->nick_prefixes
)
1804 free (serv
->nick_prefixes
);
1805 if (serv
->nick_modes
)
1806 free (serv
->nick_modes
);
1808 serv
->chantypes
= strdup ("#&!+");
1809 serv
->chanmodes
= strdup ("beI,k,l");
1810 serv
->nick_prefixes
= strdup ("@%+");
1811 serv
->nick_modes
= strdup ("ohv");
1813 serv
->nickcount
= 1;
1814 serv
->end_of_motd
= FALSE
;
1815 serv
->is_away
= FALSE
;
1816 serv
->supports_watch
= FALSE
;
1817 serv
->supports_monitor
= FALSE
;
1818 serv
->bad_prefix
= FALSE
;
1819 serv
->use_who
= TRUE
;
1820 serv
->have_namesx
= FALSE
;
1821 serv
->have_awaynotify
= FALSE
;
1822 serv
->have_uhnames
= FALSE
;
1823 serv
->have_whox
= FALSE
;
1824 serv
->have_idmsg
= FALSE
;
1825 serv
->have_accnotify
= FALSE
;
1826 serv
->have_extjoin
= FALSE
;
1827 serv
->have_sasl
= FALSE
;
1828 serv
->have_except
= FALSE
;
1832 server_get_network (server
*serv
, gboolean fallback
)
1835 return ((ircnet
*)serv
->network
)->name
;
1838 return serv
->servername
;
1844 server_set_name (server
*serv
, char *name
)
1846 GSList
*list
= sess_list
;
1850 name
= serv
->hostname
;
1852 /* strncpy parameters must NOT overlap */
1853 if (name
!= serv
->servername
)
1855 safe_strcpy (serv
->servername
, name
, sizeof (serv
->servername
));
1860 sess
= (session
*) list
->data
;
1861 if (sess
->server
== serv
)
1862 fe_set_title (sess
);
1866 if (serv
->server_session
->type
== SESS_SERVER
)
1870 safe_strcpy (serv
->server_session
->channel
, ((ircnet
*)serv
->network
)->name
, CHANLEN
);
1873 safe_strcpy (serv
->server_session
->channel
, name
, CHANLEN
);
1875 fe_set_channel (serv
->server_session
);
1880 server_away_find_message (server
*serv
, char *nick
)
1882 struct away_msg
*away
;
1883 GSList
*list
= away_list
;
1886 away
= (struct away_msg
*) list
->data
;
1887 if (away
->server
== serv
&& !serv
->p_cmp (nick
, away
->nick
))
1895 server_away_free_messages (server
*serv
)
1897 GSList
*list
, *next
;
1898 struct away_msg
*away
;
1905 if (away
->server
== serv
)
1907 away_list
= g_slist_remove (away_list
, away
);
1909 free (away
->message
);
1918 server_away_save_message (server
*serv
, char *nick
, char *msg
)
1920 struct away_msg
*away
= server_away_find_message (serv
, nick
);
1922 if (away
) /* Change message for known user */
1925 free (away
->message
);
1926 away
->message
= strdup (msg
);
1928 /* Create brand new entry */
1930 away
= malloc (sizeof (struct away_msg
));
1933 away
->server
= serv
;
1934 safe_strcpy (away
->nick
, nick
, sizeof (away
->nick
));
1935 away
->message
= strdup (msg
);
1936 away_list
= g_slist_prepend (away_list
, away
);
1942 server_free (server
*serv
)
1944 serv
->cleanup (serv
);
1946 serv_list
= g_slist_remove (serv_list
, serv
);
1948 dcc_notify_kill (serv
);
1949 serv
->flush_queue (serv
);
1950 server_away_free_messages (serv
);
1952 free (serv
->nick_modes
);
1953 free (serv
->nick_prefixes
);
1954 free (serv
->chanmodes
);
1955 free (serv
->chantypes
);
1956 if (serv
->bad_nick_prefixes
)
1957 free (serv
->bad_nick_prefixes
);
1958 if (serv
->last_away_reason
)
1959 free (serv
->last_away_reason
);
1961 free (serv
->encoding
);
1963 free (serv
->autojoin
);
1966 _SSL_context_free (serv
->ctx
);
1969 fe_server_callback (serv
);