[mastodon-client] Correctly parse invalid remote mentions

This commit is contained in:
Laura Hausmann 2023-10-12 21:31:41 +02:00
parent 0616edffa8
commit 0e39313ac4
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
5 changed files with 14 additions and 11 deletions

View file

@ -6,7 +6,7 @@ export class AnnouncementConverter {
public static encode(announcement: Announcement, isRead: boolean): MastodonEntity.Announcement { public static encode(announcement: Announcement, isRead: boolean): MastodonEntity.Announcement {
return { return {
id: announcement.id, id: announcement.id,
content: `<h1>${MfmHelpers.toHtml(mfm.parse(announcement.title), []) ?? 'Announcement'}</h1>${MfmHelpers.toHtml(mfm.parse(announcement.text), []) ?? ''}`, content: `<h1>${MfmHelpers.toHtml(mfm.parse(announcement.title), [], null) ?? 'Announcement'}</h1>${MfmHelpers.toHtml(mfm.parse(announcement.text), [], null) ?? ''}`,
starts_at: null, starts_at: null,
ends_at: null, ends_at: null,
published: true, published: true,

View file

@ -117,7 +117,7 @@ export class NoteConverter {
in_reply_to_id: note.replyId, in_reply_to_id: note.replyId,
in_reply_to_account_id: note.replyUserId, in_reply_to_account_id: note.replyUserId,
reblog: reblog.then(reblog => note.text === null ? reblog : null), reblog: reblog.then(reblog => note.text === null ? reblog : null),
content: text.then(text => text !== null ? MfmHelpers.toHtml(mfm.parse(text), JSON.parse(note.mentionedRemoteUsers)) ?? escapeMFM(text) : ""), content: text.then(async text => text !== null ? await host.then(host => MfmHelpers.toHtml(mfm.parse(text), JSON.parse(note.mentionedRemoteUsers), host)) ?? escapeMFM(text) : ""),
text: text, text: text,
created_at: note.createdAt.toISOString(), created_at: note.createdAt.toISOString(),
emojis: noteEmoji, emojis: noteEmoji,

View file

@ -31,7 +31,7 @@ export class UserConverter {
acctUrl = `https://${u.host}/@${u.username}`; acctUrl = `https://${u.host}/@${u.username}`;
} }
const profile = UserProfiles.findOneBy({ userId: u.id }); const profile = UserProfiles.findOneBy({ userId: u.id });
const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? "")) ?? escapeMFM(profile?.description ?? "")); const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? ""), [], u.host) ?? escapeMFM(profile?.description ?? ""));
const avatar = u.avatarId const avatar = u.avatarId
? (DriveFiles.findOneBy({ id: u.avatarId })) ? (DriveFiles.findOneBy({ id: u.avatarId }))
.then(p => p?.url ?? Users.getIdenticonUrl(u.id)) .then(p => p?.url ?? Users.getIdenticonUrl(u.id))
@ -92,7 +92,7 @@ export class UserConverter {
header_static: banner, header_static: banner,
emojis: populateEmojis(u.emojis, u.host).then(emoji => emoji.map((e) => EmojiConverter.encode(e))), emojis: populateEmojis(u.emojis, u.host).then(emoji => emoji.map((e) => EmojiConverter.encode(e))),
moved: null, //FIXME moved: null, //FIXME
fields: profile.then(profile => profile?.fields.map(p => this.encodeField(p)) ?? []), fields: profile.then(profile => profile?.fields.map(p => this.encodeField(p, u.host)) ?? []),
bot: u.isBot, bot: u.isBot,
discoverable: u.isExplorable discoverable: u.isExplorable
}).then(p => { }).then(p => {
@ -107,10 +107,10 @@ export class UserConverter {
return Promise.all(encoded); return Promise.all(encoded);
} }
private static encodeField(f: Field): MastodonEntity.Field { private static encodeField(f: Field, host: string | null): MastodonEntity.Field {
return { return {
name: f.name, name: f.name,
value: MfmHelpers.toHtml(mfm.parse(f.value), undefined, true) ?? escapeMFM(f.value), value: MfmHelpers.toHtml(mfm.parse(f.value), [], host, true) ?? escapeMFM(f.value),
verified_at: f.verified ? (new Date()).toISOString() : null, verified_at: f.verified ? (new Date()).toISOString() : null,
} }
} }

View file

@ -8,6 +8,7 @@ export class MfmHelpers {
public static toHtml( public static toHtml(
nodes: mfm.MfmNode[] | null, nodes: mfm.MfmNode[] | null,
mentionedRemoteUsers: IMentionedRemoteUsers = [], mentionedRemoteUsers: IMentionedRemoteUsers = [],
objectHost: string | null,
inline: boolean = false inline: boolean = false
) { ) {
if (nodes == null) { if (nodes == null) {
@ -142,7 +143,7 @@ export class MfmHelpers {
remoteUser.username === username && remoteUser.host === host, remoteUser.username === username && remoteUser.host === host,
); );
const localpart = `@${username}`; const localpart = `@${username}`;
const isLocal = host === config.domain || host === null; const isLocal = host === config.domain || (host == null && objectHost == null);
const acct = isLocal ? localpart: node.props.acct; const acct = isLocal ? localpart: node.props.acct;
a.href = remoteUserInfo a.href = remoteUserInfo
? remoteUserInfo.url ? remoteUserInfo.url
@ -150,6 +151,8 @@ export class MfmHelpers {
: remoteUserInfo.uri : remoteUserInfo.uri
: isLocal : isLocal
? `${config.url}/${acct}` ? `${config.url}/${acct}`
: host == null
? `https://${objectHost}/${localpart}`
: `https://${host}/${localpart}`; : `https://${host}/${localpart}`;
a.className = "u-url mention"; a.className = "u-url mention";
const span = doc.createElement("span"); const span = doc.createElement("span");

View file

@ -179,8 +179,8 @@ export class NoteHelpers {
} }
public static async getNoteEditHistory(note: Note, ctx: MastoContext): Promise<MastodonEntity.StatusEdit[]> { public static async getNoteEditHistory(note: Note, ctx: MastoContext): Promise<MastodonEntity.StatusEdit[]> {
const account = Promise.resolve(note.user ?? await UserHelpers.getUserCached(note.userId, ctx)) const user = Promise.resolve(note.user ?? await UserHelpers.getUserCached(note.userId, ctx));
.then(p => UserConverter.encode(p, ctx)); const account = user.then(p => UserConverter.encode(p, ctx));
const edits = await NoteEdits.find({ where: { noteId: note.id }, order: { id: "ASC" } }); const edits = await NoteEdits.find({ where: { noteId: note.id }, order: { id: "ASC" } });
const history: Promise<MastodonEntity.StatusEdit>[] = []; const history: Promise<MastodonEntity.StatusEdit>[] = [];
@ -201,7 +201,7 @@ export class NoteHelpers {
const files = DriveFiles.packMany(edit.fileIds); const files = DriveFiles.packMany(edit.fileIds);
const item = { const item = {
account: account, account: account,
content: MfmHelpers.toHtml(mfm.parse(edit.text ?? ''), JSON.parse(note.mentionedRemoteUsers)) ?? '', content: user.then(user => MfmHelpers.toHtml(mfm.parse(edit.text ?? ''), JSON.parse(note.mentionedRemoteUsers), user.host) ?? ''),
created_at: lastDate.toISOString(), created_at: lastDate.toISOString(),
emojis: [], emojis: [],
sensitive: files.then(files => files.length > 0 ? files.some((f) => f.isSensitive) : false), sensitive: files.then(files => files.length > 0 ? files.some((f) => f.isSensitive) : false),