Skip to content

Commit 1746f23

Browse files
authored
Merge pull request #105 from drduh/04aug26
wall metadata, pin tls 1.3
2 parents 1b80419 + f278411 commit 1746f23

32 files changed

Lines changed: 426 additions & 192 deletions

README.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,13 @@ Get [random values](https://github.com/drduh/gone/blob/main/util/random.go) of c
183183

184184
```bash
185185
curl 127.0.0.1:8080/random/
186-
187186
curl 127.0.0.1:8080/random/coin
188-
189187
curl 127.0.0.1:8080/random/hex
190-
191188
curl 127.0.0.1:8080/random/id
192-
193189
curl 127.0.0.1:8080/random/mask
194-
195190
curl 127.0.0.1:8080/random/name
196-
197191
curl 127.0.0.1:8080/random/nato
198-
199192
curl 127.0.0.1:8080/random/number
200-
201193
curl 127.0.0.1:8080/random/pass
202194
```
203195

@@ -244,11 +236,8 @@ Tests and lint are validated with a [workflow](https://github.com/drduh/gone/blo
244236

245237
```bash
246238
make lint
247-
248239
make test
249-
250240
make test-verbose
251-
252241
make test-race
253242
```
254243

@@ -266,14 +255,12 @@ On macOS, using [apple/container](https://github.com/apple/container):
266255

267256
```bash
268257
make build-container
269-
270258
make run-container
271259
```
272260

273261
Get the server IP address:
274262

275263
```bash
276264
container ls | grep gone | grep --color --text -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"
277-
278265
curl 192.168.64.3:8080
279266
```

assets/style.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,20 @@ form {
9191
}
9292

9393
.itemMeta::selection,
94-
.itemName::selection {
94+
.itemName::selection,
95+
.wallMeta::selection {
9596
background-color: var(--fg-light);
9697
color: var(--bg-dark);
9798
}
9899

100+
.wallMeta {
101+
color: var(--fg-norm);
102+
cursor: pointer;
103+
font-family: ui-monospace, monospace;
104+
font-size: 0.6em;
105+
margin: 0;
106+
}
107+
99108
footer {
100109
flex-shrink: 0;
101110
color: var(--fg-norm);

handlers/auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func isAuthenticated(app *config.App, r *http.Request) bool {
9393
app.Upload: app.Require.Upload,
9494
app.UserInfo: app.Require.UserInfo,
9595
app.UserRemask: app.Require.UserRemask,
96-
app.Wall: app.Require.Wall,
96+
app.WallModify: app.Require.Wall,
9797
}
9898

9999
path := strings.TrimSuffix(r.Pattern, "{$}")

handlers/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package handlers
44

55
const (
66
formFieldClear = "clear"
7+
formFieldDownload = "download"
78
formFieldDownloads = "downloads"
89
formFieldDuration = "duration"
910
formFieldMessage = "message"

handlers/form.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import (
1111

1212
// parseFormInt reads an integer form value or returns the default.
1313
func parseFormInt(r *http.Request, field string, def, maximum int) int {
14+
if maximum <= 0 {
15+
return 0
16+
}
17+
if def < 0 {
18+
def = 0
19+
}
20+
if def > maximum {
21+
def = maximum
22+
}
23+
1424
input := strings.TrimSpace(r.FormValue(field))
1525
if input == "" {
1626
return def

handlers/form_test.go

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,36 @@ func TestParseFormInt(t *testing.T) {
1616
maximum := 100
1717

1818
cases := []struct {
19-
name string
20-
query string
21-
field string
22-
def int
23-
want int
24-
maximum int
19+
name string
20+
query string
21+
want int
2522
}{
26-
{"valid", "/?downloads=5", "downloads",
27-
def, 5, maximum},
28-
{"space", "/?downloads= 5 ", "downloads",
29-
def, 5, maximum},
30-
{"missing", "/", "downloads",
31-
def, 1, maximum},
32-
{"invalid", "/?downloads=none", "downloads",
33-
def, 1, maximum},
34-
{"zero", "/?downloads=0", "downloads",
35-
def, def, maximum},
36-
{"negative", "/?downloads=-1", "downloads",
37-
def, def, maximum},
38-
{"fraction", "/?downloads=3.5", "downloads",
39-
def, def, maximum},
40-
{"large", "/?downloads=101", "downloads",
41-
def, maximum, maximum},
23+
{"valid", "/?downloads=5", 5},
24+
{"space", "/?downloads= 5 ", 5},
25+
{"unencoded", "/?downloads=+5", 5},
26+
{"encoded", "/?downloads=%2B5", 5},
27+
{"leading-zeros", "/?downloads=005", 5},
28+
{"padded", "/?downloads=%C2%A05%C2%A0", 5},
29+
{"missing", "/", def},
30+
{"invalid", "/?downloads=none", def},
31+
{"empty", "/?downloads=", def},
32+
{"zero", "/?downloads=0", def},
33+
{"negative", "/?downloads=-1", def},
34+
{"fraction", "/?downloads=3.5", def},
35+
{"hex", "/?downloads=0x5", def},
36+
{"trailing", "/?downloads=5abc", def},
37+
{"leading", "/?downloads=abc5", def},
38+
{"non-ascii", "/?downloads=%EF%BC%95", def},
39+
{"exceed max", "/?downloads=1000", maximum},
40+
{"underscore", "/?downloads=1_000", def},
41+
{"with-space", "/?downloads=1 000", def},
42+
{"only-spaces", "/?downloads= ", def},
43+
{"empty-duplicate", "/?downloads=&downloads=5", def},
44+
{"valid-duplicate", "/?downloads=5&downloads=10", 5},
45+
{"upper-case", "/?Downloads=5", def},
46+
{"multiple", "/?duration=5m&downloads=10", 10},
4247
{"xlarge", "/?downloads=999999999999999999999",
43-
"downloads", def, def, maximum}, // overflows int64
48+
def}, // overflows int64
4449
}
4550

4651
for _, tc := range cases {
@@ -52,7 +57,8 @@ func TestParseFormInt(t *testing.T) {
5257
if err != nil {
5358
t.Fatal(err)
5459
}
55-
got := parseFormInt(req, tc.field, tc.def, tc.maximum)
60+
got := parseFormInt(
61+
req, formFieldDownloads, def, maximum)
5662
if got != tc.want {
5763
t.Fatalf("parseFormInt(%q) = %d; want %d",
5864
tc.query, got, tc.want)
@@ -69,37 +75,58 @@ func TestParseFormDuration(t *testing.T) {
6975
maximum := 8 * 24 * time.Hour
7076

7177
cases := []struct {
72-
name string
73-
query string
74-
field string
75-
def time.Duration
76-
want time.Duration
77-
maximum time.Duration
78+
name string
79+
query string
80+
want time.Duration
7881
}{
79-
{"valid", "/?duration=1h30m", "duration",
80-
def, 90 * time.Minute, maximum},
81-
{"space", "/?duration= 15m ", "duration",
82-
def, 15 * time.Minute, maximum},
83-
{"missing", "/", "duration",
84-
def, def, maximum},
85-
{"invalid", "/?duration=none", "duration",
86-
def, def, maximum},
87-
{"zero", "/?duration=0s", "duration",
88-
def, def, maximum},
89-
{"negative", "/?duration=-1h", "duration",
90-
def, def, maximum},
91-
{"fraction", "/?duration=1.5h", "duration",
92-
def, 90 * time.Minute, maximum},
93-
{"no-unit", "/?duration=3333", "duration",
94-
def, def, maximum},
95-
{"bad-unit", "/duration=8h", "duration",
96-
def, def, maximum},
97-
{"large", "/?duration=9999h", "duration",
98-
def, maximum, maximum},
99-
{"xlarge", "/?duration=99999999999h", "duration",
100-
def, def, maximum}, // overflows int64
101-
{"encoded", "/?duration=%32%34%68", "duration",
102-
def, 24 * time.Hour, maximum}, // "24h" encoded
82+
{"valid", "/?duration=1h30m", 90 * time.Minute},
83+
{"space", "/?duration= 15m ", 15 * time.Minute},
84+
{"missing", "/", def},
85+
{"invalid", "/?duration=none", def},
86+
{"zero", "/?duration=0s", def},
87+
{"negative", "/?duration=-1h", def},
88+
{"fraction", "/?duration=1.5h", 90 * time.Minute},
89+
{"no-unit", "/?duration=3333", def},
90+
{"bad-unit", "/duration=8h", def},
91+
{"large", "/?duration=9999h", maximum},
92+
{"xlarge", "/?duration=99999999999h",
93+
def}, // overflows int64
94+
{"encoded", "/?duration=%32%34%68",
95+
24 * time.Hour}, // "24h" encoded
96+
{"encoded-plus",
97+
"/?duration=1h%2B30m", def}, // "1h+30m"
98+
{"unicode-microseconds",
99+
"/?duration=1500%C2%B5s", def}, // below 1s min
100+
{"microseconds",
101+
"/?duration=1500us", def}, // below 1s min
102+
{"leading-decimal",
103+
"/?duration=.5s", def}, // below 1s min
104+
{"overflow-boundary",
105+
"/?duration=2562047h47m16.854775807s", maximum},
106+
{"overflow-one-nanosecond",
107+
"/?duration=2562047h47m16.854775808s", def},
108+
{"tabs-and-newlines",
109+
"/?duration=%09%0A15m%0D%0A", 15 * time.Minute},
110+
{"plus-as-space",
111+
"/?duration=+15m+", 15 * time.Minute},
112+
{"duplicate-first-valid",
113+
"/?duration=15m&duration=2h", 15 * time.Minute},
114+
{"duplicate-first-invalid",
115+
"/?duration=invalid&duration=15m", def},
116+
{"compound-fraction",
117+
"/?duration=1h0.5m", time.Hour + 30*time.Second},
118+
{"minimum", "/?duration=1s", time.Second},
119+
{"below-minimum", "/?duration=999ms", def},
120+
{"subsecond", "/?duration=1ns", def},
121+
{"at-maximum", "/?duration=192h", maximum},
122+
{"case-sensitive-unit", "/?duration=15M", def},
123+
{"just-over-maximum", "/?duration=192h1ns", maximum},
124+
{"unsupported-days", "/?duration=1d", def},
125+
{"plus-zero", "/?duration=+0s", def},
126+
{"negative-zero", "/?duration=-0s", def},
127+
{"mixed-sign", "/?duration=1h-30m", def},
128+
{"embedded-nul", "/?duration=15m%00ignored", def},
129+
{"html", "/?duration=%3Cscript%3Ealert(1)%3C%2Fscript%3E", def},
103130
}
104131

105132
for _, tc := range cases {
@@ -112,8 +139,8 @@ func TestParseFormDuration(t *testing.T) {
112139
t.Fatal(err)
113140
}
114141

115-
got := parseFormDuration(req, tc.field, tc.def,
116-
settings.Duration{Duration: tc.maximum})
142+
got := parseFormDuration(req, formFieldDuration, def,
143+
settings.Duration{Duration: maximum})
117144
if got != tc.want {
118145
t.Fatalf("parseFormDuration(%q) = %v; want %v",
119146
tc.query, got, tc.want)

handlers/message.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func MessageAdd(app *config.App) http.HandlerFunc {
6060

6161
app.CountMessages()
6262

63-
msgLength := len(formContent)
63+
msgLength := charCount(formContent)
6464
if msgLength > app.MessageLimits.LengthChars {
6565
writeJSON(w, http.StatusBadRequest,
6666
errorJSON(app.MsgLength))

handlers/routes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func Routes(app *config.App) map[string]http.HandlerFunc {
3131
app.MessageGet: MessageGet(app),
3232

3333
// Wall
34-
app.Wall: Wall(app),
34+
app.WallModify: Wall(app),
3535

3636
// User request information
3737
app.UserInfo: UserInfo(app),

handlers/status.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func Status(app *config.App) http.HandlerFunc {
3333
Default: app.Default,
3434
Limit: app.Limit,
3535
Sizes: app.Sizes,
36+
WallMeta: app.WallMeta,
3637
}
3738

3839
app.Log.Info("serving status",

handlers/status_test.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ func TestStatus(t *testing.T) {
7171

7272
var gotAddr string
7373
if err := json.Unmarshal(
74-
response["addr"], &gotAddr); err != nil {
75-
t.Fatalf("decode addr: %v", err)
74+
response["serverAddr"], &gotAddr); err != nil {
75+
t.Fatalf("addr unavailable: %v", err)
7676
}
7777
if gotAddr != app.ServerAddr {
7878
t.Errorf("addr = %q; want %q",
@@ -81,8 +81,8 @@ func TestStatus(t *testing.T) {
8181

8282
var gotPort int
8383
if err := json.Unmarshal(
84-
response["port"], &gotPort); err != nil {
85-
t.Fatalf("decode port: %v", err)
84+
response["serverPort"], &gotPort); err != nil {
85+
t.Fatalf("port unavailable: %v", err)
8686
}
8787
if gotPort != app.ServerPort {
8888
t.Errorf("port = %d; want %d",
@@ -127,9 +127,16 @@ func TestStatus(t *testing.T) {
127127
t.Errorf("numMessages = %d; want 2",
128128
gotSizes.NumMessages)
129129
}
130-
if gotSizes.CharsWall != len(app.WallContent) {
131-
t.Errorf("charsWall = %d; want %d",
132-
gotSizes.CharsWall, len(app.WallContent))
130+
131+
var gotWall storage.WallMeta
132+
if err := json.Unmarshal(
133+
response["wallMeta"], &gotWall); err != nil {
134+
t.Fatalf("decode wall meta: %v", err)
135+
}
136+
137+
if gotWall.WallChars != len(app.WallContent) {
138+
t.Errorf("wallChars = %d; want %d",
139+
gotWall.WallChars, len(app.WallContent))
133140
}
134141
})
135142
}

0 commit comments

Comments
 (0)