Support account-notify and extended-join capabilities

This commit is contained in:
TingPing 2013-04-03 17:10:09 -04:00
parent 4c217d4ba3
commit b4c8d53394
8 changed files with 138 additions and 30 deletions

View File

@ -593,6 +593,8 @@ typedef struct server
unsigned int have_uhnames:1;
unsigned int have_whox:1; /* have undernet's WHOX features */
unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */
unsigned int have_accnotify:1; /* cap account-notify */
unsigned int have_extjoin:1; /* cap extended-join */
unsigned int have_sasl:1; /* SASL capability */
unsigned int have_except:1; /* ban exemptions +e */
unsigned int have_invite:1; /* invite exemptions +I */

View File

@ -137,7 +137,7 @@ static void
inbound_make_idtext (server *serv, char *idtext, int max, int id)
{
idtext[0] = 0;
if (serv->have_idmsg)
if (serv->have_idmsg || serv->have_accnotify)
{
if (id)
{
@ -157,6 +157,7 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id)
session *sess;
struct User *user;
char idtext[64];
gboolean nodiag = FALSE;
sess = find_dialog (serv, from);
@ -189,21 +190,24 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id)
return;
}
inbound_make_idtext (serv, idtext, sizeof (idtext), id);
sess = find_session_from_nick (from, serv);
if (!sess)
{
sess = serv->front_session;
EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0);
return;
nodiag = TRUE; /* We don't want it to look like a normal message in front sess */
}
user = userlist_find (sess, from);
if (user)
{
user->lasttalk = time (0);
if (user->account)
id = TRUE;
}
inbound_make_idtext (serv, idtext, sizeof (idtext), id);
if (sess->type == SESS_DIALOG)
if (sess->type == SESS_DIALOG && !nodiag)
EMIT_SIGNAL (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0);
else
EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0);
@ -380,6 +384,8 @@ inbound_action (session *sess, char *chan, char *from, char *ip, char *text, int
{
nickchar[0] = user->prefix[0];
user->lasttalk = time (0);
if (user->account)
id = TRUE;
}
inbound_make_idtext (serv, idtext, sizeof (idtext), id);
@ -436,6 +442,8 @@ inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text
user = userlist_find (sess, from);
if (user)
{
if (user->account)
id = TRUE;
nickchar[0] = user->prefix[0];
user->lasttalk = time (0);
}
@ -655,12 +663,12 @@ inbound_nameslist (server *serv, char *chan, char *names)
case 0:
name[pos] = 0;
if (pos != 0)
userlist_add (sess, name, 0);
userlist_add (sess, name, 0, NULL, NULL);
return;
case ' ':
name[pos] = 0;
pos = 0;
userlist_add (sess, name, 0);
userlist_add (sess, name, 0, NULL, NULL);
break;
default:
name[pos] = *names;
@ -705,13 +713,13 @@ inbound_topicnew (server *serv, char *nick, char *chan, char *topic)
}
void
inbound_join (server *serv, char *chan, char *user, char *ip)
inbound_join (server *serv, char *chan, char *user, char *ip, char *account, char *realname)
{
session *sess = find_channel (serv, chan);
if (sess)
{
EMIT_SIGNAL (XP_TE_JOIN, sess, user, chan, ip, NULL, 0);
userlist_add (sess, user, ip);
userlist_add (sess, user, ip, account, realname);
}
}
@ -783,6 +791,22 @@ inbound_quit (server *serv, char *nick, char *ip, char *reason)
notify_set_offline (serv, nick, was_on_front_session);
}
void
inbound_account (server *serv, char *nick, char *account)
{
session *sess = NULL;
GSList *list;
list = sess_list;
while (list)
{
sess = list->data;
if (sess->server == serv)
userlist_set_account (sess, nick, account);
list = list->next;
}
}
void
inbound_ping_reply (session *sess, char *timestring, char *from)
{
@ -1252,7 +1276,7 @@ inbound_user_info_start (session *sess, char *nick)
void
inbound_user_info (session *sess, char *chan, char *user, char *host,
char *servname, char *nick, char *realname,
unsigned int away)
char *account, unsigned int away)
{
server *serv = sess->server;
session *who_sess;
@ -1269,7 +1293,7 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
{
who_sess = find_channel (serv, chan);
if (who_sess)
userlist_add_hostname (who_sess, nick, uhost, realname, servname, away);
userlist_add_hostname (who_sess, nick, uhost, realname, servname, account, away);
else
{
if (serv->doing_dns && nick && host)
@ -1284,7 +1308,7 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
sess = list->data;
if (sess->type == SESS_CHANNEL && sess->server == serv)
{
userlist_add_hostname (sess, nick, uhost, realname, servname, away);
userlist_add_hostname (sess, nick, uhost, realname, servname, account, away);
}
}
}

View File

@ -23,6 +23,7 @@
void inbound_next_nick (session *sess, char *nick);
void inbound_uback (server *serv);
void inbound_uaway (server *serv);
void inbound_account (server *serv, char *nick, char *account);
void inbound_part (server *serv, char *chan, char *user, char *ip, char *reason);
void inbound_upart (server *serv, char *chan, char *ip, char *reason);
void inbound_ukick (server *serv, char *chan, char *kicker, char *reason);
@ -30,12 +31,12 @@ void inbound_kick (server *serv, char *chan, char *user, char *kicker, char *rea
void inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id);
void inbound_quit (server *serv, char *nick, char *ip, char *reason);
void inbound_topicnew (server *serv, char *nick, char *chan, char *topic);
void inbound_join (server *serv, char *chan, char *user, char *ip);
void inbound_join (server *serv, char *chan, char *user, char *ip, char *account, char *realname);
void inbound_ujoin (server *serv, char *chan, char *nick, char *ip);
void inbound_topictime (server *serv, char *chan, char *nick, time_t stamp);
void inbound_topic (server *serv, char *chan, char *topic_text);
void inbound_user_info_start (session *sess, char *nick);
void inbound_user_info (session *sess, char *chan, char *user, char *host, char *servname, char *nick, char *realname, unsigned int away);
void inbound_user_info (session *sess, char *chan, char *user, char *host, char *servname, char *nick, char *realname, char *account, unsigned int away);
void inbound_foundip (session *sess, char *ip);
int inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, int is_exemption);
void inbound_ping_reply (session *sess, char *timestring, char *from);

View File

@ -313,7 +313,10 @@ irc_join_info (server *serv, char *channel)
static void
irc_user_list (server *serv, char *channel)
{
tcp_sendf (serv, "WHO %s\r\n", channel);
if (serv->have_whox)
tcp_sendf (serv, "WHO %s %%chtsunfra,152\r\n", channel);
else
tcp_sendf (serv, "WHO %s\r\n", channel);
}
/* userhost */
@ -328,7 +331,7 @@ static void
irc_away_status (server *serv, char *channel)
{
if (serv->have_whox)
tcp_sendf (serv, "WHO %s %%ctnf,152\r\n", channel);
tcp_sendf (serv, "WHO %s %%chtsunfra,152\r\n", channel);
else
tcp_sendf (serv, "WHO %s\r\n", channel);
}
@ -560,7 +563,7 @@ process_numeric (session * sess, int n,
if (!serv->skip_next_whois)
EMIT_SIGNAL (XP_TE_WHOIS3, whois_sess, word[4], word_eol[5], NULL, NULL, 0);
else
inbound_user_info (sess, NULL, NULL, NULL, word[5], word[4], NULL, 0xff);
inbound_user_info (sess, NULL, NULL, NULL, word[5], word[4], NULL, NULL, 0xff);
break;
case 311: /* WHOIS 1st line */
@ -571,7 +574,7 @@ process_numeric (session * sess, int n,
word[6], word_eol[8] + 1, 0);
else
inbound_user_info (sess, NULL, word[5], word[6], NULL, word[4],
word_eol[8][0] == ':' ? word_eol[8] + 1 : word_eol[8], 0xff);
word_eol[8][0] == ':' ? word_eol[8] + 1 : word_eol[8], NULL, 0xff);
break;
case 314: /* WHOWAS */
@ -716,7 +719,7 @@ process_numeric (session * sess, int n,
away = 1;
inbound_user_info (sess, word[4], word[5], word[6], word[7],
word[8], word_eol[11], away);
word[8], word_eol[11], word[10], away);
/* try to show only user initiated whos */
if (!who_sess || !who_sess->doing_who)
@ -730,16 +733,17 @@ process_numeric (session * sess, int n,
unsigned int away = 0;
session *who_sess;
/* irc_away_status sends out a "152" */
/* irc_away_status and irc_user_list sends out a "152" */
if (!strcmp (word[4], "152"))
{
who_sess = find_channel (serv, word[5]);
if (*word[7] == 'G')
if (*word[10] == 'G')
away = 1;
/* :SanJose.CA.us.undernet.org 354 z1 152 #zed1 z1 H@ */
inbound_user_info (sess, word[5], 0, 0, 0, word[6], 0, away);
/* :server 354 yournick 152 #channel ~ident host servname nick H account :realname */
inbound_user_info (sess, word[5], word[6], word[7], word[8],
word[9], word_eol[12], word[11], away);
/* try to show only user initiated whos */
if (!who_sess || !who_sess->doing_who)
@ -965,13 +969,15 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
case WORDL('J','O','I','N'):
{
char *chan = word[3];
char *account = word[4];
char *realname = word_eol[5] + 1;
if (*chan == ':')
chan++;
if (!serv->p_cmp (nick, serv->nick))
inbound_ujoin (serv, chan, nick, ip);
else
inbound_join (serv, chan, nick, ip);
inbound_join (serv, chan, nick, ip, account, realname);
}
return;
@ -1047,6 +1053,11 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
/* this should compile to a bunch of: CMP.L, JE ... nice & fast */
switch (t)
{
case WORDL('A','C','C','O'):
inbound_account (serv, nick, word[3]);
return;
case WORDL('I','N','V','I'):
if (ignore_check (word[1], IG_INVI))
return;
@ -1176,6 +1187,16 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
serv->have_awaynotify = TRUE;
}
if (strstr (word_eol[5], "account-notify") != 0)
{
serv->have_accnotify = TRUE;
}
if (strstr (word_eol[5], "extended-join") != 0)
{
serv->have_extjoin = TRUE;
}
if (strstr (word_eol[5], "sasl") != 0)
{
serv->have_sasl = TRUE;
@ -1208,6 +1229,17 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
want_cap ? strcat (buffer, " away-notify") : strcpy (buffer, "CAP REQ :away-notify");
want_cap = 1;
}
if (strstr (word_eol[5], "account-notify") != 0)
{
want_cap ? strcat (buffer, " account-notify") : strcpy (buffer, "CAP REQ :account-notify");
want_cap = 1;
}
if (strstr (word_eol[5], "extended-join") != 0)
{
want_cap ? strcat (buffer, " extended-join") : strcpy (buffer, "CAP REQ :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)
{

View File

@ -1888,6 +1888,8 @@ server_set_defaults (server *serv)
serv->have_uhnames = FALSE;
serv->have_whox = FALSE;
serv->have_idmsg = FALSE;
serv->have_accnotify = FALSE;
serv->have_extjoin = FALSE;
serv->have_sasl = FALSE;
serv->have_except = FALSE;
serv->have_invite = FALSE;

View File

@ -113,9 +113,30 @@ userlist_set_away (struct session *sess, char *nick, unsigned int away)
}
}
void
userlist_set_account (struct session *sess, char *nick, char *account)
{
struct User *user;
user = userlist_find (sess, nick);
if (user)
{
if (user->account)
free (user->account);
if (strcmp (account, "*") == 0)
user->account = NULL;
else
user->account = strdup (account);
/* gui doesnt currently reflect login status, maybe later
fe_userlist_rehash (sess, user); */
}
}
int
userlist_add_hostname (struct session *sess, char *nick, char *hostname,
char *realname, char *servername, unsigned int away)
char *realname, char *servername, char *account, unsigned int away)
{
struct User *user;
@ -128,6 +149,8 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
user->realname = strdup (realname);
if (!user->servername && servername)
user->servername = strdup (servername);
if (!user->account && account && strcmp (account, ":0") != 0 && strcmp (account, "0") != 0)
user->account = strdup (account);
if (away != 0xff)
{
@ -155,6 +178,8 @@ free_user (struct User *user, gpointer data)
free (user->hostname);
if (user->servername)
free (user->servername);
if (user->account)
free (user->account);
free (user);
return TRUE;
@ -358,7 +383,7 @@ userlist_remove_user (struct session *sess, struct User *user)
}
void
userlist_add (struct session *sess, char *name, char *hostname)
userlist_add (struct session *sess, char *name, char *hostname, char *account, char *realname)
{
struct User *user;
int row, prefix_chars;
@ -384,6 +409,15 @@ userlist_add (struct session *sess, char *name, char *hostname)
/* is it me? */
if (!sess->server->p_cmp (user->nick, sess->server->nick))
user->me = TRUE;
/* extended join info */
if (sess->server->have_extjoin)
{
if (account && strcmp (account, "*") != 0)
user->account = strdup (account);
if (realname)
user->realname = strdup (realname);
}
row = userlist_insertname (sess, user);
/* duplicate? some broken servers trigger this */
@ -391,6 +425,10 @@ userlist_add (struct session *sess, char *name, char *hostname)
{
if (user->hostname)
free (user->hostname);
if (user->account)
free (user->account);
if (user->realname)
free (user->realname);
free (user);
return;
}

View File

@ -28,6 +28,7 @@ struct User
char *hostname;
char *realname;
char *servername;
char *account;
time_t lasttalk;
unsigned int access; /* axs bit field */
char prefix[2]; /* @ + % */
@ -43,13 +44,14 @@ struct User
int userlist_add_hostname (session *sess, char *nick,
char *hostname, char *realname,
char *servername, unsigned int away);
char *servername, char *account, unsigned int away);
void userlist_set_away (session *sess, char *nick, unsigned int away);
void userlist_set_account (session *sess, char *nick, char *account);
struct User *userlist_find (session *sess, const char *name);
struct User *userlist_find_global (server *serv, char *name);
void userlist_clear (session *sess);
void userlist_free (session *sess);
void userlist_add (session *sess, char *name, char *hostname);
void userlist_add (session *sess, char *name, char *hostname, char *account, char *realname);
int userlist_remove (session *sess, char *name);
void userlist_remove_user (session *sess, struct User *user);
int userlist_change (session *sess, char *oldname, char *newname);

View File

@ -624,6 +624,13 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
g_signal_connect (G_OBJECT (item), "activate",
G_CALLBACK (copy_to_clipboard_cb),
user->hostname ? user->hostname : unknown);
snprintf (buf, sizeof (buf), fmt, _("Account:"),
user->account ? user->account : unknown);
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
g_signal_connect (G_OBJECT (item), "activate",
G_CALLBACK (copy_to_clipboard_cb),
user->account ? user->account : unknown);
snprintf (buf, sizeof (buf), fmt, _("Country:"),
user->hostname ? country(user->hostname) : unknown);