Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
@@ -0,0 +1,71 @@
// Package locks provides functionality to parse lockIDs.
//
// It can be used to bridge requests from different clients that send lockIDs in different formats.
// For example, Microsoft Office Online sends the lockID in a JSON string,
// while other clients send the lockID as a plain string.
package locks
import (
"encoding/json"
)
// LockParser is the interface that wraps the ParseLock method
type LockParser interface {
ParseLock(id string) string
}
// LegacyLockParser is a lock parser that can extract the lockID from a JSON string
type LegacyLockParser struct{}
// NoopLockParser is a lock parser that does not change the lockID
type NoopLockParser struct{}
// ParseLock will return the lockID as is
func (*NoopLockParser) ParseLock(id string) string {
return id
}
// ParseLock extracts the lockID from a JSON string.
// For Microsoft Office Online we need to extract the lockID from the JSON string
// that is sent by the WOPI client.
// The JSON string is expected to have the following format:
//
// {
// "L": "12345678",
// "F": 4,
// "E": 2,
// "C": "",
// "P": "3453345345346",
// "M": "12345678"
// }
//
// or
//
// {
// "S": "12345678",
// "F": 4,
// "E": 2,
// "C": "",
// "P": "3453345345346",
// "M": "12345678"
// }
//
// If the JSON string is not in the expected format, the original lockID will be returned.
func (*LegacyLockParser) ParseLock(id string) string {
var decodedValues map[string]any
err := json.Unmarshal([]byte(id), &decodedValues)
if err != nil || len(decodedValues) == 0 {
return id
}
if v, ok := decodedValues["L"]; ok {
if idString, ok := v.(string); ok {
return idString
}
}
if v, ok := decodedValues["S"]; ok {
if idString, ok := v.(string); ok {
return idString
}
}
return id
}
@@ -0,0 +1,87 @@
package locks
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
func TestLegacyLockParser(t *testing.T) {
tests := []struct {
name string
lock string
cleanLock string
}{
{
name: "JsonStringWithLKey",
lock: createJsonString(map[string]any{"L": "12345678", "F": 4, "E": 2, "C": "", "P": "3453345345346", "M": "12345678"}),
cleanLock: "12345678",
},
{
name: "JsonStringWithSKey",
lock: createJsonString(map[string]any{"S": "12345678", "F": 4, "E": 2, "C": "", "P": "3453345345346", "M": "12345678"}),
cleanLock: "12345678",
},
{
name: "PlainString",
lock: "12345678",
cleanLock: "12345678",
},
{
name: "JsonStringUnknownFormat",
lock: createJsonString(map[string]any{"A": "12345678", "F": 4, "E": 2, "C": "", "P": "3453345345346", "X": "12345678"}),
cleanLock: `{"A":"12345678","C":"","E":2,"F":4,"P":"3453345345346","X":"12345678"}`,
},
{
name: "InvalidJsonString",
lock: `"A":"12345678","C":"","E":2,"F":4,"P":"3453345345346","X":"12345678"}`,
cleanLock: `"A":"12345678","C":"","E":2,"F":4,"P":"3453345345346","X":"12345678"}`,
},
{
name: "EmptyString",
lock: "",
cleanLock: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
lockParser := &LegacyLockParser{}
lock := lockParser.ParseLock(test.lock)
assert.Equal(t, test.cleanLock, lock)
})
}
}
func TestNoopLockParser(t *testing.T) {
tests := []struct {
name string
lock string
}{
{
name: "PlainString",
lock: "123",
},
{
name: "EmptyString",
lock: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
lockParser := &NoopLockParser{}
lock := lockParser.ParseLock(test.lock)
assert.Equal(t, test.lock, lock)
})
}
}
func createJsonString(input map[string]any) string {
rawData, err := json.Marshal(&input)
if err != nil {
return ""
}
return string(rawData)
}