Link to source

This commit is contained in:
2026-09-13 12:38:22 +02:00
parent 000f9d6984
commit 27be685834
5 changed files with 108 additions and 1 deletions
+23
View File
@@ -19,6 +19,11 @@ type Config struct {
BasePath string // normalised: always "/" or "/prefix/"
PublicURL string // absolute origin+path for generated links; "" => relative
// SourceURL is linked in the footer. It defaults to where this program is
// developed, and a fork should point it at its own; setting it empty drops
// the footer entirely, for an instance that would rather not advertise.
SourceURL string
MaxSize int64 // per-upload cap; Unlimited means no cap
MaxExpiry time.Duration // longest lifetime a caller may request
DefaultExpiry time.Duration // lifetime when the caller does not ask
@@ -37,6 +42,11 @@ type Config struct {
const EnvPrefix = "UNCENSORED_SEND_"
// defaultSourceURL is where this program is developed. Anyone running a
// modified copy should say so with --source-url, and anyone who would rather
// not mention it at all can pass an empty one.
const defaultSourceURL = "https://git.uncensored.hu/thayol/uncensored-send"
// Register wires every option onto s. Short forms exist only for the options
// reached often; everything else is long-only, by design.
func (c *Config) Register(s *Set) {
@@ -50,6 +60,8 @@ func (c *Config) Register(s *Set) {
"path prefix this service is mounted under")
s.String(&c.PublicURL, "public-url", "u", "", "URL",
"absolute base URL used in generated links; relative links when empty")
s.String(&c.SourceURL, "source-url", "", defaultSourceURL, "URL",
"where the footer's source link points; empty hides the footer")
s.Size(&c.MaxSize, "max-size", "s", "2GiB",
"largest upload accepted from an anonymous caller")
@@ -110,6 +122,17 @@ func (c *Config) Normalise() error {
c.PublicURL = strings.TrimSuffix(u.String(), "/")
}
if c.SourceURL != "" {
u, err := url.Parse(c.SourceURL)
if err != nil {
return fmt.Errorf("--source-url: %w", err)
}
if !u.IsAbs() {
return fmt.Errorf("--source-url: %q is not absolute", c.SourceURL)
}
c.SourceURL = u.String()
}
if c.TokensPath == "" {
c.TokensPath = c.DataDir + "/tokens.json"
}
+37
View File
@@ -156,6 +156,43 @@ func TestParseRefusesStrayArguments(t *testing.T) {
}
}
// The source link is a URL someone will set by hand on a fork, so a value that
// would render a broken link has to be refused at startup rather than shipped
// to every page.
func TestSourceURLMustBeAbsoluteOrEmpty(t *testing.T) {
base := func() Config {
c := Config{}
fs := NewSet("test", "UNCENSORED_SEND_TEST_")
c.Register(fs)
if err := fs.Parse(nil); err != nil {
t.Fatal(err)
}
return c
}
c := base()
if err := c.Normalise(); err != nil {
t.Fatalf("the default source URL was refused: %v", err)
}
if c.SourceURL == "" {
t.Error("the default build links no source at all")
}
c = base()
c.SourceURL = ""
if err := c.Normalise(); err != nil {
t.Errorf("switching the source link off was refused: %v", err)
}
for _, bad := range []string{"not a url", "/relative/path", "example.org/repo"} {
c = base()
c.SourceURL = bad
if err := c.Normalise(); err == nil {
t.Errorf("--source-url %q was accepted", bad)
}
}
}
// The convention is: one hyphen for a letter, two for a word. It is enforced
// here because the stdlib flag package treats both forms as the same.
func TestHyphenConvention(t *testing.T) {