fix: allow adding own JID to roster

Enable adding oneself to the roster.

Self subscriptions are implicit according to XEP-0060 / XEP-0163.
So we adapt the /sub command to handle this gracefully by just printing
an informative message.

Profanitys logic didn't handle own presence/when adding to roster
correctly. This got fixed now.

Fixes: https://github.com/profanity-im/profanity/issues/2084

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
This commit is contained in:
Michael Vetter
2026-03-20 23:28:18 +01:00
parent bbdd5e176a
commit 4c731f5241
6 changed files with 54 additions and 11 deletions

View File

@@ -1156,6 +1156,10 @@ cmd_sub(ProfWin* window, const char* const command, gchar** args)
} }
auto_jid Jid* jidp = jid_create(jid); auto_jid Jid* jidp = jid_create(jid);
if (!jidp) {
cons_bad_cmd_usage(command);
return TRUE;
}
if (strcmp(subcmd, "allow") == 0) { if (strcmp(subcmd, "allow") == 0) {
presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBED); presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBED);
@@ -1166,9 +1170,13 @@ cmd_sub(ProfWin* window, const char* const command, gchar** args)
cons_show("Deleted/denied subscription for %s", jidp->barejid); cons_show("Deleted/denied subscription for %s", jidp->barejid);
log_info("Deleted/denied subscription for %s", jidp->barejid); log_info("Deleted/denied subscription for %s", jidp->barejid);
} else if (strcmp(subcmd, "request") == 0) { } else if (strcmp(subcmd, "request") == 0) {
presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBE); if (equals_our_barejid(jidp->barejid)) {
cons_show("Sent subscription request to %s.", jidp->barejid); cons_show("Subscription to yourself is implicit.");
log_info("Sent subscription request to %s.", jidp->barejid); } else {
presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBE);
cons_show("Sent subscription request to %s.", jidp->barejid);
log_info("Sent subscription request to %s.", jidp->barejid);
}
} else if (strcmp(subcmd, "show") == 0) { } else if (strcmp(subcmd, "show") == 0) {
PContact contact = roster_get_contact(jidp->barejid); PContact contact = roster_get_contact(jidp->barejid);
if ((contact == NULL) || (p_contact_subscription(contact) == NULL)) { if ((contact == NULL) || (p_contact_subscription(contact) == NULL)) {

View File

@@ -507,8 +507,8 @@ _unavailable_handler(xmpp_stanza_t* const stanza)
return; return;
} }
auto_char char* status_str = stanza_get_status(stanza, NULL);
if (strcmp(my_jid->barejid, from_jid->barejid) != 0) { if (strcmp(my_jid->barejid, from_jid->barejid) != 0) {
auto_char char* status_str = stanza_get_status(stanza, NULL);
if (from_jid->resourcepart) { if (from_jid->resourcepart) {
sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str); sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
@@ -518,6 +518,7 @@ _unavailable_handler(xmpp_stanza_t* const stanza)
} }
} else { } else {
if (from_jid->resourcepart) { if (from_jid->resourcepart) {
sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
connection_remove_available_resource(from_jid->resourcepart); connection_remove_available_resource(from_jid->resourcepart);
} }
} }
@@ -613,8 +614,16 @@ _available_handler(xmpp_stanza_t* const stanza)
Resource* resource = stanza_resource_from_presence(xmpp_presence); Resource* resource = stanza_resource_from_presence(xmpp_presence);
char* pgpsig = NULL;
xmpp_stanza_t* x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_SIGNED);
if (x) {
pgpsig = xmpp_stanza_get_text(x);
}
if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) { if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) {
connection_add_available_resource(resource); connection_add_available_resource(resource);
Resource* resource_for_roster = resource_copy(resource);
sv_ev_contact_online(xmpp_presence->jid->barejid, resource_for_roster, xmpp_presence->last_activity, pgpsig);
const char* account_name = session_get_account_name(); const char* account_name = session_get_account_name();
int max_sessions = accounts_get_max_sessions(account_name); int max_sessions = accounts_get_max_sessions(account_name);
if (max_sessions > 0) { if (max_sessions > 0) {
@@ -678,16 +687,11 @@ _available_handler(xmpp_stanza_t* const stanza)
} }
} }
} else { } else {
char* pgpsig = NULL;
xmpp_stanza_t* x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_SIGNED);
if (x) {
pgpsig = xmpp_stanza_get_text(x);
}
sv_ev_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity, pgpsig); sv_ev_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity, pgpsig);
xmpp_ctx_t* ctx = connection_get_ctx();
xmpp_free(ctx, pgpsig);
} }
xmpp_ctx_t* ctx = connection_get_ctx();
xmpp_free(ctx, pgpsig);
stanza_free_presence(xmpp_presence); stanza_free_presence(xmpp_presence);
} }

View File

@@ -75,6 +75,16 @@ resource_destroy(Resource* resource)
} }
} }
Resource*
resource_copy(Resource* resource)
{
if (resource == NULL) {
return NULL;
}
return resource_new(resource->name, resource->presence, resource->status, resource->priority);
}
gboolean gboolean
valid_resource_presence_string(const gchar* const str) valid_resource_presence_string(const gchar* const str)
{ {

View File

@@ -22,6 +22,7 @@ typedef struct resource_t
Resource* resource_new(const gchar* const name, resource_presence_t presence, const gchar* const status, Resource* resource_new(const gchar* const name, resource_presence_t presence, const gchar* const status,
const int priority); const int priority);
Resource* resource_copy(Resource* resource);
void resource_destroy(Resource* resource); void resource_destroy(Resource* resource);
int resource_compare_availability(Resource* first, Resource* second); int resource_compare_availability(Resource* first, Resource* second);

View File

@@ -21,6 +21,7 @@
#include "xmpp/resource.h" #include "xmpp/resource.h"
#include "xmpp/contact.h" #include "xmpp/contact.h"
#include "xmpp/jid.h" #include "xmpp/jid.h"
#include "xmpp/xmpp.h"
typedef struct prof_roster_t typedef struct prof_roster_t
{ {
@@ -366,6 +367,19 @@ roster_add(const char* const barejid, const char* const name, GSList* groups, co
} }
g_hash_table_insert(roster->contacts, strdup(barejid), contact); g_hash_table_insert(roster->contacts, strdup(barejid), contact);
if (equals_our_barejid(barejid)) {
GList* resources = connection_get_available_resources();
GList* curr = resources;
while (curr) {
Resource* res = curr->data;
Resource* res_copy = resource_copy(res);
p_contact_set_presence(contact, res_copy);
curr = g_list_next(curr);
}
g_list_free(resources);
}
autocomplete_add(roster->barejid_ac, barejid); autocomplete_add(roster->barejid_ac, barejid);
_add_name_and_barejid(name, barejid); _add_name_and_barejid(name, barejid);

View File

@@ -610,3 +610,9 @@ void
blocked_ac_reset(void) blocked_ac_reset(void)
{ {
} }
GList*
connection_get_available_resources(void)
{
return NULL;
}