From d1c82849642b3f44fb77e672d8cad484211777de Mon Sep 17 00:00:00 2001 From: mjk Date: Sat, 26 Feb 2022 00:08:00 +0000 Subject: [PATCH] OMEMO QR code: URI-escape the JID --- .../omemo/src/ui/contact_details_dialog.vala | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/plugins/omemo/src/ui/contact_details_dialog.vala b/plugins/omemo/src/ui/contact_details_dialog.vala index 04694637..df98d772 100644 --- a/plugins/omemo/src/ui/contact_details_dialog.vala +++ b/plugins/omemo/src/ui/contact_details_dialog.vala @@ -92,10 +92,18 @@ public class ContactDetailsDialog : Gtk.Dialog { copy_button.clicked.connect(() => {Clipboard.get_default(get_display()).set_text(fingerprint, fingerprint.length);}); int sid = plugin.db.identity.row_with(plugin.db.identity.account_id, account.id)[plugin.db.identity.device_id]; + var iri_query = @"omemo-sid-$(sid)=$(fingerprint)"; + #if 0 + // glib >=2.66 only; never compiled + string iri = GLib.Uri.join("xmpp", null, null, 0, jid, iri_query); + #else + var iri_path_seg = escape_for_iri_path_segment(jid.to_string()); + var iri = @"xmpp:$(iri_path_seg)?$(iri_query)"; + #endif const int QUIET_ZONE_MODULES = 4; // MUST be at least 4 const int MODULE_SIZE_PX = 4; // arbitrary - var qr_pixbuf = new QRcode(@"xmpp:$(account.bare_jid)?omemo-sid-$(sid)=$(fingerprint)", 2) + var qr_pixbuf = new QRcode(iri, 2) .to_pixbuf(MODULE_SIZE_PX * qrcode_image.scale_factor); qrcode_image.set_from_surface( Gdk.cairo_surface_create_from_pixbuf(qr_pixbuf,0,get_window())); @@ -126,6 +134,14 @@ public class ContactDetailsDialog : Gtk.Dialog { fetch_unknown_bundles(); } + private static string escape_for_iri_path_segment(string s) { + // from RFC 3986, 2.2. Reserved Characters: + /*const*/ string SUB_DELIMS = "!$&'()*+,;="; + // from RFC 3986, 3.3. Path (pchar without unreserved and pct-encoded): + /*const*/ string ALLOWED_RESERVED_CHARS = SUB_DELIMS + ":@"; + return GLib.Uri.escape_string(s, ALLOWED_RESERVED_CHARS, true); + } + private void fetch_unknown_bundles() { Dino.Application app = Application.get_default() as Dino.Application; XmppStream? stream = app.stream_interactor.get_stream(account);