diff --git a/service/user/form/form_validator.go b/service/user/form/form_validator.go index 3a8c99c2..a65725da 100644 --- a/service/user/form/form_validator.go +++ b/service/user/form/form_validator.go @@ -49,7 +49,7 @@ type RegistrationForm struct { Username string `form:"username" needed:"true" len_min:"3" len_max:"20"` Email string `form:"email"` Password string `form:"password" needed:"true" len_min:"6" len_max:"72" equalInput:"ConfirmPassword"` - ConfirmPassword string `form:"password_confirmation" omit:"true" needed:"true"` + ConfirmPassword string `form:"password_confirmation" hum_name:"Password Confirmation" omit:"true" needed:"true"` CaptchaID string `form:"captchaID" omit:"true" needed:"true"` TermsAndConditions bool `form:"t_and_c" omit:"true" needed:"true" equal:"true" hum_name:"Terms and Conditions"` } @@ -67,7 +67,7 @@ type UserForm struct { Language string `form:"language" default:"en-us"` CurrentPassword string `form:"current_password" len_min:"6" len_max:"72" omit:"true"` Password string `form:"password" len_min:"6" len_max:"72" equalInput:"ConfirmPassword"` - ConfirmPassword string `form:"password_confirmation" omit:"true"` + ConfirmPassword string `form:"password_confirmation" hum_name:"Password Confirmation" omit:"true"` Status int `form:"status" default:"0"` Theme string `form:"theme"` } diff --git a/translations/en-us.all.json b/translations/en-us.all.json index 70c1df85..80d65aac 100644 --- a/translations/en-us.all.json +++ b/translations/en-us.all.json @@ -1370,5 +1370,25 @@ { "id": "filter", "translation": "Filter" + }, + { + "id": "error_min_length", + "translation": "Minimal length of %s required for the input: %s" + }, + { + "id":"error_max_length", + "translation":"Maximal length of %s required for the input: %s" + }, + { + "id":"error_same_value", + "translation": "Must be same %s" + }, + { + "id": "error_wrong_value", + "translation": "Wrong value for the input: %s" + }, + { + "id": "error_field_needed", + "translation": "Field needed: %s" } ] diff --git a/util/categories/categories_test.go b/util/categories/categories_test.go new file mode 100644 index 00000000..e1cd211c --- /dev/null +++ b/util/categories/categories_test.go @@ -0,0 +1,63 @@ +package categories + +import ( + "path" + "strings" + + "testing" + + "reflect" + + "github.com/NyaaPantsu/nyaa/config" +) + +// run before config/parse.go:init() +var _ = func() (_ struct{}) { + config.ConfigPath = path.Join("..", "..", config.ConfigPath) + config.DefaultConfigPath = path.Join("..", "..", config.DefaultConfigPath) + config.Parse() + return +}() + +func TestGetCategories(t *testing.T) { + cats := GetCategories() + if len(cats) == 0 { + t.Skip("Couldn't load categories to test Categories") + } + if !reflect.DeepEqual(cats, config.Conf.Torrents.CleanCategories) && !reflect.DeepEqual(cats, config.Conf.Torrents.SukebeiCategories) { + t.Error("Categories doesn't correspond to the configured ones") + } +} + +func TestCategoryExists(t *testing.T) { + if CategoryExists("k") { + t.Error("Category that shouldn't exist return true") + } +} + +func TestGetCategoriesSelect(t *testing.T) { + cats := GetCategoriesSelect(true, false) + for _, value := range cats { + split := strings.Split(value, "_") + if len(split) != 2 { + t.Errorf("The category %s doesn't have only one underscore", value) + } + if split[1] != "" { + t.Errorf("The function doesn't filter out child categories, expected '', got %s", split[1]) + } + } + cats = GetCategoriesSelect(false, true) + for _, value := range cats { + split := strings.Split(value, "_") + if len(split) != 2 { + t.Errorf("The category %s doesn't have only one underscore", value) + } + if split[1] == "" { + t.Error("The function doesn't filter out parent categories, expected a string, got nothing") + } + } + cats = GetCategoriesSelect(true, true) + if len(cats) != len(GetCategories()) { + t.Errorf("Same amount of categories isn't return when no filter applied") + } +} diff --git a/util/modelHelper/modelHelper_test.go b/util/modelHelper/modelHelper_test.go new file mode 100644 index 00000000..dc1039d7 --- /dev/null +++ b/util/modelHelper/modelHelper_test.go @@ -0,0 +1,81 @@ +package modelHelper + +import ( + "net/http" + "path" + "testing" + + "github.com/NyaaPantsu/nyaa/config" + msg "github.com/NyaaPantsu/nyaa/util/messages" +) + +// run before config/parse.go:init() +var _ = func() (_ struct{}) { + config.ConfigPath = path.Join("..", "..", config.ConfigPath) + config.DefaultConfigPath = path.Join("..", "..", config.DefaultConfigPath) + config.Parse() + return +}() + +type TestForm struct { + DefaultVal int `form:"default" default:"3" notnull:"true"` + ConfirmVal string `form:"confirm" needed:"true" equalInput:"ConfirmeVal" len_min:"7" len_max:"8"` + ConfirmeVal string `form:"confirme" needed:"true"` +} + +func TestValidateForm(t *testing.T) { + req, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Fatal(err) + } + messages := msg.GetMessages(req) + testform := TestForm{} + ValidateForm(&testform, messages) + if !messages.HasErrors() { + t.Errorf("No errors when parsing empty invalid form: %v", testform) + } + messages.ClearAllErrors() + testform.DefaultVal, testform.ConfirmVal, testform.ConfirmeVal = 1, "testingl", "testingl" + ValidateForm(&testform, messages) + if messages.HasErrors() { + t.Errorf("Errors when parsing valid form %v\n with errors %v", testform, messages.GetAllErrors()) + } + messages.ClearAllErrors() + testform.ConfirmVal = "test" + testform.ConfirmeVal = "test" + ValidateForm(&testform, messages) + if len(messages.GetErrors("confirm")) == 0 { + t.Errorf("No errors on minimal length test when parsing invalid form: %v", testform) + } + messages.ClearAllErrors() + testform.ConfirmVal, testform.ConfirmeVal = "testing", "testind" + ValidateForm(&testform, messages) + if len(messages.GetErrors("confirm")) == 0 { + t.Errorf("No errors on equal test when parsing invalid form: %v", testform) + } + messages.ClearAllErrors() + testform.ConfirmVal, testform.ConfirmeVal = "", "testing" + ValidateForm(&testform, messages) + if len(messages.GetErrors("confirm")) == 0 { + t.Errorf("No errors on needed test when parsing invalid form: %v", testform) + } + messages.ClearAllErrors() + testform.ConfirmVal, testform.ConfirmeVal = "azertyuid", "azertyuid" + ValidateForm(&testform, messages) + if len(messages.GetErrors("confirm")) == 0 { + t.Errorf("No errors on maximal length test when parsing invalid form %v", testform) + } + messages.ClearAllErrors() + testform.DefaultVal = 0 + ValidateForm(&testform, messages) + if testform.DefaultVal == 0 { + t.Errorf("Default value are not assigned on int with notnull specified: %v", testform) + } + messages.ClearAllErrors() + testform.DefaultVal = 1 + ValidateForm(&testform, messages) + if testform.DefaultVal != 1 { + t.Errorf("Default value are assigned on int with non null value: %v", testform) + } + messages.ClearAllErrors() +} diff --git a/util/modelHelper/model_helper.go b/util/modelHelper/model_helper.go index 559668a3..1f6e7e15 100644 --- a/util/modelHelper/model_helper.go +++ b/util/modelHelper/model_helper.go @@ -69,73 +69,88 @@ func ValidateForm(form interface{}, mes *msg.Messages) { inputName = tag.Get("hum_name") } if tag.Get("len_min") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check minimum length - lenMin, _ := strconv.Atoi(tag.Get("len_min")) - if formElem.Field(i).Len() < lenMin { - mes.AddErrorf(tag.Get("form"), "Minimal length of %s required for the input: %s", strconv.Itoa(lenMin), inputName) - } + checkMinLength(formElem.Field(i), tag, inputName, mes) } if tag.Get("len_max") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check maximum length - lenMax, _ := strconv.Atoi(tag.Get("len_max")) - if formElem.Field(i).Len() > lenMax { - mes.AddErrorf(tag.Get("form"), "Maximal length of %s required for the input: %s", strconv.Itoa(lenMax), inputName) - } + checkMaxLength(formElem.Field(i), tag, inputName, mes) } if tag.Get("equalInput") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { - otherInput := formElem.FieldByName(tag.Get("equalInput")) - if formElem.Field(i).Interface() != otherInput.Interface() { - mes.AddErrorf(tag.Get("form"), "Must be same %s", inputName) + checkEqualValue(formElem, i, tag, inputName, mes) + } + checksOnFieldTypes(formElem.Field(i), inputName, typeField, tag, mes) + } +} + +func checkMinLength(fieldElem reflect.Value, tag reflect.StructTag, inputName string, mes *msg.Messages) { + lenMin, _ := strconv.Atoi(tag.Get("len_min")) + if fieldElem.Len() < lenMin { + mes.AddErrorTf(tag.Get("form"), "error_min_length", strconv.Itoa(lenMin), inputName) + } +} +func checkMaxLength(fieldElem reflect.Value, tag reflect.StructTag, inputName string, mes *msg.Messages) { + lenMax, _ := strconv.Atoi(tag.Get("len_max")) + if fieldElem.Len() > lenMax { + mes.AddErrorTf(tag.Get("form"), "error_max_length", strconv.Itoa(lenMax), inputName) + } +} + +func checkEqualValue(formElem reflect.Value, i int, tag reflect.StructTag, inputName string, mes *msg.Messages) { + otherInput := formElem.FieldByName(tag.Get("equalInput")) + if formElem.Field(i).Interface() != otherInput.Interface() { + mes.AddErrorTf(tag.Get("form"), "error_same_value", inputName) + } +} + +func checksOnFieldTypes(fieldElem reflect.Value, inputName string, typeField reflect.StructField, tag reflect.StructTag, mes *msg.Messages) { + switch typeField.Type.Name() { + case "string": + if tag.Get("equal") != "" && fieldElem.String() != tag.Get("equal") { + mes.AddErrorTf(tag.Get("form"), "error_wrong_value", inputName) + } + if tag.Get("needed") != "" && fieldElem.String() == "" { + mes.AddErrorTf(tag.Get("form"), "error_field_needed", inputName) + } + if fieldElem.String() == "" && tag.Get("default") != "" { + fieldElem.SetString(tag.Get("default")) + } + case "int": + if tag.Get("equal") != "" { // Check minimum length + equal, _ := strconv.Atoi(tag.Get("equal")) + if fieldElem.Int() > int64(equal) { + mes.AddErrorTf(tag.Get("form"), "error_wrong_value", inputName) } } - switch typeField.Type.Name() { - case "string": - if tag.Get("equal") != "" && formElem.Field(i).String() != tag.Get("equal") { - mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName) + if tag.Get("needed") != "" && fieldElem.Int() == 0 { + mes.AddErrorTf(tag.Get("form"), "error_field_needed", inputName) + } + if fieldElem.Int() == 0 && tag.Get("default") != "" && tag.Get("notnull") != "" { + defaultValue, _ := strconv.Atoi(tag.Get("default")) + fieldElem.SetInt(int64(defaultValue)) + } + case "float": + if tag.Get("equal") != "" { // Check minimum length + equal, _ := strconv.Atoi(tag.Get("equal")) + if fieldElem.Float() != float64(equal) { + mes.AddErrorTf(tag.Get("form"), "error_wrong_value", inputName) } - if tag.Get("needed") != "" && formElem.Field(i).String() == "" { - mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName) - } - if formElem.Field(i).String() == "" && tag.Get("default") != "" { - formElem.Field(i).SetString(tag.Get("default")) - } - case "int": - if tag.Get("equal") != "" { // Check minimum length - equal, _ := strconv.Atoi(tag.Get("equal")) - if formElem.Field(i).Int() > int64(equal) { - mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName) - } - } - if tag.Get("needed") != "" && formElem.Field(i).Int() == 0 { - mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName) - } - if formElem.Field(i).Interface == nil && tag.Get("default") != "" { // FIXME: always false :'( - defaultValue, _ := strconv.Atoi(tag.Get("default")) - formElem.Field(i).SetInt(int64(defaultValue)) - } - case "float": - if tag.Get("equal") != "" { // Check minimum length - equal, _ := strconv.Atoi(tag.Get("equal")) - if formElem.Field(i).Float() != float64(equal) { - mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName) - } - } - if tag.Get("needed") != "" && formElem.Field(i).Float() == 0 { - mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName) - } - if formElem.Field(i).Interface == nil && tag.Get("default") != "" { // FIXME: always false :'( - defaultValue, _ := strconv.Atoi(tag.Get("default")) - formElem.Field(i).SetFloat(float64(defaultValue)) - } - case "bool": - if tag.Get("equal") != "" { // Check minimum length - equal, _ := strconv.ParseBool(tag.Get("equal")) - if formElem.Field(i).Bool() != equal { - mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName) - } - } - if formElem.Field(i).Interface == nil && tag.Get("default") != "" { // FIXME: always false :'( - defaultValue, _ := strconv.ParseBool(tag.Get("default")) - formElem.Field(i).SetBool(defaultValue) + } + if tag.Get("needed") != "" && fieldElem.Float() == 0 { + mes.AddErrorTf(tag.Get("form"), "error_field_needed", inputName) + } + if fieldElem.Float() == 0 && tag.Get("default") != "" && tag.Get("notnull") != "" { + defaultValue, _ := strconv.Atoi(tag.Get("default")) + fieldElem.SetFloat(float64(defaultValue)) + } + case "bool": + if tag.Get("equal") != "" { // Check minimum length + equal, _ := strconv.ParseBool(tag.Get("equal")) + if fieldElem.Bool() != equal { + mes.AddErrorTf(tag.Get("form"), "error_wrong_value", inputName) } } + if !fieldElem.Bool() && tag.Get("default") != "" && tag.Get("notnull") != "" { + defaultValue, _ := strconv.ParseBool(tag.Get("default")) + fieldElem.SetBool(defaultValue) + } } } diff --git a/util/unzlib.go b/util/unzlib.go deleted file mode 100644 index 8ef214c6..00000000 --- a/util/unzlib.go +++ /dev/null @@ -1,27 +0,0 @@ -package util - -import ( - "github.com/NyaaPantsu/nyaa/util/log" - - "bytes" - "compress/zlib" - "io/ioutil" -) - -// UnZlib : Is it deprecated? -func UnZlib(description []byte) (string, error) { - if len(description) > 0 { - b := bytes.NewReader(description) - z, err := zlib.NewReader(b) - if !log.CheckError(err) { - return "", err - } - defer z.Close() - p, err := ioutil.ReadAll(z) - if !log.CheckError(err) { - return "", err - } - return string(p), nil - } - return "", nil -} diff --git a/util/util_test.go b/util/util_test.go new file mode 100644 index 00000000..e3f978e5 --- /dev/null +++ b/util/util_test.go @@ -0,0 +1,86 @@ +package util + +import ( + "path" + "testing" + + "math" + + "github.com/NyaaPantsu/nyaa/config" +) + +// run before config/parse.go:init() +var _ = func() (_ struct{}) { + config.ConfigPath = path.Join("..", config.ConfigPath) + config.DefaultConfigPath = path.Join("..", config.DefaultConfigPath) + config.Parse() + return +}() + +func TestFormatFilesize(t *testing.T) { + format := FormatFilesize(0) + if format != "0.0 B" { + t.Fatalf("Format of 0 bytes gives %s, expected '0.0 B'", format) + } + format = FormatFilesize(int64(math.Exp2(0))) + if format != "1.0 B" { + t.Fatalf("Format of 1byte gives %s, expected '1.0 B'", format) + } + format = FormatFilesize(int64(math.Exp2(10))) + if format != "1.0 KiB" { + t.Fatalf("Format of 1024 bytes gives %s, expected '1.0 KiB'", format) + } +} + +func TestGetHostname(t *testing.T) { + hostname := GetHostname("http://exemple.com") + if hostname != "exemple.com" { + t.Fatalf("Hostname gives %s, expected 'exemple.com'", hostname) + } + hostname = GetHostname("ircs://exemple.com/ddf/?kfkf=http://something.net&id=") + if hostname != "exemple.com" { + t.Fatalf("Hostname gives %s, expected 'exemple.com'", hostname) + } + hostname = GetHostname("") + if hostname != "" { + t.Fatalf("Hostname gives %s, expected ''", hostname) + } +} + +func TestInfoHashToMagnet(t *testing.T) { + magnetExpected := "magnet:?xt=urn:btih:213d354dd354d534d&dn=Test&tr=udp://tracker.doko.moe:6969&tr=udp://tracker.zer0day.to:1337/announce" + + magnet := InfoHashToMagnet("213d354dd354d534d", "Test", "udp://tracker.doko.moe:6969", "udp://tracker.zer0day.to:1337/announce") + if magnetExpected != magnet { + t.Fatalf("Magnet URL parsed doesn't give the expected result, have this '%s', want this '%s'", magnet, magnetExpected) + } +} + +func TestSafe(t *testing.T) { + safeString := map[string]string{ + "'": "'", + "&": "&", + "http://exemple.com": "http://exemple.com", + } + for key, val := range safeString { + safe := Safe(key) + if string(safe) != val { + t.Errorf("Safe doesn't escape the right values, expected result %s, got %s", key, val) + } + } +} + +func TestSafeText(t *testing.T) { + safeString := map[string]string{ + "'": "'", + "&": "&", + "http://exemple.com": "http://exemple.com", + "test": "<em>test</em><script>lol();</script>", + } + for key, val := range safeString { + safe := Safe(key) + if string(safe) != val { + t.Errorf("Safe doesn't escape the right values, expected result %s, got %s", key, val) + } + } +}