Skip to content

Conversation

@sreeshanth-soma
Copy link

Summary

Implements XEP-0231: Bits of Binary, enabling Converse.js to receive and display inline binary data such as custom smileys from clients like Pidgin.
Closes #3611

Implementation

New converse-bob Plugin

  • In-memory cache with TTL and max-age expiration
  • API: api.bob.get(), api.bob.store(), api.bob.has()
  • IQ handling: Fetches uncached BOB data via <iq type="get">
  • Message parsing: Extracts <data xmlns="urn:xmpp:bob"> elements
  • Disco feature: Registers urn:xmpp:bob
  • Security: Image MIME types only, 8KB size limit per spec

Test Results

TOTAL: 94 SUCCESS

New Tests (7)

  • Cache storage, retrieval, expiration
  • Size and MIME validation
  • Message parsing and IQ requests
  • Error handling

Capability Hash

Adding urn:xmpp:bob updates XEP-0115 verification string from 1T0pIfIxYO645OaT9gpXVXOvb9s= to ZXDrJD54GWZYlZif9IuMxum/u+g=

import _converse from '../../shared/_converse.js';
import log from '@converse/log';

const { Strophe, $iq } = converse.env;

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable Strophe.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pay attention to these security bot messages.

Copy link
Member

@jcbrand jcbrand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your pull request @sreeshanth-soma

You noted that the headless tests failed, but there are also non-headless tests which now fail due to the new urn:xmpp:bob feature supported.

Please fix those as well.

- Add converse-bob plugin for receiving BOB images (custom smileys)
- Implements cache, API, IQ handling, and message parsing
- Register urn:xmpp:bob disco feature
- Add comprehensive test suite (7 tests)
- Update capability hashes for new feature
Update XEP-0115 entity capability verification hashes in test files
to account for the added urn:xmpp:bob feature.

Headless tests now use: 9zuZdgDXVE0fkcAjeaokq9JxHJw=
Non-headless tests now use: KjyaPNsNXajTrXVlYimRsIvje2g=
RAI tests now use: 3Tday6wfQnY1R8zGPMO3CBYFrik=
@sreeshanth-soma sreeshanth-soma force-pushed the xep-0231-bits-of-binary branch from 06c6529 to 6deb51b Compare January 27, 2026 02:14
@sreeshanth-soma
Copy link
Author

Hello @jcbrand . I've addressed your feedback. The non-headless tests that were failing due to the urn:xmpp:bob feature have been fixed:

  • Updated all capability hashes in the non-headless test files
  • Added TypeScript type definitions for the BOB plugin
    All tests are now passing locally (matching upstream/master behavior). Ready for re-review!

Copy link
Member

@jcbrand jcbrand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sreeshanth-soma, please see my review comments.

const MAX_BOB_SIZE = 8192;

// In-memory cache for BOB data
const bob_cache = new Map();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced that an in-memory cache is the right way to go here.

Every time you reload the tab the cache will be wiped and then you lose all the images.
If you then try to refetch the images, you might not get all of them due to the sender being offline.

So instead, we should probably create a persistent collection of BOB images, similar to what we do with VCards: https://github.com/conversejs/converse.js/blob/master/src/headless/plugins/vcard/vcards.js

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! I've replaced the in-memory Map with a persistent Skeletor Collection, following the VCards pattern:

  • Created bob.js model with isExpired() and getBlobURL() methods.
  • Created bobs.js collection using initStorage() for IndexedDB persistence
  • Collection is initialized on connected event and cleaned up on clearSession

BOB images now persist across page reloads and remain available even if the sender goes offline.

* @param {number} offset - The index of the passed in text relative to
* the start of the message body text.
*/
async addBOBImages(text, offset) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should go into a bob-views plugin and then in that plugin you should listen for the afterMessageBodyTransformed event in order to call this function.

See here:

api.listen.on('afterMessageBodyTransformed', handleEncryptedFiles);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Created a new bob-views plugin that:

  • Listens to afterMessageBodyTransformed event (following the omemo-views pattern)
  • Moved the BOB image handling logic from texture.js to the new plugin
  • Registered it in src/index.js and added to VIEW_PLUGINS whitelist

This properly separates the headless BOB storage from the view-layer rendering.

import { until } from "lit/directives/until.js";
import { Directive, directive } from "lit/directive.js";
import { api, u } from "@converse/headless";
import log from "@converse/log";

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import log.
import _converse from '../../shared/_converse.js';
import log from '@converse/log';

const { Strophe, $iq } = converse.env;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pay attention to these security bot messages.

…eanup

Use configurable max_bob_size setting, add setInterval for expired blob cleanup, and update test fixtures for new caps hashes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

XEP-0231: Bits of Binary - for custom smileys and CAPTCHA

2 participants