[MM-54288] Support Packet V2 (#29403)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
091d1bba8b
Коммит
8d4bf4bae0
@@ -6,6 +6,8 @@ package utils
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CommonBaseSearchPaths() []string {
|
||||
@@ -111,3 +113,25 @@ func FindDirRelBinary(dir string) (string, bool) {
|
||||
}
|
||||
return found, true
|
||||
}
|
||||
|
||||
// Valid characters are: alphanumeric, dash, underscore
|
||||
var safeFileNameRegex = regexp.MustCompile(`[^\w\-\_]`)
|
||||
|
||||
// SanitizeFileName takes a string and returns a safe file name without an extension.
|
||||
func SanitizeFileName(input string) string {
|
||||
// Trim leading or trailing dots or spaces
|
||||
safeName := strings.Trim(input, ". ")
|
||||
// Replace dots with nothing
|
||||
safeName = strings.ReplaceAll(safeName, ".", "")
|
||||
|
||||
// Replace all invalid characters with an underscore
|
||||
safeName = safeFileNameRegex.ReplaceAllString(safeName, "_")
|
||||
|
||||
// Limit length
|
||||
const maxLength = 100
|
||||
if len(safeName) > maxLength {
|
||||
safeName = safeName[:maxLength]
|
||||
}
|
||||
|
||||
return safeName
|
||||
}
|
||||
|
||||
@@ -7,12 +7,69 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSanitizeFileName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "normal characters",
|
||||
input: "normal-file_name",
|
||||
expected: "normal-file_name",
|
||||
},
|
||||
{
|
||||
name: "special characters",
|
||||
input: "file*name@#$",
|
||||
expected: "file_name___",
|
||||
},
|
||||
{
|
||||
name: "spaces",
|
||||
input: "my file name",
|
||||
expected: "my_file_name",
|
||||
},
|
||||
{
|
||||
name: "leading/trailing dots and spaces",
|
||||
input: " .filename. ",
|
||||
expected: "filename",
|
||||
},
|
||||
{
|
||||
name: "very long filename",
|
||||
input: strings.Repeat("a", 150) + ".txt",
|
||||
expected: strings.Repeat("a", 100),
|
||||
},
|
||||
{
|
||||
name: "unicode characters",
|
||||
input: "résumé",
|
||||
expected: "r_sum_",
|
||||
},
|
||||
{
|
||||
name: "german umlaute",
|
||||
input: "äëïöüß",
|
||||
expected: "______",
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := SanitizeFileName(tt.input)
|
||||
assert.Equal(t, tt.expected, result, tt.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindFile(t *testing.T) {
|
||||
t.Run("files from various paths", func(t *testing.T) {
|
||||
// Create the following directory structure:
|
||||
|
||||
29
server/public/utils/timeutils/time.go
Обычный файл
29
server/public/utils/timeutils/time.go
Обычный файл
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package timeutils
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
RFC3339Milli = "2006-01-02T15:04:05.999Z07:00"
|
||||
)
|
||||
|
||||
func FormatMillis(millis int64) string {
|
||||
return time.UnixMilli(millis).Format(RFC3339Milli)
|
||||
}
|
||||
|
||||
func ParseFormatedMillis(s string) (millis int64, err error) {
|
||||
if s == "" {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
t, err := time.Parse(RFC3339Milli, s)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return t.UnixMilli(), nil
|
||||
}
|
||||
57
server/public/utils/timeutils/time_test.go
Обычный файл
57
server/public/utils/timeutils/time_test.go
Обычный файл
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package timeutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFormatMillis(t *testing.T) {
|
||||
t.Run("zero time", func(t *testing.T) {
|
||||
result := FormatMillis(0)
|
||||
// The concrete time depends on the timezone, so we can't test the exact time
|
||||
assert.Contains(t, result, "1970-01-01")
|
||||
assert.Contains(t, result, "00:00")
|
||||
})
|
||||
|
||||
t.Run("positive time", func(t *testing.T) {
|
||||
result := FormatMillis(1609459200000) // 2021-01-01 00:00:00 UTC
|
||||
assert.Contains(t, result, "2021-01-01")
|
||||
assert.Contains(t, result, "00:00")
|
||||
})
|
||||
|
||||
t.Run("negative time", func(t *testing.T) {
|
||||
result := FormatMillis(-1609459200000) // 1919-01-01 00:00:00 UTC
|
||||
assert.Contains(t, result, "1919-01-01")
|
||||
assert.Contains(t, result, "00:00")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseFormatedMillis(t *testing.T) {
|
||||
t.Run("empty string", func(t *testing.T) {
|
||||
result, err := ParseFormatedMillis("")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(0), result)
|
||||
})
|
||||
|
||||
t.Run("valid timestamp", func(t *testing.T) {
|
||||
result, err := ParseFormatedMillis("2021-01-01T00:00:00.000Z")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1609459200000), result)
|
||||
})
|
||||
|
||||
t.Run("invalid format", func(t *testing.T) {
|
||||
result, err := ParseFormatedMillis("2021-01-01")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, int64(0), result)
|
||||
})
|
||||
|
||||
t.Run("invalid date", func(t *testing.T) {
|
||||
result, err := ParseFormatedMillis("2021-13-01T00:00:00.000Z")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, int64(0), result)
|
||||
})
|
||||
}
|
||||
Ссылка в новой задаче
Block a user