package yaml
import (
"bytes"
"errors"
"os"
"regexp"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/extensions"
fileutil "github.com/projectdiscovery/utils/file"
stringsutil "github.com/projectdiscovery/utils/strings"
)
var reImportsPattern = regexp.MustCompile(`(?m)# !include:(.+.yaml)`)
var StrictSyntax bool
func PreProcess(data []byte) ([]byte, error) {
importMatches := reImportsPattern.FindAllSubmatch(data, -1)
hasImportDirectives := len(importMatches) > 0
if hasImportDirectives && StrictSyntax {
return data, errors.New("include directive preprocessing is disabled")
}
var replaceItems []string
for _, match := range importMatches {
var (
matchString string
includeFileName string
)
matchBytes := match[0]
matchString = string(matchBytes)
if len(match) > 0 {
includeFileName = string(match[1])
}
matchIndex := bytes.Index(data, matchBytes)
lastNewLineIndex := bytes.LastIndex(data[:matchIndex], []byte("\n"))
padBytes := data[lastNewLineIndex:matchIndex]
if fileutil.FileExists(includeFileName) {
includeFileContent, err := os.ReadFile(includeFileName)
if err != nil {
return nil, err
}
if stringsutil.HasSuffixAny(includeFileName, extensions.YAML) {
if subIncludedFileContent, err := PreProcess(includeFileContent); err == nil {
includeFileContent = subIncludedFileContent
} else {
return nil, err
}
}
includeFileContent = bytes.ReplaceAll(includeFileContent, []byte("\n"), padBytes)
replaceItems = append(replaceItems, matchString)
replaceItems = append(replaceItems, string(includeFileContent))
}
}
replacer := strings.NewReplacer(replaceItems...)
return []byte(replacer.Replace(string(data))), nil
}