completed update to SetAttachment (not yet tested)
This commit is contained in:
@@ -12,9 +12,12 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
argparse "github.com/alexflint/go-arg"
|
argparse "github.com/alexflint/go-arg"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -95,6 +98,11 @@ type AmConfig struct {
|
|||||||
} `yaml:"posting"`
|
} `yaml:"posting"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AmConfigComputed struct {
|
||||||
|
UploadMaxSize int32
|
||||||
|
UploadNoCompress map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
//go:embed default.yaml
|
//go:embed default.yaml
|
||||||
var defaultConfigData []byte
|
var defaultConfigData []byte
|
||||||
|
|
||||||
@@ -104,6 +112,9 @@ var defaultConfig AmConfig
|
|||||||
// GlobalConfig holds the global configuration.
|
// GlobalConfig holds the global configuration.
|
||||||
var GlobalConfig AmConfig
|
var GlobalConfig AmConfig
|
||||||
|
|
||||||
|
// GlobalComputedConfig holds the computed values based on GlobalConfig.
|
||||||
|
var GlobalComputedConfig AmConfigComputed
|
||||||
|
|
||||||
// init prepares the default configuration for the application.
|
// init prepares the default configuration for the application.
|
||||||
func init() {
|
func init() {
|
||||||
if err := yaml.Unmarshal(defaultConfigData, &defaultConfig); err != nil {
|
if err := yaml.Unmarshal(defaultConfigData, &defaultConfig); err != nil {
|
||||||
@@ -125,6 +136,14 @@ func overlayString(loaded string, defaulted string) string {
|
|||||||
return loaded
|
return loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* overlayString is a helper that takes a loaded or defaulted string array and returns it. (It merges the two
|
||||||
|
* if two different arrays are specified.)
|
||||||
|
* Parameters:
|
||||||
|
* loaded - The array loaded from a configuration file.
|
||||||
|
* defaulted - The default value of this array.
|
||||||
|
* Returns:
|
||||||
|
* Merged version of the two arrays.
|
||||||
|
*/
|
||||||
func overlayStringArray(loaded, defaulted []string) []string {
|
func overlayStringArray(loaded, defaulted []string) []string {
|
||||||
m := make(map[string]bool)
|
m := make(map[string]bool)
|
||||||
for _, s := range defaulted {
|
for _, s := range defaulted {
|
||||||
@@ -191,6 +210,31 @@ func overlayConfig(dest *AmConfig, loaded *AmConfig, defaults *AmConfig) {
|
|||||||
dest.Posting.Uploads.NoCompressTypes = overlayStringArray(loaded.Posting.Uploads.NoCompressTypes, defaults.Posting.Uploads.NoCompressTypes)
|
dest.Posting.Uploads.NoCompressTypes = overlayStringArray(loaded.Posting.Uploads.NoCompressTypes, defaults.Posting.Uploads.NoCompressTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseDataSize converts the data size in bytes, kilobytes, megabytes, or gigabytes to a number value.
|
||||||
|
func parseDataSize(s string) (int32, error) {
|
||||||
|
re, err := regexp.Compile(`^\s*(\d+)\s*([KkMmGg]?)[Bb]?`)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
m := re.FindStringSubmatch(s)
|
||||||
|
if m == nil {
|
||||||
|
return -1, errors.New("invalid value spacified")
|
||||||
|
}
|
||||||
|
rc, err := strconv.Atoi(m[1])
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
switch m[2] {
|
||||||
|
case "k", "K":
|
||||||
|
rc *= 1024
|
||||||
|
case "m", "M":
|
||||||
|
rc *= (1024 * 1024)
|
||||||
|
case "g", "G":
|
||||||
|
rc *= (1024 * 1024 * 1024)
|
||||||
|
}
|
||||||
|
return int32(rc), nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetupConfig loads the command line arguments, loads the config file, and prepares GlobalConfig.
|
// SetupConfig loads the command line arguments, loads the config file, and prepares GlobalConfig.
|
||||||
func SetupConfig() {
|
func SetupConfig() {
|
||||||
argparse.MustParse(&CommandLine)
|
argparse.MustParse(&CommandLine)
|
||||||
@@ -209,4 +253,15 @@ func SetupConfig() {
|
|||||||
} else {
|
} else {
|
||||||
GlobalConfig = defaultConfig // just copy over the defaults
|
GlobalConfig = defaultConfig // just copy over the defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute additional values.
|
||||||
|
tmp, err := parseDataSize(GlobalConfig.Posting.Uploads.MaxSize)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
GlobalComputedConfig.UploadMaxSize = tmp
|
||||||
|
GlobalComputedConfig.UploadNoCompress = make(map[string]bool)
|
||||||
|
for _, s := range GlobalConfig.Posting.Uploads.NoCompressTypes {
|
||||||
|
GlobalComputedConfig.UploadNoCompress[s] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-3
@@ -10,10 +10,14 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.erbosoft.com/amy/amsterdam/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PostHeader represents the "header" of a post, everything except for its text and attachment.
|
// PostHeader represents the "header" of a post, everything except for its text and attachment.
|
||||||
@@ -115,9 +119,33 @@ func (p *PostHeader) SetAttachment(ctx context.Context, u *User, fileName string
|
|||||||
if ai != nil {
|
if ai != nil {
|
||||||
return errors.New("attachment already present for this post")
|
return errors.New("attachment already present for this post")
|
||||||
}
|
}
|
||||||
// TODO
|
if length > config.GlobalComputedConfig.UploadMaxSize {
|
||||||
_, err = amdb.ExecContext(ctx, "INSERT INTO postattach (postid, datalen, filename, mimetype, data) VALUES (?, ?, ?, ?, ?)",
|
return fmt.Errorf("file too large to be attached; maximum size is %s", config.GlobalConfig.Posting.Uploads.MaxSize)
|
||||||
p.PostId, length, fileName, mimeType, data)
|
}
|
||||||
|
|
||||||
|
// Compress the data with GZIP if we need to.
|
||||||
|
var stgmethod int16
|
||||||
|
var realData []byte
|
||||||
|
if _, ok := config.GlobalComputedConfig.UploadNoCompress[mimeType]; ok {
|
||||||
|
realData = data
|
||||||
|
stgmethod = stgMethodPlain
|
||||||
|
} else {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := gzip.NewWriter(buf)
|
||||||
|
_, err := w.Write(data)
|
||||||
|
if err == nil {
|
||||||
|
err = w.Close()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
realData = buf.Bytes()
|
||||||
|
stgmethod = stgMethodGZIP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the database.
|
||||||
|
_, err = amdb.ExecContext(ctx, "INSERT INTO postattach (postid, datalen, filename, mimetype, stgmethod, data) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
|
p.PostId, length, fileName, mimeType, stgmethod, realData)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user