فهرست منبع

add user handle/password validation

Mike 1 سال پیش
والد
کامیت
4a7151fab4
2فایلهای تغییر یافته به همراه171 افزوده شده و 0 حذف شده
  1. 63 0
      wire/user.go
  2. 108 0
      wire/user_test.go

+ 63 - 0
wire/user.go

@@ -2,7 +2,9 @@ package wire
 
 import (
 	"crypto/md5"
+	"errors"
 	"io"
+	"unicode"
 )
 
 // WeakMD5PasswordHash hashes password and authKey for AIM v3.5-v4.7.
@@ -43,3 +45,64 @@ func RoastPassword(roastedPass []byte) []byte {
 	}
 	return clearPass
 }
+
+// ValidateAIMHandle returns an error if the AIM screen name is invalid.
+// A valid screen name meets the following criteria:
+//   - 3-16 letters/numbers
+//   - must start with a letter
+//   - doesn't end with a space
+func ValidateAIMHandle(screenName string) error {
+	if len(screenName) < 3 || len(screenName) > 16 {
+		return errors.New("screen name must be between 3 and 16 characters")
+	}
+
+	// Must start with a letter
+	if !unicode.IsLetter(rune(screenName[0])) {
+		return errors.New("screen name must start with a letter")
+	}
+
+	// Cannot end with a space
+	if screenName[len(screenName)-1] == ' ' {
+		return errors.New("screen name cannot end with a space")
+	}
+
+	// Must contain only letters, numbers, and spaces
+	for _, ch := range screenName {
+		if !unicode.IsLetter(ch) && !unicode.IsDigit(ch) && ch != ' ' {
+			return errors.New("screen name must contain only letters, numbers, and spaces")
+		}
+	}
+
+	return nil
+}
+
+// ValidateAIMPassword returns an error if the AIM password is invalid.
+// A valid password is 4-16 characters long. The minimum password length is
+// set here for software preservation purposes; operators should set more
+// stringent password requirements.
+func ValidateAIMPassword(pass string) error {
+	if len(pass) < 4 || len(pass) > 16 {
+		return errors.New("password must be between 4 and 16 characters")
+	}
+	return nil
+}
+
+// ValidateICQHandle returns an error if the ICQ UIN is invalid.
+// A valid UIN is a number in the range 10000-2147483646.
+func ValidateICQHandle(UIN uint32) error {
+	if UIN < 10000 || UIN > 2147483646 {
+		return errors.New("UIN must be between 10000 and 2147483646")
+	}
+	return nil
+}
+
+// ValidateICQPassword returns an error if the ICQ password is invalid.
+// A valid password is 1-8 characters long. The minimum password length is set
+// here for software preservation purposes; operators should set more stringent
+// password requirements.
+func ValidateICQPassword(pass string) error {
+	if len(pass) < 1 || len(pass) > 8 {
+		return errors.New("password must be between 1 and 8 characters")
+	}
+	return nil
+}

+ 108 - 0
wire/user_test.go

@@ -0,0 +1,108 @@
+package wire
+
+import (
+	"errors"
+	"fmt"
+	"testing"
+)
+
+func TestValidateAIMHandle(t *testing.T) {
+	tests := []struct {
+		screenName string
+		expected   error
+	}{
+		{"ValidName", nil},
+		{"Valid Name", nil},
+		{"Val1dName", nil},
+		{"Va", errors.New("screen name must be between 3 and 16 characters")},
+		{"ThisIsAVeryLongScreenName", errors.New("screen name must be between 3 and 16 characters")},
+		{"1Invalid", errors.New("screen name must start with a letter")},
+		{"Invalid ", errors.New("screen name cannot end with a space")},
+		{"Inval!dName", errors.New("screen name must contain only letters, numbers, and spaces")},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.screenName, func(t *testing.T) {
+			err := ValidateAIMHandle(tt.screenName)
+			if err != nil && err.Error() != tt.expected.Error() {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+			if err == nil && tt.expected != nil {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+		})
+	}
+}
+
+func TestValidateAIMPassword(t *testing.T) {
+	tests := []struct {
+		password string
+		expected error
+	}{
+		{"pass1234", nil},
+		{"1234", nil},
+		{"pa", errors.New("password must be between 4 and 16 characters")},
+		{"thisisaverylongpassword", errors.New("password must be between 4 and 16 characters")},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.password, func(t *testing.T) {
+			err := ValidateAIMPassword(tt.password)
+			if err != nil && err.Error() != tt.expected.Error() {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+			if err == nil && tt.expected != nil {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+		})
+	}
+}
+
+func TestValidateICQHandle(t *testing.T) {
+	tests := []struct {
+		UIN      uint32
+		expected error
+	}{
+		{123456, nil},
+		{10000, nil},
+		{2147483646, nil},
+		{9999, errors.New("UIN must be between 10000 and 2147483646")},
+		{2147483647, errors.New("UIN must be between 10000 and 2147483646")},
+	}
+
+	for _, tt := range tests {
+		t.Run(fmt.Sprintf("%d", tt.UIN), func(t *testing.T) {
+			err := ValidateICQHandle(tt.UIN)
+			if err != nil && err.Error() != tt.expected.Error() {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+			if err == nil && tt.expected != nil {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+		})
+	}
+}
+
+func TestValidateICQPassword(t *testing.T) {
+	tests := []struct {
+		password string
+		expected error
+	}{
+		{"pass", nil},
+		{"12345678", nil},
+		{"", errors.New("password must be between 1 and 8 characters")},
+		{"123456789", errors.New("password must be between 1 and 8 characters")},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.password, func(t *testing.T) {
+			err := ValidateICQPassword(tt.password)
+			if err != nil && err.Error() != tt.expected.Error() {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+			if err == nil && tt.expected != nil {
+				t.Errorf("got %v, want %v", err, tt.expected)
+			}
+		})
+	}
+}