Merge pull request #586 from bviktor/authcleanup

Login and network list cleanup
This commit is contained in:
TingPing 2013-05-16 09:07:38 -07:00
commit 69c2893234
20 changed files with 1222 additions and 1085 deletions

View File

@ -184,7 +184,7 @@ dnl *********************************************************************
dnl ** GLIB *************************************************************
dnl *********************************************************************
AM_PATH_GLIB_2_0(2.14.0, glib=yes, glib=no)
AM_PATH_GLIB_2_0(2.28.0, glib=yes, glib=no)
if test "$glib" = no; then
AC_MSG_ERROR(Cannot find GLib!)
fi
@ -199,7 +199,7 @@ dnl *********************************************************************
# we might get undefined macro without this test
if test "$gtkfe" = yes ; then
AM_PATH_GTK_2_0(2.14.0, havegtk=yes, havegtk=no)
AM_PATH_GTK_2_0(2.24.0, havegtk=yes, havegtk=no)
if test "$havegtk" = no; then
gtkfe=no

View File

@ -2,10 +2,10 @@
Just some tips if you're going to help with HexChat code (patches etc):
* Use tabs, not spaces, to indent code.
* Use tabs, not spaces, to indent and align code.
* Use a tab size of 3 (most editors will let you choose this).
Type :set ts=3 in vim/gvim.
* Use a tab size of 4 (most editors will let you choose this).
Type :set ts=4 in vim/gvim.
* Try to stick to the same consistant coding style (vertically aligned braces, a space after if, while, functions etc.):

View File

@ -21,8 +21,8 @@ in general. HexChat runs on most BSD and POSIX compliant operating systems.
## Requirements:
* GTK+ 2.14
* GLib 2.14
* GTK+ 2.24
* GLib 2.28
HexChat is known to work on, at least:

View File

@ -66,15 +66,6 @@
#define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
#endif
/* This is practically copy-paste from gstdio.h.
* GStatBuf was added in 2.26. On Win32 we already use that,
* so we only gotta check this on Unix */
#ifndef WIN32
#if !GLIB_CHECK_VERSION(2,26,0)
typedef struct stat GStatBuf;
#endif
#endif
static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
struct dccstat_info dccstat[] = {

View File

@ -479,7 +479,7 @@ typedef struct server
void (*p_ns_identify)(struct server *, char *pass);
void (*p_ns_ghost)(struct server *, char *usname, char *pass);
void (*p_join)(struct server *, char *channel, char *key);
void (*p_join_list)(struct server *, GSList *channels, GSList *keys);
void (*p_join_list)(struct server *, GSList *favorites);
void (*p_login)(struct server *, char *user, char *realname);
void (*p_join_info)(struct server *, char *channel);
void (*p_mode)(struct server *, char *target, char *mode);
@ -527,14 +527,12 @@ typedef struct server
char hostname[128]; /* real ip number */
char servername[128]; /* what the server says is its name */
char password[86];
char sasluser[32]; /* this is just a buffer for network->user */
char saslpassword[86]; /* we could reuse password but then we couldn't guarantee NickServ doesn't register first */
char nick[NICKLEN];
char linebuf[2048]; /* RFC says 512 chars including \r\n */
char *last_away_reason;
int pos; /* current position in linebuf */
int nickcount;
int nickservtype; /* 0=/MSG nickserv 1=/NICKSERV 2=/NS */
int loginmethod; /* see login_types[] */
char *chantypes; /* for 005 numeric - free me */
char *chanmodes; /* for 005 numeric - free me */
@ -568,7 +566,7 @@ typedef struct server
time_t away_time; /* when we were marked away */
char *encoding; /* NULL for system */
char *autojoin; /* list of channels & keys to join */
GSList *favlist; /* list of channels & keys to join */
unsigned int motd_skipped:1;
unsigned int connected:1;

View File

@ -1066,38 +1066,26 @@ inbound_nameslist_end (server *serv, char *chan)
return FALSE;
}
static gboolean
static void
check_autojoin_channels (server *serv)
{
char *po;
int i = 0;
session *sess;
GSList *list = sess_list;
int i = 0;
GSList *channels, *keys;
GSList *sess_channels = NULL; /* joined channels that are not in the favorites list */
favchannel *fav;
/* shouldnt really happen, the io tag is destroyed in server.c */
/* shouldn't really happen, the io tag is destroyed in server.c */
if (!is_server (serv))
return FALSE;
/* send auto join list */
if (serv->autojoin)
{
joinlist_split (serv->autojoin, &channels, &keys);
serv->p_join_list (serv, channels, keys);
joinlist_free (channels, keys);
free (serv->autojoin);
serv->autojoin = NULL;
i++;
return;
}
/* this is really only for re-connects when you
* join channels not in the auto-join list. */
channels = NULL;
keys = NULL;
/* If there's a session (i.e. this is a reconnect), autojoin to everything that was open previously. */
while (list)
{
sess = list->data;
if (sess->server == serv)
{
if (sess->willjoinchannel[0] != 0)
@ -1105,39 +1093,54 @@ check_autojoin_channels (server *serv)
strcpy (sess->waitchannel, sess->willjoinchannel);
sess->willjoinchannel[0] = 0;
po = strchr (sess->waitchannel, ',');
if (po)
*po = 0;
po = strchr (sess->waitchannel, ' ');
if (po)
*po = 0;
fav = servlist_favchan_find (serv->network, sess->waitchannel, NULL); /* Is this channel in our favorites? */
/* There can be no gap between keys, list keyed chans first. */
if (sess->channelkey[0] != 0)
/* session->channelkey is initially unset for channels joined from the favorites. You have to fill them up manually from favorites settings. */
if (fav)
{
channels = g_slist_prepend (channels, g_strdup (sess->waitchannel));
keys = g_slist_prepend (keys, g_strdup (sess->channelkey));
/* session->channelkey is set if there was a key change during the session. In that case, use the session key, not the one from favorites. */
if (fav->key && !strlen (sess->channelkey))
{
safe_strcpy (sess->channelkey, fav->key, sizeof (sess->channelkey));
}
}
/* for easier checks, ensure that favchannel->key is just NULL when session->channelkey is empty i.e. '' */
if (strlen (sess->channelkey))
{
sess_channels = servlist_favchan_listadd (sess_channels, sess->waitchannel, sess->channelkey);
}
else
{
channels = g_slist_append (channels, g_strdup (sess->waitchannel));
keys = g_slist_append (keys, g_strdup (sess->channelkey));
sess_channels = servlist_favchan_listadd (sess_channels, sess->waitchannel, NULL);
}
i++;
}
}
list = list->next;
}
if (channels)
if (sess_channels)
{
serv->p_join_list (serv, channels, keys);
joinlist_free (channels, keys);
serv->p_join_list (serv, sess_channels);
g_slist_free_full (sess_channels, (GDestroyNotify) servlist_favchan_free);
}
else
{
/* If there's no session, just autojoin to favorites. */
if (serv->favlist)
{
serv->p_join_list (serv, serv->favlist);
i++;
/* FIXME this is not going to work and is not needed either. server_free() does the job already. */
/* g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free); */
}
}
serv->joindelay_tag = 0;
fe_server_event (serv, FE_SE_LOGGEDIN, i);
return FALSE;
}
void
@ -1367,9 +1370,28 @@ inbound_exec_eom_cmd (char *str, void *sess)
return 1;
}
static int
inbound_nickserv_login (server *serv)
{
/* this could grow ugly, but let's hope there won't be new NickServ types */
switch (serv->loginmethod)
{
case LOGIN_MSG_NICKSERV:
case LOGIN_NICKSERV:
case LOGIN_NS:
case LOGIN_MSG_NS:
case LOGIN_AUTH:
return 1;
default:
return 0;
}
}
void
inbound_login_end (session *sess, char *text)
{
GSList *cmdlist;
commandentry *cmd;
server *serv = sess->server;
if (!serv->end_of_motd)
@ -1384,35 +1406,48 @@ inbound_login_end (session *sess, char *text)
if (serv->network)
{
/* there may be more than 1, separated by \n */
if (((ircnet *)serv->network)->command)
token_foreach (((ircnet *)serv->network)->command, '\n',
inbound_exec_eom_cmd, sess);
cmdlist = ((ircnet *)serv->network)->commandlist;
while (cmdlist)
{
cmd = cmdlist->data;
inbound_exec_eom_cmd (cmd->command, sess);
cmdlist = cmdlist->next;
}
/* send nickserv password */
if (((ircnet *)serv->network)->nickserv)
serv->p_ns_identify (serv, ((ircnet *)serv->network)->nickserv);
if (((ircnet *)serv->network)->pass && inbound_nickserv_login (serv))
{
serv->p_ns_identify (serv, ((ircnet *)serv->network)->pass);
}
}
/* send JOIN now or wait? */
if (serv->network && ((ircnet *)serv->network)->nickserv &&
prefs.hex_irc_join_delay)
serv->joindelay_tag = fe_timeout_add (prefs.hex_irc_join_delay * 1000,
check_autojoin_channels, serv);
if (serv->network && ((ircnet *)serv->network)->pass && prefs.hex_irc_join_delay && inbound_nickserv_login (serv))
{
serv->joindelay_tag = fe_timeout_add (prefs.hex_irc_join_delay * 1000, check_autojoin_channels, serv);
}
else
{
check_autojoin_channels (serv);
}
if (serv->supports_watch || serv->supports_monitor)
{
notify_send_watches (serv);
}
serv->end_of_motd = TRUE;
}
if (prefs.hex_irc_skip_motd && !serv->motd_skipped)
{
serv->motd_skipped = TRUE;
EMIT_SIGNAL (XP_TE_MOTDSKIP, serv->server_session, NULL, NULL,
NULL, NULL, 0);
EMIT_SIGNAL (XP_TE_MOTDSKIP, serv->server_session, NULL, NULL, NULL, NULL, 0);
return;
}
EMIT_SIGNAL (XP_TE_MOTD, serv->server_session, text, NULL,
NULL, NULL, 0);
EMIT_SIGNAL (XP_TE_MOTD, serv->server_session, text, NULL, NULL, NULL, 0);
}
void

View File

@ -1111,11 +1111,6 @@ hexchat_get_info (hexchat_plugin *ph, const char *id)
case 0x339763: /* nick */
return sess->server->nick;
case 0x438fdf9: /* nickserv */
if (sess->server->network)
return ((ircnet *)sess->server->network)->nickserv;
return NULL;
case 0xca022f43: /* server */
if (!sess->server->connected)
return NULL;

View File

@ -42,6 +42,7 @@
#include "util.h"
#include "hexchatc.h"
#include "url.h"
#include "servlist.h"
static void
@ -49,7 +50,7 @@ irc_login (server *serv, char *user, char *realname)
{
tcp_sendf (serv, "CAP LS\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */
if (serv->password[0])
if (serv->password[0] && serv->loginmethod == LOGIN_PASS)
{
tcp_sendf (serv, "PASS %s\r\n", serv->password);
}
@ -64,21 +65,23 @@ static void
irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
{
/* are all ircd authors idiots? */
switch (serv->nickservtype)
switch (serv->loginmethod)
{
case 0:
case LOGIN_MSG_NICKSERV:
tcp_sendf (serv, "PRIVMSG NICKSERV :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case 1:
case LOGIN_NICKSERV:
tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case 2:
#if 0
case LOGIN_NS:
tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case 3:
#endif
case LOGIN_MSG_NS:
tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case 4:
case LOGIN_AUTH:
/* why couldn't QuakeNet implement one of the existing ones? */
tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2);
}
@ -87,7 +90,7 @@ irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
static void
irc_ns_identify (server *serv, char *pass)
{
if (serv->nickservtype == 4) /* QuakeNet needs to do everything in its own ways... */
if (serv->loginmethod == LOGIN_AUTH) /* QuakeNet needs to do everything in its own ways... */
{
irc_nickserv (serv, "", serv->nick, pass, "");
}
@ -100,8 +103,10 @@ irc_ns_identify (server *serv, char *pass)
static void
irc_ns_ghost (server *serv, char *usname, char *pass)
{
if (serv->nickservtype != 4)
if (serv->loginmethod != LOGIN_AUTH)
{
irc_nickserv (serv, "GHOST", usname, " ", pass);
}
}
static void
@ -114,118 +119,97 @@ irc_join (server *serv, char *channel, char *key)
}
static void
irc_join_list_flush (server *serv, GString *c, GString *k)
irc_join_list_flush (server *serv, GString *channels, GString *keys, int send_keys)
{
char *chanstr, *keystr;
char *chanstr;
char *keystr;
chanstr = g_string_free (c, FALSE);
keystr = g_string_free (k, FALSE);
if (chanstr[0])
chanstr = g_string_free (channels, FALSE); /* convert our strings to char arrays */
keystr = g_string_free (keys, FALSE);
if (send_keys)
{
if (keystr[0])
tcp_sendf (serv, "JOIN %s %s\r\n", chanstr, keystr);
else
tcp_sendf (serv, "JOIN %s\r\n", chanstr);
tcp_sendf (serv, "JOIN %s %s\r\n", chanstr, keystr); /* send the actual command */
}
else
{
tcp_sendf (serv, "JOIN %s\r\n", chanstr); /* send the actual command */
}
g_free (chanstr);
g_free (keystr);
}
/* join a whole list of channels & keys, split to multiple lines
* to get around 512 limit */
/* Join a whole list of channels & keys, split to multiple lines
* to get around the 512 limit.
*/
static void
irc_join_list (server *serv, GSList *channels, GSList *keys)
irc_join_list (server *serv, GSList *favorites)
{
GSList *clist;
GSList *klist;
GString *c = g_string_new (NULL);
GString *k = g_string_new (NULL);
int len;
int add;
int i, j;
int first_item = 1; /* determine whether we add commas or not */
int send_keys = 0; /* if none of our channels have keys, we can omit the 'x' fillers altogether */
int len = 9; /* JOIN<space>channels<space>keys\r\n\0 */
favchannel *fav;
GString *chanlist = g_string_new (NULL);
GString *keylist = g_string_new (NULL);
GSList *favlist;
i = j = 0;
len = 9; /* "JOIN<space><space>\r\n" */
clist = channels;
klist = keys;
favlist = favorites;
while (clist)
while (favlist)
{
/* measure how many bytes this channel would add... */
if (1)
fav = favlist->data;
len += strlen (fav->name);
if (fav->key)
{
add = strlen (clist->data);
if (i != 0)
add++; /* comma */
len += strlen (fav->key);
}
if (klist->data)
if (len >= 512) /* command length exceeds the IRC hard limit, flush it and start from scratch */
{
add += strlen (klist->data);
}
else
{
add++; /* 'x' filler */
}
irc_join_list_flush (serv, chanlist, keylist, send_keys);
if (j != 0)
add++; /* comma */
chanlist = g_string_new (NULL);
keylist = g_string_new (NULL);
/* too big? dump buffer and start a fresh one */
if (len + add > 512)
{
irc_join_list_flush (serv, c, k);
c = g_string_new (NULL);
k = g_string_new (NULL);
i = j = 0;
len = 9;
first_item = 1; /* list dumped, omit commas once again */
send_keys = 0; /* also omit keys until we actually find one */
}
/* now actually add it to our GStrings */
if (1)
if (!first_item)
{
add = strlen (clist->data);
if (i != 0)
{
add++;
g_string_append_c (c, ',');
}
g_string_append (c, clist->data);
i++;
/* This should be done before the length check, but channel names
* are already at least 2 characters long so it would trigger the
* flush anyway.
*/
len += 2;
/* add separators but only if it's not the 1st element */
g_string_append_c (chanlist, ',');
g_string_append_c (keylist, ',');
}
if (klist->data)
g_string_append (chanlist, fav->name);
if (fav->key)
{
add += strlen (klist->data);
if (j != 0)
{
add++;
g_string_append_c (k, ',');
}
g_string_append (k, klist->data);
j++;
g_string_append (keylist, fav->key);
send_keys = 1;
}
else
{
add++;
if (j != 0)
{
add++;
g_string_append_c (k, ',');
}
g_string_append_c (k, 'x');
j++;
g_string_append_c (keylist, 'x'); /* 'x' filler for keyless channels so that our JOIN command is always well-formatted */
}
len += add;
klist = klist->next;
clist = clist->next;
first_item = 0;
favlist = favlist->next;
}
irc_join_list_flush (serv, c, k);
irc_join_list_flush (serv, chanlist, keylist, send_keys);
g_slist_free (favlist);
}
static void
@ -1218,10 +1202,23 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
if (strstr (word_eol[5], "sasl") != 0)
{
serv->have_sasl = TRUE;
EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0);
EMIT_SIGNAL
(
XP_TE_SASLAUTH,
serv->server_session,
(((ircnet *)sess->server->network)->user) ? (((ircnet *)sess->server->network)->user) : prefs.hex_irc_user_name,
NULL,
NULL,
NULL,
0
);
tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20);
pass = encode_sasl_pass (sess->server->sasluser, sess->server->saslpassword);
pass = encode_sasl_pass
(
(((ircnet *)sess->server->network)->user) ? (((ircnet *)sess->server->network)->user) : prefs.hex_irc_user_name,
sess->server->password
);
tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass);
free (pass);
}
@ -1259,8 +1256,8 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
strcat (buffer, "extended-join ");
want_cap = 1;
}
/* if the SASL password is set, request SASL auth */
if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0)
/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->password) != 0 && serv->loginmethod == LOGIN_SASL)
{
strcat (buffer, "sasl ");
want_cap = 1;

View File

@ -2030,8 +2030,8 @@ server_free (server *serv)
free (serv->last_away_reason);
if (serv->encoding)
free (serv->encoding);
if (serv->autojoin)
free (serv->autojoin);
if (serv->favlist)
g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
fe_server_callback (serv);

View File

@ -43,7 +43,7 @@ struct defaultserver
char *host;
char *channel;
char *charset;
int nsmode; /* default NickServ type */
int loginmode; /* default authentication type */
};
static const struct defaultserver def[] =
@ -167,7 +167,7 @@ static const struct defaultserver def[] =
{0, "irc.criten.net"},
{0, "irc.eu.criten.net"},
{"DALnet", 0, 0, 0, 2},
{"DALnet", 0},
{0, "irc.dal.net"},
{0, "irc.eu.dal.net"},
@ -245,7 +245,7 @@ static const struct defaultserver def[] =
{0, "irc.ggn.net"},
{0, "irc.vendetta.com"},
{"freenode", 0, "#hexchat"},
{"freenode", 0, "#hexchat", 0, LOGIN_SASL},
#ifdef USE_OPENSSL
{0, "irc.freenode.net/+6697"},
#endif
@ -263,7 +263,7 @@ static const struct defaultserver def[] =
/* {0, "sprynet.us.galaxynet.org"},
{0, "atlanta.ga.us.galaxynet.org"},*/
{"GameSurge", 0, 0, 0, 2},
{"GameSurge", 0},
{0, "irc.gamesurge.net"},
/* {"GamesNET", 0},
@ -426,7 +426,7 @@ static const struct defaultserver def[] =
{0, "nfsi.ptnet.org"},
{0, "fctunl.ptnet.org"},
{"QuakeNet", 0, 0, 0, 5},
{"QuakeNet", 0, 0, 0, LOGIN_AUTH},
{0, "irc.quakenet.org"},
{0, "irc.se.quakenet.org"},
{0, "irc.dk.quakenet.org"},
@ -460,7 +460,7 @@ static const struct defaultserver def[] =
{"Rizon", 0},
{0, "irc.rizon.net"},
{"RusNet", 0, 0, "KOI8-R (Cyrillic)", 2},
{"RusNet", 0, 0, "KOI8-R (Cyrillic)"},
{0, "irc.tomsk.net"},
{0, "irc.rinet.ru"},
{0, "irc.run.net"},
@ -545,7 +545,7 @@ static const struct defaultserver def[] =
{0, "us.undernet.org"},
{0, "eu.undernet.org"},
{"UniBG", 0, 0, 0, 4},
{"UniBG", 0, 0, 0, LOGIN_MSG_NS},
{0, "irc.lirex.com"},
{0, "irc.naturella.com"},
{0, "irc.spnet.net"},
@ -581,6 +581,55 @@ static const struct defaultserver def[] =
GSList *network_list = 0;
#if !GLIB_CHECK_VERSION(2,34,0)
#define g_slist_copy_deep servlist_slist_copy_deep
/* FIXME copy-paste from gslist.c, should be dumped sometime */
static GSList*
servlist_slist_copy_deep (GSList *list, GCopyFunc func, gpointer user_data)
{
GSList *new_list = NULL;
if (list)
{
GSList *last;
new_list = g_slice_new (GSList);
if (func)
new_list->data = func (list->data, user_data);
else
new_list->data = list->data;
last = new_list;
list = list->next;
while (list)
{
last->next = g_slice_new (GSList);
last = last->next;
if (func)
last->data = func (list->data, user_data);
else
last->data = list->data;
list = list->next;
}
last->next = NULL;
}
return new_list;
}
#endif
favchannel *
servlist_favchan_copy (favchannel *fav)
{
favchannel *newfav;
newfav = malloc (sizeof (favchannel));
memset (newfav, 0, sizeof (favchannel));
newfav->name = g_strdup (fav->name);
newfav->key = g_strdup (fav->key); /* g_strdup() can handle NULLs so no need to check it */
return newfav;
}
void
servlist_connect (session *sess, ircnet *net, gboolean join)
@ -603,53 +652,39 @@ servlist_connect (session *sess, ircnet *net, gboolean join)
return;
ircserv = list->data;
/* incase a protocol switch is added to the servlist gui */
/* in case a protocol switch is added to the servlist gui */
server_fill_her_up (sess->server);
if (join)
{
sess->willjoinchannel[0] = 0;
if (net->autojoin)
if (net->favchanlist)
{
if (serv->autojoin)
free (serv->autojoin);
serv->autojoin = strdup (net->autojoin);
if (serv->favlist)
{
g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
}
serv->favlist = g_slist_copy_deep (net->favchanlist, (GCopyFunc) servlist_favchan_copy, NULL);
}
}
if (net->nstype >= 1) /* once again, make sure gtk_combo_box_get_active() is not bugging us, just in case */
if (net->logintype)
{
serv->nickservtype = net->nstype - 1; /* ircnet->nstype starts at 1, server->nickservtype starts at 0! */
serv->loginmethod = net->logintype;
}
else
{
serv->nickservtype = 1; /* use /NickServ by default */
serv->loginmethod = LOGIN_DEFAULT_REAL;
}
serv->password[0] = 0;
serv->sasluser[0] = 0;
serv->saslpassword[0] = 0;
if (net->pass)
{
safe_strcpy (serv->password, net->pass, sizeof (serv->password));
}
if (net->flags & FLAG_USE_GLOBAL || net->user == NULL)
{
strcpy (serv->sasluser, prefs.hex_irc_user_name);
}
else
{
safe_strcpy (serv->sasluser, net->user, sizeof (serv->sasluser));
}
if (net->saslpass)
{
safe_strcpy (serv->saslpassword, net->saslpass, sizeof (serv->saslpassword));
}
if (net->flags & FLAG_USE_GLOBAL)
{
strcpy (serv->nick, prefs.hex_irc_nick1);
@ -820,7 +855,9 @@ servlist_server_find (ircnet *net, char *name, int *pos)
if (strcmp (serv->hostname, name) == 0)
{
if (pos)
{
*pos = i;
}
return serv;
}
i++;
@ -830,6 +867,56 @@ servlist_server_find (ircnet *net, char *name, int *pos)
return NULL;
}
favchannel *
servlist_favchan_find (ircnet *net, char *channel, int *pos)
{
GSList *list = net->favchanlist;
favchannel *favchan;
int i = 0;
while (list)
{
favchan = list->data;
if (strcmp (favchan->name, channel) == 0)
{
if (pos)
{
*pos = i;
}
return favchan;
}
i++;
list = list->next;
}
return NULL;
}
commandentry *
servlist_command_find (ircnet *net, char *cmd, int *pos)
{
GSList *list = net->commandlist;
commandentry *entry;
int i = 0;
while (list)
{
entry = list->data;
if (strcmp (entry->command, cmd) == 0)
{
if (pos)
{
*pos = i;
}
return entry;
}
i++;
list = list->next;
}
return NULL;
}
/* find a network (e.g. (ircnet *) to "FreeNode") from a hostname
(e.g. "irc.eu.freenode.net") */
@ -897,6 +984,60 @@ servlist_server_add (ircnet *net, char *name)
return serv;
}
commandentry *
servlist_command_add (ircnet *net, char *cmd)
{
commandentry *entry;
entry = malloc (sizeof (commandentry));
memset (entry, 0, sizeof (commandentry));
entry->command = strdup (cmd);
net->commandlist = g_slist_append (net->commandlist, entry);
return entry;
}
GSList *
servlist_favchan_listadd (GSList *chanlist, char *channel, char *key)
{
favchannel *chan;
chan = malloc (sizeof (favchannel));
memset (chan, 0, sizeof (favchannel));
chan->name = g_strdup (channel);
chan->key = g_strdup (key);
chanlist = g_slist_append (chanlist, chan);
return chanlist;
}
void
servlist_favchan_add (ircnet *net, char *channel)
{
int pos;
char *name;
char *key;
if (strchr (channel, ',') != NULL)
{
pos = (int) (strchr (channel, ',') - channel);
name = g_strndup (channel, pos);
key = g_strdup (channel + pos + 1);
}
else
{
name = g_strdup (channel);
key = NULL;
}
net->favchanlist = servlist_favchan_listadd (net->favchanlist, name, key);
g_free (name);
g_free (key);
}
void
servlist_server_remove (ircnet *net, ircserver *serv)
{
@ -917,6 +1058,35 @@ servlist_server_remove_all (ircnet *net)
}
}
void
servlist_command_free (commandentry *entry)
{
g_free (entry->command);
g_free (entry);
}
void
servlist_command_remove (ircnet *net, commandentry *entry)
{
servlist_command_free (entry);
net->commandlist = g_slist_remove (net->commandlist, entry);
}
void
servlist_favchan_free (favchannel *channel)
{
g_free (channel->name);
g_free (channel->key);
g_free (channel);
}
void
servlist_favchan_remove (ircnet *net, favchannel *channel)
{
servlist_favchan_free (channel);
net->favchanlist = g_slist_remove (net->favchanlist, channel);
}
static void
free_and_clear (char *str)
{
@ -941,8 +1111,6 @@ servlist_cleanup (void)
{
net = list->data;
free_and_clear (net->pass);
free_and_clear (net->saslpass);
free_and_clear (net->nickserv);
}
}
@ -964,12 +1132,10 @@ servlist_net_remove (ircnet *net)
if (net->real)
free (net->real);
free_and_clear (net->pass);
free_and_clear (net->saslpass);
if (net->autojoin)
free (net->autojoin);
if (net->command)
free (net->command);
free_and_clear (net->nickserv);
if (net->favchanlist)
g_slist_free_full (net->favchanlist, (GDestroyNotify) servlist_favchan_free);
if (net->commandlist)
g_slist_free_full (net->commandlist, (GDestroyNotify) servlist_command_free);
if (net->comment)
free (net->comment);
if (net->encoding)
@ -983,7 +1149,9 @@ servlist_net_remove (ircnet *net)
{
serv = list->data;
if (serv->network == net)
{
serv->network = NULL;
}
list = list->next;
}
}
@ -1022,16 +1190,16 @@ servlist_load_defaults (void)
net->encoding = strdup (IRC_DEFAULT_CHARSET);
if (def[i].channel)
{
net->autojoin = strdup (def[i].channel);
servlist_favchan_add (net, def[i].channel);
}
if (def[i].charset)
{
free (net->encoding);
net->encoding = strdup (def[i].charset);
}
if (def[i].nsmode)
if (def[i].loginmode)
{
net->nstype = def[i].nsmode;
net->logintype = def[i].loginmode;
}
if (g_str_hash (def[i].network) == def_hash)
{
@ -1057,7 +1225,6 @@ servlist_load (void)
FILE *fp;
char buf[2048];
int len;
char *tmp;
ircnet *net = NULL;
/* simple migration we will keep for a short while */
@ -1100,43 +1267,55 @@ servlist_load (void)
case 'P':
net->pass = strdup (buf + 2);
break;
case 'A':
net->saslpass = strdup (buf + 2);
break;
case 'J':
net->autojoin = strdup (buf + 2);
break;
case 'C':
if (net->command)
{
/* concat extra commands with a \n separator */
tmp = net->command;
net->command = malloc (strlen (tmp) + strlen (buf + 2) + 2);
strcpy (net->command, tmp);
strcat (net->command, "\n");
strcat (net->command, buf + 2);
free (tmp);
} else
net->command = strdup (buf + 2);
break;
case 'F':
net->flags = atoi (buf + 2);
break;
case 'D':
net->selected = atoi (buf + 2);
case 'L':
net->logintype = atoi (buf + 2);
break;
case 'E':
net->encoding = strdup (buf + 2);
break;
case 'F':
net->flags = atoi (buf + 2);
break;
case 'S': /* new server/hostname for this network */
servlist_server_add (net, buf + 2);
break;
case 'C':
servlist_command_add (net, buf + 2);
break;
case 'J':
servlist_favchan_add (net, buf + 2);
break;
case 'D':
net->selected = atoi (buf + 2);
break;
/* FIXME Migration code. In 2.9.5 the order was:
*
* P=serverpass, A=saslpass, B=nickservpass
*
* So if server password was unset, we can safely use SASL
* password for our new universal password, or if that's also
* unset, use NickServ password.
*
* Should be removed at some point.
*/
case 'A':
if (!net->pass)
{
net->pass = strdup (buf + 2);
if (!net->logintype)
{
net->logintype = LOGIN_SASL;
}
}
case 'B':
net->nickserv = strdup (buf + 2);
break;
case 'T':
net->nstype = atoi (buf + 2);
break;
if (!net->pass)
{
net->pass = strdup (buf + 2);
if (!net->logintype)
{
net->logintype = LOGIN_NICKSERV;
}
}
}
}
if (buf[0] == 'N')
@ -1187,13 +1366,6 @@ servlist_check_encoding (char *charset)
return FALSE;
}
static int
servlist_write_ccmd (char *str, void *fp)
{
return fprintf (fp, "C=%s\n", (str[0] == '/') ? str + 1 : str);
}
int
servlist_save (void)
{
@ -1201,8 +1373,12 @@ servlist_save (void)
char *buf;
ircnet *net;
ircserver *serv;
commandentry *cmd;
favchannel *favchan;
GSList *list;
GSList *hlist;
GSList *netlist;
GSList *cmdlist;
GSList *favlist;
#ifndef WIN32
int first = FALSE;
@ -1244,26 +1420,8 @@ servlist_save (void)
fprintf (fp, "R=%s\n", net->real);
if (net->pass)
fprintf (fp, "P=%s\n", net->pass);
if (net->saslpass)
fprintf (fp, "A=%s\n", net->saslpass);
if (net->autojoin)
fprintf (fp, "J=%s\n", net->autojoin);
if (net->nickserv)
fprintf (fp, "B=%s\n", net->nickserv);
if (net->nstype)
{
if (net->nstype == -1) /* gtk_combo_box_get_active() returns -1 for invalid indices */
{
net->nstype = 0; /* avoid further crashes for the current session */
buf = g_strdup_printf (_("Warning: invalid NickServ type. Falling back to default type for network %s."), net->name);
fe_message (buf, FE_MSG_WARN);
g_free (buf);
}
else /* the selection was fine, save it */
{
fprintf (fp, "T=%d\n", net->nstype);
}
}
if (net->logintype)
fprintf (fp, "L=%d\n", net->logintype);
if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") &&
g_ascii_strcasecmp (net->encoding, "System default"))
{
@ -1277,17 +1435,39 @@ servlist_save (void)
}
}
if (net->command)
token_foreach (net->command, '\n', servlist_write_ccmd, fp);
fprintf (fp, "F=%d\nD=%d\n", net->flags, net->selected);
hlist = net->servlist;
while (hlist)
netlist = net->servlist;
while (netlist)
{
serv = hlist->data;
serv = netlist->data;
fprintf (fp, "S=%s\n", serv->hostname);
hlist = hlist->next;
netlist = netlist->next;
}
cmdlist = net->commandlist;
while (cmdlist)
{
cmd = cmdlist->data;
fprintf (fp, "C=%s\n", cmd->command);
cmdlist = cmdlist->next;
}
favlist = net->favchanlist;
while (favlist)
{
favchan = favlist->data;
if (favchan->key)
{
fprintf (fp, "J=%s,%s\n", favchan->name, favchan->key);
}
else
{
fprintf (fp, "J=%s\n", favchan->name);
}
favlist = favlist->next;
}
if (fprintf (fp, "\n") < 1)
@ -1303,162 +1483,33 @@ servlist_save (void)
return TRUE;
}
static void
joinlist_free1 (GSList *list)
static int
joinlist_find_chan (favchannel *curr_item, const char *channel)
{
GSList *head = list;
for (; list; list = list->next)
g_free (list->data);
g_slist_free (head);
}
void
joinlist_free (GSList *channels, GSList *keys)
{
joinlist_free1 (channels);
joinlist_free1 (keys);
if (!g_ascii_strcasecmp (curr_item->name, channel))
{
return 0;
}
else
{
return 1;
}
}
gboolean
joinlist_is_in_list (server *serv, char *channel)
{
GSList *channels, *keys;
GSList *list;
if (!serv->network || !((ircnet *)serv->network)->autojoin)
if (!serv->network || !((ircnet *)serv->network)->favchanlist)
{
return FALSE;
joinlist_split (((ircnet *)serv->network)->autojoin, &channels, &keys);
for (list = channels; list; list = list->next)
{
if (serv->p_cmp (list->data, channel) == 0)
return TRUE;
}
joinlist_free (channels, keys);
return FALSE;
if (g_slist_find_custom (((ircnet *)serv->network)->favchanlist, channel, (GCompareFunc) joinlist_find_chan))
{
return TRUE;
}
else
{
return FALSE;
}
}
gchar *
joinlist_merge (GSList *channels, GSList *keys)
{
GString *out = g_string_new (NULL);
GSList *list;
int i, j;
for (; channels; channels = channels->next)
{
g_string_append (out, channels->data);
if (channels->next)
g_string_append_c (out, ',');
}
/* count number of REAL keys */
for (i = 0, list = keys; list; list = list->next)
if (list->data)
i++;
if (i > 0)
{
g_string_append_c (out, ' ');
for (j = 0; keys; keys = keys->next)
{
if (keys->data)
{
g_string_append (out, keys->data);
j++;
if (j == i)
break;
}
if (keys->next)
g_string_append_c (out, ',');
}
}
return g_string_free (out, FALSE);
}
void
joinlist_split (char *autojoin, GSList **channels, GSList **keys)
{
char *parta, *partb;
char *chan, *key;
int len;
*channels = NULL;
*keys = NULL;
/* after the first space, the keys begin */
parta = autojoin;
partb = strchr (autojoin, ' ');
if (partb)
partb++;
while (1)
{
chan = parta;
key = partb;
if (1)
{
while (parta[0] != 0 && parta[0] != ',' && parta[0] != ' ')
{
parta++;
}
}
if (partb)
{
while (partb[0] != 0 && partb[0] != ',' && partb[0] != ' ')
{
partb++;
}
}
len = parta - chan;
if (len < 1)
break;
*channels = g_slist_append (*channels, g_strndup (chan, len));
len = partb - key;
*keys = g_slist_append (*keys, len ? g_strndup (key, len) : NULL);
if (parta[0] == ' ' || parta[0] == 0)
break;
parta++;
if (partb)
{
if (partb[0] == 0 || partb[0] == ' ')
partb = NULL; /* no more keys, but maybe more channels? */
else
partb++;
}
}
#if 0
GSList *lista, *listb;
int i;
printf("-----\n");
i = 0;
lista = *channels;
listb = *keys;
while (lista)
{
printf("%d. |%s| |%s|\n", i, lista->data, listb->data);
i++;
lista = lista->next;
listb = listb->next;
}
printf("-----\n\n");
#endif
}

View File

@ -25,6 +25,17 @@ typedef struct ircserver
char *hostname;
} ircserver;
typedef struct commandentry
{
char *command;
} commandentry;
typedef struct favchannel
{
char *name;
char *key;
} favchannel;
typedef struct ircnet
{
char *name;
@ -33,14 +44,12 @@ typedef struct ircnet
char *user;
char *real;
char *pass;
char *saslpass;
char *autojoin;
char *command;
char *nickserv;
int nstype;
int logintype;
char *comment;
char *encoding;
GSList *servlist;
GSList *commandlist;
GSList *favchanlist;
int selected;
guint32 flags;
} ircnet;
@ -49,13 +58,24 @@ extern GSList *network_list;
#define FLAG_CYCLE 1
#define FLAG_USE_GLOBAL 2
#define FLAG_USE_SSL 4
#define FLAG_USE_SSL 4
#define FLAG_AUTO_CONNECT 8
#define FLAG_USE_PROXY 16
#define FLAG_ALLOW_INVALID 32
#define FLAG_FAVORITE 64
#define FLAG_COUNT 7
/* Login methods. Use server password by default - if we had a NickServ password, it'd be set to 2 already by servlist_load() */
#define LOGIN_DEFAULT_REAL LOGIN_PASS /* this is to set the default login method for unknown servers */
#define LOGIN_DEFAULT 0 /* this is for the login type dropdown, doesn't serve any other purpose */
#define LOGIN_MSG_NICKSERV 1
#define LOGIN_NICKSERV 2
#define LOGIN_NS 3
#define LOGIN_MSG_NS 4
#define LOGIN_AUTH 5
#define LOGIN_SASL 6
#define LOGIN_PASS 7
/* DEFAULT_CHARSET is already defined in wingdi.h */
#define IRC_DEFAULT_CHARSET "UTF-8 (Unicode)"
@ -74,13 +94,28 @@ void servlist_net_remove (ircnet *net);
ircnet *servlist_net_find (char *name, int *pos, int (*cmpfunc) (const char *, const char *));
ircnet *servlist_net_find_from_server (char *server_name);
void servlist_server_remove (ircnet *net, ircserver *serv);
ircserver *servlist_server_add (ircnet *net, char *name);
ircserver *servlist_server_find (ircnet *net, char *name, int *pos);
commandentry *servlist_command_find (ircnet *net, char *cmd, int *pos);
favchannel *servlist_favchan_find (ircnet *net, char *channel, int *pos);
ircserver *servlist_server_add (ircnet *net, char *name);
commandentry *servlist_command_add (ircnet *net, char *command);
void servlist_favchan_add (ircnet *net, char *channel);
void servlist_command_free (commandentry *entry);
void servlist_favchan_free (favchannel *channel);
void servlist_server_remove (ircnet *net, ircserver *serv);
void servlist_command_remove (ircnet *net, commandentry *entry);
void servlist_favchan_remove (ircnet *net, favchannel *channel);
favchannel *servlist_favchan_copy (favchannel *fav);
GSList *servlist_favchan_listadd (GSList *chanlist, char *channel, char *key);
void joinlist_split (char *autojoin, GSList **channels, GSList **keys);
gboolean joinlist_is_in_list (server *serv, char *channel);
void joinlist_free (GSList *channels, GSList *keys);
gchar *joinlist_merge (GSList *channels, GSList *keys);
/* FIXME
void joinlist_split (char *autojoin, GSList **channels, GSList **keys);
void joinlist_free (GSList *channels, GSList *keys);
*/
#endif

View File

@ -1886,7 +1886,7 @@ int main (int argc, char *argv[])
list = get_subdirs ("foo");
display_list (list);
#if GLIB_CHECK_VERSION(2,28,0)
g_slist_free_full (list, (GFunc) g_free);
g_slist_free_full (list, (GDestroyNotify) g_free);
#else
g_slist_foreach (list, (GFunc) g_free, NULL);
g_slist_free (list);

View File

@ -685,14 +685,14 @@ dcc_detail_label (char *text, GtkWidget *box, int num)
static void
dcc_exp_cb (GtkWidget *exp, GtkWidget *box)
{
#if GTK_CHECK_VERSION(2,20,0)
if (gtk_widget_get_visible (box))
#else
if (GTK_WIDGET_VISIBLE (box))
#endif
{
gtk_widget_hide (box);
}
else
{
gtk_widget_show (box);
}
}
static void

View File

@ -897,15 +897,15 @@ fe_gui_info (session *sess, int info_type)
switch (info_type)
{
case 0: /* window status */
#if GTK_CHECK_VERSION(2,20,0)
if (!gtk_widget_get_visible (GTK_WIDGET (sess->gui->window)))
#else
if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (sess->gui->window)))
#endif
{
return 2; /* hidden (iconified or systray) */
}
if (gtk_window_is_active (GTK_WINDOW (sess->gui->window)))
{
return 1; /* active/focused */
}
return 0; /* normal (no keyboard focus or behind a window) */
}
@ -920,11 +920,7 @@ fe_gui_info_ptr (session *sess, int info_type)
{
case 0: /* native window pointer (for plugins) */
#ifdef WIN32
#if GTK_CHECK_VERSION(2,24,8)
return gdk_win32_window_get_impl_hwnd (sess->gui->window->window);
#else
return GDK_WINDOW_HWND (sess->gui->window->window);
#endif
#else
return sess->gui->window;
#endif

View File

@ -1637,10 +1637,6 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
strncat (buf, result, COMP_BUF - prefix_len);
cursor_pos = strlen (buf);
g_free(result);
#if !GLIB_CHECK_VERSION(2,4,0)
g_utf8_validate (buf, -1, (const gchar **)&result);
(*result) = 0;
#endif
if (postfix)
{
strcat (buf, " ");

View File

@ -1048,9 +1048,13 @@ menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel)
}
if (joinlist_is_in_list (serv, channel))
{
mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE, menu, menu_delfav_cb, serv);
}
else
{
mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD, menu, menu_addfav_cb, serv);
}
}
static void
@ -1729,11 +1733,7 @@ static gboolean
menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
{
/* GTK2.2 behaviour */
#if GTK_CHECK_VERSION(2,20,0)
return gtk_widget_is_sensitive (widget);
#else
return GTK_WIDGET_IS_SENSITIVE (widget);
#endif
}
/* === STUFF FOR /MENU === */

View File

@ -414,11 +414,7 @@ tray_toggle_visibility (gboolean force_hide)
if (!win)
return FALSE;
#if GTK_CHECK_VERSION(2,20,0)
if (force_hide || gtk_widget_get_visible (GTK_WIDGET (win)))
#else
if (force_hide || GTK_WIDGET_VISIBLE (win))
#endif
{
if (prefs.hex_gui_tray_away)
hexchat_command (ph, "ALLSERV AWAY");

File diff suppressed because it is too large Load Diff

View File

@ -954,7 +954,6 @@ enchant_has_lang(const gchar *lang, GSList *langs) {
void
sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
{
#if GLIB_CHECK_VERSION (2, 6, 0)
/*const gchar* const *langs;
int i;
gchar *lastprefix = NULL;*/
@ -1003,26 +1002,6 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
/* If we don't have any languages activated, use "en" */
if (entry->priv->dict_list == NULL)
sexy_spell_entry_activate_language_internal(entry, "en", NULL);
#else
gchar *lang;
if (!have_enchant)
return;
lang = (gchar *) g_getenv("LANG");
if (lang != NULL) {
if (g_ascii_strncasecmp(lang, "C", 1) == 0)
lang = NULL;
else if (lang[0] == '\0')
lang = NULL;
}
if (lang == NULL)
lang = "en";
sexy_spell_entry_activate_language_internal(entry, lang, NULL);
#endif
}
static void

View File

@ -1034,11 +1034,7 @@ gtk_xtext_realize (GtkWidget * widget)
gdk_window_set_user_data (widget->window, widget);
#if GTK_CHECK_VERSION(2,24,0)
xtext->depth = gdk_window_get_visual (widget->window)->depth;
#else
xtext->depth = gdk_drawable_get_visual (widget->window)->depth;
#endif
val.subwindow_mode = GDK_INCLUDE_INFERIORS;
val.graphics_exposures = 0;