mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 22:37:28 +00:00
fix(nntpd): support open-ended NNTP ranges in XOVER/OVER
parseRange split the spec on '-' and required BOTH bounds to parse as
integers. For a valid open-ended range like '5-' (RFC 3977 6.2.3 / RFC 2980
XOVER: article 5 through the last) strconv.ParseInt('') fails, so parseRange
returned (0, 0) and handleOver asked the backend for articles in [0, 0] —
zero rows. '-10' (first..10) was likewise broken.
Treat an empty bound as the extreme (low 0 / high MaxInt64) while still
returning an empty range for genuinely malformed specs. Add table-driven
tests for the open-ended and malformed forms.
This commit is contained in:
parent
43dbdf0e06
commit
5fba77f295
2 changed files with 48 additions and 13 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
package nntpd
|
package nntpd
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestParseRangeSingleArticle(t *testing.T) {
|
func TestParseRangeSingleArticle(t *testing.T) {
|
||||||
low, high := parseRange("5")
|
low, high := parseRange("5")
|
||||||
|
|
@ -8,3 +11,27 @@ func TestParseRangeSingleArticle(t *testing.T) {
|
||||||
t.Fatalf(`parseRange("5") = %d, %d; want 5, 5`, low, high)
|
t.Fatalf(`parseRange("5") = %d, %d; want 5, 5`, low, high)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseRange(t *testing.T) {
|
||||||
|
// spec -> (low, high). Empty bounds mean the extreme; malformed -> (0, 0).
|
||||||
|
cases := []struct {
|
||||||
|
spec string
|
||||||
|
low int64
|
||||||
|
high int64
|
||||||
|
}{
|
||||||
|
{"5", 5, 5},
|
||||||
|
{"5-10", 5, 10},
|
||||||
|
{"5-", 5, math.MaxInt64},
|
||||||
|
{"-10", 0, 10},
|
||||||
|
{"", 0, math.MaxInt64},
|
||||||
|
{"abc", 0, 0},
|
||||||
|
{"5-abc", 0, 0},
|
||||||
|
{"abc-10", 0, 0},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
low, high := parseRange(c.spec)
|
||||||
|
if low != c.low || high != c.high {
|
||||||
|
t.Errorf("parseRange(%q) = %d, %d; want %d, %d", c.spec, low, high, c.low, c.high)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,27 +165,35 @@ func (s *Server) Process(nc net.Conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseRange parses an NNTP article range spec (RFC 3977 §6.2.3 / RFC 2980).
|
||||||
|
// An empty bound means "the extreme": "5-" is article 5 through the last
|
||||||
|
// article, "-10" is the first article through 10, "5-10" is 5..10, "5" is the
|
||||||
|
// single article 5, and "" is all articles. A genuinely malformed bound yields
|
||||||
|
// an empty range (0, 0).
|
||||||
func parseRange(spec string) (low, high int64) {
|
func parseRange(spec string) (low, high int64) {
|
||||||
if spec == "" {
|
if spec == "" {
|
||||||
return 0, math.MaxInt64
|
return 0, math.MaxInt64
|
||||||
}
|
}
|
||||||
parts := strings.Split(spec, "-")
|
parts := strings.SplitN(spec, "-", 2)
|
||||||
if len(parts) == 1 {
|
low, high = 0, math.MaxInt64
|
||||||
h, err := strconv.ParseInt(parts[0], 10, 64)
|
if parts[0] != "" {
|
||||||
|
v, err := strconv.ParseInt(parts[0], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0 // malformed — empty range instead of all articles
|
return 0, 0 // malformed low bound — empty range
|
||||||
}
|
}
|
||||||
return h, h
|
low = v
|
||||||
}
|
}
|
||||||
l, err := strconv.ParseInt(parts[0], 10, 64)
|
if len(parts) == 1 { // single article, e.g. "5"
|
||||||
|
return low, low
|
||||||
|
}
|
||||||
|
if parts[1] != "" {
|
||||||
|
v, err := strconv.ParseInt(parts[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0 // malformed — empty range
|
return 0, 0 // malformed high bound — empty range
|
||||||
}
|
}
|
||||||
h, err := strconv.ParseInt(parts[1], 10, 64)
|
high = v
|
||||||
if err != nil {
|
|
||||||
return 0, 0 // malformed — empty range
|
|
||||||
}
|
}
|
||||||
return l, h
|
return low, high
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleOver(args []string, s *session, c *textproto.Conn) error {
|
func handleOver(args []string, s *session, c *textproto.Conn) error {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue