restructure configure so pkg-config derived SSL flags get used
[rofl0r-ixchat.git] / src / common / servlist.c
blobbd652345929866ad69834836e7b1e124b2333209
1 /* X-Chat
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
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
26 #include "xchat.h"
27 #include <glib.h>
29 #include "cfgfiles.h"
30 #include "fe.h"
31 #include "server.h"
32 #include "text.h"
33 #include "util.h" /* token_foreach */
34 #include "xchatc.h"
36 #include "servlist.h"
39 struct defaultserver
41 char *network;
42 char *host;
43 char *channel;
44 char *charset;
45 int loginmode; /* default authentication type */
48 static const struct defaultserver def[] =
50 {"2600net", 0},
51 {0, "irc.2600.net"},
53 {"7-indonesia", 0},
54 {0, "irc.7-indonesia.org"},
56 {"AccessIRC", 0},
57 {0, "irc.accessirc.net"},
58 {0, "eu.accessirc.net"},
60 {"AfterNET", 0},
61 {0, "irc.afternet.org"},
62 {0, "us.afternet.org"},
63 {0, "eu.afternet.org"},
65 {"Aitvaras", 0},
66 #ifdef USE_IPV6
67 #ifdef USE_OPENSSL
68 {0, "irc6.ktu.lt/+7668"},
69 #endif
70 {0, "irc6.ktu.lt/7666"},
71 #endif
72 #ifdef USE_OPENSSL
73 {0, "irc.data.lt/+6668"},
74 {0, "irc-ssl.omnitel.net/+6668"},
75 {0, "irc-ssl.le.lt/+9999"},
76 #endif
77 {0, "irc.data.lt"},
78 {0, "irc.omnitel.net"},
79 {0, "irc.ktu.lt"},
80 {0, "irc.le.lt"},
81 {0, "irc.takas.lt"},
82 {0, "irc.5ci.net"},
83 {0, "irc.kis.lt"},
85 {"AmigaNet", 0},
86 {0, "irc.amiganet.org"},
87 {0, "us.amiganet.org"},
88 {0, "uk.amiganet.org"},
89 /* {0, "no.amiganet.org"},
90 {0, "au.amiganet.org"},*/
92 {"ARCNet", 0},
93 {0, "se1.arcnet.vapor.com"},
94 {0, "us1.arcnet.vapor.com"},
95 {0, "us2.arcnet.vapor.com"},
96 {0, "us3.arcnet.vapor.com"},
97 {0, "ca1.arcnet.vapor.com"},
98 {0, "de1.arcnet.vapor.com"},
99 {0, "de3.arcnet.vapor.com"},
100 {0, "ch1.arcnet.vapor.com"},
101 {0, "be1.arcnet.vapor.com"},
102 {0, "nl3.arcnet.vapor.com"},
103 {0, "uk1.arcnet.vapor.com"},
104 {0, "uk2.arcnet.vapor.com"},
105 /* {0, "uk3.arcnet.vapor.com"},*/
106 {0, "fr1.arcnet.vapor.com"},
108 {"AstroLink", 0},
109 {0, "irc.astrolink.org"},
111 {"AustNet", 0},
112 {0, "au.austnet.org"},
113 {0, "us.austnet.org"},
114 {0, "ca.austnet.org"},
116 /* {"AxeNet", 0},
117 {0, "irc.axenet.org"},
118 {0, "angel.axenet.org"},
119 {0, "energy.axenet.org"},
120 {0, "python.axenet.org"},*/
122 {"AzzurraNet", 0},
123 {0, "irc.azzurra.org"},
124 {0, "crypto.azzurra.org"},
126 {"Beirut", 0},
127 {0, "irc.beirut.com"},
129 {"ChattingAway", 0},
130 {0, "irc.chattingaway.com"},
132 {"ChatJunkies", 0, "#xchat"},
133 {0, "irc.chatjunkies.org"},
134 {0, "nl.chatjunkies.org"},
136 {"ChatNet", 0},
137 {0, "US.ChatNet.Org"},
138 {0, "EU.ChatNet.Org"},
140 {"ChatSociety", 0},
141 {0, "us.chatsociety.net"},
142 {0, "eu.chatsociety.net"},
144 {"ChatSpike", 0},
145 {0, "irc.chatspike.net"},
147 {"CoolChat", 0},
148 {0, "irc.coolchat.net"},
149 /* {0, "unix.coolchat.net"},
150 {0, "toronto.coolchat.net"},*/
152 {"Criten", 0},
153 {0, "irc.criten.net"},
154 {0, "irc.eu.criten.net"},
156 {"DALnet", 0},
157 {0, "irc.dal.net"},
158 {0, "irc.eu.dal.net"},
160 {"Dark-Tou-Net", 0},
161 {0, "irc.d-t-net.de"},
162 {0, "bw.d-t-net.de"},
163 {0, "nc.d-t-net.de"},
164 {0, "wakka.d-t-net.de"},
166 {"DarkMyst", 0},
167 {0, "irc.darkmyst.org"},
169 {"DeepIRC", 0},
170 {0, "irc.deepirc.net"},
172 {"DeltaAnime", 0},
173 {0, "irc.deltaanime.net"},
175 {"EFnet", 0},
176 {0, "irc.blackened.com"},
177 {0, "irc.Prison.NET"},
178 {0, "irc.Qeast.net"},
179 {0, "irc.efnet.pl"},
180 {0, "efnet.demon.co.uk"},
181 /* {0, "irc.lagged.org"},*/
182 {0, "irc.lightning.net"},
183 {0, "irc.mindspring.com"},
184 {0, "irc.easynews.com"},
185 {0, "irc.servercentral.net"},
187 {"EnterTheGame", 0},
188 {0, "IRC.EnterTheGame.Com"},
190 {"EsperNet", 0},
191 {0, "irc.esper.net/+6697"},
192 {0, "na.irc.esper.net/+6697"},
193 {0, "eu.irc.esper.net/+6697"},
195 {"EUIrc", 0},
196 {0, "irc.euirc.net"},
197 {0, "irc.ham.de.euirc.net"},
198 {0, "irc.ber.de.euirc.net"},
199 {0, "irc.ffm.de.euirc.net"},
200 {0, "irc.bre.de.euirc.net"},
201 {0, "irc.hes.de.euirc.net"},
202 {0, "irc.vie.at.euirc.net"},
203 {0, "irc.inn.at.euirc.net"},
204 {0, "irc.bas.ch.euirc.net"},
206 {"EuropNet", 0},
207 {0, "irc.europnet.org"},
209 {"EU-IRC", 0},
210 {0, "irc.eu-irc.net"},
212 {"FDFNet", 0},
213 {0, "irc.fdfnet.net"},
214 {0, "irc.eu.fdfnet.net"},
216 {"FEFNet", 0},
217 {0, "irc.fef.net"},
218 {0, "irc.ggn.net"},
219 {0, "irc.vendetta.com"},
221 {"freenode", 0, "#xchat", 0, LOGIN_SASL},
222 {0, "chat.freenode.net/+6697"},
224 /* {"Freeworld", 0},
225 {0, "kabel.freeworld.nu"},
226 {0, "irc.freeworld.nu"},*/
228 {"GalaxyNet", 0},
229 {0, "irc.galaxynet.org"},
230 /* {0, "sprynet.us.galaxynet.org"},
231 {0, "atlanta.ga.us.galaxynet.org"},*/
233 {"GamesNET", 0},
234 {0, "irc.gamesnet.net"},
235 /* {0, "irc.us.gamesnet.net"},
236 {0, "east.us.gamesnet.net"},
237 {0, "west.us.gamesnet.net"},*/
238 {0, "irc.ca.gamesnet.net"},
239 {0, "irc.eu.gamesnet.net"},
241 {"GeekShed", 0},
242 {0, "irc.geekshed.net"},
244 {"German-Elite", 0},
245 {0, "dominion.german-elite.net"},
246 {0, "komatu.german-elite.net"},
247 /* {0, "liberty.german-elite.net"},*/
249 {"GimpNet", 0},
250 {0, "irc.gimp.org"},
251 /* {0, "irc.au.gimp.org"},*/
252 {0, "irc.us.gimp.org"},
254 {"HabberNet", 0},
255 {0, "irc.habber.net"},
257 {"Hashmark", 0},
258 {0, "irc.hashmark.net"},
260 {"IdleMonkeys", 0},
261 {0, "irc.idlemonkeys.net"},
263 /* {"Infinity-IRC", 0},
264 {0, "Atlanta.GA.US.Infinity-IRC.Org"},
265 {0, "Babylon.NY.US.Infinity-IRC.Org"},
266 {0, "Sunshine.Ca.US.Infinity-IRC.Org"},
267 {0, "IRC.Infinity-IRC.Org"},*/
269 {"iZ-smart.net", 0},
270 {0, "irc.iZ-smart.net/6666"},
271 {0, "irc.iZ-smart.net/6667"},
272 {0, "irc.iZ-smart.net/6668"},
274 {"IrcLink", 0},
275 {0, "irc.irclink.net"},
276 {0, "Alesund.no.eu.irclink.net"},
277 {0, "Oslo.no.eu.irclink.net"},
278 {0, "frogn.no.eu.irclink.net"},
279 {0, "tonsberg.no.eu.irclink.net"},
281 {"IRCNet", 0},
282 {0, "irc.ircnet.com"},
283 {0, "irc.stealth.net/6668"},
284 {0, "ircnet.demon.co.uk"},
285 /* {0, "ircnet.hinet.hr"},*/
286 {0, "irc.datacomm.ch"},
287 /* {0, "ircnet.kaptech.fr"},
288 {0, "ircnet.easynet.co.uk"},*/
289 {0, "random.ircd.de"},
290 {0, "ircnet.netvision.net.il"},
291 /* {0, "irc.seed.net.tw"},*/
292 {0, "irc.cs.hut.fi"},
294 {"Irctoo.net", 0},
295 {0, "irc.irctoo.net"},
297 {"Krstarica", 0},
298 {0, "irc.krstarica.com"},
300 {"Librenet", 0},
301 {0, "irc.librenet.net"},
302 {0, "ielf.fr.librenet.net"},
304 {"LinkNet", 0},
305 {0, "irc.link-net.org"},
306 {0, "irc.no.link-net.org"},
307 /* {0, "irc.gamesden.net.au"},*/
308 {0, "irc.bahnhof.se"},
309 /* {0, "irc.kinexuseurope.co.uk"},
310 {0, "irc.gamiix.com"},*/
312 {"MagicStar", 0},
313 {0, "irc.magicstar.net"},
315 {"Majistic", 0},
316 {0, "irc.majistic.net"},
318 {"MindForge", 0},
319 {0, "irc.mindforge.org"},
321 {"MintIRC", 0},
322 {0, "irc.mintirc.net"},
324 {"MIXXnet", 0},
325 {0, "irc.mixxnet.net"},
327 {"NeverNET", 0},
328 {0, "irc.nevernet.net"},
329 {0, "imagine.nevernet.net"},
330 {0, "dimension.nevernet.net"},
331 {0, "universe.nevernet.net"},
332 {0, "wayland.nevernet.net"},
333 {0, "forte.nevernet.net"},
335 {"NixHelpNet", 0},
336 {0, "irc.nixhelp.org"},
337 {0, "us.nixhelp.org"},
338 {0, "uk.nixhelp.org"},
339 {0, "uk2.nixhelp.org"},
340 {0, "uk3.nixhelp.org"},
341 {0, "nl.nixhelp.org"},
342 {0, "ca.ld.nixhelp.org"},
343 {0, "us.co.nixhelp.org"},
344 {0, "us.ca.nixhelp.org"},
345 {0, "us.pa.nixhelp.org"},
347 {"NullusNet", 0},
348 {0, "irc.nullus.net"},
350 {"Oceanius", 0},
351 {0, "irc.oceanius.com"},
353 {"OFTC", 0},
354 {0, "irc.oftc.net/+6697"},
356 {"OtherNet", 0},
357 {0, "irc.othernet.org"},
359 {"OzNet", 0},
360 {0, "irc.oz.org"},
362 {"PIRC.PL", 0},
363 {0, "irc.pirc.pl"},
365 {"PTlink", 0},
366 {0, "irc.PTlink.net"},
367 {0, "aaia.PTlink.net"},
369 {"PTNet.org", 0},
370 {0, "irc.PTNet.org"},
371 {0, "world.PTnet.org"},
372 {0, "netvisao.PTnet.org"},
373 {0, "uevora.PTnet.org"},
374 {0, "vianetworks.PTnet.org"},
375 {0, "uc.PTnet.org"},
376 {0, "nfsi.ptnet.org"},
378 {"QuakeNet", 0, 0, 0, LOGIN_CHALLENGEAUTH},
379 {0, "irc.quakenet.org"},
380 {0, "irc.se.quakenet.org"},
381 {0, "irc.dk.quakenet.org"},
382 {0, "irc.no.quakenet.org"},
383 {0, "irc.fi.quakenet.org"},
384 {0, "irc.be.quakenet.org"},
385 {0, "irc.uk.quakenet.org"},
386 {0, "irc.de.quakenet.org"},
387 {0, "irc.it.quakenet.org"},
389 {"RebelChat", 0},
390 {0, "irc.rebelchat.org"},
392 /* {"Recycled-IRC", 0},
393 {0, "irc.recycled-irc.org"},
394 {0, "vermin.recycled-irc.org"},
395 {0, "waste.recycled-irc.org"},
396 {0, "lumber.recycled-irc.org"},
397 {0, "trash.recycled-irc.org"},
398 {0, "unwashed.recycled-irc.org"},
399 {0, "garbage.recycled-irc.org"},
400 {0, "dustbin.recycled-irc.org"},*/
402 {"RizeNET", 0},
403 {0, "irc.rizenet.org"},
404 {0, "omega.rizenet.org"},
405 {0, "evelance.rizenet.org"},
406 {0, "lisa.rizenet.org"},
407 {0, "scott.rizenet.org"},
409 {"Rizon", 0},
410 {0, "irc.rizon.net/+6697"},
412 {"RusNet", 0, 0, "KOI8-R (Cyrillic)"},
413 {0, "irc.tomsk.net"},
414 {0, "irc.rinet.ru"},
415 {0, "irc.run.net"},
416 {0, "irc.ru"},
417 {0, "irc.lucky.net"},
419 {"SceneNet", 0},
420 {0, "irc.scene.org"},
421 {0, "irc.eu.scene.org"},
422 {0, "irc.us.scene.org"},
424 {"SeilEn.de", 0},
425 {0, "irc.seilen.de"},
427 {"SlashNET", 0},
428 {0, "irc.slashnet.org"},
429 {0, "area51.slashnet.org"},
430 {0, "moo.slashnet.org"},
431 {0, "radon.slashnet.org"},
433 {"Sohbet.Net", 0},
434 {0, "irc.sohbet.net"},
436 {"SolidIRC", 0},
437 {0, "irc.solidirc.com"},
439 {"SorceryNet", 0},
440 {0, "irc.sorcery.net/9000"},
441 {0, "irc.us.sorcery.net/9000"},
442 {0, "irc.eu.sorcery.net/9000"},
444 {"Spidernet", 0},
445 {0, "us.spidernet.org"},
446 {0, "eu.spidernet.org"},
447 {0, "irc.spidernet.org"},
449 {"StarChat", 0},
450 {0, "irc.starchat.net"},
451 {0, "gainesville.starchat.net"},
452 {0, "freebsd.starchat.net"},
453 {0, "sunset.starchat.net"},
454 {0, "revenge.starchat.net"},
455 {0, "tahoma.starchat.net"},
456 {0, "neo.starchat.net"},
458 {"TNI3", 0},
459 {0, "irc.tni3.com"},
461 {"TURLINet", 0},
462 {0, "irc.turli.net"},
463 {0, "irc.servx.ru"},
464 {0, "irc.gavnos.ru"},
466 {"UnderNet", 0, 0, 0, LOGIN_CUSTOM},
467 {0, "us.undernet.org"},
468 {0, "eu.undernet.org"},
470 {"UniBG", 0, 0, 0, LOGIN_CUSTOM},
471 {0, "irc.lirex.com"},
472 {0, "irc.naturella.com"},
473 {0, "irc.spnet.net"},
474 {0, "irc.techno-link.com"},
475 {0, "irc.telecoms.bg"},
476 {0, "irc.tu-varna.edu"},
478 {"Whiffle", 0},
479 {0, "irc.whiffle.org"},
481 {"Worldnet", 0},
482 {0, "irc.worldnet.net"},
483 {0, "irc.fr.worldnet.net"},
485 {"Xentonix.net", 0},
486 {0, "irc.xentonix.net"},
488 {"XWorld", 0},
489 {0, "Buffalo.NY.US.XWorld.org"},
490 {0, "Minneapolis.MN.US.Xworld.Org"},
491 {0, "Rochester.NY.US.XWorld.org"},
492 {0, "Bayern.DE.EU.XWorld.Org"},
493 {0, "Chicago.IL.US.XWorld.Org"},
495 {0,0}
498 GSList *network_list = 0;
501 void
502 servlist_connect (session *sess, ircnet *net, gboolean join)
504 ircserver *ircserv;
505 GSList *list;
506 char *port;
507 server *serv;
509 if (!sess)
510 sess = new_ircwindow (NULL, NULL, SESS_SERVER, TRUE);
512 serv = sess->server;
514 /* connect to the currently selected Server-row */
515 list = g_slist_nth (net->servlist, net->selected);
516 if (!list)
517 list = net->servlist;
518 if (!list)
519 return;
520 ircserv = list->data;
522 /* incase a protocol switch is added to the servlist gui */
523 server_fill_her_up (sess->server);
525 if (join)
527 sess->willjoinchannel[0] = 0;
529 if (net->autojoin)
531 if (serv->autojoin)
532 free (serv->autojoin);
533 serv->autojoin = strdup (net->autojoin);
537 if (net->logintype)
539 serv->loginmethod = net->logintype;
541 else
543 serv->loginmethod = LOGIN_DEFAULT_REAL;
546 serv->password[0] = 0;
548 if (net->pass)
549 safe_strcpy (serv->password, net->pass, sizeof (serv->password));
551 if (net->flags & FLAG_USE_GLOBAL)
553 strcpy (serv->nick, prefs.nick1);
554 } else
556 if (net->nick) {
557 strcpy (serv->nick, net->nick);
561 serv->dont_use_proxy = (net->flags & FLAG_USE_PROXY) ? FALSE : TRUE;
563 #ifdef USE_OPENSSL
564 serv->use_ssl = (net->flags & FLAG_USE_SSL) ? TRUE : FALSE;
565 serv->accept_invalid_cert =
566 (net->flags & FLAG_ALLOW_INVALID) ? TRUE : FALSE;
567 #endif
569 serv->network = net;
571 port = strrchr (ircserv->hostname, '/');
572 if (port)
574 *port = 0;
576 /* support "+port" to indicate SSL (like mIRC does) */
577 if (port[1] == '+')
579 #ifdef USE_OPENSSL
580 serv->use_ssl = TRUE;
581 #endif
582 serv->connect (serv, ircserv->hostname, atoi (port + 2), FALSE);
583 } else
585 serv->connect (serv, ircserv->hostname, atoi (port + 1), FALSE);
588 *port = '/';
589 } else
590 serv->connect (serv, ircserv->hostname, -1, FALSE);
592 server_set_encoding (serv, net->encoding);
596 servlist_connect_by_netname (session *sess, char *network, gboolean join)
598 ircnet *net;
599 GSList *list = network_list;
601 while (list)
603 net = list->data;
605 if (strcasecmp (net->name, network) == 0)
607 servlist_connect (sess, net, join);
608 return 1;
611 list = list->next;
614 return 0;
618 servlist_have_auto (void)
620 GSList *list = network_list;
621 ircnet *net;
623 while (list)
625 net = list->data;
627 if (net->flags & FLAG_AUTO_CONNECT)
628 return 1;
630 list = list->next;
633 return 0;
637 servlist_auto_connect (session *sess)
639 GSList *list = network_list;
640 ircnet *net;
641 int ret = 0;
643 while (list)
645 net = list->data;
647 if (net->flags & FLAG_AUTO_CONNECT)
649 servlist_connect (sess, net, TRUE);
650 ret = 1;
653 list = list->next;
656 return ret;
659 static gint
660 servlist_cycle_cb (server *serv)
662 if (serv->network)
664 PrintTextf (serv->server_session,
665 _("Cycling to next server in %s...\n"), ((ircnet *)serv->network)->name);
666 servlist_connect (serv->server_session, serv->network, TRUE);
669 return 0;
673 servlist_cycle (server *serv)
675 ircnet *net;
676 int max, del;
678 net = serv->network;
679 if (net)
681 max = g_slist_length (net->servlist);
682 if (max > 0)
684 /* try the next server, if that option is on */
685 if (net->flags & FLAG_CYCLE)
687 net->selected++;
688 if (net->selected >= max)
689 net->selected = 0;
692 del = prefs.recon_delay * 1000;
693 if (del < 1000)
694 del = 500; /* so it doesn't block the gui */
696 if (del)
697 serv->recondelay_tag = fe_timeout_add (del, servlist_cycle_cb, serv);
698 else
699 servlist_connect (serv->server_session, net, TRUE);
701 return TRUE;
705 return FALSE;
708 ircserver *
709 servlist_server_find (ircnet *net, char *name, int *pos)
711 GSList *list = net->servlist;
712 ircserver *serv;
713 int i = 0;
715 while (list)
717 serv = list->data;
718 if (strcmp (serv->hostname, name) == 0)
720 if (pos)
721 *pos = i;
722 return serv;
724 i++;
725 list = list->next;
728 return NULL;
731 /* find a network (e.g. (ircnet *) to "FreeNode") from a hostname
732 (e.g. "irc.eu.freenode.net") */
734 ircnet *
735 servlist_net_find_from_server (char *server_name)
737 GSList *list = network_list;
738 GSList *slist;
739 ircnet *net;
740 ircserver *serv;
742 while (list)
744 net = list->data;
746 slist = net->servlist;
747 while (slist)
749 serv = slist->data;
750 if (strcasecmp (serv->hostname, server_name) == 0)
751 return net;
752 slist = slist->next;
755 list = list->next;
758 return NULL;
761 ircnet *
762 servlist_net_find (char *name, int *pos, int (*cmpfunc) (const char *, const char *))
764 GSList *list = network_list;
765 ircnet *net;
766 int i = 0;
768 while (list)
770 net = list->data;
771 if (cmpfunc (net->name, name) == 0)
773 if (pos)
774 *pos = i;
775 return net;
777 i++;
778 list = list->next;
781 return NULL;
784 ircserver *
785 servlist_server_add (ircnet *net, char *name)
787 ircserver *serv;
789 serv = malloc (sizeof (ircserver));
790 memset (serv, 0, sizeof (ircserver));
791 serv->hostname = strdup (name);
793 net->servlist = g_slist_append (net->servlist, serv);
795 return serv;
798 void
799 servlist_server_remove (ircnet *net, ircserver *serv)
801 free (serv->hostname);
802 free (serv);
803 net->servlist = g_slist_remove (net->servlist, serv);
806 static void
807 servlist_server_remove_all (ircnet *net)
809 ircserver *serv;
811 while (net->servlist)
813 serv = net->servlist->data;
814 servlist_server_remove (net, serv);
818 static void
819 free_and_clear (char *str)
821 if (str)
823 char *orig = str;
824 while (*str)
825 *str++ = 0;
826 free (orig);
830 /* executed on exit: Clear any password strings */
832 void
833 servlist_cleanup (void)
835 GSList *list;
836 ircnet *net;
838 for (list = network_list; list; list = list->next)
840 net = list->data;
841 free_and_clear (net->pass);
845 void
846 servlist_net_remove (ircnet *net)
848 GSList *list;
849 server *serv;
851 servlist_server_remove_all (net);
852 network_list = g_slist_remove (network_list, net);
854 if (net->nick)
855 free (net->nick);
856 if (net->nick2)
857 free (net->nick2);
858 if (net->user)
859 free (net->user);
860 if (net->real)
861 free (net->real);
862 free_and_clear (net->pass);
863 if (net->autojoin)
864 free (net->autojoin);
865 if (net->command)
866 free (net->command);
867 if (net->comment)
868 free (net->comment);
869 if (net->encoding)
870 free (net->encoding);
871 free (net->name);
872 free (net);
874 /* for safety */
875 list = serv_list;
876 while (list)
878 serv = list->data;
879 if (serv->network == net)
880 serv->network = NULL;
881 list = list->next;
885 ircnet *
886 servlist_net_add (char *name, char *comment, int prepend)
888 ircnet *net;
890 net = malloc (sizeof (ircnet));
891 memset (net, 0, sizeof (ircnet));
892 net->name = strdup (name);
893 /* net->comment = strdup (comment);*/
894 net->flags = FLAG_CYCLE | FLAG_USE_GLOBAL | FLAG_USE_PROXY;
896 if (prepend)
897 network_list = g_slist_prepend (network_list, net);
898 else
899 network_list = g_slist_append (network_list, net);
901 return net;
904 static void
905 servlist_load_defaults (void)
907 int i = 0, j = 0;
908 ircnet *net = NULL;
910 while (1)
912 if (def[i].network)
914 net = servlist_net_add (def[i].network, def[i].host, FALSE);
915 net->encoding = strdup ("UTF-8 (Unicode)");
916 if (def[i].channel)
917 net->autojoin = strdup (def[i].channel);
918 if (def[i].charset)
920 free (net->encoding);
921 net->encoding = strdup (def[i].charset);
923 if (def[i].loginmode)
925 net->logintype = def[i].loginmode;
927 if (g_str_hash (def[i].network) == 0x8e1b96f7)
928 prefs.slist_select = j;
929 j++;
930 } else
932 servlist_server_add (net, def[i].host);
933 if (!def[i+1].host && !def[i+1].network)
934 break;
936 i++;
940 static int
941 servlist_load (void)
943 FILE *fp;
944 char buf[2048];
945 int len;
946 char *tmp;
947 ircnet *net = NULL;
949 fp = xchat_fopen_file ("servlist_.conf", "r", 0);
950 if (!fp)
951 return FALSE;
953 while (fgets (buf, sizeof (buf) - 2, fp))
955 len = strlen (buf);
956 buf[len] = 0;
957 buf[len-1] = 0; /* remove the trailing \n */
958 if (net)
960 switch (buf[0])
962 case 'I':
963 net->nick = strdup (buf + 2);
964 break;
965 case 'i':
966 net->nick2 = strdup (buf + 2);
967 break;
968 case 'U':
969 net->user = strdup (buf + 2);
970 break;
971 case 'R':
972 net->real = strdup (buf + 2);
973 break;
974 case 'P':
975 net->pass = strdup (buf + 2);
976 break;
977 case 'J':
978 net->autojoin = strdup (buf + 2);
979 break;
980 case 'C':
981 if (net->command)
983 /* concat extra commands with a \n separator */
984 tmp = net->command;
985 net->command = malloc (strlen (tmp) + strlen (buf + 2) + 2);
986 strcpy (net->command, tmp);
987 strcat (net->command, "\n");
988 strcat (net->command, buf + 2);
989 free (tmp);
990 } else
991 net->command = strdup (buf + 2);
992 break;
993 case 'F':
994 net->flags = atoi (buf + 2);
995 break;
996 case 'D':
997 net->selected = atoi (buf + 2);
998 break;
999 case 'E':
1000 net->encoding = strdup (buf + 2);
1001 break;
1002 case 'S': /* new server/hostname for this network */
1003 servlist_server_add (net, buf + 2);
1004 break;
1005 case 'L':
1006 net->logintype = atoi (buf + 2);
1007 break;
1010 if (buf[0] == 'N')
1011 net = servlist_net_add (buf + 2, /* comment */ NULL, FALSE);
1013 fclose (fp);
1015 return TRUE;
1018 void
1019 servlist_init (void)
1021 if (!network_list)
1022 if (!servlist_load ())
1023 servlist_load_defaults ();
1026 /* check if a charset is known by Iconv */
1028 servlist_check_encoding (char *charset)
1030 GIConv gic;
1031 char *c;
1033 c = strchr (charset, ' ');
1034 if (c)
1035 c[0] = 0;
1037 if (!strcasecmp (charset, "IRC")) /* special case */
1039 if (c)
1040 c[0] = ' ';
1041 return TRUE;
1044 gic = g_iconv_open (charset, "UTF-8");
1046 if (c)
1047 c[0] = ' ';
1049 if (gic != (GIConv)-1)
1051 g_iconv_close (gic);
1052 return TRUE;
1055 return FALSE;
1058 static int
1059 servlist_write_ccmd (char *str, void *fp)
1061 return fprintf (fp, "C=%s\n", (str[0] == '/') ? str + 1 : str);
1066 servlist_save (void)
1068 FILE *fp;
1069 char buf[256];
1070 ircnet *net;
1071 ircserver *serv;
1072 GSList *list;
1073 GSList *hlist;
1074 int first = FALSE;
1076 snprintf (buf, sizeof (buf), "%s/servlist_.conf", get_xdir_fs ());
1077 if (access (buf, F_OK) != 0)
1078 first = TRUE;
1080 fp = xchat_fopen_file ("servlist_.conf", "w", 0);
1081 if (!fp)
1082 return FALSE;
1084 if (first)
1085 chmod (buf, 0600);
1087 fprintf (fp, "v="PACKAGE_VERSION"\n\n");
1089 list = network_list;
1090 while (list)
1092 net = list->data;
1094 fprintf (fp, "N=%s\n", net->name);
1095 if (net->nick)
1096 fprintf (fp, "I=%s\n", net->nick);
1097 if (net->nick2)
1098 fprintf (fp, "i=%s\n", net->nick2);
1099 if (net->user)
1100 fprintf (fp, "U=%s\n", net->user);
1101 if (net->real)
1102 fprintf (fp, "R=%s\n", net->real);
1103 if (net->pass)
1104 fprintf (fp, "P=%s\n", net->pass);
1105 if (net->autojoin)
1106 fprintf (fp, "J=%s\n", net->autojoin);
1107 if (net->logintype)
1108 fprintf (fp, "L=%d\n", net->logintype);
1109 if (net->encoding && strcasecmp (net->encoding, "System") &&
1110 strcasecmp (net->encoding, "System default"))
1112 fprintf (fp, "E=%s\n", net->encoding);
1113 if (!servlist_check_encoding (net->encoding))
1115 snprintf (buf, sizeof (buf), _("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."),
1116 net->encoding, net->name);
1117 fe_message (buf, FE_MSG_WARN);
1121 if (net->command)
1122 token_foreach (net->command, '\n', servlist_write_ccmd, fp);
1124 fprintf (fp, "F=%d\nD=%d\n", net->flags, net->selected);
1126 hlist = net->servlist;
1127 while (hlist)
1129 serv = hlist->data;
1130 fprintf (fp, "S=%s\n", serv->hostname);
1131 hlist = hlist->next;
1134 if (fprintf (fp, "\n") < 1)
1136 fclose (fp);
1137 return FALSE;
1140 list = list->next;
1143 fclose (fp);
1144 return TRUE;
1147 static void
1148 joinlist_free1 (GSList *list)
1150 GSList *head = list;
1152 for (; list; list = list->next)
1153 g_free (list->data);
1154 g_slist_free (head);
1157 void
1158 joinlist_free (GSList *channels, GSList *keys)
1160 joinlist_free1 (channels);
1161 joinlist_free1 (keys);
1164 gboolean
1165 joinlist_is_in_list (server *serv, char *channel)
1167 GSList *channels, *keys;
1168 GSList *list;
1170 if (!serv->network || !((ircnet *)serv->network)->autojoin)
1171 return FALSE;
1173 joinlist_split (((ircnet *)serv->network)->autojoin, &channels, &keys);
1175 for (list = channels; list; list = list->next)
1177 if (serv->p_cmp (list->data, channel) == 0)
1178 return TRUE;
1181 joinlist_free (channels, keys);
1183 return FALSE;
1186 gchar *
1187 joinlist_merge (GSList *channels, GSList *keys)
1189 GString *out = g_string_new (NULL);
1190 GSList *list;
1191 int i, j;
1193 for (; channels; channels = channels->next)
1195 g_string_append (out, channels->data);
1197 if (channels->next)
1198 g_string_append_c (out, ',');
1201 /* count number of REAL keys */
1202 for (i = 0, list = keys; list; list = list->next)
1203 if (list->data)
1204 i++;
1206 if (i > 0)
1208 g_string_append_c (out, ' ');
1210 for (j = 0; keys; keys = keys->next)
1212 if (keys->data)
1214 g_string_append (out, keys->data);
1215 j++;
1216 if (j == i)
1217 break;
1220 if (keys->next)
1221 g_string_append_c (out, ',');
1225 return g_string_free (out, FALSE);
1228 void
1229 joinlist_split (char *autojoin, GSList **channels, GSList **keys)
1231 char *parta, *partb;
1232 char *chan, *key;
1233 int len;
1235 *channels = NULL;
1236 *keys = NULL;
1238 /* after the first space, the keys begin */
1239 parta = autojoin;
1240 partb = strchr (autojoin, ' ');
1241 if (partb)
1242 partb++;
1244 while (1)
1246 chan = parta;
1247 key = partb;
1249 if (1)
1251 while (parta[0] != 0 && parta[0] != ',' && parta[0] != ' ')
1253 parta++;
1257 if (partb)
1259 while (partb[0] != 0 && partb[0] != ',' && partb[0] != ' ')
1261 partb++;
1265 len = parta - chan;
1266 if (len < 1)
1267 break;
1268 *channels = g_slist_append (*channels, g_strndup (chan, len));
1270 len = partb - key;
1271 *keys = g_slist_append (*keys, len ? g_strndup (key, len) : NULL);
1273 if (parta[0] == ' ' || parta[0] == 0)
1274 break;
1275 parta++;
1277 if (partb)
1279 if (partb[0] == 0 || partb[0] == ' ')
1280 partb = NULL; /* no more keys, but maybe more channels? */
1281 else
1282 partb++;
1286 #if 0
1287 GSList *lista, *listb;
1288 int i;
1290 printf("-----\n");
1291 i = 0;
1292 lista = *channels;
1293 listb = *keys;
1294 while (lista)
1296 printf("%d. |%s| |%s|\n", i, lista->data, listb->data);
1297 i++;
1298 lista = lista->next;
1299 listb = listb->next;
1301 printf("-----\n\n");
1302 #endif