212 lines
7.1 KiB
Go
212 lines
7.1 KiB
Go
package cmd
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"reflect"
|
||
"strings"
|
||
)
|
||
|
||
// Проверка пути на пустое значение
|
||
// Принимает на вход экземпляр bodyOutput и возвращает флаг, означающий непустой путь
|
||
func (o CSVOutput) Enabled() bool {
|
||
return strings.TrimSpace(o.CSVPath) != ""
|
||
}
|
||
|
||
// Проверка пути на пустое значение
|
||
// Принимает на вход экземпляр bodyOutput и возвращает флаг, означающий непустой путь
|
||
func (o JSONOutput) Enabled() bool {
|
||
return strings.TrimSpace(o.JSONPath) != ""
|
||
}
|
||
|
||
// Проверка пути на пустое значение.
|
||
// Принимает на вход экземпляр bodyOutput и возвращает флаг, означающий непустой путь
|
||
func (o BodyOutput) Enabled() bool {
|
||
return strings.TrimSpace(o.BodyPath) != ""
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр mftParseCmd и возвращает ошибку
|
||
func (c *MFTParseCmd) Validate() error {
|
||
if !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() && !c.BodyOutput.Enabled() {
|
||
return fmt.Errorf("mft parse requires at least one output: --csv, --json, or --body") // Проверка на наличие флага формата файла вывода
|
||
}
|
||
if c.BodyOutput.Enabled() && strings.TrimSpace(c.DriveLetter) == "" {
|
||
return fmt.Errorf("--drive-letter is required when using --body") // Проверка наличия буквы диска в Bodyfile
|
||
}
|
||
if c.FileList && !c.CSVOutput.Enabled() {
|
||
return fmt.Errorf("--file-list requires --csv") // Проверка CSV вывода для листинга файлов
|
||
}
|
||
if (c.DumpResidentFiles || c.IncludeResidentData) && !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() {
|
||
return fmt.Errorf("--dump-resident-files and --include-resident-data require --csv or --json") // Проверка CSV или JSON вывода для резидентных файлов
|
||
}
|
||
if c.ResidentMaxBytes <= 0 || c.ResidentMaxBytes > MaxResidentDataBytes {
|
||
return fmt.Errorf("--resident-max-bytes must be between 1 and %d", MaxResidentDataBytes) // Проверка максимального значения размера резидентных файлов
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр mftShowCmd и возвращает ошибку
|
||
func (c *MFTShowCmd) Validate() error {
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр mftExportRecordCmd и возвращает ошибку
|
||
func (c *MFTExportRecordCmd) Validate() error {
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр journalParseCmd и возвращает ошибку
|
||
func (c *JournalParseCmd) Validate() error {
|
||
if !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() {
|
||
return fmt.Errorf("j parse requires at least one output: --csv or --json") // Проверка вывода
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр bootParseCmd и возвращает ошибку
|
||
func (c *BootParseCmd) Validate() error {
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр sdsParseCmd и возвращает ошибку
|
||
func (c *SDSParseCmd) Validate() error {
|
||
if !c.CSVOutput.Enabled() {
|
||
return fmt.Errorf("sds parse requires --csv") // Проверка вывода в CSV
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр sdsShowCmd и возвращает ошибку
|
||
func (c *SDSShowCmd) Validate() error {
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов
|
||
// Принимает на вход указатель на экземпляр i30ParseCmd и возвращает ошибку
|
||
func (c *I30ParseCmd) Validate() error {
|
||
if !c.CSVOutput.Enabled() {
|
||
return fmt.Errorf("i30 parse requires --csv") // Проверка вывода в CSV
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Валидация флагов.
|
||
// Принимает на вход указатель на экземпляр logFileParseCmd и возвращает ошибку
|
||
func (c *LogFileParseCmd) Validate() error {
|
||
return nil
|
||
}
|
||
|
||
// Валидация команд.
|
||
// Принимает на вход объект и при наличии метода Validate производит валидацию
|
||
func ValidateLeaf(cmd any) error {
|
||
switch v := cmd.(type) {
|
||
case interface{ Validate() error }:
|
||
return v.Validate()
|
||
default:
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// Валидация путей.
|
||
// Принимает на вход объект и при наличии метода Enabled производит валидацию
|
||
func ValidatePath(cmd any) error {
|
||
switch v := cmd.(type) {
|
||
case interface{ Enabled() error }:
|
||
return v.Enabled()
|
||
default:
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// Проверяет, что у команды с output-блоками включён хотя бы один вывод.
|
||
func ValidateOutput(cmd any) error {
|
||
if cmd == nil {
|
||
return nil
|
||
}
|
||
|
||
v := reflect.ValueOf(cmd)
|
||
if v.Kind() == reflect.Pointer {
|
||
if v.IsNil() {
|
||
return nil
|
||
}
|
||
v = v.Elem()
|
||
}
|
||
|
||
if v.Kind() != reflect.Struct {
|
||
return nil
|
||
}
|
||
|
||
var hasOutputBlocks bool
|
||
var hasEnabledOutput bool
|
||
|
||
for i := 0; i < v.NumField(); i++ {
|
||
field := v.Field(i)
|
||
fieldType := v.Type().Field(i)
|
||
|
||
switch fieldType.Type {
|
||
case reflect.TypeOf(CSVOutput{}):
|
||
hasOutputBlocks = true
|
||
if enabled, ok := callEnabled(field); ok && enabled {
|
||
hasEnabledOutput = true
|
||
}
|
||
|
||
case reflect.TypeOf(JSONOutput{}):
|
||
hasOutputBlocks = true
|
||
if enabled, ok := callEnabled(field); ok && enabled {
|
||
hasEnabledOutput = true
|
||
}
|
||
|
||
case reflect.TypeOf(BodyOutput{}):
|
||
hasOutputBlocks = true
|
||
if enabled, ok := callEnabled(field); ok && enabled {
|
||
hasEnabledOutput = true
|
||
}
|
||
}
|
||
}
|
||
|
||
if hasOutputBlocks && !hasEnabledOutput {
|
||
return errors.New("you must specify at least one output path: --csv, --json or --body")
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Вызов Enabled у поля
|
||
// Возвращает результат Enabled() и флаг успешности поиска метода
|
||
func callEnabled(v reflect.Value) (bool, bool) {
|
||
if !v.IsValid() {
|
||
return false, false
|
||
}
|
||
|
||
// Пробуем метод у самого значения
|
||
if method := v.MethodByName("Enabled"); method.IsValid() {
|
||
if method.Type().NumIn() == 0 &&
|
||
method.Type().NumOut() == 1 &&
|
||
method.Type().Out(0).Kind() == reflect.Bool {
|
||
out := method.Call(nil)
|
||
return out[0].Bool(), true
|
||
}
|
||
}
|
||
|
||
// Пробуем метод у указателя
|
||
if v.CanAddr() {
|
||
if method := v.Addr().MethodByName("Enabled"); method.IsValid() {
|
||
if method.Type().NumIn() == 0 &&
|
||
method.Type().NumOut() == 1 &&
|
||
method.Type().Out(0).Kind() == reflect.Bool {
|
||
out := method.Call(nil)
|
||
return out[0].Bool(), true
|
||
}
|
||
}
|
||
}
|
||
|
||
return false, false
|
||
}
|