}
oldId := member.Id()
- member.SetId(args[0])
-
+ member.SetId(SanitizeName(args[0]))
err := room.Rename(oldId, member)
if err != nil {
member.SetId(oldId)
// closed.
var ErrRoomClosed = errors.New("room closed")
+// The error returned when a user attempts to join with an invalid name, such
+// as empty string.
+var ErrInvalidName = errors.New("invalid name")
+
// Member is a User with per-Room metadata attached to it.
type Member struct {
*User
if r.closed {
return nil, ErrRoomClosed
}
+ if u.Id() == "" {
+ return nil, ErrInvalidName
+ }
member := Member{u, false}
err := r.members.Add(&member)
if err != nil {
// Rename member with a new identity. This will not call rename on the member.
func (r *Room) Rename(oldId string, identity Identifier) error {
+ if identity.Id() == "" {
+ return ErrInvalidName
+ }
err := r.members.Replace(oldId, identity)
if err != nil {
return err
--- /dev/null
+package chat
+
+import "regexp"
+
+var reStripName = regexp.MustCompile("[^\\w.-]")
+
+// SanitizeName returns a name with only allowed characters.
+func SanitizeName(s string) string {
+ return reStripName.ReplaceAllString(s, "")
+}
+
+var reStripData = regexp.MustCompile("[^[:ascii:]]")
+
+// SanitizeData returns a string with only allowed characters for client-provided metadata inputs.
+func SanitizeData(s string) string {
+ return reStripData.ReplaceAllString(s, "")
+}
}
member, err := h.Join(user)
- if err == chat.ErrIdTaken {
+ if err != nil {
// Try again...
id.SetName(fmt.Sprintf("Guest%d", h.count))
member, err = h.Join(user)
func NewIdentity(conn sshd.Connection) *Identity {
return &Identity{
Connection: conn,
- id: conn.Name(),
+ id: chat.SanitizeName(conn.Name()),
}
}