aboutsummaryrefslogtreecommitdiffstats
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Makefile2
-rw-r--r--protocols/jabber/Makefile2
-rw-r--r--protocols/jabber/conference.c11
-rw-r--r--protocols/jabber/iq.c3
-rw-r--r--protocols/jabber/jabber.h20
-rw-r--r--protocols/jabber/jabber_util.c16
-rw-r--r--protocols/jabber/presence.c34
-rw-r--r--protocols/jabber/sasl.c27
-rw-r--r--protocols/msn/Makefile2
-rw-r--r--protocols/msn/ns.c2
-rw-r--r--protocols/msn/sb.c2
-rw-r--r--protocols/oscar/Makefile2
-rw-r--r--protocols/oscar/oscar.c10
-rw-r--r--protocols/yahoo/Makefile2
14 files changed, 97 insertions, 38 deletions
diff --git a/protocols/Makefile b/protocols/Makefile
index f7d76e0f..18d79e8d 100644
--- a/protocols/Makefile
+++ b/protocols/Makefile
@@ -26,7 +26,7 @@ LFLAGS += -r
# [SH] Phony targets
all: protocols.o
check: all
-lcov:
+lcov: check
gcov:
gcov *.c
diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile
index e042f812..3ce78127 100644
--- a/protocols/jabber/Makefile
+++ b/protocols/jabber/Makefile
@@ -17,7 +17,7 @@ LFLAGS += -r
# [SH] Phony targets
all: jabber_mod.o
check: all
-lcov:
+lcov: check
gcov:
gcov *.c
diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c
index 515194fc..79fdd053 100644
--- a/protocols/jabber/conference.c
+++ b/protocols/jabber/conference.c
@@ -36,6 +36,8 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *
node = xt_new_node( "x", NULL, NULL );
xt_add_attr( node, "xmlns", XMLNS_MUC );
node = jabber_make_packet( "presence", NULL, roomjid, node );
+ if( password )
+ xt_add_child( node, xt_new_node( "password", password, NULL ) );
jabber_cache_add( ic, node, jabber_chat_join_failed );
if( !jabber_write_packet( ic, node ) )
@@ -122,6 +124,8 @@ int jabber_chat_msg( struct groupchat *c, char *message, int flags )
struct jabber_chat *jc = c->data;
struct xt_node *node;
+ jc->flags |= JCFLAG_MESSAGE_SENT;
+
node = xt_new_node( "body", message, NULL );
node = jabber_make_packet( "message", "groupchat", jc->name, node );
@@ -294,10 +298,11 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud
{
struct xt_node *subject = xt_find_node( node->children, "subject" );
struct xt_node *body = xt_find_node( node->children, "body" );
- struct groupchat *chat = NULL;
+ struct groupchat *chat = bud ? jabber_chat_by_jid( ic, bud->bare_jid ) : NULL;
+ struct jabber_chat *jc = chat ? chat->data : NULL;
char *s;
- if( bud == NULL )
+ if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) )
{
char *nick;
@@ -345,7 +350,7 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud
return;
}
- else if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL )
+ else if( chat == NULL )
{
/* How could this happen?? We could do kill( self, 11 )
now or just wait for the OS to do it. :-) */
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c
index e1bab29e..c88bc0b0 100644
--- a/protocols/jabber/iq.c
+++ b/protocols/jabber/iq.c
@@ -91,7 +91,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
}
else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
{
- const char *features[] = { XMLNS_VERSION,
+ const char *features[] = { XMLNS_DISCOVER,
+ XMLNS_VERSION,
XMLNS_TIME,
XMLNS_CHATSTATES,
XMLNS_MUC,
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index cf0f8e6a..1ff0e8dd 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -48,16 +48,22 @@ typedef enum
typedef enum
{
- JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make
+ JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make
sure it gets sent only once. */
- JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support
+ JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support
XEP85 (typing notification shite). */
- JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for
+ JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for
groupchat state info too. */
- JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have
+ JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have
have a real JID. */
} jabber_buddy_flags_t;
+typedef enum
+{
+ JCFLAG_MESSAGE_SENT = 1, /* Set this after sending the first message, so
+ we can detect echoes/backlogs. */
+} jabber_chat_flags_t;
+
struct jabber_data
{
struct im_connection *ic;
@@ -94,6 +100,7 @@ typedef xt_status (*jabber_cache_event) ( struct im_connection *ic, struct xt_no
struct jabber_cache_entry
{
+ time_t saved_at;
struct xt_node *node;
jabber_cache_event func;
};
@@ -140,6 +147,10 @@ struct jabber_chat
#define JABBER_PACKET_ID "BeeP"
#define JABBER_CACHED_ID "BeeC"
+/* The number of seconds to keep cached packets before garbage collecting
+ them. This gc is done on every keepalive (every minute). */
+#define JABBER_CACHE_MAX_AGE 600
+
/* RFC 392[01] stuff */
#define XMLNS_TLS "urn:ietf:params:xml:ns:xmpp-tls"
#define XMLNS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
@@ -160,6 +171,7 @@ struct jabber_chat
#define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */
#define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */
#define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */
+#define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */
/* iq.c */
xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c
index 794a1040..6e872040 100644
--- a/protocols/jabber/jabber_util.c
+++ b/protocols/jabber/jabber_util.c
@@ -141,6 +141,7 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca
entry->node = node;
entry->func = func;
+ entry->saved_at = time( NULL );
g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry );
}
@@ -162,22 +163,17 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpo
void jabber_cache_clean( struct im_connection *ic )
{
struct jabber_data *jd = ic->proto_data;
+ time_t threshold = time( NULL ) - JABBER_CACHE_MAX_AGE;
- g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL );
+ g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, &threshold );
}
-gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer )
+gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer threshold_ )
{
struct jabber_cache_entry *entry = entry_;
- struct xt_node *node = entry->node;
+ time_t *threshold = threshold_;
- if( node->flags & XT_SEEN )
- return TRUE;
- else
- {
- node->flags |= XT_SEEN;
- return FALSE;
- }
+ return entry->saved_at < *threshold;
}
xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node )
diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c
index 2c49b800..6fc360b7 100644
--- a/protocols/jabber/presence.c
+++ b/protocols/jabber/presence.c
@@ -28,7 +28,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
struct im_connection *ic = data;
char *from = xt_find_attr( node, "from" );
char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */
- struct xt_node *c;
+ struct xt_node *c, *cap;
struct jabber_buddy *bud, *send_presence = NULL;
int is_chat = 0;
char *s;
@@ -76,6 +76,26 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
else
bud->priority = 0;
+ if( bud && ( cap = xt_find_node( node->children, "c" ) ) &&
+ ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 )
+ {
+ /* This <presence> stanza includes an XEP-0115
+ capabilities part. Not too interesting, but we can
+ see if it has an ext= attribute. */
+ s = xt_find_attr( cap, "ext" );
+ if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) )
+ bud->flags |= JBFLAG_DOES_XEP85;
+
+ /* This field can contain more information like xhtml
+ support, but we don't support that ourselves.
+ Officially the ext= tag was deprecated, but enough
+ clients do send it.
+
+ (I'm aware that this is not the right way to use
+ this field.) See for an explanation of ext=:
+ http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/
+ }
+
if( is_chat )
jabber_chat_pkt_presence( ic, bud, node );
else
@@ -185,7 +205,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
int presence_send_update( struct im_connection *ic )
{
struct jabber_data *jd = ic->proto_data;
- struct xt_node *node;
+ struct xt_node *node, *cap;
char *show = jd->away_state->code;
char *status = jd->away_message;
struct groupchat *c;
@@ -198,6 +218,16 @@ int presence_send_update( struct im_connection *ic )
if( status )
xt_add_child( node, xt_new_node( "status", status, NULL ) );
+ /* This makes the packet slightly bigger, but clients interested in
+ capabilities can now cache the discovery info. This reduces the
+ usual post-login iq-flood. See XEP-0115. At least libpurple and
+ Trillian seem to do this right. */
+ cap = xt_new_node( "c", NULL, NULL );
+ xt_add_attr( cap, "xmlns", XMLNS_CAPS );
+ xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" );
+ xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */
+ xt_add_child( node, cap );
+
st = jabber_write_packet( ic, node );
/* Have to send this update to all groupchats too, the server won't
diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c
index 87059051..53248ef3 100644
--- a/protocols/jabber/sasl.c
+++ b/protocols/jabber/sasl.c
@@ -21,6 +21,8 @@
* *
\***************************************************************************/
+#include <ctype.h>
+
#include "jabber.h"
#include "base64.h"
@@ -106,12 +108,17 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
return XT_HANDLED;
}
-static char *sasl_get_part( char *data, char *field )
+/* Non-static function, but not mentioned in jabber.h because it's for internal
+ use, just that the unittest should be able to reach it... */
+char *sasl_get_part( char *data, char *field )
{
int i, len;
len = strlen( field );
+ while( isspace( *data ) || *data == ',' )
+ data ++;
+
if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' )
{
i = strlen( field ) + 1;
@@ -128,13 +135,19 @@ static char *sasl_get_part( char *data, char *field )
i ++;
}
- /* If we got a comma, we got a new field. Check it. */
- if( data[i] == ',' &&
- g_strncasecmp( data + i + 1, field, len ) == 0 &&
- data[i+len+1] == '=' )
+ /* If we got a comma, we got a new field. Check it,
+ find the next key after it. */
+ if( data[i] == ',' )
{
- i += len + 2;
- break;
+ while( isspace( data[i] ) || data[i] == ',' )
+ i ++;
+
+ if( g_strncasecmp( data + i, field, len ) == 0 &&
+ data[i+len] == '=' )
+ {
+ i += len + 1;
+ break;
+ }
}
}
}
diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile
index 3440658d..6a588613 100644
--- a/protocols/msn/Makefile
+++ b/protocols/msn/Makefile
@@ -17,7 +17,7 @@ LFLAGS += -r
# [SH] Phony targets
all: msn_mod.o
check: all
-lcov:
+lcov: check
gcov:
gcov *.c
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index 3735aad6..0bb84a74 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -583,7 +583,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
}
else
{
- debug( "Received unknown command from main server: %s", cmd[0] );
+ /* debug( "Received unknown command from main server: %s", cmd[0] ); */
}
return( 1 );
diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c
index cdf2e8ad..18c41ef5 100644
--- a/protocols/msn/sb.c
+++ b/protocols/msn/sb.c
@@ -593,7 +593,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts )
}
else
{
- debug( "Received unknown command from switchboard server: %s", cmd[0] );
+ /* debug( "Received unknown command from switchboard server: %s", cmd[0] ); */
}
return( 1 );
diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile
index 95e85ec2..2792f22a 100644
--- a/protocols/oscar/Makefile
+++ b/protocols/oscar/Makefile
@@ -17,7 +17,7 @@ LFLAGS += -r
# [SH] Phony targets
all: oscar_mod.o
check: all
-lcov:
+lcov: check
gcov:
gcov *.c
diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c
index 9167f6a3..120ebc3e 100644
--- a/protocols/oscar/oscar.c
+++ b/protocols/oscar/oscar.c
@@ -1065,12 +1065,14 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_
} else if (args->mpmsg.numparts == 0) {
g_snprintf(tmp, BUF_LONG, "%s", args->msg);
} else {
- int i;
+ aim_mpmsg_section_t *part;
*tmp = 0;
- for (i = 0; i < args->mpmsg.numparts; i ++) {
- g_strlcat(tmp, (char*) args->mpmsg.parts[i].data, BUF_LONG);
- g_strlcat(tmp, "\n", BUF_LONG);
+ for (part = args->mpmsg.parts; part; part = part->next) {
+ if (part->data) {
+ g_strlcat(tmp, (char*) part->data, BUF_LONG);
+ g_strlcat(tmp, "\n", BUF_LONG);
+ }
}
}
diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile
index 2cfd147b..b4fe56e2 100644
--- a/protocols/yahoo/Makefile
+++ b/protocols/yahoo/Makefile
@@ -17,7 +17,7 @@ LFLAGS += -r
# [SH] Phony targets
all: yahoo_mod.o
check: all
-lcov:
+lcov: check
gcov:
gcov *.c