Fix panic when ARTICLE command goes w/o args

This commit is contained in:
ChronosX88 2022-02-05 19:03:54 +03:00
parent e6f8e39a8e
commit 1197ded1aa
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
3 changed files with 45 additions and 18 deletions

View File

@ -132,6 +132,9 @@ func (sb *SQLiteBackend) GetArticle(messageID string) (models.Article, error) {
if err := sb.db.Get(&a, "SELECT * FROM articles WHERE json_extract(articles.header, '$.Message-Id[0]') = ?", messageID); err != nil { if err := sb.db.Get(&a, "SELECT * FROM articles WHERE json_extract(articles.header, '$.Message-Id[0]') = ?", messageID); err != nil {
return a, err return a, err
} }
if err := sb.db.Get(&a.ArticleNumber, "SELECT article_number FROM articles_to_groups WHERE article_id = ?", a.ID); err != nil {
return a, err
}
return a, json.Unmarshal([]byte(a.HeaderRaw), &a.Header) return a, json.Unmarshal([]byte(a.HeaderRaw), &a.Header)
} }
@ -140,6 +143,7 @@ func (sb *SQLiteBackend) GetArticleByNumber(g *models.Group, num int) (models.Ar
if err := sb.db.Get(&a, "SELECT articles.* FROM articles INNER JOIN articles_to_groups atg on atg.article_id = articles.id WHERE atg.article_number = ? AND atg.group_id = ?", num, g.ID); err != nil { if err := sb.db.Get(&a, "SELECT articles.* FROM articles INNER JOIN articles_to_groups atg on atg.article_id = articles.id WHERE atg.article_number = ? AND atg.group_id = ?", num, g.ID); err != nil {
return a, err return a, err
} }
a.ArticleNumber = num
return a, json.Unmarshal([]byte(a.HeaderRaw), &a.Header) return a, json.Unmarshal([]byte(a.HeaderRaw), &a.Header)
} }

View File

@ -7,10 +7,12 @@ import (
) )
type Article struct { type Article struct {
ID int `db:"id"` ID int `db:"id"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
HeaderRaw string `db:"header"` HeaderRaw string `db:"header"`
Header textproto.MIMEHeader `db:"-"` Body string `db:"body"`
Body string `db:"body"` Thread sql.NullString `db:"thread"`
Thread sql.NullString `db:"thread"`
Header textproto.MIMEHeader `db:"-"`
ArticleNumber int `db:"-"`
} }

View File

@ -197,6 +197,15 @@ func (h *Handler) handleGroup(s *Session, command string, arguments []string, id
s.currentGroup = &g s.currentGroup = &g
if lowWaterMark != 0 {
a, err := h.backend.GetArticleByNumber(&g, lowWaterMark)
if err != nil {
return err
}
s.currentArticle = &a
}
return s.tconn.PrintfLine(protocol.NNTPResponse{ return s.tconn.PrintfLine(protocol.NNTPResponse{
Code: 211, Code: 211,
Message: fmt.Sprintf("%d %d %d %s", articlesCount, lowWaterMark, highWaterMark, g.GroupName), Message: fmt.Sprintf("%d %d %d %s", articlesCount, lowWaterMark, highWaterMark, g.GroupName),
@ -395,28 +404,35 @@ func (h *Handler) handleArticle(s *Session, command string, arguments []string,
s.tconn.StartResponse(id) s.tconn.StartResponse(id)
defer s.tconn.EndResponse(id) defer s.tconn.EndResponse(id)
if len(arguments) == 0 && s.currentArticle == nil { var err error
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 420, Message: "No current article selected"}.String()) getByArticleNum := true
if len(arguments) == 0 {
if s.currentArticle == nil {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 420, Message: "No current article selected"}.String())
}
getByArticleNum = false
} }
if len(arguments) > 1 { if len(arguments) > 1 {
return s.tconn.PrintfLine(protocol.ErrSyntaxError.String()) return s.tconn.PrintfLine(protocol.ErrSyntaxError.String())
} }
getByArticleNum := true var num int
num, err := strconv.Atoi(arguments[0]) if getByArticleNum {
if err != nil { num, err = strconv.Atoi(arguments[0])
getByArticleNum = false if err != nil {
getByArticleNum = false
}
} }
if getByArticleNum && s.currentGroup == nil { if getByArticleNum && s.currentGroup == nil {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 412, Message: "No newsgroup selected"}.String()) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 412, Message: "No newsgroup selected"}.String())
} }
var a models.Article var a *models.Article
if getByArticleNum { if getByArticleNum {
a, err = h.backend.GetArticleByNumber(s.currentGroup, num) article, err := h.backend.GetArticleByNumber(s.currentGroup, num)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 423, Message: "No article with that number"}.String()) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 423, Message: "No article with that number"}.String())
@ -424,8 +440,10 @@ func (h *Handler) handleArticle(s *Session, command string, arguments []string,
return err return err
} }
} }
} else { a = &article
a, err = h.backend.GetArticle(arguments[0]) s.currentArticle = &article
} else if len(arguments) > 0 {
article, err := h.backend.GetArticle(arguments[0])
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 430, Message: "No Such Article Found"}.String()) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 430, Message: "No Such Article Found"}.String())
@ -433,10 +451,13 @@ func (h *Handler) handleArticle(s *Session, command string, arguments []string,
return err return err
} }
} }
a = &article
s.currentArticle = &article
} else {
a = s.currentArticle
num = s.currentArticle.ArticleNumber
} }
s.currentArticle = &a
switch command { switch command {
case protocol.CommandArticle: case protocol.CommandArticle:
{ {