aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--account.c2
-rw-r--r--bitlbee.c12
-rw-r--r--bitlbee.conf8
-rw-r--r--bitlbee.h4
-rw-r--r--conf.c6
-rw-r--r--conf.h1
-rwxr-xr-xconfigure7
-rw-r--r--doc/CHANGES21
-rw-r--r--doc/user-guide/commands.xml17
-rw-r--r--irc.c2
-rw-r--r--irc_commands.c2
-rw-r--r--lib/misc.c3
-rw-r--r--lib/misc.h2
-rw-r--r--protocols/jabber/io.c42
-rw-r--r--protocols/jabber/iq.c29
-rw-r--r--protocols/jabber/jabber.h5
-rw-r--r--protocols/msn/msn.c4
-rw-r--r--protocols/msn/msn.h6
-rw-r--r--protocols/msn/ns.c25
-rw-r--r--protocols/nogaim.c61
-rw-r--r--protocols/nogaim.h16
-rw-r--r--protocols/yahoo/libyahoo2.c336
-rw-r--r--protocols/yahoo/yahoo.c2
-rw-r--r--protocols/yahoo/yahoo2_types.h23
-rw-r--r--root_commands.c15
-rw-r--r--user.h1
26 files changed, 365 insertions, 287 deletions
diff --git a/account.c b/account.c
index 99c3ff53..a844d229 100644
--- a/account.c
+++ b/account.c
@@ -54,6 +54,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass )
s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a );
+ s = set_add( &a->set, "nick_source", "handle", NULL, a );
+
s = set_add( &a->set, "password", NULL, set_eval_account, a );
s->flags |= ACC_SET_NOSAVE | SET_NULL_OK;
diff --git a/bitlbee.c b/bitlbee.c
index b31c31fe..26d12b6c 100644
--- a/bitlbee.c
+++ b/bitlbee.c
@@ -108,11 +108,13 @@ int bitlbee_daemon_init()
chdir( "/" );
- /* Sometimes std* are already closed (for example when we're in a RESTARTed
- BitlBee process. So let's only close TTY-fds. */
- if( isatty( 0 ) ) close( 0 );
- if( isatty( 1 ) ) close( 1 );
- if( isatty( 2 ) ) close( 2 );
+ if( getenv( "_BITLBEE_RESTART_STATE" ) == NULL )
+ for( i = 0; i < 3; i ++ )
+ if( close( i ) == 0 )
+ {
+ /* Keep something bogus on those fd's just in case. */
+ open( "/dev/null", O_WRONLY );
+ }
}
#endif
diff --git a/bitlbee.conf b/bitlbee.conf
index 4a3bbddf..c5dafd9f 100644
--- a/bitlbee.conf
+++ b/bitlbee.conf
@@ -119,6 +119,14 @@
## Proxy = socks4://socksproxy.localnet.com
## Proxy = socks5://socksproxy.localnet.com
+## Protocols offered by bitlbee
+##
+## As recompiling may be quite unpractical for some people, this option
+## allows to remove the support of protocol, even if compiled in. If
+## nothing is given, there are no restrictions.
+##
+## Protocols = jabber yahoo
+
[defaults]
diff --git a/bitlbee.h b/bitlbee.h
index 46a91419..15592020 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -26,13 +26,15 @@
#ifndef _BITLBEE_H
#define _BITLBEE_H
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* Stupid GNU :-P */
+#endif
/* Depend on Windows 2000 for now since we need getaddrinfo() */
#define _WIN32_WINNT 0x0501
#define PACKAGE "BitlBee"
-#define BITLBEE_VERSION "1.2.4"
+#define BITLBEE_VERSION "1.2.5"
#define VERSION BITLBEE_VERSION
#define MAX_STRING 511
diff --git a/conf.c b/conf.c
index c8cfaad8..b997fb0a 100644
--- a/conf.c
+++ b/conf.c
@@ -62,6 +62,7 @@ conf_t *conf_load( int argc, char *argv[] )
conf->ping_interval = 180;
conf->ping_timeout = 300;
conf->user = NULL;
+ conf->protocols = NULL;
proxytype = 0;
i = conf_loadini( conf, global.conf_file );
@@ -306,6 +307,11 @@ static int conf_loadini( conf_t *conf, char *file )
g_free( conf->user );
conf->user = g_strdup( ini->value );
}
+ else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
+ {
+ g_strfreev( conf->protocols );
+ conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 );
+ }
else
{
fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line );
diff --git a/conf.h b/conf.h
index c41fd096..b112681d 100644
--- a/conf.h
+++ b/conf.h
@@ -49,6 +49,7 @@ typedef struct conf
int ping_interval;
int ping_timeout;
char *user;
+ char **protocols;
} conf_t;
G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] );
diff --git a/configure b/configure
index cac1161e..c7af5fb3 100755
--- a/configure
+++ b/configure
@@ -443,6 +443,12 @@ else
echo '#define WITH_PLUGINS' >> config.h
fi
+if [ ! -e doc/user-guide/help.txt ] && ! type xmlto > /dev/null 2> /dev/null; then
+ echo
+ echo 'WARNING: Building from an unreleased source tree without prebuilt helpfile.'
+ echo 'Install xmlto if you want online help to work.'
+fi
+
echo
if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then
nick=`bzr nick`
@@ -528,6 +534,7 @@ GNU/* )
*BSD )
;;
Darwin )
+ echo 'STRIP=\# skip strip' >> Makefile.settings
;;
IRIX )
;;
diff --git a/doc/CHANGES b/doc/CHANGES
index 1bfd71d4..1cac2dc7 100644
--- a/doc/CHANGES
+++ b/doc/CHANGES
@@ -3,6 +3,27 @@ found in the bzr commit logs, for example you can try:
http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on
+Version 1.2.5:
+- Many bug fixes, including a fix for MSN login issues, Jabber login timing
+ issues, Yahoo! crashes at login time with huge contact lists,
+- Avoid linking in a static version of libresolv now that glibc has all
+ relevant functions available in the dynamic version.
+- Improved away state code and added the ability to set (non-away) status
+ messages using "set status" (also possible per account) and see them in
+ blist and /whois output.
+- Added a post-1.2 equivalent of encode/decode to quickly encrypt/decrypt
+ passwords in a way that BitlBee can read them.
+- Allow using the full name for generating nicknames, instead of just the
+ handle. This is especially useful when using the Facebook XMPP server.
+- Auto reconnect is now enabled by default since all protocols can properly
+ detect cases where auto reconnect should be avoided (i.e. concurrent
+ logins).
+- Changed the default resource_select setting which should reduce message
+ routing issues on Jabber (i.e. messages going someone's phone instead of
+ the main client).
+
+Fixed 17 Mar 2010
+
Version 1.2.4:
- Most important change (and main reason for releasing now): Upgraded Yahoo!
module to a newer version to get it working again.
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index a7d06cf1..700df7bb 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -607,6 +607,21 @@
</description>
</bitlbee-setting>
+ <bitlbee-setting name="nick_source" type="string" scope="account">
+ <default>handle</default>
+ <possible-values>handle, full_name, first_name</possible-values>
+
+ <description>
+ <para>
+ By default, BitlBee generates a nickname for every contact by taking its handle and chopping off everything after the @. In some cases, this gives very inconvenient nicknames. The Facebook XMPP server is a good example, as all Facebook XMPP handles are numeric.
+ </para>
+
+ <para>
+ With this setting set to <emphasis>full_name</emphasis>, the person's full name is used to generate a nickname. Or if you don't like long nicknames, set this setting to <emphasis>first_name</emphasis> instead and only the first word will be used. Note that the full name can be full of non-ASCII characters which will be stripped off.
+ </para>
+ </description>
+ </bitlbee-setting>
+
<bitlbee-setting name="ops" type="string" scope="global">
<default>both</default>
<possible-values>both, root, user, none</possible-values>
@@ -700,7 +715,7 @@
</bitlbee-setting>
<bitlbee-setting name="resource_select" type="string" scope="account">
- <default>priority</default>
+ <default>activity</default>
<possible-values>priority, activity</possible-values>
<description>
diff --git a/irc.c b/irc.c
index 8d503e02..ee7b4b0d 100644
--- a/irc.c
+++ b/irc.c
@@ -165,7 +165,7 @@ irc_t *irc_new( int fd )
s->flags |= SET_NULL_OK;
s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc );
s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
- s = set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
+ s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc );
s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
diff --git a/irc_commands.c b/irc_commands.c
index 750bbcf5..a417e0d9 100644
--- a/irc_commands.c
+++ b/irc_commands.c
@@ -496,6 +496,8 @@ static void irc_cmd_whois( irc_t *irc, char **cmd )
irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
else if( u->away )
irc_reply( irc, 301, "%s :%s", u->nick, u->away );
+ if( u->status_msg )
+ irc_reply( irc, 333, "%s :Status: %s", u->nick, u->status_msg );
irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
}
diff --git a/lib/misc.c b/lib/misc.c
index 3976e01b..fe2ff17c 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -33,6 +33,7 @@
#define BITLBEE_CORE
#include "nogaim.h"
#include "base64.h"
+#include "md5.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -522,7 +523,7 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain )
}
/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */
-char *word_wrap( char *msg, int line_len )
+char *word_wrap( const char *msg, int line_len )
{
GString *ret = g_string_sized_new( strlen( msg ) + 16 );
diff --git a/lib/misc.h b/lib/misc.h
index 5376cd22..ce36caf5 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -61,7 +61,7 @@ G_MODULE_EXPORT int bool2int( char *value );
G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain );
-G_MODULE_EXPORT char *word_wrap( char *msg, int line_len );
+G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len );
G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl );
diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c
index 10efad37..a14ad21c 100644
--- a/protocols/jabber/io.c
+++ b/protocols/jabber/io.c
@@ -374,39 +374,13 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
}
if( ( c = xt_find_node( node->children, "bind" ) ) )
- {
- reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
- xt_add_attr( reply, "xmlns", XMLNS_BIND );
- reply = jabber_make_packet( "iq", "set", NULL, reply );
- jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
-
- if( !jabber_write_packet( ic, reply ) )
- return XT_ABORT;
-
- jd->flags |= JFLAG_WAIT_BIND;
- }
+ jd->flags |= JFLAG_WANT_BIND;
if( ( c = xt_find_node( node->children, "session" ) ) )
- {
- reply = xt_new_node( "session", NULL, NULL );
- xt_add_attr( reply, "xmlns", XMLNS_SESSION );
- reply = jabber_make_packet( "iq", "set", NULL, reply );
- jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
-
- if( !jabber_write_packet( ic, reply ) )
- return XT_ABORT;
-
- jd->flags |= JFLAG_WAIT_SESSION;
- }
+ jd->flags |= JFLAG_WANT_SESSION;
- /* This flag is already set if we authenticated via SASL, so now
- we can resume the session in the new stream, if we don't have
- to bind/initialize the session. */
- if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
- {
- if( !jabber_get_roster( ic ) )
- return XT_ABORT;
- }
+ if( jd->flags & JFLAG_AUTHENTICATED )
+ return jabber_pkt_bind_sess( ic, NULL, NULL );
return XT_HANDLED;
}
@@ -440,6 +414,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )
imcb_log( ic, "Converting stream to TLS" );
+ jd->flags |= JFLAG_STARTTLS_DONE;
jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic );
return XT_HANDLED;
@@ -530,9 +505,10 @@ gboolean jabber_start_stream( struct im_connection *ic )
if( jd->r_inpa <= 0 )
jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
- greet = g_strdup_printf( "<?xml version='1.0' ?>"
- "<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
- "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );
+ greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
+ "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">",
+ ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>",
+ jd->server );
st = jabber_write( ic, greet, strlen( greet ) );
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c
index 875b5c81..1b76a761 100644
--- a/protocols/jabber/iq.c
+++ b/protocols/jabber/iq.c
@@ -297,24 +297,39 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node
xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
{
struct jabber_data *jd = ic->proto_data;
- struct xt_node *c;
+ struct xt_node *c, *reply = NULL;
char *s;
- if( ( c = xt_find_node( node->children, "bind" ) ) )
+ if( node && ( c = xt_find_node( node->children, "bind" ) ) )
{
c = xt_find_node( c->children, "jid" );
if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 )
imcb_log( ic, "Server changed session resource string to `%s'", s + 1 );
-
- jd->flags &= ~JFLAG_WAIT_BIND;
}
- else
+
+ if( jd->flags & JFLAG_WANT_BIND )
{
- jd->flags &= ~JFLAG_WAIT_SESSION;
+ reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
+ xt_add_attr( reply, "xmlns", XMLNS_BIND );
+ jd->flags &= ~JFLAG_WANT_BIND;
+ }
+ else if( jd->flags & JFLAG_WANT_SESSION )
+ {
+ reply = xt_new_node( "session", NULL, NULL );
+ xt_add_attr( reply, "xmlns", XMLNS_SESSION );
+ jd->flags &= ~JFLAG_WANT_SESSION;
}
- if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+ if( reply != NULL )
+ {
+ reply = jabber_make_packet( "iq", "set", NULL, reply );
+ jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
+
+ if( !jabber_write_packet( ic, reply ) )
+ return XT_ABORT;
+ }
+ else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )
{
if( !jabber_get_roster( ic ) )
return XT_ABORT;
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 5f48cc43..40cf3957 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -39,12 +39,13 @@ typedef enum
JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */
JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after
SASL or TLS). */
- JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply
+ JFLAG_WANT_SESSION = 8, /* Set if the server wants a <session/> tag
before we continue. */
- JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */
+ JFLAG_WANT_BIND = 16, /* ... for <bind> tag. */
JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this
activates all XEP-85 related code. */
JFLAG_XMLCONSOLE = 64, /* If the user added an xmlconsole buddy. */
+ JFLAG_STARTTLS_DONE = 128, /* If a plaintext session was converted to TLS. */
} jabber_flags_t;
typedef enum
diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c
index e12fb3a9..8930847d 100644
--- a/protocols/msn/msn.c
+++ b/protocols/msn/msn.c
@@ -26,6 +26,10 @@
#include "nogaim.h"
#include "msn.h"
+int msn_chat_id;
+GSList *msn_connections;
+GSList *msn_switchboards;
+
static char *msn_set_display_name( set_t *set, char *value );
static void msn_init( account_t *acc )
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index 333ae7f0..84914bc3 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -134,7 +134,7 @@ struct msn_handler_data
#define STATUS_SB_IM_SPARE 4 /* Make one-to-one conversation switchboard available again, invite failed. */
#define STATUS_SB_CHAT_SPARE 8 /* Same, but also for groupchats (not used yet). */
-int msn_chat_id;
+extern int msn_chat_id;
extern const struct msn_away_state msn_away_state_list[];
extern const struct msn_status_code msn_status_code_list[];
@@ -143,8 +143,8 @@ extern const struct msn_status_code msn_status_code_list[];
is down already (for example, when an impatient user disabled the
connection), the callback should check whether it's still listed here
before doing *anything* else. */
-GSList *msn_connections;
-GSList *msn_switchboards;
+extern GSList *msn_connections;
+extern GSList *msn_switchboards;
/* ns.c */
gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index d05d8e0d..d78d753a 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -228,19 +228,26 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
return( 0 );
}
}
- else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 )
+ else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )
{
set_t *s;
- http_decode( cmd[4] );
-
- strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
- ic->displayname[sizeof(ic->displayname)-1] = 0;
-
- if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
+ if( num_parts == 7 )
{
- g_free( s->value );
- s->value = g_strdup( cmd[4] );
+ http_decode( cmd[4] );
+
+ strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
+ ic->displayname[sizeof(ic->displayname)-1] = 0;
+
+ if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
+ {
+ g_free( s->value );
+ s->value = g_strdup( cmd[4] );
+ }
+ }
+ else
+ {
+ imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
}
imcb_log( ic, "Authenticated, getting buddy list" );
diff --git a/protocols/nogaim.c b/protocols/nogaim.c
index 603905ab..c326e378 100644
--- a/protocols/nogaim.c
+++ b/protocols/nogaim.c
@@ -97,7 +97,19 @@ GList *protocols = NULL;
void register_protocol (struct prpl *p)
{
- protocols = g_list_append(protocols, p);
+ int i;
+ gboolean refused = global.conf->protocols != NULL;
+
+ for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++)
+ {
+ if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0)
+ refused = FALSE;
+ }
+
+ if (refused)
+ log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name);
+ else
+ protocols = g_list_append(protocols, p);
}
struct prpl *find_protocol(const char *name)
@@ -370,7 +382,7 @@ void imcb_ask( struct im_connection *ic, char *msg, void *data,
/* list.c */
-void imcb_add_buddy( struct im_connection *ic, char *handle, char *group )
+void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
{
user_t *u;
char nick[MAX_NICK_LENGTH+1], *s;
@@ -444,9 +456,10 @@ struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )
return( b );
}
-void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )
+void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
{
user_t *u = user_findhandle( ic, handle );
+ char *set;
if( !u || !realname ) return;
@@ -459,9 +472,26 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )
if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )
imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
}
+
+ set = set_getstr( &ic->acc->set, "nick_source" );
+ if( strcmp( set, "handle" ) != 0 )
+ {
+ char *name = g_strdup( realname );
+
+ if( strcmp( set, "first_name" ) == 0 )
+ {
+ int i;
+ for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
+ name[i] = '\0';
+ }
+
+ imcb_buddy_nick_hint( ic, handle, name );
+
+ g_free( name );
+ }
}
-void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )
+void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
{
user_t *u;
@@ -471,7 +501,7 @@ void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )
/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
modules to suggest a nickname for a handle. */
-void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick )
+void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
{
user_t *u = user_findhandle( ic, handle );
char newnick[MAX_NICK_LENGTH+1], *orig_nick;
@@ -616,11 +646,9 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,
oa = u->away != NULL;
oo = u->online;
- if( u->away )
- {
- g_free( u->away );
- u->away = NULL;
- }
+ g_free( u->away );
+ g_free( u->status_msg );
+ u->away = u->status_msg = NULL;
if( ( flags & OPT_LOGGED_IN ) && !u->online )
{
@@ -658,7 +686,10 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,
u->away = g_strdup( "Away" );
}
}
- /* else waste_any_state_information_for_now(); */
+ else
+ {
+ u->status_msg = g_strdup( message );
+ }
/* LISPy... */
if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */
@@ -683,7 +714,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,
}
}
-void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at )
+void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
{
irc_t *irc = ic->irc;
char *wrapped;
@@ -816,7 +847,7 @@ void imcb_chat_free( struct groupchat *c )
}
}
-void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at )
+void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
{
struct im_connection *ic = c->ic;
char *wrapped;
@@ -888,7 +919,7 @@ void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at
/* buddy_chat.c */
-void imcb_chat_add_buddy( struct groupchat *b, char *handle )
+void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
{
user_t *u = user_findhandle( b->ic, handle );
int me = 0;
@@ -923,7 +954,7 @@ void imcb_chat_add_buddy( struct groupchat *b, char *handle )
}
/* This function is one BIG hack... :-( EREWRITE */
-void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason )
+void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
{
user_t *u;
int me = 0;
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index 4fc32281..a523a3a5 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -274,11 +274,11 @@ G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, const char *handle,
/* This function should be called for each handle which are visible to the
* user, usually after a login, or if the user added a buddy and the IM
* server confirms that the add was successful. Don't forget to do this! */
-G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group );
-G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group );
+G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group );
+G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group );
G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle );
-G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname );
-G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );
+G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname );
+G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
/* Buddy activity */
/* To manipulate the status of a handle.
@@ -288,7 +288,7 @@ G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handl
G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );
/* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
-G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at );
+G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
@@ -301,11 +301,11 @@ G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle,
* the user her/himself. At that point the group chat will be visible to the
* user, too. */
G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
-G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle );
+G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const char *handle );
/* To remove a handle from a group chat. Reason can be NULL. */
-G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason );
+G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason );
/* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */
-G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at );
+G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at );
/* System messages specific to a groupchat, so they can be displayed in the right context. */
G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
/* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */
diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c
index 721f4b7c..1bfc2e59 100644
--- a/protocols/yahoo/libyahoo2.c
+++ b/protocols/yahoo/libyahoo2.c
@@ -854,55 +854,6 @@ static int is_same_bud(const void * a, const void * b) {
return strcmp(subject->id, object->id);
}
-static YList * bud_str2list(char *rawlist)
-{
- YList * l = NULL;
-
- char **lines;
- char **split;
- char **buddies;
- char **tmp, **bud;
-
- lines = y_strsplit(rawlist, "\n", -1);
- for (tmp = lines; *tmp; tmp++) {
- struct yahoo_buddy *newbud;
-
- split = y_strsplit(*tmp, ":", 2);
- if (!split)
- continue;
- if (!split[0] || !split[1]) {
- y_strfreev(split);
- continue;
- }
- buddies = y_strsplit(split[1], ",", -1);
-
- for (bud = buddies; bud && *bud; bud++) {
- newbud = y_new0(struct yahoo_buddy, 1);
- newbud->id = strdup(*bud);
- newbud->group = strdup(split[0]);
-
- if(y_list_find_custom(l, newbud, is_same_bud)) {
- FREE(newbud->id);
- FREE(newbud->group);
- FREE(newbud);
- continue;
- }
-
- newbud->real_name = NULL;
-
- l = y_list_append(l, newbud);
-
- NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group));
- }
-
- y_strfreev(buddies);
- y_strfreev(split);
- }
- y_strfreev(lines);
-
- return l;
-}
-
static char * getcookie(char *rawcookie)
{
char * cookie=NULL;
@@ -1359,140 +1310,154 @@ static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_pac
y_list_free(messages);
}
-
-static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_status(struct yahoo_input_data *yid,
+ struct yahoo_packet *pkt)
{
YList *l;
struct yahoo_data *yd = yid->yd;
- struct user
- {
- char *name; /* 7 name */
- int state; /* 10 state */
- int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
- int mobile; /* 60 mobile */
- char *msg; /* 19 custom status message */
- int away; /* 47 away (or invisible)*/
- int buddy_session; /* 11 state */
- int f17; /* 17 in chat? then what about flags? */
- int idle; /* 137 seconds idle */
- int f138; /* 138 state */
- char *f184; /* 184 state */
- int f192; /* 192 state */
- int f10001; /* 10001 state */
- int f10002; /* 10002 state */
- int f198; /* 198 state */
- char *f197; /* 197 state */
- char *f205; /* 205 state */
- int f213; /* 213 state */
- } *u;
+ struct yahoo_process_status_entry *u;
YList *users = 0;
-
+
if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
- YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL);
+ YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+ YAHOO_LOGIN_DUPL, NULL);
return;
}
+ /* Status updates may be spread accross multiple packets and not
+ even on buddy boundaries, so keeping some state is important.
+ So, continue where we left off, and only add a user entry to
+ the list once it's complete (301-315 End buddy). */
+ u = yd->half_user;
+
for (l = pkt->hash; l; l = l->next) {
struct yahoo_pair *pair = l->data;
switch (pair->key) {
- case 0: /* we won't actually do anything with this */
+ case 300: /* Begin buddy */
+ if (!strcmp(pair->value, "315") && !u) {
+ u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1);
+ }
+ break;
+ case 301: /* End buddy */
+ if (!strcmp(pair->value, "315") && u) {
+ /* Sometimes user info comes in an odd format with no
+ "begin buddy" but *with* an "end buddy". Don't add
+ it twice. */
+ if (!y_list_find(users, u))
+ users = y_list_prepend(users, u);
+ u = yd->half_user = NULL;
+ }
+ break;
+ case 0: /* we won't actually do anything with this */
NOTICE(("key %d:%s", pair->key, pair->value));
break;
- case 1: /* we don't get the full buddy list here. */
+ case 1: /* we don't get the full buddy list here. */
if (!yd->logged_in) {
- yd->logged_in = TRUE;
- if(yd->current_status < 0)
+ yd->logged_in = 1;
+ if (yd->current_status < 0)
yd->current_status = yd->initial_status;
- YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
+ YAHOO_CALLBACK(ext_yahoo_login_response) (yd->
+ client_id, YAHOO_LOGIN_OK, NULL);
}
break;
- case 8: /* how many online buddies we have */
+ case 8: /* how many online buddies we have */
NOTICE(("key %d:%s", pair->key, pair->value));
break;
- case 7: /* the current buddy */
- u = y_new0(struct user, 1);
+ case 7: /* the current buddy */
+ if (!u) {
+ /* This will only happen in case of a single level message */
+ u = y_new0(struct yahoo_process_status_entry, 1);
+ users = y_list_prepend(users, u);
+ }
u->name = pair->value;
- users = y_list_prepend(users, u);
break;
- case 10: /* state */
- ((struct user*)users->data)->state = strtol(pair->value, NULL, 10);
+ case 10: /* state */
+ u->state = strtol(pair->value, NULL, 10);
break;
- case 19: /* custom status message */
- ((struct user*)users->data)->msg = pair->value;
+ case 19: /* custom status message */
+ u->msg = pair->value;
break;
- case 47: /* is it an away message or not */
- ((struct user*)users->data)->away = atoi(pair->value);
+ case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */
+ u->away = atoi(pair->value);
break;
- case 137: /* seconds idle */
- ((struct user*)users->data)->idle = atoi(pair->value);
+ case 137: /* seconds idle */
+ u->idle = atoi(pair->value);
break;
- case 11: /* this is the buddy's session id */
- ((struct user*)users->data)->buddy_session = atoi(pair->value);
+ case 11: /* this is the buddy's session id */
+ u->buddy_session = atoi(pair->value);
break;
- case 17: /* in chat? */
- ((struct user*)users->data)->f17 = atoi(pair->value);
+ case 17: /* in chat? */
+ u->f17 = atoi(pair->value);
break;
- case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
- ((struct user*)users->data)->flags = atoi(pair->value);
+ case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
+ u->flags = atoi(pair->value);
break;
- case 60: /* SMS -> 1 MOBILE USER */
+ case 60: /* SMS -> 1 MOBILE USER */
/* sometimes going offline makes this 2, but invisible never sends it */
- ((struct user*)users->data)->mobile = atoi(pair->value);
+ u->mobile = atoi(pair->value);
break;
case 138:
- ((struct user*)users->data)->f138 = atoi(pair->value);
+ u->f138 = atoi(pair->value);
break;
case 184:
- ((struct user*)users->data)->f184 = pair->value;
+ u->f184 = pair->value;
break;
case 192:
- ((struct user*)users->data)->f192 = atoi(pair->value);
+ u->f192 = atoi(pair->value);
break;
case 10001:
- ((struct user*)users->data)->f10001 = atoi(pair->value);
+ u->f10001 = atoi(pair->value);
break;
case 10002:
- ((struct user*)users->data)->f10002 = atoi(pair->value);
+ u->f10002 = atoi(pair->value);
break;
case 198:
- ((struct user*)users->data)->f198 = atoi(pair->value);
+ u->f198 = atoi(pair->value);
break;
case 197:
- ((struct user*)users->data)->f197 = pair->value;
+ u->f197 = pair->value;
break;
case 205:
- ((struct user*)users->data)->f205 = pair->value;
+ u->f205 = pair->value;
break;
case 213:
- ((struct user*)users->data)->f213 = atoi(pair->value);
+ u->f213 = atoi(pair->value);
break;
- case 16: /* Custom error message */
- YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM);
+ case 16: /* Custom error message */
+ YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id,
+ pair->value, 0, E_CUSTOM);
break;
default:
- WARNING(("unknown status key %d:%s", pair->key, pair->value));
+ WARNING(("unknown status key %d:%s", pair->key,
+ pair->value));
break;
}
}
-
+
while (users) {
YList *t = users;
- struct user *u = users->data;
+ struct yahoo_process_status_entry *u = users->data;
if (u->name != NULL) {
- if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */
- YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
+ if (pkt->service ==
+ YAHOO_SERVICE_LOGOFF
+ /*|| u->flags == 0 No flags for YMSG16 */ ) {
+ YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
+ client_id, u->name,
+ YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
} else {
/* Key 47 always seems to be 1 for YMSG16 */
- if(!u->state)
+ if (!u->state)
u->away = 0;
else
u->away = 1;
- YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
+ YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
+ client_id, u->name, u->state, u->msg,
+ u->away, u->idle, u->mobile);
}
}
@@ -1502,7 +1467,8 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack
}
}
-static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_buddy_list(struct yahoo_input_data *yid,
+ struct yahoo_packet *pkt)
{
struct yahoo_data *yd = yid->yd;
YList *l;
@@ -1514,141 +1480,117 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_
for (l = pkt->hash; l; l = l->next) {
struct yahoo_pair *pair = l->data;
- switch(pair->key) {
+ switch (pair->key) {
case 300:
case 301:
case 302:
+ break; /* Separators. Our logic does not need them */
case 303:
- if ( 315 == atoi(pair->value) )
+ if (318 == atoi(pair->value))
last_packet = 1;
break;
case 65:
- g_free(cur_group);
cur_group = strdup(pair->value);
break;
case 7:
newbud = y_new0(struct yahoo_buddy, 1);
newbud->id = strdup(pair->value);
- if (cur_group) {
+ if (cur_group)
newbud->group = strdup(cur_group);
- } else {
- YList *last;
- struct yahoo_buddy *lastbud;
-
- for (last = yd->buddies; last && last->next; last = last->next);
- if (last) {
- lastbud = last->data;
- newbud->group = strdup(lastbud->group);
- } else {
- newbud->group = strdup("Buddies");
- }
- }
+ else if (yd->buddies) {
+ struct yahoo_buddy *lastbud =
+ (struct yahoo_buddy *)y_list_nth(yd->
+ buddies,
+ y_list_length(yd->buddies) - 1)->data;
+ newbud->group = strdup(lastbud->group);
+ } else
+ newbud->group = strdup("Buddies");
yd->buddies = y_list_append(yd->buddies, newbud);
break;
}
}
-
- g_free(cur_group);
/* we could be getting multiple packets here */
- if (last_packet)
+ if (pkt->hash && !last_packet)
return;
- YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
+ YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies);
- /*** We login at the very end of the packet communication */
+ /* Logged in */
if (!yd->logged_in) {
- yd->logged_in = TRUE;
- if(yd->current_status < 0)
+ yd->logged_in = 1;
+ if (yd->current_status < 0)
yd->current_status = yd->initial_status;
- YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
+ YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+ YAHOO_LOGIN_OK, NULL);
+
+ /*
+ yahoo_set_away(yd->client_id, yd->initial_status, NULL,
+ (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1);
+
+ yahoo_get_yab(yd->client_id);
+ */
}
+
}
-static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_list(struct yahoo_input_data *yid,
+ struct yahoo_packet *pkt)
{
struct yahoo_data *yd = yid->yd;
YList *l;
- if (!yd->logged_in) {
- yd->logged_in = TRUE;
- if(yd->current_status < 0)
- yd->current_status = yd->initial_status;
- YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
- }
-
+ /* we could be getting multiple packets here */
for (l = pkt->hash; l; l = l->next) {
struct yahoo_pair *pair = l->data;
- switch(pair->key) {
- case 87: /* buddies */
- if(!yd->rawbuddylist)
- yd->rawbuddylist = strdup(pair->value);
- else {
- yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value);
- }
- break;
-
- case 88: /* ignore list */
- if(!yd->ignorelist)
- yd->ignorelist = strdup("Ignore:");
- yd->ignorelist = y_string_append(yd->ignorelist, pair->value);
- break;
-
- case 89: /* identities */
+ switch (pair->key) {
+ case 89: /* identities */
{
- char **identities = y_strsplit(pair->value, ",", -1);
- int i;
- for(i=0; identities[i]; i++)
- yd->identities = y_list_append(yd->identities,
+ char **identities =
+ y_strsplit(pair->value, ",", -1);
+ int i;
+ for (i = 0; identities[i]; i++)
+ yd->identities =
+ y_list_append(yd->identities,
strdup(identities[i]));
- y_strfreev(identities);
+ y_strfreev(identities);
}
- YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities);
+ YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id,
+ yd->identities);
break;
- case 59: /* cookies */
- if(yd->ignorelist) {
- yd->ignore = bud_str2list(yd->ignorelist);
- FREE(yd->ignorelist);
- YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore);
- }
- if(yd->rawbuddylist) {
- yd->buddies = bud_str2list(yd->rawbuddylist);
- FREE(yd->rawbuddylist);
- YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
- }
-
- if(pair->value[0]=='Y') {
+ case 59: /* cookies */
+ if (pair->value[0] == 'Y') {
FREE(yd->cookie_y);
FREE(yd->login_cookie);
yd->cookie_y = getcookie(pair->value);
yd->login_cookie = getlcookie(yd->cookie_y);
- } else if(pair->value[0]=='T') {
+ } else if (pair->value[0] == 'T') {
FREE(yd->cookie_t);
yd->cookie_t = getcookie(pair->value);
- } else if(pair->value[0]=='C') {
+ } else if (pair->value[0] == 'C') {
FREE(yd->cookie_c);
yd->cookie_c = getcookie(pair->value);
- }
-
- if(yd->cookie_y && yd->cookie_t)
- YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id);
+ }
break;
- case 3: /* my id */
- case 90: /* 1 */
- case 100: /* 0 */
- case 101: /* NULL */
- case 102: /* NULL */
- case 93: /* 86400/1440 */
+ case 3: /* my id */
+ case 90: /* 1 */
+ case 100: /* 0 */
+ case 101: /* NULL */
+ case 102: /* NULL */
+ case 93: /* 86400/1440 */
break;
}
}
+
+ if (yd->cookie_y && yd->cookie_t) /* We don't get cookie_c anymore */
+ YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id);
}
static void yahoo_process_verify(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index a47de966..b61f6ff9 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -226,7 +226,7 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg )
else
yd->current_status = YAHOO_STATUS_CUSTOM;
}
- else if( state )
+ else if( msg )
yd->current_status = YAHOO_STATUS_CUSTOM;
else
yd->current_status = YAHOO_STATUS_AVAILABLE;
diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h
index 3507e13a..f05acb3c 100644
--- a/protocols/yahoo/yahoo2_types.h
+++ b/protocols/yahoo/yahoo2_types.h
@@ -195,6 +195,8 @@ struct yahoo_data {
char *ignorelist;
void *server_settings;
+
+ struct yahoo_process_status_entry *half_user;
};
struct yab {
@@ -260,6 +262,27 @@ struct yahoo_chat_member {
char *location;
};
+struct yahoo_process_status_entry {
+ char *name; /* 7 name */
+ int state; /* 10 state */
+ int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
+ int mobile; /* 60 mobile */
+ char *msg; /* 19 custom status message */
+ int away; /* 47 away (or invisible) */
+ int buddy_session; /* 11 state */
+ int f17; /* 17 in chat? then what about flags? */
+ int idle; /* 137 seconds idle */
+ int f138; /* 138 state */
+ char *f184; /* 184 state */
+ int f192; /* 192 state */
+ int f10001; /* 10001 state */
+ int f10002; /* 10002 state */
+ int f198; /* 198 state */
+ char *f197; /* 197 state */
+ char *f205; /* 205 state */
+ int f213; /* 213 state */
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/root_commands.c b/root_commands.c
index c79ff325..15e6e72a 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -143,6 +143,12 @@ static void cmd_identify( irc_t *irc, char **cmd )
storage_status_t status = storage_load( irc, cmd[1] );
char *account_on[] = { "account", "on", NULL };
+ if( strchr( irc->umode, 'R' ) != NULL )
+ {
+ irc_usermsg( irc, "You're already logged in." );
+ return;
+ }
+
switch (status) {
case STORAGE_INVALID_PASSWORD:
irc_usermsg( irc, "Incorrect password" );
@@ -907,7 +913,7 @@ static void cmd_blist( irc_t *irc, char **cmd )
else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 )
online = 1;
else
- online = away = 1;
+ online = away = 1;
if( strchr( irc->umode, 'b' ) != NULL )
format = "%s\t%s\t%s";
@@ -920,8 +926,13 @@ static void cmd_blist( irc_t *irc, char **cmd )
{
if( online == 1 )
{
+ char st[256] = "Online";
+
+ if( u->status_msg )
+ g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
+
g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
- irc_usermsg( irc, format, u->nick, s, "Online" );
+ irc_usermsg( irc, format, u->nick, s, st );
}
n_online ++;
diff --git a/user.h b/user.h
index 9d8a41a0..8c4f9c44 100644
--- a/user.h
+++ b/user.h
@@ -33,6 +33,7 @@ typedef struct __USER
char *realname;
char *away;
+ char *status_msg; /* Non-IRC extension, but nice on IM. */
char is_private;
char online;