github.com/rajatvaryani/mattermost-server@v5.11.1+incompatible/model/file_info.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package model 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "image" 10 "image/gif" 11 "io" 12 "mime" 13 "net/http" 14 "path/filepath" 15 "strings" 16 ) 17 18 type FileInfo struct { 19 Id string `json:"id"` 20 CreatorId string `json:"user_id"` 21 PostId string `json:"post_id,omitempty"` 22 CreateAt int64 `json:"create_at"` 23 UpdateAt int64 `json:"update_at"` 24 DeleteAt int64 `json:"delete_at"` 25 Path string `json:"-"` // not sent back to the client 26 ThumbnailPath string `json:"-"` // not sent back to the client 27 PreviewPath string `json:"-"` // not sent back to the client 28 Name string `json:"name"` 29 Extension string `json:"extension"` 30 Size int64 `json:"size"` 31 MimeType string `json:"mime_type"` 32 Width int `json:"width,omitempty"` 33 Height int `json:"height,omitempty"` 34 HasPreviewImage bool `json:"has_preview_image,omitempty"` 35 } 36 37 func (info *FileInfo) ToJson() string { 38 b, _ := json.Marshal(info) 39 return string(b) 40 } 41 42 func FileInfoFromJson(data io.Reader) *FileInfo { 43 decoder := json.NewDecoder(data) 44 45 var info FileInfo 46 if err := decoder.Decode(&info); err != nil { 47 return nil 48 } else { 49 return &info 50 } 51 } 52 53 func FileInfosToJson(infos []*FileInfo) string { 54 b, _ := json.Marshal(infos) 55 return string(b) 56 } 57 58 func FileInfosFromJson(data io.Reader) []*FileInfo { 59 decoder := json.NewDecoder(data) 60 61 var infos []*FileInfo 62 if err := decoder.Decode(&infos); err != nil { 63 return nil 64 } else { 65 return infos 66 } 67 } 68 69 func (o *FileInfo) PreSave() { 70 if o.Id == "" { 71 o.Id = NewId() 72 } 73 74 if o.CreateAt == 0 { 75 o.CreateAt = GetMillis() 76 } 77 78 if o.UpdateAt < o.CreateAt { 79 o.UpdateAt = o.CreateAt 80 } 81 } 82 83 func (o *FileInfo) IsValid() *AppError { 84 if len(o.Id) != 26 { 85 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest) 86 } 87 88 if len(o.CreatorId) != 26 && o.CreatorId != "nouser" { 89 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) 90 } 91 92 if len(o.PostId) != 0 && len(o.PostId) != 26 { 93 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.post_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) 94 } 95 96 if o.CreateAt == 0 { 97 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) 98 } 99 100 if o.UpdateAt == 0 { 101 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) 102 } 103 104 if o.Path == "" { 105 return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.path.app_error", nil, "id="+o.Id, http.StatusBadRequest) 106 } 107 108 return nil 109 } 110 111 func (o *FileInfo) IsImage() bool { 112 return strings.HasPrefix(o.MimeType, "image") 113 } 114 115 func NewInfo(name string) *FileInfo { 116 info := &FileInfo{ 117 Name: name, 118 } 119 120 extension := strings.ToLower(filepath.Ext(name)) 121 info.MimeType = mime.TypeByExtension(extension) 122 123 if extension != "" && extension[0] == '.' { 124 // The client expects a file extension without the leading period 125 info.Extension = extension[1:] 126 } else { 127 info.Extension = extension 128 } 129 130 return info 131 } 132 133 func GetInfoForBytes(name string, data []byte) (*FileInfo, *AppError) { 134 info := &FileInfo{ 135 Name: name, 136 Size: int64(len(data)), 137 } 138 var err *AppError 139 140 extension := strings.ToLower(filepath.Ext(name)) 141 info.MimeType = mime.TypeByExtension(extension) 142 143 if extension != "" && extension[0] == '.' { 144 // The client expects a file extension without the leading period 145 info.Extension = extension[1:] 146 } else { 147 info.Extension = extension 148 } 149 150 if info.IsImage() { 151 // Only set the width and height if it's actually an image that we can understand 152 if config, _, err := image.DecodeConfig(bytes.NewReader(data)); err == nil { 153 info.Width = config.Width 154 info.Height = config.Height 155 156 if info.MimeType == "image/gif" { 157 // Just show the gif itself instead of a preview image for animated gifs 158 if gifConfig, err := gif.DecodeAll(bytes.NewReader(data)); err != nil { 159 // Still return the rest of the info even though it doesn't appear to be an actual gif 160 info.HasPreviewImage = true 161 err = NewAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "name="+name, http.StatusBadRequest) 162 } else { 163 info.HasPreviewImage = len(gifConfig.Image) == 1 164 } 165 } else { 166 info.HasPreviewImage = true 167 } 168 } 169 } 170 171 return info, err 172 } 173 174 func GetEtagForFileInfos(infos []*FileInfo) string { 175 if len(infos) == 0 { 176 return Etag() 177 } 178 179 var maxUpdateAt int64 180 181 for _, info := range infos { 182 if info.UpdateAt > maxUpdateAt { 183 maxUpdateAt = info.UpdateAt 184 } 185 } 186 187 return Etag(infos[0].PostId, maxUpdateAt) 188 }