diff --git a/app/post.go b/app/post.go index d0c0114294..3ddfe0bb72 100644 --- a/app/post.go +++ b/app/post.go @@ -292,6 +292,14 @@ func (a *App) CreatePost(c *request.Context, post *model.Post, channel *model.Ch // We make a copy of the post for the plugin hook to avoid a race condition. rPostCopy := rpost.Clone() + + // FIXME: Removes PreviewPost from the post payload sent to the MessageHasBeenPosted hook so that plugins compiled with older versions of + // Mattermost—without the gob registeration of the PreviewPost struct—won't crash. + if rPostCopy.Metadata != nil { + rPostCopy.Metadata = rPostCopy.Metadata.Copy() + } + rPostCopy.RemovePreviewPost() + if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv().Go(func() { pluginContext := pluginContext(c) diff --git a/model/post.go b/model/post.go index 695971cf50..d13fef0a67 100644 --- a/model/post.go +++ b/model/post.go @@ -686,6 +686,20 @@ func (o *Post) ToNilIfInvalid() *Post { return o } +func (o *Post) RemovePreviewPost() { + if o.Metadata == nil || o.Metadata.Embeds == nil { + return + } + n := 0 + for _, embed := range o.Metadata.Embeds { + if embed.Type != PostEmbedPermalink { + o.Metadata.Embeds[n] = embed + n++ + } + } + o.Metadata.Embeds = o.Metadata.Embeds[:n] +} + func (o *Post) GetPreviewPost() *PreviewPost { for _, embed := range o.Metadata.Embeds { if embed.Type == PostEmbedPermalink { diff --git a/model/post_metadata.go b/model/post_metadata.go index a316eb771f..0f9e61d3d4 100644 --- a/model/post_metadata.go +++ b/model/post_metadata.go @@ -34,3 +34,31 @@ type PostImage struct { // FrameCount stores the number of frames in this image, if it is an animated gif. It will be 0 for other formats. FrameCount int `json:"frame_count"` } + +// Copy does a deep copy +func (p *PostMetadata) Copy() *PostMetadata { + embedsCopy := make([]*PostEmbed, len(p.Embeds)) + copy(embedsCopy, p.Embeds) + + emojisCopy := make([]*Emoji, len(p.Emojis)) + copy(emojisCopy, p.Emojis) + + filesCopy := make([]*FileInfo, len(p.Files)) + copy(filesCopy, p.Files) + + imagesCopy := map[string]*PostImage{} + for k, v := range p.Images { + imagesCopy[k] = v + } + + reactionsCopy := make([]*Reaction, len(p.Reactions)) + copy(reactionsCopy, p.Reactions) + + return &PostMetadata{ + Embeds: embedsCopy, + Emojis: emojisCopy, + Files: filesCopy, + Images: imagesCopy, + Reactions: reactionsCopy, + } +}