diff --git a/kernel/api/block.go b/kernel/api/block.go index 8bf57072e..c8d31d55f 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -626,13 +626,18 @@ func getBlockInfo(c *gin.Context) { } rootTitle := root.IAL["title"] rootTitle = html.UnescapeString(rootTitle) + icon := root.IAL["icon"] + if strings.Contains(icon, ".") { + // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 + icon = util.FilterUploadFileName(icon) + } ret.Data = map[string]string{ "box": block.Box, "path": block.Path, "rootID": block.RootID, "rootTitle": rootTitle, "rootChildID": rootChildID, - "rootIcon": root.IAL["icon"], + "rootIcon": icon, } } diff --git a/kernel/api/setting.go b/kernel/api/setting.go index e5765d64a..14a015a19 100644 --- a/kernel/api/setting.go +++ b/kernel/api/setting.go @@ -654,7 +654,12 @@ func setEmoji(c *gin.Context) { argEmoji := arg["emoji"].([]interface{}) var emoji []string for _, ae := range argEmoji { - emoji = append(emoji, ae.(string)) + e := ae.(string) + if strings.Contains(e, ".") { + // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 + e = util.FilterUploadFileName(e) + } + emoji = append(emoji, e) } model.Conf.Editor.Emoji = emoji diff --git a/kernel/av/layout_gallery.go b/kernel/av/layout_gallery.go index 20c0c4c5b..660e3a226 100644 --- a/kernel/av/layout_gallery.go +++ b/kernel/av/layout_gallery.go @@ -97,12 +97,13 @@ type ViewGalleryCardField struct { type Gallery struct { *BaseInstance - CoverFrom CoverFrom `json:"coverFrom"` // 封面来源 - CoverFromAssetKeyID string `json:"coverFromAssetKeyID,omitempty"` // 资源字段 ID,CoverFrom 为 CoverFromAssetField 时有效 - CardSize CardSize `json:"cardSize"` // 卡片大小 - FitImage bool `json:"fitImage"` // 是否适应封面图片大小 - ShowIcon bool `json:"showIcon"` // 是否显示字段图标 - WrapField bool `json:"wrapField"` // 是否换行字段内容 + CoverFrom CoverFrom `json:"coverFrom"` // 封面来源 + CoverFromAssetKeyID string `json:"coverFromAssetKeyID,omitempty"` // 资源字段 ID,CoverFrom 为 CoverFromAssetField 时有效 + CardAspectRatio CardAspectRatio `json:"cardAspectRatio"` // 卡片宽高比 + CardSize CardSize `json:"cardSize"` // 卡片大小 + FitImage bool `json:"fitImage"` // 是否适应封面图片大小 + ShowIcon bool `json:"showIcon"` // 是否显示字段图标 + WrapField bool `json:"wrapField"` // 是否换行字段内容 Fields []*GalleryField `json:"fields"` // 画廊字段 Cards []*GalleryCard `json:"cards"` // 画廊卡片 diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 147fc5cab..8c83bd9d1 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -44,6 +44,36 @@ import ( "github.com/xrash/smetrics" ) +func (tx *Transaction) doSetAttrViewCardAspectRatio(operation *Operation) (ret *TxErr) { + err := setAttrViewCardSize(operation) + if err != nil { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + +func setAttrViewCardAspectRatio(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if err != nil { + return + } + + view, err := getAttrViewViewByBlockID(attrView, operation.BlockID) + if err != nil { + return + } + + switch view.LayoutType { + case av.LayoutTypeTable: + return + case av.LayoutTypeGallery: + view.Gallery.CardAspectRatio = av.CardAspectRatio(operation.Data.(float64)) + } + + err = av.SaveAttributeView(attrView) + return +} + func (tx *Transaction) doSetAttrViewBlockView(operation *Operation) (ret *TxErr) { err := SetDatabaseBlockView(operation.BlockID, operation.AvID, operation.ID) if err != nil { diff --git a/kernel/model/box.go b/kernel/model/box.go index 9eb1102f4..23b963ef6 100644 --- a/kernel/model/box.go +++ b/kernel/model/box.go @@ -699,6 +699,11 @@ func ChangeBoxSort(boxIDs []string) { } func SetBoxIcon(boxID, icon string) { + if strings.Contains(icon, ".") { + // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 + icon = util.FilterUploadFileName(icon) + } + box := &Box{ID: boxID} boxConf := box.GetConf() boxConf.Icon = icon diff --git a/kernel/model/conf.go b/kernel/model/conf.go index daeea45a3..feaabc449 100644 --- a/kernel/model/conf.go +++ b/kernel/model/conf.go @@ -231,6 +231,13 @@ func InitConf() { if 1 > len(Conf.Editor.Emoji) { Conf.Editor.Emoji = []string{} } + for i, emoji := range Conf.Editor.Emoji { + if strings.Contains(emoji, ".") { + // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 + emoji = util.FilterUploadFileName(emoji) + Conf.Editor.Emoji[i] = emoji + } + } if 9 > Conf.Editor.FontSize || 72 < Conf.Editor.FontSize { Conf.Editor.FontSize = 16 } diff --git a/kernel/model/file.go b/kernel/model/file.go index bd3c51ddf..3ad04ee94 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -80,7 +80,12 @@ func (box *Box) docFromFileInfo(fileInfo *FileInfo, ial map[string]string) (ret ret.Path = fileInfo.path ret.Size = uint64(fileInfo.size) ret.Name = ial["title"] + ".sy" - ret.Icon = ial["icon"] + icon := ial["icon"] + if strings.Contains(icon, ".") { + // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 + icon = util.FilterUploadFileName(icon) + } + ret.Icon = icon ret.ID = ial["id"] ret.Name1 = ial["name"] ret.Alias = ial["alias"] diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 861bec733..d96a146e5 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -292,6 +292,8 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doChangeAttrViewLayout(op) case "setAttrViewBlockView": ret = tx.doSetAttrViewBlockView(op) + case "setAttrViewCardAspectRatio": + ret = tx.doSetAttrViewCardAspectRatio(op) } if nil != ret { diff --git a/kernel/sql/av_gallery.go b/kernel/sql/av_gallery.go index f3cf5a550..dc01ba9ec 100644 --- a/kernel/sql/av_gallery.go +++ b/kernel/sql/av_gallery.go @@ -27,6 +27,7 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query }, CoverFrom: view.Gallery.CoverFrom, CoverFromAssetKeyID: view.Gallery.CoverFromAssetKeyID, + CardAspectRatio: view.Gallery.CardAspectRatio, CardSize: view.Gallery.CardSize, FitImage: view.Gallery.FitImage, ShowIcon: view.Gallery.ShowIcon,