Browse Source

fix: make date parse more exact (#514)

Co-authored-by: Jon Lundy <jon@xuu.cc>
Reviewed-on: #514
Co-authored-by: xuu <xuu@noreply@mills.io>
Co-committed-by: xuu <xuu@noreply@mills.io>
pull/516/head
xuu 3 months ago
committed by James Mills
parent
commit
3882134ebe
  1. 4
      types/lextwt/lextwt.go
  2. 3
      types/lextwt/lextwt_test.go
  3. 44
      types/lextwt/parser.go

4
types/lextwt/lextwt.go

@ -40,7 +40,7 @@ func ParseFile(r io.Reader, twter types.Twter) (types.TwtFile, error) {
f.comments = append(f.comments, e)
case *Twt:
if e.IsNil() {
log.Errorf("invalid feed or bad line parsing %#v", twter)
log.Errorf("invalid feed or bad line parsing %#v", twter.URL)
nErrors++
continue
}
@ -129,7 +129,7 @@ func ParseLine(line string, twter types.Twter) (twt types.Twt, err error) {
twt = parser.ParseTwt()
if twt.IsZero() {
return types.NilTwt, fmt.Errorf("Empty Twt: %s", line)
return types.NilTwt, fmt.Errorf("empty Twt: %s", line)
}
return twt, err

3
types/lextwt/lextwt_test.go

@ -212,6 +212,8 @@ func TestParseDateTime(t *testing.T) {
{lit: "2016-02-03T23:05", dt: time.Date(2016, 2, 3, 23, 5, 0, 0, time.UTC)},
{lit: "2016-02-03", errs: []error{lextwt.ErrParseToken}},
{lit: "2016", errs: []error{lextwt.ErrParseToken}},
{lit: "22021-02-03", errs: []error{lextwt.ErrParseToken}},
{lit: "2021-102-03", errs: []error{lextwt.ErrParseToken}},
}
for i, tt := range tests {
r := strings.NewReader(tt.lit)
@ -957,6 +959,7 @@ func TestParseFile(t *testing.T) {
# follows = xuu@txt.sour.is https://txt.sour.is/users/xuu.txt
2016-02-03T23:05:00Z @<example http://example.org/twtxt.txt>` + "\u2028" + `welcome to twtxt!
22016-0203 ignored
2020-12-02T01:04:00Z This is an OpenPGP proof that connects my OpenPGP key to this Twtxt account. See https://key.sour.is/id/me@sour.is for more.

[Verifying my OpenPGP key: openpgp4fpr:20AE2F310A74EA7CEC3AE69F8B3B0604F164E04F]
2020-11-13T16:13:22+01:00 @<prologic https://twtxt.net/user/prologic/twtxt.txt> (#<pdrsg2q https://twtxt.net/search?tag=pdrsg2q>) Thanks!
`),

44
types/lextwt/parser.go

@ -62,6 +62,9 @@ func (p *parser) ParseLine() Line {
e = p.ParseComment()
case TokNUMBER:
e = p.ParseTwt()
if e.IsNil() {
p.nextLine()
}
default:
p.nextLine()
}
@ -178,6 +181,9 @@ func (p *parser) ParseDateTime() *DateTime {
loc := time.UTC
// Year
if !p.expectLen(p.curTok, 4, 4) {
return nil
}
p.append(p.curTok.Literal...)
if year, ok = p.parseDigit(); !ok {
return nil
@ -190,6 +196,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// Month
if !p.expectLen(p.curTok, 2, 2) {
return nil
}
p.append(p.curTok.Literal...)
if month, ok = p.parseDigit(); !ok {
return nil
@ -202,6 +211,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// Day
if !p.expectLen(p.curTok, 2, 2) {
return nil
}
p.append(p.curTok.Literal...)
if day, ok = p.parseDigit(); !ok {
return nil
@ -214,6 +226,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// Hour
if !p.expectLen(p.curTok, 1, 2) {
return nil
}
p.append(p.curTok.Literal...)
if hour, ok = p.parseDigit(); !ok {
return nil
@ -226,6 +241,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// Minute
if !p.expectLen(p.curTok, 2, 2) {
return nil
}
p.append(p.curTok.Literal...)
if min, ok = p.parseDigit(); !ok {
return nil
@ -239,6 +257,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// Second
if !p.expectLen(p.curTok, 2, 2) {
return nil
}
p.append(p.curTok.Literal...)
if sec, ok = p.parseDigit(); !ok {
return nil
@ -253,6 +274,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// NSecond
if !p.expectLen(p.curTok, 1, 9) {
return nil
}
p.append(p.curTok.Literal...)
if nsec, ok = p.parseDigit(); !ok {
return nil
@ -277,6 +301,9 @@ func (p *parser) ParseDateTime() *DateTime {
if !p.expectNext(TokNUMBER) {
return nil
}
if !p.expectLen(p.curTok, 2, 4) {
return nil
}
p.append(p.curTok.Literal...)
if tzhour, ok = p.parseDigit(); !ok {
return nil
@ -295,6 +322,9 @@ func (p *parser) ParseDateTime() *DateTime {
}
// TZMin
if !p.expectLen(p.curTok, 2, 2) {
return nil
}
p.append(p.curTok.Literal...)
if tzmin, ok = p.parseDigit(); !ok {
return nil
@ -934,6 +964,20 @@ func (p *parser) expectNext(t TokType) bool {
return false
}
func (p *parser) expectLen(t Token, min, max int) bool {
if len(t.Literal) < min {
p.addError(fmt.Errorf("%w: expected min len %v got %v", ErrParseToken, min, len(t.Literal)))
return false
}
if len(t.Literal) > max {
p.addError(fmt.Errorf("%w: expected max len %v got %v", ErrParseToken, max, len(t.Literal)))
return false
}
return true
}
// parseDigit converts current token to int. adds error if fails.
func (p *parser) parseDigit() (int, bool) {
if !p.curTokenIs(TokNUMBER) {

Loading…
Cancel
Save