Skip to content

[SDK] Reply event 'body' contains HTML instead of plain text #9164

Description

@GabrielTessier

Description

The body field of reply events can contain HTML markup, even though it should contain the plain-text representation of the message.

I think the bug come from that :

When creating a reply event, createNewRepliedEvent() calls createReplyTextContent().

val replyText = localEchoEventFactory
                .bodyForReply(currentTimelineEvent.getLastMessageContent(), true).takeFormatted()

val newContent = localEchoEventFactory.createReplyTextContent(
        timelineEventMapper.map(timelineEventEntity),
        replyText,
        null,
        false,
        showInThread = false,
        isRedactedEvent = isRedactedEvent
).toContent()
fun createReplyTextContent(
        eventReplied: TimelineEvent,
        replyText: CharSequence,
        replyTextFormatted: CharSequence?,
        autoMarkdown: Boolean,
        rootThreadEventId: String? = null,
        showInThread: Boolean,
        isRedactedEvent: Boolean = false
): MessageContent? {
    // Fallbacks and event representation
    // TODO Add error/warning logs when any of this is null
    val permalink = permalinkFactory.createPermalink(eventReplied.root, false) ?: return null
    val userId = eventReplied.root.senderId ?: return null
    val userLink = permalinkFactory.createPermalink(userId, false) ?: return null

    val body = bodyForReply(timelineEvent = eventReplied, isRedactedEvent = isRedactedEvent)

    // As we always supply formatted body for replies we should force the MarkdownParser to produce html.
    val finalReplyTextFormatted = replyTextFormatted?.toString() ?: markdownParser.parse(replyText, force = true, advanced = autoMarkdown).takeFormatted()
    // Body of the original message may not have formatted version, so may also have to convert to html.
    val bodyFormatted = body.formattedText ?: markdownParser.parse(body.text, force = true, advanced = autoMarkdown).takeFormatted()
    val replyFormatted = buildFormattedReply(
            permalink,
            userLink,
            userId,
            bodyFormatted,
            finalReplyTextFormatted
    )
    //
    // > <@alice:example.org> This is the original body
    //
    val replyFallback = buildReplyFallback(body, userId, replyText.toString())

    val eventId = eventReplied.root.eventId ?: return null
    return MessageTextContent(
            msgType = MessageType.MSGTYPE_TEXT,
            format = MessageFormat.FORMAT_MATRIX_HTML,
            body = replyFallback,
            formattedBody = replyFormatted,
            relatesTo = generateReplyRelationContent(
                    eventId = eventId,
                    rootThreadEventId = rootThreadEventId,
                    showInThread = showInThread
            )
    )
}

The issue appears to be caused by createNewRepliedEvent() passing a formatted version of the reply text as replyText, while passing null as replyTextFormatted.

As a result, createReplyTextContent() receives the already-formatted HTML content as replyText and null as replyTextFormatted. It then uses replyText to build both the formatted reply and the reply fallback.

Since replyText already contains formatted content, replyFallback also contain HTML markup. replyFallback is then assigned directly to the body field.

This results in HTML markup being present in body, whereas body should contain the plain-text representation and the formatted representation should only be present in formatted_body.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions