Trim flags to avoid mistakes due to empty lines or espaces...

This commit is contained in:
nemunaire 2021-12-07 16:33:30 +01:00
parent e6d8f2db1b
commit 0cc72712a4
7 changed files with 24 additions and 14 deletions

View File

@ -404,6 +404,7 @@ type uploadedFlag struct {
Placeholder string Placeholder string
IgnoreCase bool IgnoreCase bool
Multiline bool Multiline bool
NoTrim bool
ValidatorRe *string `json:"validator_regexp"` ValidatorRe *string `json:"validator_regexp"`
Flag string Flag string
Value []byte Value []byte
@ -425,7 +426,7 @@ func createExerciceFlag(exercice *fic.Exercice, body []byte) (interface{}, error
vre = uk.ValidatorRe vre = uk.ValidatorRe
} }
return exercice.AddRawFlagKey(uk.Label, uk.Type, uk.Placeholder, uk.IgnoreCase, uk.Multiline, vre, []byte(uk.Flag), uk.ChoicesCost) return exercice.AddRawFlagKey(uk.Label, uk.Type, uk.Placeholder, uk.IgnoreCase, uk.NoTrim, uk.Multiline, vre, []byte(uk.Flag), uk.ChoicesCost)
} }
func showExerciceFlag(flag *fic.FlagKey, _ *fic.Exercice, body []byte) (interface{}, error) { func showExerciceFlag(flag *fic.FlagKey, _ *fic.Exercice, body []byte) (interface{}, error) {

View File

@ -38,6 +38,7 @@ type ExerciceFlag struct {
ShowLines bool `toml:",omitempty"` ShowLines bool `toml:",omitempty"`
Ordered bool `toml:",omitempty"` Ordered bool `toml:",omitempty"`
CaseSensitive bool `toml:",omitempty"` CaseSensitive bool `toml:",omitempty"`
NoTrim bool `toml:",omitempty"`
ValidatorRe string `toml:"validator_regexp,omitempty"` ValidatorRe string `toml:"validator_regexp,omitempty"`
Placeholder string `toml:",omitempty"` Placeholder string `toml:",omitempty"`
Help string `toml:",omitempty"` Help string `toml:",omitempty"`

View File

@ -124,7 +124,7 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau
errs = append(errs, fmt.Sprintf("%q: WARNING flag #%d: non-printable characters in flag, is this really expected?", path.Base(exercice.Path), flagline)) errs = append(errs, fmt.Sprintf("%q: WARNING flag #%d: non-printable characters in flag, is this really expected?", path.Base(exercice.Path), flagline))
} }
hashedFlag, err := fic.ComputeHashedFlag([]byte(raw), !flag.CaseSensitive, validatorRegexp(flag.ValidatorRe)) hashedFlag, err := fic.ComputeHashedFlag([]byte(raw), !flag.CaseSensitive, flag.NoTrim, validatorRegexp(flag.ValidatorRe))
if err != nil { if err != nil {
errs = append(errs, fmt.Sprintf("%q: flag #%d: %s", path.Base(exercice.Path), flagline, err.Error())) errs = append(errs, fmt.Sprintf("%q: flag #%d: %s", path.Base(exercice.Path), flagline, err.Error()))
return return

View File

@ -188,6 +188,7 @@ CREATE TABLE IF NOT EXISTS exercice_flags(
help VARCHAR(255) NOT NULL, help VARCHAR(255) NOT NULL,
unit VARCHAR(255) NOT NULL, unit VARCHAR(255) NOT NULL,
ignorecase BOOLEAN NOT NULL DEFAULT 0, ignorecase BOOLEAN NOT NULL DEFAULT 0,
notrim BOOLEAN NOT NULL DEFAULT 0,
multiline BOOLEAN NOT NULL DEFAULT 0, multiline BOOLEAN NOT NULL DEFAULT 0,
validator_regexp VARCHAR(255) NULL, validator_regexp VARCHAR(255) NULL,
cksum BINARY(64) NOT NULL, cksum BINARY(64) NOT NULL,

View File

@ -332,7 +332,7 @@ func (f *EFile) GetDepends() ([]Flag, error) {
if err := rows.Scan(&d); err != nil { if err := rows.Scan(&d); err != nil {
return nil, err return nil, err
} }
deps = append(deps, &FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, nil, []byte{}, 0}) deps = append(deps, &FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, false, nil, []byte{}, 0})
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
return nil, err return nil, err

View File

@ -29,6 +29,8 @@ type FlagKey struct {
Unit string `json:"unit"` Unit string `json:"unit"`
// IgnoreCase indicates if the case is sensitive to case or not // IgnoreCase indicates if the case is sensitive to case or not
IgnoreCase bool `json:"ignorecase"` IgnoreCase bool `json:"ignorecase"`
// NoTrim indicates if the flag should not be trimed to avoid mistakes
NoTrim bool `json:"notrim,omitempty"`
// Multiline indicates if the flag is stored on multiple lines // Multiline indicates if the flag is stored on multiple lines
Multiline bool `json:"multiline"` Multiline bool `json:"multiline"`
// ValidatorRegexp extracts a subset of the player's answer, that will be checked. // ValidatorRegexp extracts a subset of the player's answer, that will be checked.
@ -41,7 +43,7 @@ type FlagKey struct {
// GetFlagKeys returns a list of key's flags comming with the challenge. // GetFlagKeys returns a list of key's flags comming with the challenge.
func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) { func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
if rows, err := DBQuery("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil { if rows, err := DBQuery("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
return nil, err return nil, err
} else { } else {
defer rows.Close() defer rows.Close()
@ -51,7 +53,7 @@ func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
k := &FlagKey{} k := &FlagKey{}
k.IdExercice = e.Id k.IdExercice = e.Id
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost); err != nil { if err := rows.Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost); err != nil {
return nil, err return nil, err
} }
@ -68,23 +70,27 @@ func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
// GetFlagKey returns a list of flags comming with the challenge. // GetFlagKey returns a list of flags comming with the challenge.
func GetFlagKey(id int) (k *FlagKey, err error) { func GetFlagKey(id int) (k *FlagKey, err error) {
k = &FlagKey{} k = &FlagKey{}
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_flag = ?", id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost) err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_flag = ?", id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.NoTrim, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost)
return return
} }
// GetFlagKeyByLabel returns a flag matching the given label. // GetFlagKeyByLabel returns a flag matching the given label.
func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) { func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) {
k = &FlagKey{} k = &FlagKey{}
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost) err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost)
return return
} }
// ComputeHashedFlag calculates the expected checksum for the given raw_value. // ComputeHashedFlag calculates the expected checksum for the given raw_value.
func ComputeHashedFlag(raw_value []byte, ignorecase bool, validator_regexp *string) (hash [blake2b.Size]byte, err error) { func ComputeHashedFlag(raw_value []byte, ignorecase bool, notrim bool, validator_regexp *string) (hash [blake2b.Size]byte, err error) {
if ignorecase { if ignorecase {
raw_value = bytes.ToLower(raw_value) raw_value = bytes.ToLower(raw_value)
} }
if !notrim {
raw_value = bytes.TrimSpace(raw_value)
}
// Check that raw value passes through the regexp // Check that raw value passes through the regexp
if validator_regexp != nil { if validator_regexp != nil {
if raw_value, err = ExecValidatorRegexp(*validator_regexp, raw_value, ignorecase); err != nil { if raw_value, err = ExecValidatorRegexp(*validator_regexp, raw_value, ignorecase); err != nil {
@ -115,8 +121,8 @@ func ExecValidatorRegexp(vre string, val []byte, ignorecase bool) ([]byte, error
} }
// AddRawFlagKey creates and fills a new struct FlagKey, from a non-hashed flag, and registers it into the database. // AddRawFlagKey creates and fills a new struct FlagKey, from a non-hashed flag, and registers it into the database.
func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, validator_regexp *string, raw_value []byte, choicescost int64) (*FlagKey, error) { func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, notrim bool, validator_regexp *string, raw_value []byte, choicescost int64) (*FlagKey, error) {
hash, err := ComputeHashedFlag(raw_value, ignorecase, validator_regexp) hash, err := ComputeHashedFlag(raw_value, ignorecase, notrim, validator_regexp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -126,6 +132,7 @@ func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, igno
Label: name, Label: name,
Placeholder: placeholder, Placeholder: placeholder,
IgnoreCase: ignorecase, IgnoreCase: ignorecase,
NoTrim: notrim,
Multiline: multiline, Multiline: multiline,
ValidatorRegexp: validator_regexp, ValidatorRegexp: validator_regexp,
Checksum: hash[:], Checksum: hash[:],
@ -159,7 +166,7 @@ func (k *FlagKey) Create(e *Exercice) (Flag, error) {
} }
} }
if res, err := DBExec("INSERT INTO exercice_flags (id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", e.Id, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.Multiline, k.ValidatorRegexp, k.Checksum, k.ChoicesCost); err != nil { if res, err := DBExec("INSERT INTO exercice_flags (id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, cksum, choices_cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", e.Id, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.Checksum, k.ChoicesCost); err != nil {
return k, err return k, err
} else if kid, err := res.LastInsertId(); err != nil { } else if kid, err := res.LastInsertId(); err != nil {
return k, err return k, err
@ -172,7 +179,7 @@ func (k *FlagKey) Create(e *Exercice) (Flag, error) {
// ComputeChecksum calculates the checksum for a given value. // ComputeChecksum calculates the checksum for a given value.
func (k *FlagKey) ComputeChecksum(val []byte) ([]byte, error) { func (k *FlagKey) ComputeChecksum(val []byte) ([]byte, error) {
cksum, err := ComputeHashedFlag(val, k.IgnoreCase, k.ValidatorRegexp) cksum, err := ComputeHashedFlag(val, k.IgnoreCase, k.NoTrim, k.ValidatorRegexp)
return cksum[:], err return cksum[:], err
} }
@ -184,7 +191,7 @@ func (k *FlagKey) Update() (int64, error) {
} }
} }
if res, err := DBExec("UPDATE exercice_flags SET id_exercice = ?, ordre = ?, label = ?, type = ?, placeholder = ?, help = ?, unit = ?, ignorecase = ?, multiline = ?, validator_regexp = ?, cksum = ?, choices_cost = ? WHERE id_flag = ?", k.IdExercice, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.Multiline, k.ValidatorRegexp, k.Checksum, k.ChoicesCost, k.Id); err != nil { if res, err := DBExec("UPDATE exercice_flags SET id_exercice = ?, ordre = ?, label = ?, type = ?, placeholder = ?, help = ?, unit = ?, ignorecase = ?, notrim = ?, multiline = ?, validator_regexp = ?, cksum = ?, choices_cost = ? WHERE id_flag = ?", k.IdExercice, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.Checksum, k.ChoicesCost, k.Id); err != nil {
return 0, err return 0, err
} else if nb, err := res.RowsAffected(); err != nil { } else if nb, err := res.RowsAffected(); err != nil {
return 0, err return 0, err

View File

@ -351,7 +351,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
} }
if t == nil { if t == nil {
h, _ := ComputeHashedFlag([]byte(soluce), false, nil) h, _ := ComputeHashedFlag([]byte(soluce), false, false, nil)
m.Soluce = hex.EncodeToString(h[:]) m.Soluce = hex.EncodeToString(h[:])
} }