configure: add stuff for spell checking
[rofl0r-ixchat.git] / src / common / servlist.c
blob66bc8115b13a42c90158938959e656a1debfb58a
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;
47 static const struct defaultserver def[] =
49 {"2600net", 0},
50 {0, "irc.2600.net"},
52 {"7-indonesia", 0},
53 {0, "irc.7-indonesia.org"},
55 {"AccessIRC", 0},
56 {0, "irc.accessirc.net"},
57 {0, "eu.accessirc.net"},
59 {"AfterNET", 0},
60 {0, "irc.afternet.org"},
61 {0, "us.afternet.org"},
62 {0, "eu.afternet.org"},
64 {"Aitvaras", 0},
65 #ifdef USE_IPV6
66 #ifdef USE_OPENSSL
67 {0, "irc6.ktu.lt/+7668"},
68 #endif
69 {0, "irc6.ktu.lt/7666"},
70 #endif
71 #ifdef USE_OPENSSL
72 {0, "irc.data.lt/+6668"},
73 {0, "irc-ssl.omnitel.net/+6668"},
74 {0, "irc-ssl.le.lt/+9999"},
75 #endif
76 {0, "irc.data.lt"},
77 {0, "irc.omnitel.net"},
78 {0, "irc.ktu.lt"},
79 {0, "irc.le.lt"},
80 {0, "irc.takas.lt"},
81 {0, "irc.5ci.net"},
82 {0, "irc.kis.lt"},
84 {"AmigaNet", 0},
85 {0, "irc.amiganet.org"},
86 {0, "us.amiganet.org"},
87 {0, "uk.amiganet.org"},
88 /* {0, "no.amiganet.org"},
89 {0, "au.amiganet.org"},*/
91 {"ARCNet", 0},
92 {0, "se1.arcnet.vapor.com"},
93 {0, "us1.arcnet.vapor.com"},
94 {0, "us2.arcnet.vapor.com"},
95 {0, "us3.arcnet.vapor.com"},
96 {0, "ca1.arcnet.vapor.com"},
97 {0, "de1.arcnet.vapor.com"},
98 {0, "de3.arcnet.vapor.com"},
99 {0, "ch1.arcnet.vapor.com"},
100 {0, "be1.arcnet.vapor.com"},
101 {0, "nl3.arcnet.vapor.com"},
102 {0, "uk1.arcnet.vapor.com"},
103 {0, "uk2.arcnet.vapor.com"},
104 /* {0, "uk3.arcnet.vapor.com"},*/
105 {0, "fr1.arcnet.vapor.com"},
107 {"AstroLink", 0},
108 {0, "irc.astrolink.org"},
110 {"AustNet", 0},
111 {0, "au.austnet.org"},
112 {0, "us.austnet.org"},
113 {0, "ca.austnet.org"},
115 /* {"AxeNet", 0},
116 {0, "irc.axenet.org"},
117 {0, "angel.axenet.org"},
118 {0, "energy.axenet.org"},
119 {0, "python.axenet.org"},*/
121 {"AzzurraNet", 0},
122 {0, "irc.azzurra.org"},
123 {0, "crypto.azzurra.org"},
125 {"Beirut", 0},
126 {0, "irc.beirut.com"},
128 {"ChattingAway", 0},
129 {0, "irc.chattingaway.com"},
131 {"ChatJunkies", 0, "#xchat"},
132 {0, "irc.chatjunkies.org"},
133 {0, "nl.chatjunkies.org"},
135 {"ChatNet", 0},
136 {0, "US.ChatNet.Org"},
137 {0, "EU.ChatNet.Org"},
139 {"ChatSociety", 0},
140 {0, "us.chatsociety.net"},
141 {0, "eu.chatsociety.net"},
143 {"ChatSpike", 0},
144 {0, "irc.chatspike.net"},
146 {"CoolChat", 0},
147 {0, "irc.coolchat.net"},
148 /* {0, "unix.coolchat.net"},
149 {0, "toronto.coolchat.net"},*/
151 {"Criten", 0},
152 {0, "irc.criten.net"},
153 {0, "irc.eu.criten.net"},
155 {"DALnet", 0},
156 {0, "irc.dal.net"},
157 {0, "irc.eu.dal.net"},
159 {"Dark-Tou-Net", 0},
160 {0, "irc.d-t-net.de"},
161 {0, "bw.d-t-net.de"},
162 {0, "nc.d-t-net.de"},
163 {0, "wakka.d-t-net.de"},
165 {"DarkMyst", 0},
166 {0, "irc.darkmyst.org"},
168 {"DeepIRC", 0},
169 {0, "irc.deepirc.net"},
171 {"DeltaAnime", 0},
172 {0, "irc.deltaanime.net"},
174 {"EFnet", 0},
175 {0, "irc.blackened.com"},
176 {0, "irc.Prison.NET"},
177 {0, "irc.Qeast.net"},
178 {0, "irc.efnet.pl"},
179 {0, "efnet.demon.co.uk"},
180 /* {0, "irc.lagged.org"},*/
181 {0, "irc.lightning.net"},
182 {0, "irc.mindspring.com"},
183 {0, "irc.easynews.com"},
184 {0, "irc.servercentral.net"},
186 {"EnterTheGame", 0},
187 {0, "IRC.EnterTheGame.Com"},
189 {"EUIrc", 0},
190 {0, "irc.euirc.net"},
191 {0, "irc.ham.de.euirc.net"},
192 {0, "irc.ber.de.euirc.net"},
193 {0, "irc.ffm.de.euirc.net"},
194 {0, "irc.bre.de.euirc.net"},
195 {0, "irc.hes.de.euirc.net"},
196 {0, "irc.vie.at.euirc.net"},
197 {0, "irc.inn.at.euirc.net"},
198 {0, "irc.bas.ch.euirc.net"},
200 {"EuropNet", 0},
201 {0, "irc.europnet.org"},
203 {"EU-IRC", 0},
204 {0, "irc.eu-irc.net"},
206 {"FDFNet", 0},
207 {0, "irc.fdfnet.net"},
208 {0, "irc.eu.fdfnet.net"},
210 {"FEFNet", 0},
211 {0, "irc.fef.net"},
212 {0, "irc.ggn.net"},
213 {0, "irc.vendetta.com"},
215 {"FreeNode", 0},
216 {0, "irc.freenode.net"},
218 /* {"Freeworld", 0},
219 {0, "kabel.freeworld.nu"},
220 {0, "irc.freeworld.nu"},*/
222 {"GalaxyNet", 0},
223 {0, "irc.galaxynet.org"},
224 /* {0, "sprynet.us.galaxynet.org"},
225 {0, "atlanta.ga.us.galaxynet.org"},*/
227 {"GamesNET", 0},
228 {0, "irc.gamesnet.net"},
229 /* {0, "irc.us.gamesnet.net"},
230 {0, "east.us.gamesnet.net"},
231 {0, "west.us.gamesnet.net"},*/
232 {0, "irc.ca.gamesnet.net"},
233 {0, "irc.eu.gamesnet.net"},
235 {"GeekShed", 0},
236 {0, "irc.geekshed.net"},
238 {"German-Elite", 0},
239 {0, "dominion.german-elite.net"},
240 {0, "komatu.german-elite.net"},
241 /* {0, "liberty.german-elite.net"},*/
243 {"GimpNet", 0},
244 {0, "irc.gimp.org"},
245 /* {0, "irc.au.gimp.org"},*/
246 {0, "irc.us.gimp.org"},
248 {"HabberNet", 0},
249 {0, "irc.habber.net"},
251 {"Hashmark", 0},
252 {0, "irc.hashmark.net"},
254 {"IdleMonkeys", 0},
255 {0, "irc.idlemonkeys.net"},
257 /* {"Infinity-IRC", 0},
258 {0, "Atlanta.GA.US.Infinity-IRC.Org"},
259 {0, "Babylon.NY.US.Infinity-IRC.Org"},
260 {0, "Sunshine.Ca.US.Infinity-IRC.Org"},
261 {0, "IRC.Infinity-IRC.Org"},*/
263 {"iZ-smart.net", 0},
264 {0, "irc.iZ-smart.net/6666"},
265 {0, "irc.iZ-smart.net/6667"},
266 {0, "irc.iZ-smart.net/6668"},
268 {"IrcLink", 0},
269 {0, "irc.irclink.net"},
270 {0, "Alesund.no.eu.irclink.net"},
271 {0, "Oslo.no.eu.irclink.net"},
272 {0, "frogn.no.eu.irclink.net"},
273 {0, "tonsberg.no.eu.irclink.net"},
275 {"IRCNet", 0},
276 {0, "irc.ircnet.com"},
277 {0, "irc.stealth.net/6668"},
278 {0, "ircnet.demon.co.uk"},
279 /* {0, "ircnet.hinet.hr"},*/
280 {0, "irc.datacomm.ch"},
281 /* {0, "ircnet.kaptech.fr"},
282 {0, "ircnet.easynet.co.uk"},*/
283 {0, "random.ircd.de"},
284 {0, "ircnet.netvision.net.il"},
285 /* {0, "irc.seed.net.tw"},*/
286 {0, "irc.cs.hut.fi"},
288 {"Irctoo.net", 0},
289 {0, "irc.irctoo.net"},
291 {"Krstarica", 0},
292 {0, "irc.krstarica.com"},
294 {"Librenet", 0},
295 {0, "irc.librenet.net"},
296 {0, "ielf.fr.librenet.net"},
298 {"LinkNet", 0},
299 {0, "irc.link-net.org"},
300 {0, "irc.no.link-net.org"},
301 /* {0, "irc.gamesden.net.au"},*/
302 {0, "irc.bahnhof.se"},
303 /* {0, "irc.kinexuseurope.co.uk"},
304 {0, "irc.gamiix.com"},*/
306 {"MagicStar", 0},
307 {0, "irc.magicstar.net"},
309 {"Majistic", 0},
310 {0, "irc.majistic.net"},
312 {"MindForge", 0},
313 {0, "irc.mindforge.org"},
315 {"MintIRC", 0},
316 {0, "irc.mintirc.net"},
318 {"MIXXnet", 0},
319 {0, "irc.mixxnet.net"},
321 {"NeverNET", 0},
322 {0, "irc.nevernet.net"},
323 {0, "imagine.nevernet.net"},
324 {0, "dimension.nevernet.net"},
325 {0, "universe.nevernet.net"},
326 {0, "wayland.nevernet.net"},
327 {0, "forte.nevernet.net"},
329 {"NixHelpNet", 0},
330 {0, "irc.nixhelp.org"},
331 {0, "us.nixhelp.org"},
332 {0, "uk.nixhelp.org"},
333 {0, "uk2.nixhelp.org"},
334 {0, "uk3.nixhelp.org"},
335 {0, "nl.nixhelp.org"},
336 {0, "ca.ld.nixhelp.org"},
337 {0, "us.co.nixhelp.org"},
338 {0, "us.ca.nixhelp.org"},
339 {0, "us.pa.nixhelp.org"},
341 {"NullusNet", 0},
342 {0, "irc.nullus.net"},
344 {"Oceanius", 0},
345 {0, "irc.oceanius.com"},
347 {"OFTC", 0},
348 {0, "irc.oftc.net"},
350 {"OtherNet", 0},
351 {0, "irc.othernet.org"},
353 {"OzNet", 0},
354 {0, "irc.oz.org"},
356 {"PIRC.PL", 0},
357 {0, "irc.pirc.pl"},
359 {"PTlink", 0},
360 {0, "irc.PTlink.net"},
361 {0, "aaia.PTlink.net"},
363 {"PTNet.org", 0},
364 {0, "irc.PTNet.org"},
365 {0, "world.PTnet.org"},
366 {0, "netvisao.PTnet.org"},
367 {0, "uevora.PTnet.org"},
368 {0, "vianetworks.PTnet.org"},
369 {0, "uc.PTnet.org"},
370 {0, "nfsi.ptnet.org"},
372 {"QuakeNet", 0},
373 {0, "irc.quakenet.org"},
374 {0, "irc.se.quakenet.org"},
375 {0, "irc.dk.quakenet.org"},
376 {0, "irc.no.quakenet.org"},
377 {0, "irc.fi.quakenet.org"},
378 {0, "irc.be.quakenet.org"},
379 {0, "irc.uk.quakenet.org"},
380 {0, "irc.de.quakenet.org"},
381 {0, "irc.it.quakenet.org"},
383 {"RebelChat", 0},
384 {0, "irc.rebelchat.org"},
386 /* {"Recycled-IRC", 0},
387 {0, "irc.recycled-irc.org"},
388 {0, "vermin.recycled-irc.org"},
389 {0, "waste.recycled-irc.org"},
390 {0, "lumber.recycled-irc.org"},
391 {0, "trash.recycled-irc.org"},
392 {0, "unwashed.recycled-irc.org"},
393 {0, "garbage.recycled-irc.org"},
394 {0, "dustbin.recycled-irc.org"},*/
396 {"RizeNET", 0},
397 {0, "irc.rizenet.org"},
398 {0, "omega.rizenet.org"},
399 {0, "evelance.rizenet.org"},
400 {0, "lisa.rizenet.org"},
401 {0, "scott.rizenet.org"},
403 {"Rizon", 0},
404 {0, "irc.rizon.net"},
406 {"RusNet", 0, 0, "KOI8-R (Cyrillic)"},
407 {0, "irc.tomsk.net"},
408 {0, "irc.rinet.ru"},
409 {0, "irc.run.net"},
410 {0, "irc.ru"},
411 {0, "irc.lucky.net"},
413 {"SceneNet", 0},
414 {0, "irc.scene.org"},
415 {0, "irc.eu.scene.org"},
416 {0, "irc.us.scene.org"},
418 {"SeilEn.de", 0},
419 {0, "irc.seilen.de"},
421 {"SlashNET", 0},
422 {0, "irc.slashnet.org"},
423 {0, "area51.slashnet.org"},
424 {0, "moo.slashnet.org"},
425 {0, "radon.slashnet.org"},
427 {"Sohbet.Net", 0},
428 {0, "irc.sohbet.net"},
430 {"SolidIRC", 0},
431 {0, "irc.solidirc.com"},
433 {"SorceryNet", 0},
434 {0, "irc.sorcery.net/9000"},
435 {0, "irc.us.sorcery.net/9000"},
436 {0, "irc.eu.sorcery.net/9000"},
438 {"Spidernet", 0},
439 {0, "us.spidernet.org"},
440 {0, "eu.spidernet.org"},
441 {0, "irc.spidernet.org"},
443 {"StarChat", 0},
444 {0, "irc.starchat.net"},
445 {0, "gainesville.starchat.net"},
446 {0, "freebsd.starchat.net"},
447 {0, "sunset.starchat.net"},
448 {0, "revenge.starchat.net"},
449 {0, "tahoma.starchat.net"},
450 {0, "neo.starchat.net"},
452 {"TNI3", 0},
453 {0, "irc.tni3.com"},
455 {"TURLINet", 0},
456 {0, "irc.turli.net"},
457 {0, "irc.servx.ru"},
458 {0, "irc.gavnos.ru"},
460 {"UnderNet", 0},
461 {0, "us.undernet.org"},
462 {0, "eu.undernet.org"},
464 {"UniBG", 0},
465 {0, "irc.lirex.com"},
466 {0, "irc.naturella.com"},
467 {0, "irc.spnet.net"},
468 {0, "irc.techno-link.com"},
469 {0, "irc.telecoms.bg"},
470 {0, "irc.tu-varna.edu"},
472 {"Whiffle", 0},
473 {0, "irc.whiffle.org"},
475 {"Worldnet", 0},
476 {0, "irc.worldnet.net"},
477 {0, "irc.fr.worldnet.net"},
479 {"Xentonix.net", 0},
480 {0, "irc.xentonix.net"},
482 {"XWorld", 0},
483 {0, "Buffalo.NY.US.XWorld.org"},
484 {0, "Minneapolis.MN.US.Xworld.Org"},
485 {0, "Rochester.NY.US.XWorld.org"},
486 {0, "Bayern.DE.EU.XWorld.Org"},
487 {0, "Chicago.IL.US.XWorld.Org"},
489 {0,0}
492 GSList *network_list = 0;
495 void
496 servlist_connect (session *sess, ircnet *net, gboolean join)
498 ircserver *ircserv;
499 GSList *list;
500 char *port;
501 server *serv;
503 if (!sess)
504 sess = new_ircwindow (NULL, NULL, SESS_SERVER, TRUE);
506 serv = sess->server;
508 /* connect to the currently selected Server-row */
509 list = g_slist_nth (net->servlist, net->selected);
510 if (!list)
511 list = net->servlist;
512 if (!list)
513 return;
514 ircserv = list->data;
516 /* incase a protocol switch is added to the servlist gui */
517 server_fill_her_up (sess->server);
519 if (join)
521 sess->willjoinchannel[0] = 0;
523 if (net->autojoin)
525 if (serv->autojoin)
526 free (serv->autojoin);
527 serv->autojoin = strdup (net->autojoin);
531 serv->password[0] = 0;
532 if (net->pass)
533 safe_strcpy (serv->password, net->pass, sizeof (serv->password));
535 if (net->flags & FLAG_USE_GLOBAL)
537 strcpy (serv->nick, prefs.nick1);
538 } else
540 if (net->nick)
541 strcpy (serv->nick, net->nick);
544 serv->dont_use_proxy = (net->flags & FLAG_USE_PROXY) ? FALSE : TRUE;
546 #ifdef USE_OPENSSL
547 serv->use_ssl = (net->flags & FLAG_USE_SSL) ? TRUE : FALSE;
548 serv->accept_invalid_cert =
549 (net->flags & FLAG_ALLOW_INVALID) ? TRUE : FALSE;
550 #endif
552 serv->network = net;
554 port = strrchr (ircserv->hostname, '/');
555 if (port)
557 *port = 0;
559 /* support "+port" to indicate SSL (like mIRC does) */
560 if (port[1] == '+')
562 #ifdef USE_OPENSSL
563 serv->use_ssl = TRUE;
564 #endif
565 serv->connect (serv, ircserv->hostname, atoi (port + 2), FALSE);
566 } else
568 serv->connect (serv, ircserv->hostname, atoi (port + 1), FALSE);
571 *port = '/';
572 } else
573 serv->connect (serv, ircserv->hostname, -1, FALSE);
575 server_set_encoding (serv, net->encoding);
579 servlist_connect_by_netname (session *sess, char *network, gboolean join)
581 ircnet *net;
582 GSList *list = network_list;
584 while (list)
586 net = list->data;
588 if (strcasecmp (net->name, network) == 0)
590 servlist_connect (sess, net, join);
591 return 1;
594 list = list->next;
597 return 0;
601 servlist_have_auto (void)
603 GSList *list = network_list;
604 ircnet *net;
606 while (list)
608 net = list->data;
610 if (net->flags & FLAG_AUTO_CONNECT)
611 return 1;
613 list = list->next;
616 return 0;
620 servlist_auto_connect (session *sess)
622 GSList *list = network_list;
623 ircnet *net;
624 int ret = 0;
626 while (list)
628 net = list->data;
630 if (net->flags & FLAG_AUTO_CONNECT)
632 servlist_connect (sess, net, TRUE);
633 ret = 1;
636 list = list->next;
639 return ret;
642 static gint
643 servlist_cycle_cb (server *serv)
645 if (serv->network)
647 PrintTextf (serv->server_session,
648 _("Cycling to next server in %s...\n"), ((ircnet *)serv->network)->name);
649 servlist_connect (serv->server_session, serv->network, TRUE);
652 return 0;
656 servlist_cycle (server *serv)
658 ircnet *net;
659 int max, del;
661 net = serv->network;
662 if (net)
664 max = g_slist_length (net->servlist);
665 if (max > 0)
667 /* try the next server, if that option is on */
668 if (net->flags & FLAG_CYCLE)
670 net->selected++;
671 if (net->selected >= max)
672 net->selected = 0;
675 del = prefs.recon_delay * 1000;
676 if (del < 1000)
677 del = 500; /* so it doesn't block the gui */
679 if (del)
680 serv->recondelay_tag = fe_timeout_add (del, servlist_cycle_cb, serv);
681 else
682 servlist_connect (serv->server_session, net, TRUE);
684 return TRUE;
688 return FALSE;
691 ircserver *
692 servlist_server_find (ircnet *net, char *name, int *pos)
694 GSList *list = net->servlist;
695 ircserver *serv;
696 int i = 0;
698 while (list)
700 serv = list->data;
701 if (strcmp (serv->hostname, name) == 0)
703 if (pos)
704 *pos = i;
705 return serv;
707 i++;
708 list = list->next;
711 return NULL;
714 /* find a network (e.g. (ircnet *) to "FreeNode") from a hostname
715 (e.g. "irc.eu.freenode.net") */
717 ircnet *
718 servlist_net_find_from_server (char *server_name)
720 GSList *list = network_list;
721 GSList *slist;
722 ircnet *net;
723 ircserver *serv;
725 while (list)
727 net = list->data;
729 slist = net->servlist;
730 while (slist)
732 serv = slist->data;
733 if (strcasecmp (serv->hostname, server_name) == 0)
734 return net;
735 slist = slist->next;
738 list = list->next;
741 return NULL;
744 ircnet *
745 servlist_net_find (char *name, int *pos, int (*cmpfunc) (const char *, const char *))
747 GSList *list = network_list;
748 ircnet *net;
749 int i = 0;
751 while (list)
753 net = list->data;
754 if (cmpfunc (net->name, name) == 0)
756 if (pos)
757 *pos = i;
758 return net;
760 i++;
761 list = list->next;
764 return NULL;
767 ircserver *
768 servlist_server_add (ircnet *net, char *name)
770 ircserver *serv;
772 serv = malloc (sizeof (ircserver));
773 memset (serv, 0, sizeof (ircserver));
774 serv->hostname = strdup (name);
776 net->servlist = g_slist_append (net->servlist, serv);
778 return serv;
781 void
782 servlist_server_remove (ircnet *net, ircserver *serv)
784 free (serv->hostname);
785 free (serv);
786 net->servlist = g_slist_remove (net->servlist, serv);
789 static void
790 servlist_server_remove_all (ircnet *net)
792 ircserver *serv;
794 while (net->servlist)
796 serv = net->servlist->data;
797 servlist_server_remove (net, serv);
801 static void
802 free_and_clear (char *str)
804 if (str)
806 char *orig = str;
807 while (*str)
808 *str++ = 0;
809 free (orig);
813 /* executed on exit: Clear any password strings */
815 void
816 servlist_cleanup (void)
818 GSList *list;
819 ircnet *net;
821 for (list = network_list; list; list = list->next)
823 net = list->data;
824 free_and_clear (net->pass);
825 free_and_clear (net->nickserv);
829 void
830 servlist_net_remove (ircnet *net)
832 GSList *list;
833 server *serv;
835 servlist_server_remove_all (net);
836 network_list = g_slist_remove (network_list, net);
838 if (net->nick)
839 free (net->nick);
840 if (net->nick2)
841 free (net->nick2);
842 if (net->user)
843 free (net->user);
844 if (net->real)
845 free (net->real);
846 free_and_clear (net->pass);
847 if (net->autojoin)
848 free (net->autojoin);
849 if (net->command)
850 free (net->command);
851 free_and_clear (net->nickserv);
852 if (net->comment)
853 free (net->comment);
854 if (net->encoding)
855 free (net->encoding);
856 free (net->name);
857 free (net);
859 /* for safety */
860 list = serv_list;
861 while (list)
863 serv = list->data;
864 if (serv->network == net)
865 serv->network = NULL;
866 list = list->next;
870 ircnet *
871 servlist_net_add (char *name, char *comment, int prepend)
873 ircnet *net;
875 net = malloc (sizeof (ircnet));
876 memset (net, 0, sizeof (ircnet));
877 net->name = strdup (name);
878 /* net->comment = strdup (comment);*/
879 net->flags = FLAG_CYCLE | FLAG_USE_GLOBAL | FLAG_USE_PROXY;
881 if (prepend)
882 network_list = g_slist_prepend (network_list, net);
883 else
884 network_list = g_slist_append (network_list, net);
886 return net;
889 static void
890 servlist_load_defaults (void)
892 int i = 0, j = 0;
893 ircnet *net = NULL;
895 while (1)
897 if (def[i].network)
899 net = servlist_net_add (def[i].network, def[i].host, FALSE);
900 net->encoding = strdup ("IRC (Latin/Unicode Hybrid)");
901 if (def[i].channel)
902 net->autojoin = strdup (def[i].channel);
903 if (def[i].charset)
905 free (net->encoding);
906 net->encoding = strdup (def[i].charset);
908 if (g_str_hash (def[i].network) == 0x8e1b96f7)
909 prefs.slist_select = j;
910 j++;
911 } else
913 servlist_server_add (net, def[i].host);
914 if (!def[i+1].host && !def[i+1].network)
915 break;
917 i++;
921 static int
922 servlist_load (void)
924 FILE *fp;
925 char buf[2048];
926 int len;
927 char *tmp;
928 ircnet *net = NULL;
930 fp = xchat_fopen_file ("servlist_.conf", "r", 0);
931 if (!fp)
932 return FALSE;
934 while (fgets (buf, sizeof (buf) - 2, fp))
936 len = strlen (buf);
937 buf[len] = 0;
938 buf[len-1] = 0; /* remove the trailing \n */
939 if (net)
941 switch (buf[0])
943 case 'I':
944 net->nick = strdup (buf + 2);
945 break;
946 case 'i':
947 net->nick2 = strdup (buf + 2);
948 break;
949 case 'U':
950 net->user = strdup (buf + 2);
951 break;
952 case 'R':
953 net->real = strdup (buf + 2);
954 break;
955 case 'P':
956 net->pass = strdup (buf + 2);
957 break;
958 case 'J':
959 net->autojoin = strdup (buf + 2);
960 break;
961 case 'C':
962 if (net->command)
964 /* concat extra commands with a \n separator */
965 tmp = net->command;
966 net->command = malloc (strlen (tmp) + strlen (buf + 2) + 2);
967 strcpy (net->command, tmp);
968 strcat (net->command, "\n");
969 strcat (net->command, buf + 2);
970 free (tmp);
971 } else
972 net->command = strdup (buf + 2);
973 break;
974 case 'F':
975 net->flags = atoi (buf + 2);
976 break;
977 case 'D':
978 net->selected = atoi (buf + 2);
979 break;
980 case 'E':
981 net->encoding = strdup (buf + 2);
982 break;
983 case 'S': /* new server/hostname for this network */
984 servlist_server_add (net, buf + 2);
985 break;
986 case 'B':
987 net->nickserv = strdup (buf + 2);
988 break;
991 if (buf[0] == 'N')
992 net = servlist_net_add (buf + 2, /* comment */ NULL, FALSE);
994 fclose (fp);
996 return TRUE;
999 void
1000 servlist_init (void)
1002 if (!network_list)
1003 if (!servlist_load ())
1004 servlist_load_defaults ();
1007 /* check if a charset is known by Iconv */
1009 servlist_check_encoding (char *charset)
1011 GIConv gic;
1012 char *c;
1014 c = strchr (charset, ' ');
1015 if (c)
1016 c[0] = 0;
1018 if (!strcasecmp (charset, "IRC")) /* special case */
1020 if (c)
1021 c[0] = ' ';
1022 return TRUE;
1025 gic = g_iconv_open (charset, "UTF-8");
1027 if (c)
1028 c[0] = ' ';
1030 if (gic != (GIConv)-1)
1032 g_iconv_close (gic);
1033 return TRUE;
1036 return FALSE;
1039 static int
1040 servlist_write_ccmd (char *str, void *fp)
1042 return fprintf (fp, "C=%s\n", (str[0] == '/') ? str + 1 : str);
1047 servlist_save (void)
1049 FILE *fp;
1050 char buf[256];
1051 ircnet *net;
1052 ircserver *serv;
1053 GSList *list;
1054 GSList *hlist;
1055 #ifndef WIN32
1056 int first = FALSE;
1058 snprintf (buf, sizeof (buf), "%s/servlist_.conf", get_xdir_fs ());
1059 if (access (buf, F_OK) != 0)
1060 first = TRUE;
1061 #endif
1063 fp = xchat_fopen_file ("servlist_.conf", "w", 0);
1064 if (!fp)
1065 return FALSE;
1067 #ifndef WIN32
1068 if (first)
1069 chmod (buf, 0600);
1070 #endif
1071 fprintf (fp, "v="PACKAGE_VERSION"\n\n");
1073 list = network_list;
1074 while (list)
1076 net = list->data;
1078 fprintf (fp, "N=%s\n", net->name);
1079 if (net->nick)
1080 fprintf (fp, "I=%s\n", net->nick);
1081 if (net->nick2)
1082 fprintf (fp, "i=%s\n", net->nick2);
1083 if (net->user)
1084 fprintf (fp, "U=%s\n", net->user);
1085 if (net->real)
1086 fprintf (fp, "R=%s\n", net->real);
1087 if (net->pass)
1088 fprintf (fp, "P=%s\n", net->pass);
1089 if (net->autojoin)
1090 fprintf (fp, "J=%s\n", net->autojoin);
1091 if (net->nickserv)
1092 fprintf (fp, "B=%s\n", net->nickserv);
1093 if (net->encoding && strcasecmp (net->encoding, "System") &&
1094 strcasecmp (net->encoding, "System default"))
1096 fprintf (fp, "E=%s\n", net->encoding);
1097 if (!servlist_check_encoding (net->encoding))
1099 snprintf (buf, sizeof (buf), _("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."),
1100 net->encoding, net->name);
1101 fe_message (buf, FE_MSG_WARN);
1105 if (net->command)
1106 token_foreach (net->command, '\n', servlist_write_ccmd, fp);
1108 fprintf (fp, "F=%d\nD=%d\n", net->flags, net->selected);
1110 hlist = net->servlist;
1111 while (hlist)
1113 serv = hlist->data;
1114 fprintf (fp, "S=%s\n", serv->hostname);
1115 hlist = hlist->next;
1118 if (fprintf (fp, "\n") < 1)
1120 fclose (fp);
1121 return FALSE;
1124 list = list->next;
1127 fclose (fp);
1128 return TRUE;
1131 static void
1132 joinlist_free1 (GSList *list)
1134 GSList *head = list;
1136 for (; list; list = list->next)
1137 g_free (list->data);
1138 g_slist_free (head);
1141 void
1142 joinlist_free (GSList *channels, GSList *keys)
1144 joinlist_free1 (channels);
1145 joinlist_free1 (keys);
1148 gboolean
1149 joinlist_is_in_list (server *serv, char *channel)
1151 GSList *channels, *keys;
1152 GSList *list;
1154 if (!serv->network || !((ircnet *)serv->network)->autojoin)
1155 return FALSE;
1157 joinlist_split (((ircnet *)serv->network)->autojoin, &channels, &keys);
1159 for (list = channels; list; list = list->next)
1161 if (serv->p_cmp (list->data, channel) == 0)
1162 return TRUE;
1165 joinlist_free (channels, keys);
1167 return FALSE;
1170 gchar *
1171 joinlist_merge (GSList *channels, GSList *keys)
1173 GString *out = g_string_new (NULL);
1174 GSList *list;
1175 int i, j;
1177 for (; channels; channels = channels->next)
1179 g_string_append (out, channels->data);
1181 if (channels->next)
1182 g_string_append_c (out, ',');
1185 /* count number of REAL keys */
1186 for (i = 0, list = keys; list; list = list->next)
1187 if (list->data)
1188 i++;
1190 if (i > 0)
1192 g_string_append_c (out, ' ');
1194 for (j = 0; keys; keys = keys->next)
1196 if (keys->data)
1198 g_string_append (out, keys->data);
1199 j++;
1200 if (j == i)
1201 break;
1204 if (keys->next)
1205 g_string_append_c (out, ',');
1209 return g_string_free (out, FALSE);
1212 void
1213 joinlist_split (char *autojoin, GSList **channels, GSList **keys)
1215 char *parta, *partb;
1216 char *chan, *key;
1217 int len;
1219 *channels = NULL;
1220 *keys = NULL;
1222 /* after the first space, the keys begin */
1223 parta = autojoin;
1224 partb = strchr (autojoin, ' ');
1225 if (partb)
1226 partb++;
1228 while (1)
1230 chan = parta;
1231 key = partb;
1233 if (1)
1235 while (parta[0] != 0 && parta[0] != ',' && parta[0] != ' ')
1237 parta++;
1241 if (partb)
1243 while (partb[0] != 0 && partb[0] != ',' && partb[0] != ' ')
1245 partb++;
1249 len = parta - chan;
1250 if (len < 1)
1251 break;
1252 *channels = g_slist_append (*channels, g_strndup (chan, len));
1254 len = partb - key;
1255 *keys = g_slist_append (*keys, len ? g_strndup (key, len) : NULL);
1257 if (parta[0] == ' ' || parta[0] == 0)
1258 break;
1259 parta++;
1261 if (partb)
1263 if (partb[0] == 0 || partb[0] == ' ')
1264 partb = NULL; /* no more keys, but maybe more channels? */
1265 else
1266 partb++;
1270 #if 0
1271 GSList *lista, *listb;
1272 int i;
1274 printf("-----\n");
1275 i = 0;
1276 lista = *channels;
1277 listb = *keys;
1278 while (lista)
1280 printf("%d. |%s| |%s|\n", i, lista->data, listb->data);
1281 i++;
1282 lista = lista->next;
1283 listb = listb->next;
1285 printf("-----\n\n");
1286 #endif