mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
fix(sshd_config): Improve indexes structure
This commit is contained in:
parent
7bb34c32b4
commit
35c722995d
@ -15,7 +15,7 @@ func analyzeMatchBlocks(
|
||||
) []common.LSPError {
|
||||
errs := make([]common.LSPError, 0)
|
||||
|
||||
for matchBlock, options := range d.Indexes.GetAllOptionsForName("Match") {
|
||||
for matchBlock, options := range d.Indexes.AllOptionsPerName["Match"] {
|
||||
option := options[0]
|
||||
// Check if the match block has filled out all fields
|
||||
if matchBlock == nil || matchBlock.MatchValue == nil || len(matchBlock.MatchValue.Entries) == 0 {
|
||||
|
@ -10,13 +10,13 @@ import (
|
||||
)
|
||||
|
||||
func GetIncludeOptionLocation(
|
||||
include *indexes.SSHIndexIncludeLine,
|
||||
include *indexes.SSHDIndexIncludeLine,
|
||||
cursor uint32,
|
||||
) []protocol.Location {
|
||||
index, found := slices.BinarySearchFunc(
|
||||
include.Values,
|
||||
cursor,
|
||||
func(i *indexes.SSHIndexIncludeValue, cursor uint32) int {
|
||||
func(i *indexes.SSHDIndexIncludeValue, cursor uint32) int {
|
||||
if cursor < i.Start.Character {
|
||||
return -1
|
||||
}
|
||||
|
125
handlers/sshd_config/indexes/handlers.go
Normal file
125
handlers/sshd_config/indexes/handlers.go
Normal file
@ -0,0 +1,125 @@
|
||||
package indexes
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
"config-lsp/handlers/sshd_config/fields"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var whitespacePattern = regexp.MustCompile(`\S+`)
|
||||
|
||||
func CreateIndexes(config ast.SSHDConfig) (*SSHDIndexes, []common.LSPError) {
|
||||
errs := make([]common.LSPError, 0)
|
||||
indexes := &SSHDIndexes{
|
||||
AllOptionsPerName: make(map[string](map[*ast.SSHDMatchBlock]([]*ast.SSHDOption))),
|
||||
Includes: make(map[uint32]*SSHDIndexIncludeLine),
|
||||
}
|
||||
|
||||
it := config.Options.Iterator()
|
||||
for it.Next() {
|
||||
entry := it.Value().(ast.SSHDEntry)
|
||||
|
||||
switch entry.(type) {
|
||||
case *ast.SSHDOption:
|
||||
option := entry.(*ast.SSHDOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, nil)...)
|
||||
case *ast.SSHDMatchBlock:
|
||||
matchBlock := entry.(*ast.SSHDMatchBlock)
|
||||
|
||||
errs = append(errs, addOption(indexes, matchBlock.MatchEntry, matchBlock)...)
|
||||
|
||||
it := matchBlock.Options.Iterator()
|
||||
for it.Next() {
|
||||
option := it.Value().(*ast.SSHDOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, matchBlock)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Includes
|
||||
for matchBlock, options := range indexes.AllOptionsPerName["Include"] {
|
||||
includeOption := options[0]
|
||||
rawValue := includeOption.OptionValue.Value.Value
|
||||
pathIndexes := whitespacePattern.FindAllStringIndex(rawValue, -1)
|
||||
paths := make([]*SSHDIndexIncludeValue, 0)
|
||||
|
||||
for _, pathIndex := range pathIndexes {
|
||||
startIndex := pathIndex[0]
|
||||
endIndex := pathIndex[1]
|
||||
|
||||
rawPath := rawValue[startIndex:endIndex]
|
||||
|
||||
offset := includeOption.OptionValue.Start.Character
|
||||
path := SSHDIndexIncludeValue{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: common.Location{
|
||||
Line: includeOption.Start.Line,
|
||||
Character: uint32(startIndex) + offset,
|
||||
},
|
||||
End: common.Location{
|
||||
Line: includeOption.Start.Line,
|
||||
Character: uint32(endIndex) + offset - 1,
|
||||
},
|
||||
},
|
||||
Value: rawPath,
|
||||
Paths: make([]ValidPath, 0),
|
||||
}
|
||||
|
||||
paths = append(paths, &path)
|
||||
}
|
||||
|
||||
indexes.Includes[includeOption.Start.Line] = &SSHDIndexIncludeLine{
|
||||
Values: paths,
|
||||
Option: includeOption,
|
||||
MatchBlock: matchBlock,
|
||||
}
|
||||
}
|
||||
|
||||
return indexes, errs
|
||||
}
|
||||
|
||||
func addOption(
|
||||
i *SSHDIndexes,
|
||||
option *ast.SSHDOption,
|
||||
matchBlock *ast.SSHDMatchBlock,
|
||||
) []common.LSPError {
|
||||
var errs []common.LSPError
|
||||
|
||||
if optionsMap, found := i.AllOptionsPerName[option.Key.Key]; found {
|
||||
if options, found := optionsMap[matchBlock]; found {
|
||||
if _, duplicatesAllowed := fields.AllowedDuplicateOptions[option.Key.Key]; !duplicatesAllowed {
|
||||
firstDefinedOption := options[0]
|
||||
errs = append(errs, common.LSPError{
|
||||
Range: option.Key.LocationRange,
|
||||
Err: errors.New(fmt.Sprintf(
|
||||
"Option '%s' has already been defined on line %d",
|
||||
option.Key.Key,
|
||||
firstDefinedOption.Start.Line+1,
|
||||
)),
|
||||
})
|
||||
} else {
|
||||
i.AllOptionsPerName[option.Key.Key][matchBlock] = append(
|
||||
i.AllOptionsPerName[option.Key.Key][matchBlock],
|
||||
option,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
i.AllOptionsPerName[option.Key.Key][matchBlock] = []*ast.SSHDOption{
|
||||
option,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i.AllOptionsPerName[option.Key.Key] = map[*ast.SSHDMatchBlock]([]*ast.SSHDOption){
|
||||
matchBlock: {
|
||||
option,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
@ -3,10 +3,6 @@ package indexes
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
"config-lsp/handlers/sshd_config/fields"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type ValidPath string
|
||||
@ -15,13 +11,13 @@ func (v ValidPath) AsURI() string {
|
||||
return "file://" + string(v)
|
||||
}
|
||||
|
||||
// SSHIndexIncludeValue Used to store the individual includes
|
||||
// SSHDIndexIncludeValue Used to store the individual includes
|
||||
// An `Include` statement can have multiple paths,
|
||||
// each [SSHIndexIncludeValue] represents a single entered path.
|
||||
// each [SSHDIndexIncludeValue] represents a single entered path.
|
||||
// Note that an entered path can represent multiple real paths, as
|
||||
// the path can contain wildcards.
|
||||
// All true paths are stored in the [Paths] field.
|
||||
type SSHIndexIncludeValue struct {
|
||||
type SSHDIndexIncludeValue struct {
|
||||
common.LocationRange
|
||||
Value string
|
||||
|
||||
@ -29,142 +25,15 @@ type SSHIndexIncludeValue struct {
|
||||
Paths []ValidPath
|
||||
}
|
||||
|
||||
type SSHIndexIncludeLine struct {
|
||||
Values []*SSHIndexIncludeValue
|
||||
type SSHDIndexIncludeLine struct {
|
||||
Values []*SSHDIndexIncludeValue
|
||||
Option *ast.SSHDOption
|
||||
MatchBlock *ast.SSHDMatchBlock
|
||||
}
|
||||
|
||||
type SSHIndexes struct {
|
||||
type SSHDIndexes struct {
|
||||
// This is a map of `Option name` to a list of options with that name
|
||||
AllOptionsPerName map[*ast.SSHDMatchBlock](map[string]([]*ast.SSHDOption))
|
||||
AllOptionsPerName map[string](map[*ast.SSHDMatchBlock]([]*ast.SSHDOption))
|
||||
|
||||
Includes map[uint32]*SSHIndexIncludeLine
|
||||
}
|
||||
|
||||
func (i SSHIndexes) GetAllOptionsForName(name string) map[*ast.SSHDMatchBlock][]*ast.SSHDOption {
|
||||
allOptions := make(map[*ast.SSHDMatchBlock][]*ast.SSHDOption)
|
||||
|
||||
for matchBlock, options := range i.AllOptionsPerName {
|
||||
if opts, found := options[name]; found {
|
||||
allOptions[matchBlock] = opts
|
||||
}
|
||||
}
|
||||
|
||||
return allOptions
|
||||
}
|
||||
|
||||
var whitespacePattern = regexp.MustCompile(`\S+`)
|
||||
|
||||
func CreateIndexes(config ast.SSHDConfig) (*SSHIndexes, []common.LSPError) {
|
||||
errs := make([]common.LSPError, 0)
|
||||
indexes := &SSHIndexes{
|
||||
AllOptionsPerName: make(map[*ast.SSHDMatchBlock](map[string]([]*ast.SSHDOption))),
|
||||
Includes: make(map[uint32]*SSHIndexIncludeLine),
|
||||
}
|
||||
|
||||
it := config.Options.Iterator()
|
||||
for it.Next() {
|
||||
entry := it.Value().(ast.SSHDEntry)
|
||||
|
||||
switch entry.(type) {
|
||||
case *ast.SSHDOption:
|
||||
option := entry.(*ast.SSHDOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, nil)...)
|
||||
case *ast.SSHDMatchBlock:
|
||||
matchBlock := entry.(*ast.SSHDMatchBlock)
|
||||
|
||||
errs = append(errs, addOption(indexes, matchBlock.MatchEntry, matchBlock)...)
|
||||
|
||||
it := matchBlock.Options.Iterator()
|
||||
for it.Next() {
|
||||
option := it.Value().(*ast.SSHDOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, matchBlock)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Includes
|
||||
for matchBlock, options := range indexes.GetAllOptionsForName("Include") {
|
||||
includeOption := options[0]
|
||||
rawValue := includeOption.OptionValue.Value.Value
|
||||
pathIndexes := whitespacePattern.FindAllStringIndex(rawValue, -1)
|
||||
paths := make([]*SSHIndexIncludeValue, 0)
|
||||
|
||||
for _, pathIndex := range pathIndexes {
|
||||
startIndex := pathIndex[0]
|
||||
endIndex := pathIndex[1]
|
||||
|
||||
rawPath := rawValue[startIndex:endIndex]
|
||||
|
||||
offset := includeOption.OptionValue.Start.Character
|
||||
path := SSHIndexIncludeValue{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: common.Location{
|
||||
Line: includeOption.Start.Line,
|
||||
Character: uint32(startIndex) + offset,
|
||||
},
|
||||
End: common.Location{
|
||||
Line: includeOption.Start.Line,
|
||||
Character: uint32(endIndex) + offset - 1,
|
||||
},
|
||||
},
|
||||
Value: rawPath,
|
||||
Paths: make([]ValidPath, 0),
|
||||
}
|
||||
|
||||
paths = append(paths, &path)
|
||||
}
|
||||
|
||||
indexes.Includes[includeOption.Start.Line] = &SSHIndexIncludeLine{
|
||||
Values: paths,
|
||||
Option: includeOption,
|
||||
MatchBlock: matchBlock,
|
||||
}
|
||||
}
|
||||
|
||||
return indexes, errs
|
||||
}
|
||||
|
||||
func addOption(
|
||||
i *SSHIndexes,
|
||||
option *ast.SSHDOption,
|
||||
matchBlock *ast.SSHDMatchBlock,
|
||||
) []common.LSPError {
|
||||
var errs []common.LSPError
|
||||
|
||||
if optionsMap, found := i.AllOptionsPerName[matchBlock]; found {
|
||||
if options, found := optionsMap[option.Key.Key]; found {
|
||||
if _, duplicatesAllowed := fields.AllowedDuplicateOptions[option.Key.Key]; !duplicatesAllowed {
|
||||
firstDefinedOption := options[0]
|
||||
errs = append(errs, common.LSPError{
|
||||
Range: option.Key.LocationRange,
|
||||
Err: errors.New(fmt.Sprintf(
|
||||
"Option '%s' has already been defined on line %d",
|
||||
option.Key.Key,
|
||||
firstDefinedOption.Start.Line+1,
|
||||
)),
|
||||
})
|
||||
} else {
|
||||
i.AllOptionsPerName[matchBlock][option.Key.Key] = append(
|
||||
i.AllOptionsPerName[matchBlock][option.Key.Key],
|
||||
option,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
i.AllOptionsPerName[matchBlock][option.Key.Key] = []*ast.SSHDOption{
|
||||
option,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i.AllOptionsPerName[matchBlock] = map[string]([]*ast.SSHDOption){
|
||||
option.Key.Key: {
|
||||
option,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
Includes map[uint32]*SSHDIndexIncludeLine
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ Match Address 192.168.0.1/24
|
||||
}
|
||||
|
||||
firstMatchBlock := config.FindMatchBlock(uint32(6))
|
||||
opts := indexes.GetAllOptionsForName("PermitRootLogin")
|
||||
opts := indexes.AllOptionsPerName["PermitRootLogin"]
|
||||
if !(len(opts) == 2 &&
|
||||
len(opts[nil]) == 1 &&
|
||||
opts[nil][0].Value.Value == "PermitRootLogin yes" &&
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
type SSHDocument struct {
|
||||
Config *ast.SSHDConfig
|
||||
Indexes *indexes.SSHIndexes
|
||||
Indexes *indexes.SSHDIndexes
|
||||
}
|
||||
|
||||
var DocumentParserMap = map[protocol.DocumentUri]*SSHDocument{}
|
||||
|
Loading…
x
Reference in New Issue
Block a user