diff --git a/docs/advanced.rst b/docs/advanced.rst index ddb99aa..1598eff 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -91,6 +91,8 @@ General +---------------------+--------------------------------------------------------------------------------------+-------------+-----------------------------------+-------------------------------+ | GOKAPI_LENGTH_ID | Sets the length of the download IDs. Value needs to be 5 or more | Yes | 15 | No | +---------------------+--------------------------------------------------------------------------------------+-------------+-----------------------------------+-------------------------------+ +| GOKAPI_MAX_FILESIZE | Sets the maximum allowed file size in MB | Yes | 102400 (100GB) | No | ++---------------------+--------------------------------------------------------------------------------------+-------------+-----------------------------------+-------------------------------+ \*Variables that are persistent must be submitted during the first start when Gokapi creates a new config file. They can be omitted afterwards. Non-persistent variables need to be set on every start. diff --git a/internal/configuration/Configuration.go b/internal/configuration/Configuration.go index 6b1295a..9092508 100644 --- a/internal/configuration/Configuration.go +++ b/internal/configuration/Configuration.go @@ -33,7 +33,7 @@ var Environment environment.Environment var serverSettings Configuration // Version of the configuration structure. Used for upgrading -const currentConfigVersion = 7 +const currentConfigVersion = 8 // For locking this object to prevent race conditions var mutex sync.RWMutex @@ -60,6 +60,7 @@ type Configuration struct { DataDir string `json:"DataDir"` MaxMemory int `json:"MaxMemory"` UseSsl bool `json:"UseSsl"` + MaxFileSizeMB int `json:"MaxFileSizeMB"` } // Load loads the configuration or creates the folder structure and a default configuration @@ -149,6 +150,10 @@ func updateConfig() { serverSettings.UseSsl = true } } + // < v1.3.1 + if serverSettings.ConfigVersion < 8 { + serverSettings.MaxFileSizeMB = Environment.MaxFileSize + } if serverSettings.ConfigVersion < currentConfigVersion { fmt.Println("Successfully upgraded database") @@ -202,6 +207,7 @@ func generateDefaultConfig() { DataDir: Environment.DataDir, LengthId: Environment.LengthId, UseSsl: useSsl, + MaxFileSizeMB: Environment.MaxFileSize, } save() } diff --git a/internal/configuration/Configuration_test.go b/internal/configuration/Configuration_test.go index fbb6edc..fa184d9 100644 --- a/internal/configuration/Configuration_test.go +++ b/internal/configuration/Configuration_test.go @@ -79,6 +79,7 @@ func TestCreateNewConfig(t *testing.T) { test.IsEqualInt(t, len(serverSettings.SaltAdmin), 30) test.IsEqualInt(t, serverSettings.MaxMemory, 20) test.IsNotEqualString(t, serverSettings.SaltAdmin, "eefwkjqweduiotbrkl##$2342brerlk2321") + test.IsEqualInt(t, serverSettings.MaxFileSizeMB, 102400) os.Unsetenv("GOKAPI_USERNAME") os.Unsetenv("GOKAPI_PASSWORD") os.Unsetenv("GOKAPI_PORT") @@ -91,6 +92,7 @@ func TestCreateNewConfig(t *testing.T) { func TestUpgradeDb(t *testing.T) { testconfiguration.WriteUpgradeConfigFile() os.Setenv("GOKAPI_USE_SSL", "true") + os.Setenv("GOKAPI_MAX_FILESIZE", "5") Load() test.IsEqualString(t, serverSettings.SaltAdmin, "eefwkjqweduiotbrkl##$2342brerlk2321") test.IsEqualString(t, serverSettings.SaltFiles, "P1UI5sRNDwuBgOvOYhNsmucZ2pqo4KEvOoqqbpdu") @@ -102,7 +104,9 @@ func TestUpgradeDb(t *testing.T) { test.IsEqualString(t, serverSettings.Files["MgXJLe4XLfpXcL12ec4i"].ContentType, "application/octet-stream") test.IsEqualInt(t, serverSettings.ConfigVersion, currentConfigVersion) test.IsEqualBool(t, serverSettings.UseSsl, true) + test.IsEqualInt(t, serverSettings.MaxFileSizeMB, 5) os.Unsetenv("GOKAPI_USE_SSL") + os.Unsetenv("GOKAPI_MAX_FILESIZE") testconfiguration.Create(false) Load() } diff --git a/internal/environment/Environment.go b/internal/environment/Environment.go index 8e1520b..608b3fb 100644 --- a/internal/environment/Environment.go +++ b/internal/environment/Environment.go @@ -35,6 +35,7 @@ type Environment struct { AwsKeyId string AwsKeySecret string AwsEndpoint string + MaxFileSize int } // IsAwsProvided returns true if all required env variables have been set for using AWS S3 / Backblaze @@ -51,6 +52,7 @@ var defaultValues = defaultsEnvironment{ DATA_DIR: "data", LENGTH_ID: 15, MAX_MEMORY_UPLOAD_MB: 20, + MAX_FILESIZE: 102400, // 100GB } // New parses the env variables @@ -80,6 +82,7 @@ func New() Environment { AwsKeyId: envString("AWS_KEY"), AwsKeySecret: envString("AWS_KEY_SECRET"), AwsEndpoint: envString("AWS_ENDPOINT"), + MaxFileSize: envInt("MAX_FILESIZE", 1), } } @@ -151,4 +154,5 @@ type defaultsEnvironment struct { SALT_FILES string LENGTH_ID int MAX_MEMORY_UPLOAD_MB int + MAX_FILESIZE int } diff --git a/internal/storage/FileServing.go b/internal/storage/FileServing.go index 9679bc1..44550e9 100644 --- a/internal/storage/FileServing.go +++ b/internal/storage/FileServing.go @@ -14,6 +14,7 @@ import ( "bytes" "crypto/sha1" "encoding/hex" + "errors" "fmt" "io" "io/ioutil" @@ -31,6 +32,12 @@ import ( // it into the global configuration. func NewFile(fileContent io.Reader, fileHeader *multipart.FileHeader, uploadRequest models.UploadRequest) (models.File, error) { id := helper.GenerateRandomString(configuration.GetLengthId()) + settings := configuration.GetServerSettingsReadOnly() + maxSize := settings.MaxFileSizeMB + configuration.ReleaseReadOnly() + if fileHeader.Size > int64(maxSize)*1014*1024 { + return models.File{}, errors.New("upload limit exceeded") + } var hasBeenRenamed bool reader, hash, tempFile := generateHash(fileContent, fileHeader, uploadRequest) defer deleteTempFile(tempFile, &hasBeenRenamed) @@ -49,7 +56,7 @@ func NewFile(fileContent io.Reader, fileHeader *multipart.FileHeader, uploadRequ if aws.IsAvailable() { aws.AddBucketName(&file) } - settings := configuration.GetServerSettings() + settings = configuration.GetServerSettings() filename := settings.DataDir + "/" + file.SHA256 dataDir := settings.DataDir settings.Files[id] = file diff --git a/internal/storage/FileServing_test.go b/internal/storage/FileServing_test.go index 1e5f174..0c9992d 100644 --- a/internal/storage/FileServing_test.go +++ b/internal/storage/FileServing_test.go @@ -154,6 +154,28 @@ func TestNewFile(t *testing.T) { test.IsEqualString(t, file.Size, "20.0 MB") testconfiguration.DisableS3() } + + createBigFile("bigfile", 30) + bigFile, _ = os.Open("bigfile") + mimeHeader = make(textproto.MIMEHeader) + mimeHeader.Set("Content-Disposition", "form-data; name=\"file\"; filename=\"bigfile\"") + mimeHeader.Set("Content-Type", "application/binary") + header = multipart.FileHeader{ + Filename: "bigfile", + Header: mimeHeader, + Size: int64(30) * 1024 * 1024, + } + request = models.UploadRequest{ + AllowedDownloads: 1, + Expiry: 999, + ExpiryTimestamp: 2147483600, + MaxMemory: 10, + DataDir: "test/data", + } + file, err = NewFile(bigFile, &header, request) + test.IsNotNil(t, err) + bigFile.Close() + os.Remove("bigfile") } func TestServeFile(t *testing.T) { diff --git a/internal/test/testconfiguration/TestConfiguration.go b/internal/test/testconfiguration/TestConfiguration.go index 3e1c945..46bec58 100644 --- a/internal/test/testconfiguration/TestConfiguration.go +++ b/internal/test/testconfiguration/TestConfiguration.go @@ -294,7 +294,8 @@ var configTestFile = []byte(`{ "SaltFiles":"lL5wMTtnVCn5TPbpRaSe4vAQodWW0hgk00WCZE", "LengthId":20, "DataDir":"test/data", - "UseSsl":false + "UseSsl":false, + "MaxFileSizeMB":25 }`) var configUpgradeTestFile = []byte(`{ diff --git a/internal/webserver/Webserver.go b/internal/webserver/Webserver.go index 42066cc..736f17f 100644 --- a/internal/webserver/Webserver.go +++ b/internal/webserver/Webserver.go @@ -357,6 +357,7 @@ type UploadView struct { IsAdminView bool IsMainView bool IsApiView bool + MaxFileSize int } // Converts the globalConfig variable to an UploadView struct to pass the infos to @@ -401,6 +402,7 @@ func (u *UploadView) convertGlobalConfig(isMainView bool) *UploadView { u.TimeNow = time.Now().Unix() u.IsAdminView = true u.IsMainView = isMainView + u.MaxFileSize = settings.MaxFileSizeMB configuration.ReleaseReadOnly() return u } diff --git a/internal/webserver/web/templates/html_admin.tmpl b/internal/webserver/web/templates/html_admin.tmpl index ae8ecdd..00f9e10 100644 --- a/internal/webserver/web/templates/html_admin.tmpl +++ b/internal/webserver/web/templates/html_admin.tmpl @@ -71,6 +71,9 @@ + {{ template "footer" }}