chore: 初始化 Cloudreve 源码仓库
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package wopi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrActionNotSupported = errors.New("action not supported by current wopi endpoint")
|
||||
|
||||
queryPlaceholders = map[string]string{
|
||||
"BUSINESS_USER": "",
|
||||
"DC_LLCC": "lng",
|
||||
"DISABLE_ASYNC": "",
|
||||
"DISABLE_CHAT": "",
|
||||
"EMBEDDED": "true",
|
||||
"FULLSCREEN": "true",
|
||||
"HOST_SESSION_ID": "",
|
||||
"SESSION_CONTEXT": "",
|
||||
"RECORDING": "",
|
||||
"THEME_ID": "darkmode",
|
||||
"UI_LLCC": "lng",
|
||||
"VALIDATOR_TEST_CATEGORY": "",
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
SessionCachePrefix = "wopi_session_"
|
||||
AccessTokenQuery = "access_token"
|
||||
OverwriteHeader = WopiHeaderPrefix + "Override"
|
||||
ServerErrorHeader = WopiHeaderPrefix + "ServerError"
|
||||
RenameRequestHeader = WopiHeaderPrefix + "RequestedName"
|
||||
LockTokenHeader = WopiHeaderPrefix + "Lock"
|
||||
ItemVersionHeader = WopiHeaderPrefix + "ItemVersion"
|
||||
SuggestedTargetHeader = WopiHeaderPrefix + "SuggestedTarget"
|
||||
InvalidFileNameHeader = WopiHeaderPrefix + "InvalidFileNameError"
|
||||
|
||||
MethodLock = "LOCK"
|
||||
MethodUnlock = "UNLOCK"
|
||||
MethodRefreshLock = "REFRESH_LOCK"
|
||||
MethodPutRelative = "PUT_RELATIVE"
|
||||
wopiSrcPlaceholder = "WOPI_SOURCE"
|
||||
wopiSrcParamDefault = "WOPISrc"
|
||||
languageParamDefault = "lang"
|
||||
WopiHeaderPrefix = "X-WOPI-"
|
||||
|
||||
LockDuration = time.Duration(30) * time.Minute
|
||||
)
|
||||
|
||||
func GenerateWopiSrc(ctx context.Context, action types.ViewerAction, viewer *types.Viewer, viewerSession *manager.ViewerSession) (*url.URL, error) {
|
||||
dep := dependency.FromContext(ctx)
|
||||
base := dep.SettingProvider().SiteURL(setting.UseFirstSiteUrl(ctx))
|
||||
hasher := dep.HashIDEncoder()
|
||||
|
||||
availableActions, ok := viewer.WopiActions[viewerSession.File.Ext()]
|
||||
if !ok {
|
||||
return nil, ErrActionNotSupported
|
||||
}
|
||||
|
||||
var (
|
||||
src string
|
||||
)
|
||||
fallbackOrder := []types.ViewerAction{action, types.ViewerActionView, types.ViewerActionEdit}
|
||||
for _, a := range fallbackOrder {
|
||||
if src, ok = availableActions[a]; ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if src == "" {
|
||||
return nil, ErrActionNotSupported
|
||||
}
|
||||
|
||||
actionUrl, err := generateActionUrl(src,
|
||||
routes.MasterWopiSrc(base, hashid.EncodeFileID(hasher, viewerSession.File.ID())).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return actionUrl, nil
|
||||
}
|
||||
|
||||
// Replace query parameters in action URL template. Some placeholders need to be replaced
|
||||
// at the frontend, e.g. `THEME_ID`.
|
||||
func generateActionUrl(src string, fileSrc string) (*url.URL, error) {
|
||||
src = strings.ReplaceAll(src, "<", "")
|
||||
src = strings.ReplaceAll(src, ">", "")
|
||||
actionUrl, err := url.Parse(src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse action url: %s", err)
|
||||
}
|
||||
|
||||
queries := actionUrl.Query()
|
||||
srcReplaced := false
|
||||
queryReplaced := url.Values{}
|
||||
for k := range queries {
|
||||
if placeholder, ok := queryPlaceholders[queries.Get(k)]; ok {
|
||||
if placeholder != "" {
|
||||
queryReplaced.Set(k, placeholder)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if queries.Get(k) == wopiSrcPlaceholder {
|
||||
queryReplaced.Set(k, fileSrc)
|
||||
srcReplaced = true
|
||||
continue
|
||||
}
|
||||
|
||||
queryReplaced.Set(k, queries.Get(k))
|
||||
}
|
||||
|
||||
if !srcReplaced {
|
||||
queryReplaced.Set(wopiSrcParamDefault, fileSrc)
|
||||
}
|
||||
|
||||
// LibreOffice require this flag to show correct language
|
||||
queryReplaced.Set(languageParamDefault, "lng")
|
||||
|
||||
actionUrl.RawQuery = queryReplaced.Encode()
|
||||
return actionUrl, nil
|
||||
}
|
||||
Reference in New Issue
Block a user