mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Store capabilities against fulljid when unsupported hash
This commit is contained in:
parent
e263e00a85
commit
94bd9dbdfe
@ -55,14 +55,17 @@
|
|||||||
static gchar *cache_loc;
|
static gchar *cache_loc;
|
||||||
static GKeyFile *cache;
|
static GKeyFile *cache;
|
||||||
|
|
||||||
static GHashTable *jid_lookup;
|
static GHashTable *jid_to_ver;
|
||||||
|
static GHashTable *jid_to_caps;
|
||||||
|
|
||||||
static char *my_sha1;
|
static char *my_sha1;
|
||||||
|
|
||||||
static void _caps_destroy(Capabilities *caps);
|
static void _caps_destroy(Capabilities *caps);
|
||||||
static gchar* _get_cache_file(void);
|
static gchar* _get_cache_file(void);
|
||||||
static void _save_cache(void);
|
static void _save_cache(void);
|
||||||
static Capabilities * _caps_get(const char * const caps_str);
|
static Capabilities * _caps_by_ver(const char * const ver);
|
||||||
|
static Capabilities * _caps_by_jid(const char * const jid);
|
||||||
|
Capabilities * _caps_copy(Capabilities *caps);
|
||||||
|
|
||||||
void
|
void
|
||||||
caps_init(void)
|
caps_init(void)
|
||||||
@ -78,13 +81,14 @@ caps_init(void)
|
|||||||
g_key_file_load_from_file(cache, cache_loc, G_KEY_FILE_KEEP_COMMENTS,
|
g_key_file_load_from_file(cache, cache_loc, G_KEY_FILE_KEEP_COMMENTS,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
jid_lookup = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
jid_to_ver = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
jid_to_caps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_caps_destroy);
|
||||||
|
|
||||||
my_sha1 = NULL;
|
my_sha1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
caps_add(const char * const ver, Capabilities *caps)
|
caps_add_by_ver(const char * const ver, Capabilities *caps)
|
||||||
{
|
{
|
||||||
gboolean cached = g_key_file_has_group(cache, ver);
|
gboolean cached = g_key_file_has_group(cache, ver);
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
@ -126,66 +130,72 @@ caps_add(const char * const ver, Capabilities *caps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
caps_map(const char * const jid, const char * const ver)
|
caps_add_by_jid(const char * const jid, Capabilities *caps)
|
||||||
{
|
{
|
||||||
g_hash_table_insert(jid_lookup, strdup(jid), strdup(ver));
|
g_hash_table_insert(jid_to_caps, strdup(jid), caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
caps_map_jid_to_ver(const char * const jid, const char * const ver)
|
||||||
|
{
|
||||||
|
g_hash_table_insert(jid_to_ver, strdup(jid), strdup(ver));
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
caps_contains(const char * const caps_ver)
|
caps_contains(const char * const ver)
|
||||||
{
|
{
|
||||||
return (g_key_file_has_group(cache, caps_ver));
|
return (g_key_file_has_group(cache, ver));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capabilities *
|
static Capabilities *
|
||||||
_caps_get(const char * const caps_str)
|
_caps_by_ver(const char * const ver)
|
||||||
{
|
{
|
||||||
if (g_key_file_has_group(cache, caps_str)) {
|
if (g_key_file_has_group(cache, ver)) {
|
||||||
Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
|
Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
|
||||||
|
|
||||||
char *category = g_key_file_get_string(cache, caps_str, "category", NULL);
|
char *category = g_key_file_get_string(cache, ver, "category", NULL);
|
||||||
if (category) {
|
if (category) {
|
||||||
new_caps->category = strdup(category);
|
new_caps->category = strdup(category);
|
||||||
} else {
|
} else {
|
||||||
new_caps->category = NULL;
|
new_caps->category = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *type = g_key_file_get_string(cache, caps_str, "type", NULL);
|
char *type = g_key_file_get_string(cache, ver, "type", NULL);
|
||||||
if (type) {
|
if (type) {
|
||||||
new_caps->type = strdup(type);
|
new_caps->type = strdup(type);
|
||||||
} else {
|
} else {
|
||||||
new_caps->type = NULL;
|
new_caps->type = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *name = g_key_file_get_string(cache, caps_str, "name", NULL);
|
char *name = g_key_file_get_string(cache, ver, "name", NULL);
|
||||||
if (name) {
|
if (name) {
|
||||||
new_caps->name = strdup(name);
|
new_caps->name = strdup(name);
|
||||||
} else {
|
} else {
|
||||||
new_caps->name = NULL;
|
new_caps->name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *software = g_key_file_get_string(cache, caps_str, "software", NULL);
|
char *software = g_key_file_get_string(cache, ver, "software", NULL);
|
||||||
if (software) {
|
if (software) {
|
||||||
new_caps->software = strdup(software);
|
new_caps->software = strdup(software);
|
||||||
} else {
|
} else {
|
||||||
new_caps->software = NULL;
|
new_caps->software = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *software_version = g_key_file_get_string(cache, caps_str, "software_version", NULL);
|
char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL);
|
||||||
if (software_version) {
|
if (software_version) {
|
||||||
new_caps->software_version = strdup(software_version);
|
new_caps->software_version = strdup(software_version);
|
||||||
} else {
|
} else {
|
||||||
new_caps->software_version = NULL;
|
new_caps->software_version = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *os = g_key_file_get_string(cache, caps_str, "os", NULL);
|
char *os = g_key_file_get_string(cache, ver, "os", NULL);
|
||||||
if (os) {
|
if (os) {
|
||||||
new_caps->os = strdup(os);
|
new_caps->os = strdup(os);
|
||||||
} else {
|
} else {
|
||||||
new_caps->os = NULL;
|
new_caps->os = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *os_version = g_key_file_get_string(cache, caps_str, "os_version", NULL);
|
char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL);
|
||||||
if (os_version) {
|
if (os_version) {
|
||||||
new_caps->os_version = strdup(os_version);
|
new_caps->os_version = strdup(os_version);
|
||||||
} else {
|
} else {
|
||||||
@ -193,7 +203,7 @@ _caps_get(const char * const caps_str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gsize features_len = 0;
|
gsize features_len = 0;
|
||||||
gchar **features = g_key_file_get_string_list(cache, caps_str, "features", &features_len, NULL);
|
gchar **features = g_key_file_get_string_list(cache, ver, "features", &features_len, NULL);
|
||||||
if (features != NULL && features_len > 0) {
|
if (features != NULL && features_len > 0) {
|
||||||
GSList *features_list = NULL;
|
GSList *features_list = NULL;
|
||||||
int i;
|
int i;
|
||||||
@ -211,20 +221,60 @@ _caps_get(const char * const caps_str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Capabilities *
|
||||||
|
_caps_by_jid(const char * const jid)
|
||||||
|
{
|
||||||
|
return g_hash_table_lookup(jid_to_caps, jid);
|
||||||
|
}
|
||||||
|
|
||||||
static Capabilities *
|
static Capabilities *
|
||||||
_caps_lookup(const char * const jid)
|
_caps_lookup(const char * const jid)
|
||||||
{
|
{
|
||||||
char *ver = g_hash_table_lookup(jid_lookup, jid);
|
char *ver = g_hash_table_lookup(jid_to_ver, jid);
|
||||||
if (ver) {
|
if (ver) {
|
||||||
Capabilities *caps = _caps_get(ver);
|
Capabilities *caps = _caps_by_ver(ver);
|
||||||
if (caps) {
|
if (caps) {
|
||||||
|
log_debug("Capabilities lookup %s, found by verification string %s.", jid, ver);
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Capabilities *caps = _caps_by_jid(jid);
|
||||||
|
if (caps) {
|
||||||
|
log_debug("Capabilities lookup %s, found by JID.", jid);
|
||||||
|
return _caps_copy(caps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_debug("Capabilities lookup %s, none found.", jid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Capabilities *
|
||||||
|
_caps_copy(Capabilities *caps)
|
||||||
|
{
|
||||||
|
if (!caps) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
Capabilities *result = (Capabilities *)malloc(sizeof(Capabilities));
|
||||||
|
result->category = caps->category ? strdup(caps->category) : NULL;
|
||||||
|
result->type = caps->type ? strdup(caps->type) : NULL;
|
||||||
|
result->name = caps->name ? strdup(caps->name) : NULL;
|
||||||
|
result->software = caps->software ? strdup(caps->software) : NULL;
|
||||||
|
result->software_version = caps->software_version ? strdup(caps->software_version) : NULL;
|
||||||
|
result->os = caps->os ? strdup(caps->os) : NULL;
|
||||||
|
result->os_version = caps->os_version ? strdup(caps->os_version) : NULL;
|
||||||
|
|
||||||
|
result->features = NULL;
|
||||||
|
GSList *curr = caps->features;
|
||||||
|
while (curr) {
|
||||||
|
result->features = g_slist_append(result->features, strdup(curr->data));
|
||||||
|
curr = g_slist_next(curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
caps_create_sha1_str(xmpp_stanza_t * const query)
|
caps_create_sha1_str(xmpp_stanza_t * const query)
|
||||||
{
|
{
|
||||||
@ -579,7 +629,8 @@ _caps_close(void)
|
|||||||
{
|
{
|
||||||
g_key_file_free(cache);
|
g_key_file_free(cache);
|
||||||
cache = NULL;
|
cache = NULL;
|
||||||
g_hash_table_destroy(jid_lookup);
|
g_hash_table_destroy(jid_to_ver);
|
||||||
|
g_hash_table_destroy(jid_to_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -40,9 +40,12 @@
|
|||||||
#include "xmpp/xmpp.h"
|
#include "xmpp/xmpp.h"
|
||||||
|
|
||||||
void caps_init(void);
|
void caps_init(void);
|
||||||
void caps_add(const char * const ver, Capabilities *caps);
|
|
||||||
void caps_map(const char * const jid, const char * const ver);
|
void caps_add_by_ver(const char * const ver, Capabilities *caps);
|
||||||
gboolean caps_contains(const char * const caps_ver);
|
void caps_add_by_jid(const char * const jid, Capabilities *caps);
|
||||||
|
void caps_map_jid_to_ver(const char * const jid, const char * const ver);
|
||||||
|
gboolean caps_contains(const char * const ver);
|
||||||
|
|
||||||
char* caps_create_sha1_str(xmpp_stanza_t * const query);
|
char* caps_create_sha1_str(xmpp_stanza_t * const query);
|
||||||
xmpp_stanza_t* caps_create_query_response_stanza(xmpp_ctx_t * const ctx);
|
xmpp_stanza_t* caps_create_query_response_stanza(xmpp_ctx_t * const ctx);
|
||||||
Capabilities* caps_create(xmpp_stanza_t *query);
|
Capabilities* caps_create(xmpp_stanza_t *query);
|
||||||
|
@ -180,6 +180,33 @@ _iq_room_info_request(gchar *room)
|
|||||||
xmpp_stanza_release(iq);
|
xmpp_stanza_release(iq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_iq_send_caps_request_for_jid(const char * const to, const char * const id,
|
||||||
|
const char * const node, const char * const ver)
|
||||||
|
{
|
||||||
|
xmpp_conn_t * const conn = connection_get_conn();
|
||||||
|
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
log_error("Could not create caps request, no node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ver) {
|
||||||
|
log_error("Could not create caps request, no ver");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GString *node_str = g_string_new("");
|
||||||
|
g_string_printf(node_str, "%s#%s", node, ver);
|
||||||
|
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, to, node_str->str);
|
||||||
|
g_string_free(node_str, TRUE);
|
||||||
|
|
||||||
|
xmpp_id_handler_add(conn, _caps_response_handler, id, strdup(to));
|
||||||
|
|
||||||
|
xmpp_send(conn, iq);
|
||||||
|
xmpp_stanza_release(iq);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_iq_send_caps_request(const char * const to, const char * const id,
|
_iq_send_caps_request(const char * const to, const char * const id,
|
||||||
const char * const node, const char * const ver)
|
const char * const node, const char * const ver)
|
||||||
@ -457,6 +484,12 @@ _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
|
|||||||
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
|
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
|
||||||
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
|
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
|
||||||
|
|
||||||
|
char *type = xmpp_stanza_get_type(stanza);
|
||||||
|
// ignore non result
|
||||||
|
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
log_info("Capabilities response handler fired for id %s", id);
|
log_info("Capabilities response handler fired for id %s", id);
|
||||||
} else {
|
} else {
|
||||||
@ -469,7 +502,6 @@ _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *type = xmpp_stanza_get_type(stanza);
|
|
||||||
// handle error responses
|
// handle error responses
|
||||||
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
|
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
|
||||||
char *error_message = stanza_get_error_message(stanza);
|
char *error_message = stanza_get_error_message(stanza);
|
||||||
@ -489,6 +521,12 @@ _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userdata) {
|
||||||
|
char *jid = (char *)userdata;
|
||||||
|
log_info("Associating capabilities with: %s", jid);
|
||||||
|
Capabilities *capabilities = caps_create(query);
|
||||||
|
caps_add_by_jid(jid, capabilities);
|
||||||
|
} else {
|
||||||
// validate sha1
|
// validate sha1
|
||||||
gchar **split = g_strsplit(node, "#", -1);
|
gchar **split = g_strsplit(node, "#", -1);
|
||||||
char *given_sha1 = split[1];
|
char *given_sha1 = split[1];
|
||||||
@ -502,19 +540,21 @@ _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
|
|||||||
log_info("Valid SHA-1 hash found: %s", given_sha1);
|
log_info("Valid SHA-1 hash found: %s", given_sha1);
|
||||||
|
|
||||||
if (caps_contains(given_sha1)) {
|
if (caps_contains(given_sha1)) {
|
||||||
log_info("Capabilties cached: %s", given_sha1);
|
log_info("Capabilties already cached: %s", given_sha1);
|
||||||
} else {
|
} else {
|
||||||
log_info("Capabilities not cached: %s, storing", given_sha1);
|
log_info("Capabilities not cached: %s, storing", given_sha1);
|
||||||
Capabilities *capabilities = caps_create(query);
|
Capabilities *capabilities = caps_create(query);
|
||||||
caps_add(given_sha1, capabilities);
|
caps_add_by_ver(given_sha1, capabilities);
|
||||||
caps_destroy(capabilities);
|
caps_destroy(capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
caps_map(from, given_sha1);
|
caps_map_jid_to_ver(from, given_sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(generated_sha1);
|
g_free(generated_sha1);
|
||||||
g_strfreev(split);
|
g_strfreev(split);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1254,6 +1294,7 @@ iq_init_module(void)
|
|||||||
iq_room_config_cancel = _iq_room_config_cancel;
|
iq_room_config_cancel = _iq_room_config_cancel;
|
||||||
iq_submit_room_config = _iq_submit_room_config;
|
iq_submit_room_config = _iq_submit_room_config;
|
||||||
iq_send_caps_request = _iq_send_caps_request;
|
iq_send_caps_request = _iq_send_caps_request;
|
||||||
|
iq_send_caps_request_for_jid = _iq_send_caps_request_for_jid;
|
||||||
iq_room_info_request = _iq_room_info_request;
|
iq_room_info_request = _iq_room_info_request;
|
||||||
iq_room_affiliation_set = _iq_room_affiliation_set;
|
iq_room_affiliation_set = _iq_room_affiliation_set;
|
||||||
iq_room_affiliation_list = _iq_room_affiliation_list;
|
iq_room_affiliation_list = _iq_room_affiliation_list;
|
||||||
|
@ -507,22 +507,26 @@ _handle_caps(char *jid, XMPPCaps *caps)
|
|||||||
log_info("Hash %s supported", caps->hash);
|
log_info("Hash %s supported", caps->hash);
|
||||||
if (caps->ver) {
|
if (caps->ver) {
|
||||||
if (caps_contains(caps->ver)) {
|
if (caps_contains(caps->ver)) {
|
||||||
log_info("Capabilities cached: %s", caps->ver);
|
log_info("Capabilities cache hit: %s, for %s.", caps->ver, jid);
|
||||||
caps_map(jid, caps->ver);
|
caps_map_jid_to_ver(jid, caps->ver);
|
||||||
} else {
|
} else {
|
||||||
log_info("Capabilities not cached: %s, sending service discovery request", caps->ver);
|
log_info("Capabilities cache miss: %s, for %s, sending service discovery request", caps->ver, jid);
|
||||||
char *id = create_unique_id("caps");
|
char *id = create_unique_id("caps");
|
||||||
iq_send_caps_request(jid, id, caps->node, caps->ver);
|
iq_send_caps_request(jid, id, caps->node, caps->ver);
|
||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no hash, or not supported
|
// unsupported hash
|
||||||
} else if (caps->hash) {
|
} else if (caps->hash) {
|
||||||
log_info("Hash %s not supported, not sending service discovery request", caps->hash);
|
log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid);
|
||||||
// send service discovery request, cache against from full jid
|
char *id = create_unique_id("caps");
|
||||||
|
iq_send_caps_request_for_jid(jid, id, caps->node, caps->ver);
|
||||||
|
free(id);
|
||||||
|
|
||||||
|
// no hash
|
||||||
} else {
|
} else {
|
||||||
log_info("No hash specified, not sending service discovery request");
|
log_info("No hash specified: %s, not sending service discovery request", jid);
|
||||||
// do legacy
|
// do legacy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,8 @@ void (*iq_room_config_cancel)(const char * const room_jid);
|
|||||||
void (*iq_send_ping)(const char * const target);
|
void (*iq_send_ping)(const char * const target);
|
||||||
void (*iq_send_caps_request)(const char * const to, const char * const id,
|
void (*iq_send_caps_request)(const char * const to, const char * const id,
|
||||||
const char * const node, const char * const ver);
|
const char * const node, const char * const ver);
|
||||||
|
void (*iq_send_caps_request_for_jid)(const char * const to, const char * const id,
|
||||||
|
const char * const node, const char * const ver);
|
||||||
void (*iq_room_info_request)(gchar *room);
|
void (*iq_room_info_request)(gchar *room);
|
||||||
void (*iq_room_affiliation_list)(const char * const room, char *affiliation);
|
void (*iq_room_affiliation_list)(const char * const room, char *affiliation);
|
||||||
void (*iq_room_affiliation_set)(const char * const room, const char * const jid, char *affiliation,
|
void (*iq_room_affiliation_set)(const char * const room, const char * const jid, char *affiliation,
|
||||||
|
Loading…
Reference in New Issue
Block a user