@@ -3,10 +3,13 @@ package controllers
33import (
44 "fmt"
55 "net/http"
6+ "net/url"
67 "path/filepath"
78 "strings"
89
10+ "github.com/TruthHun/BookStack/conf"
911 "github.com/TruthHun/BookStack/models"
12+ "github.com/TruthHun/BookStack/models/store"
1013
1114 "github.com/TruthHun/BookStack/utils"
1215 "github.com/astaxie/beego"
@@ -39,7 +42,7 @@ func (this *StaticController) Uploads() {
3942 http .ServeFile (this .Ctx .ResponseWriter , this .Ctx .Request , path )
4043}
4144
42- //静态文件,这个加在路由的最后
45+ // 静态文件,这个加在路由的最后
4346func (this * StaticController ) StaticFile () {
4447 file := this .GetString (":splat" )
4548 if strings .HasPrefix (file , ".well-known" ) || file == "sitemap.xml" {
@@ -51,12 +54,104 @@ func (this *StaticController) StaticFile() {
5154 http .ServeFile (this .Ctx .ResponseWriter , this .Ctx .Request , path )
5255}
5356
54- // 书籍静态文件
57+ // ProjectsFile 书籍静态文件
5558func (this * StaticController ) ProjectsFile () {
59+ if utils .StoreType != utils .StoreOss {
60+ this .Abort ("404" )
61+ }
62+
5663 object := filepath .Join ("projects/" , strings .TrimLeft (this .GetString (":splat" ), "./" ))
57- if utils .StoreType == utils .StoreOss { //oss
64+ object = strings .ReplaceAll (object , "\\ " , "/" )
65+ // 不是音频和视频,直接跳转
66+ if ! this .isMedia (object ) {
5867 this .Redirect (this .OssDomain + "/" + object , 302 )
59- } else { //local
60- this .Abort ("404" )
68+ return
69+ }
70+
71+ // query := this.Ctx.Request.URL.Query()
72+ // 签名验证
73+ sign := this .GetString ("sign" )
74+ if ! this .isValidSign (sign ) {
75+ // 签名验证不通过,需要再次验证书籍是否是用户的(针对编辑状态)
76+ if ! this .isBookOwner () {
77+ this .Abort ("404" )
78+ return
79+ }
80+ }
81+
82+ var expireInSec int64 = 2
83+ if bucket , err := store .ModelStoreOss .GetBucket (); err == nil {
84+ object , _ = bucket .SignURL (object , http .MethodGet , expireInSec )
85+ if slice := strings .Split (object , "/" ); len (slice ) > 2 {
86+ object = strings .Join (slice [3 :], "/" )
87+ }
88+ }
89+ this .Redirect (this .OssDomain + "/" + object , 302 )
90+ }
91+
92+ // 是否是音视频
93+ func (this * StaticController ) isMedia (path string ) (yes bool ) {
94+ var videoOK , audioOK bool
95+ ext := strings .ToLower (filepath .Ext (path ))
96+ _ , videoOK = conf .VideoExt .Load (ext )
97+ _ , audioOK = conf .VideoExt .Load (ext )
98+ return audioOK || videoOK
99+ }
100+
101+ // 是否是书籍项目所有人(书籍项目所有人,可以直链播放音视频)
102+ func (this * StaticController ) isBookOwner () (yes bool ) {
103+ memberID := 0
104+ // 从session中获取用户信息
105+ if member , ok := this .GetSession (conf .LoginSessionName ).(models.Member ); ok {
106+ memberID = member .MemberId
107+ }
108+
109+ if memberID <= 0 {
110+ // 如果Cookie中存在登录信息,从cookie中获取用户信息
111+ if cookie , ok := this .GetSecureCookie (conf .GetAppKey (), "login" ); ok {
112+ var remember CookieRemember
113+ if err := utils .Decode (cookie , & remember ); err == nil {
114+ memberID = remember .MemberId
115+ }
116+ }
117+ }
118+ if memberID <= 0 {
119+ return
61120 }
121+
122+ referer := this .Ctx .Request .Referer ()
123+ if referer == "" {
124+ return
125+ }
126+
127+ bookIdentify := ""
128+ if u , err := url .Parse (referer ); err == nil {
129+ fmt .Println (u .Path )
130+ if slice := strings .Split (u .Path , "/" ); len (slice ) >= 3 && slice [1 ] == "api" {
131+ bookIdentify = slice [2 ]
132+ }
133+ }
134+
135+ if bookIdentify == "" {
136+ return
137+ }
138+
139+ bookID := 0
140+ if book , err := models .NewBook ().FindByIdentify (bookIdentify , "book_id" ); err == nil {
141+ bookID = book .BookId
142+ }
143+ if bookID <= 0 {
144+ return
145+ }
146+
147+ if r , err := models .NewRelationship ().FindByBookIdAndMemberId (bookID , memberID ); err == nil && r .RelationshipId > 0 {
148+ return true
149+ }
150+
151+ return false
152+ }
153+
154+ // 是否是合法的签名(针对音频和视频,签名不可用的时候再验证用户有没有登录,用户登录了再验证用户是不是书籍所有人)
155+ func (this * StaticController ) isValidSign (sign string ) bool {
156+ return false
62157}
0 commit comments