From f251cc8bb30e4f22c454080e56a8ed91a7ffe45b Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 6 Mar 2026 13:17:13 +0100 Subject: [PATCH] feat: handle and allow JIDs with trailing slashes Make jid_is_valid() allow JIDs ending with a slash (`user@domain/`). In these cases, the parser now treats the input as a Bare JID with no resource part, rather than rejecting it as invalid. We will then just get `user@domain`. --- src/xmpp/jid.c | 4 ++-- tests/unittests/unittests.c | 1 + tests/unittests/xmpp/test_jid.c | 14 ++++++++++---- tests/unittests/xmpp/test_jid.h | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/xmpp/jid.c b/src/xmpp/jid.c index 26dfabdc..58b602bd 100644 --- a/src/xmpp/jid.c +++ b/src/xmpp/jid.c @@ -157,11 +157,11 @@ jid_is_valid(const gchar* const str) domain_start = at + 1; } - // Resourcepart validation + // Resourcepart validation if present if (slash) { domain_len = slash - domain_start; size_t resource_len = strlen(slash + 1); - if (resource_len == 0 || resource_len > JID_MAX_PART_LEN) { + if (resource_len > JID_MAX_PART_LEN) { return FALSE; } } else { diff --git a/tests/unittests/unittests.c b/tests/unittests/unittests.c index e2372745..ee81d4f8 100644 --- a/tests/unittests/unittests.c +++ b/tests/unittests/unittests.c @@ -150,6 +150,7 @@ main(int argc, char* argv[]) cmocka_unit_test(jid_create__returns__correct_parts_with_trailing_slash), cmocka_unit_test(jid_fulljid_or_barejid__returns__fulljid_when_exists), cmocka_unit_test(jid_fulljid_or_barejid__returns__barejid_when_fulljid_not_exists), + cmocka_unit_test(jid_create__returns__bare_from_trailing_slash), cmocka_unit_test(jid_create__returns__null_from_invalid_localpart_chars), cmocka_unit_test(jid_create__returns__null_from_empty_parts), cmocka_unit_test(jid_create__returns__null_from_multiple_at_in_bare), diff --git a/tests/unittests/xmpp/test_jid.c b/tests/unittests/xmpp/test_jid.c index 421a9321..7a643d68 100644 --- a/tests/unittests/xmpp/test_jid.c +++ b/tests/unittests/xmpp/test_jid.c @@ -235,6 +235,16 @@ jid_fulljid_or_barejid__returns__barejid_when_fulljid_not_exists(void** state) jid_destroy(jid); } +void +jid_create__returns__bare_from_trailing_slash(void** state) +{ + Jid* result = jid_create("myuser@mydomain/"); + assert_non_null(result); + assert_string_equal("myuser@mydomain", result->barejid); + assert_null(result->resourcepart); + jid_destroy(result); +} + void jid_create__returns__null_from_invalid_localpart_chars(void** state) { @@ -278,10 +288,6 @@ jid_create__returns__null_from_empty_parts(void** state) result = jid_create("user@"); assert_null(result); - // Empty resource (trailing /) - result = jid_create("user@domain.com/"); - assert_null(result); - // Empty domain in full jid result = jid_create("user@/resource"); assert_null(result); diff --git a/tests/unittests/xmpp/test_jid.h b/tests/unittests/xmpp/test_jid.h index 8f582413..f8c6cb99 100644 --- a/tests/unittests/xmpp/test_jid.h +++ b/tests/unittests/xmpp/test_jid.h @@ -26,6 +26,7 @@ void jid_create__returns__correct_parts_with_at_and_slash_in_resource(void** sta void jid_create__returns__correct_parts_with_trailing_slash(void** state); void jid_fulljid_or_barejid__returns__fulljid_when_exists(void** state); void jid_fulljid_or_barejid__returns__barejid_when_fulljid_not_exists(void** state); +void jid_create__returns__bare_from_trailing_slash(void** state); void jid_create__returns__null_from_invalid_localpart_chars(void** state); void jid_create__returns__null_from_empty_parts(void** state); void jid_create__returns__null_from_multiple_at_in_bare(void** state);