Mercurial > projects > sievemgr
view cmd/sievemgr/internal/config/parser.go @ 22:fc5e6970a0d5 default tip
Add support for specifying an authorization identity on the command line
author | Guido Berhoerster <guido+sievemgr@berhoerster.name> |
---|---|
date | Wed, 17 Feb 2021 07:50:55 +0100 |
parents | 854167f55839 |
children |
line wrap: on
line source
// Copyright (C) 2020 Guido Berhoerster <guido+sievemgr@berhoerster.name> // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package config import ( "fmt" "strconv" ) type parser struct { s *scanner } func (p *parser) scanType(expectedTok token) (string, error) { tok, lit, err := p.s.scan() if err != nil { return lit, NewParserError(err.Error(), p.s.line) } else if tok != expectedTok { return lit, NewParserError(fmt.Sprintf("expected %s, got %s %q", expectedTok, tok, lit), p.s.line) } return lit, nil } func (p *parser) validateAccount(acct *Account) error { if acct.Host == "" { return NewParserError(fmt.Sprintf("no host specified for account %q", acct.Name), 0) } else if acct.User == "" { return NewParserError(fmt.Sprintf("no user specified for account %q", acct.Name), 0) } return nil } func (p *parser) parse(conf *Configuration) error { var acct *Account var isDefault bool var tok token var lit string var err error parsing: for { tok, lit, err = p.s.scan() if err != nil { err = NewParserError(err.Error(), p.s.line) break parsing } if tok == tokenIllegal { err = NewParserError(fmt.Sprintf("illegal token %q", lit), p.s.line) break parsing } else if tok == tokenEOF { break parsing } else if tok != tokenIdent { err = NewParserError(fmt.Sprintf("expected identifier, got %s %q", tok, lit), p.s.line) break parsing } switch lit { case "account": if acct != nil { if err = p.validateAccount(acct); err != nil { break parsing } conf.Accounts = append(conf.Accounts, acct) if isDefault { conf.Default = acct isDefault = false } } // account name if lit, err = p.scanType(tokenString); err != nil { break parsing } acct = &Account{ Name: lit, } case "default": isDefault = true case "host": if lit, err = p.scanType(tokenString); err != nil { break parsing } acct.Host = lit case "port": if lit, err = p.scanType(tokenNumber); err != nil { break parsing } var port int if port, err = strconv.Atoi(lit); err != nil { err = NewParserError(fmt.Sprintf("failed to parse port: %s", err), p.s.line) break parsing } else if port < 1 || port > 65535 { err = NewParserError(fmt.Sprintf("invalid port number %d", port), p.s.line) break parsing } acct.Port = lit case "user": if lit, err = p.scanType(tokenString); err != nil { break parsing } acct.User = lit case "pass": if lit, err = p.scanType(tokenString); err != nil { break parsing } acct.Password = lit case "insecure": acct.Insecure = true default: err = NewParserError(fmt.Sprintf("unknown %s: %q", tok, lit), p.s.line) break parsing } } if err != nil { return err } if acct != nil { if err = p.validateAccount(acct); err != nil { return err } conf.Accounts = append(conf.Accounts, acct) if isDefault { conf.Default = acct } } return nil }