mirror of
https://github.com/profanity-im/profanity.git
synced 2025-01-03 14:57:42 -05:00
Refactored parsing caps
This commit is contained in:
parent
508bfeb2bf
commit
e263e00a85
14
src/jid.c
14
src/jid.c
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user