1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-22 19:45:54 -04:00

Refactored parsing caps

This commit is contained in:
James Booth 2014-11-26 21:59:36 +00:00
parent 508bfeb2bf
commit e263e00a85
8 changed files with 111 additions and 99 deletions

View File

@ -176,3 +176,17 @@ get_nick_from_full_jid(const char * const full_room_jid)
return nick_part;
}
/*
* get the fulljid, fall back to the barejid
*/
char *
jid_fulljid_or_barejid(Jid *jid)
{
if (jid->fulljid) {
return jid->fulljid;
} else {
return jid->barejid;
}
}

View File

@ -56,4 +56,6 @@ gboolean jid_is_valid_room_form(Jid *jid);
char * create_fulljid(const char * const barejid, const char * const resource);
char * get_nick_from_full_jid(const char * const full_room_jid);
char * jid_fulljid_or_barejid(Jid *jid);
#endif

View File

@ -500,43 +500,30 @@ _unavailable_handler(xmpp_conn_t * const conn,
}
static void
_handle_caps(xmpp_stanza_t *const stanza)
_handle_caps(char *jid, XMPPCaps *caps)
{
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (from) {
char *hash = stanza_caps_get_hash(stanza);
// hash supported xep-0115
if (g_strcmp0(hash, "sha-1") == 0) {
log_info("Hash %s supported");
char *ver = stanza_get_caps_ver(stanza);
if (ver) {
if (caps_contains(ver)) {
log_info("Capabilities cached: %s", ver);
caps_map(from, ver);
} else {
log_info("Capabilities not cached: %s, sending service discovery request", ver);
char *node = stanza_caps_get_node(stanza);
char *id = create_unique_id("caps");
iq_send_caps_request(from, id, node, ver);
free(id);
}
}
// no hash, or not supported
} else {
if (hash) {
log_info("Hash %s not supported, not sending service discovery request");
// send service discovery request, cache against from full jid
// hash supported xep-0115
if (g_strcmp0(caps->hash, "sha-1") == 0) {
log_info("Hash %s supported", caps->hash);
if (caps->ver) {
if (caps_contains(caps->ver)) {
log_info("Capabilities cached: %s", caps->ver);
caps_map(jid, caps->ver);
} else {
log_info("No hash specified, not sending service discovery request");
// do legacy
log_info("Capabilities not cached: %s, sending service discovery request", caps->ver);
char *id = create_unique_id("caps");
iq_send_caps_request(jid, id, caps->node, caps->ver);
free(id);
}
}
// no hash, or not supported
} else if (caps->hash) {
log_info("Hash %s not supported, not sending service discovery request", caps->hash);
// send service discovery request, cache against from full jid
} else {
log_info("No hash specified, not sending service discovery request");
// do legacy
}
}
@ -580,18 +567,21 @@ _available_handler(xmpp_conn_t * const conn,
break;
}
return 1;
} else if (xmpp_presence->jid->fulljid) {
log_debug("Presence available handler fired for: %s", xmpp_presence->jid->fulljid);
} else {
log_debug("Presence available handler fired for: %s", xmpp_presence->jid->barejid);
char *jid = jid_fulljid_or_barejid(xmpp_presence->jid);
log_debug("Presence available handler fired for: %s", jid);
}
const char *my_jid_str = xmpp_conn_get_jid(conn);
Jid *my_jid = jid_create(my_jid_str);
if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && (stanza_contains_caps(stanza))) {
XMPPCaps *caps = stanza_parse_caps(stanza);
if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && caps) {
log_info("Presence contains capabilities.");
_handle_caps(stanza);
char *jid = jid_fulljid_or_barejid(xmpp_presence->jid);
_handle_caps(jid, caps);
}
stanza_free_caps(caps);
Resource *resource = stanza_resource_from_presence(xmpp_presence);
@ -627,6 +617,7 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
log_debug("No node string, not sending discovery IQ.");
}
}
static int
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
@ -757,10 +748,12 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
// room occupant online
} else {
// send disco info for capabilities, if not cached
if (stanza_contains_caps(stanza)) {
XMPPCaps *caps = stanza_parse_caps(stanza);
if (caps) {
log_info("Presence contains capabilities.");
_handle_caps(stanza);
_handle_caps(from, caps);
}
stanza_free_caps(caps);
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);

View File

@ -1313,72 +1313,30 @@ stanza_get_idle_time(xmpp_stanza_t * const stanza)
}
}
gboolean
stanza_contains_caps(xmpp_stanza_t * const stanza)
XMPPCaps*
stanza_parse_caps(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
xmpp_stanza_t *caps_st = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
if (!caps) {
return FALSE;
}
char *ns = xmpp_stanza_get_ns(caps);
if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
return FALSE;
}
return TRUE;
}
char *
stanza_caps_get_hash(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
if (!caps) {
if (!caps_st) {
return NULL;
}
char *ns = xmpp_stanza_get_ns(caps);
char *ns = xmpp_stanza_get_ns(caps_st);
if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
return NULL;
}
return xmpp_stanza_get_attribute(caps, STANZA_ATTR_HASH);
}
char *hash = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_HASH);
char *node = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_NODE);
char *ver = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_VER);
char *
stanza_caps_get_node(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
XMPPCaps *caps = (XMPPCaps *)malloc(sizeof(XMPPCaps));
caps->hash = hash ? strdup(hash) : NULL;
caps->node = node ? strdup(node) : NULL;
caps->ver = ver ? strdup(ver) : NULL;
if (!caps) {
return NULL;
}
char *ns = xmpp_stanza_get_ns(caps);
if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
return NULL;
}
return xmpp_stanza_get_attribute(caps, STANZA_ATTR_NODE);
}
char *
stanza_get_caps_ver(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
if (!caps) {
return NULL;
}
char *ns = xmpp_stanza_get_ns(caps);
if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
return NULL;
}
return xmpp_stanza_get_attribute(caps, STANZA_ATTR_VER);
return caps;
}
char *
@ -1593,6 +1551,23 @@ stanza_resource_from_presence(XMPPPresence *presence)
return resource;
}
void
stanza_free_caps(XMPPCaps *caps)
{
if (caps) {
if (caps->hash) {
free(caps->hash);
}
if (caps->node) {
free(caps->node);
}
if (caps->ver) {
free(caps->ver);
}
FREE_SET_NULL(caps);
}
}
void
stanza_free_presence(XMPPPresence *presence)
{
@ -1609,6 +1584,7 @@ stanza_free_presence(XMPPPresence *presence)
if (presence->status) {
free(presence->status);
}
FREE_SET_NULL(presence);
}
}

View File

@ -157,6 +157,12 @@
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
typedef struct caps_stanza_t {
char *hash;
char *node;
char *ver;
} XMPPCaps;
typedef struct presence_stanza_t {
Jid *jid;
char *show;
@ -233,10 +239,6 @@ xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t * const ctx, const char * c
int stanza_get_idle_time(xmpp_stanza_t * const stanza);
char * stanza_get_caps_str(xmpp_stanza_t * const stanza);
gboolean stanza_contains_caps(xmpp_stanza_t * const stanza);
char * stanza_caps_get_hash(xmpp_stanza_t * const stanza);
char * stanza_get_caps_ver(xmpp_stanza_t * const stanza);
char * stanza_caps_get_node(xmpp_stanza_t * const stanza);
DataForm * stanza_create_form(xmpp_stanza_t * const stanza);
void stanza_destroy_form(DataForm *form);
@ -278,4 +280,7 @@ Resource* stanza_resource_from_presence(XMPPPresence *presence);
XMPPPresence* stanza_parse_presence(xmpp_stanza_t *stanza, int *err);
void stanza_free_presence(XMPPPresence *presence);
XMPPCaps* stanza_parse_caps(xmpp_stanza_t * const stanza);
void stanza_free_caps(XMPPCaps *caps);
#endif

View File

@ -165,3 +165,21 @@ void create_full_with_trailing_slash(void **state)
assert_string_equal("room@conference.domain.org", result->barejid);
assert_string_equal("room@conference.domain.org/nick/", result->fulljid);
}
void returns_fulljid_when_exists(void **state)
{
Jid *jid = jid_create("localpart@domainpart/resourcepart");
char *result = jid_fulljid_or_barejid(jid);
assert_string_equal("localpart@domainpart/resourcepart", result);
}
void returns_barejid_when_fulljid_not_exists(void **state)
{
Jid *jid = jid_create("localpart@domainpart");
char *result = jid_fulljid_or_barejid(jid);
assert_string_equal("localpart@domainpart", result);
}

View File

@ -21,3 +21,5 @@ void create_with_slash_in_resource(void **state);
void create_with_at_in_resource(void **state);
void create_with_at_and_slash_in_resource(void **state);
void create_full_with_trailing_slash(void **state);
void returns_fulljid_when_exists(void **state);
void returns_barejid_when_fulljid_not_exists(void **state);

View File

@ -131,6 +131,8 @@ int main(int argc, char* argv[]) {
unit_test(create_with_at_in_resource),
unit_test(create_with_at_and_slash_in_resource),
unit_test(create_full_with_trailing_slash),
unit_test(returns_fulljid_when_exists),
unit_test(returns_barejid_when_fulljid_not_exists),
unit_test(parse_null_returns_null),
unit_test(parse_empty_returns_null),