diff --git a/app/peppy/common.go b/app/peppy/common.go index b9c0ff0..84cbefa 100644 --- a/app/peppy/common.go +++ b/app/peppy/common.go @@ -40,23 +40,23 @@ func genUser(c *gin.Context, db *sqlx.DB) (string, string) { switch { // We know for sure that it's an username. case c.Query("type") == "string": - whereClause = "users.username = ?" - p = c.Query("u") + whereClause = "users.username_safe = ?" + p = common.SafeUsername(c.Query("u")) // It could be an user ID, so we look for an user with that username first. case err == nil: err = db.QueryRow("SELECT id FROM users WHERE id = ? LIMIT 1", s).Scan(&p) if err == sql.ErrNoRows { // If no user with that userID were found, assume username. - p = c.Query("u") - whereClause = "users.username = ?" + whereClause = "users.username_safe = ?" + p = common.SafeUsername(c.Query("u")) } else { // An user with that userID was found. Thus it's an userID. whereClause = "users.id = ?" } // u contains letters, so it's an username. default: - p = c.Query("u") - whereClause = "users.username = ?" + whereClause = "users.username_safe = ?" + p = common.SafeUsername(c.Query("u")) } return whereClause, p } diff --git a/app/v1/token.go b/app/v1/token.go index d96fe8f..d22e6cf 100644 --- a/app/v1/token.go +++ b/app/v1/token.go @@ -59,7 +59,7 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager { if data.UserID != 0 { q = md.DB.QueryRow(base+"WHERE id = ? LIMIT 1", data.UserID) } else { - q = md.DB.QueryRow(base+"WHERE username = ? LIMIT 1", data.Username) + q = md.DB.QueryRow(base+"WHERE username = ? LIMIT 1", common.SafeUsername(data.Username)) } var ( diff --git a/app/v1/user.go b/app/v1/user.go index 01d0335..bd26e84 100644 --- a/app/v1/user.go +++ b/app/v1/user.go @@ -76,14 +76,14 @@ func userPutsMulti(md common.MethodData) common.CodeMessager { // query composition wh := common. - Where("users.username = ?", md.Query("nname")). + Where("users.username_safe = ?", common.SafeUsername(md.Query("nname"))). Where("users.id = ?", md.Query("iid")). Where("users.privileges = ?", md.Query("privileges")). Where("users.privileges & ? > 0", md.Query("has_privileges")). Where("users_stats.country = ?", md.Query("country")). Where("users_stats.username_aka = ?", md.Query("name_aka")). In("users.id", q["ids"]...). - In("users.username", q["names"]...). + In("users.username_safe", safeUsernameBulk(q["names"])...). In("users_stats.username_aka", q["names_aka"]...). In("users_stats.country", q["countries"]...) query := "" + @@ -128,6 +128,13 @@ func UserSelfGET(md common.MethodData) common.CodeMessager { return UsersGET(md) } +func safeUsernameBulk(us []string) []string { + for i, u := range us { + us[i] = common.SafeUsername(u) + } + return us +} + type whatIDResponse struct { common.ResponseBase ID int `json:"id"` @@ -139,7 +146,7 @@ func UserWhatsTheIDGET(md common.MethodData) common.CodeMessager { r whatIDResponse privileges uint64 ) - err := md.DB.QueryRow("SELECT id, privileges FROM users WHERE username = ? LIMIT 1", md.Query("name")).Scan(&r.ID, &privileges) + err := md.DB.QueryRow("SELECT id, privileges FROM users WHERE username_safe = ? LIMIT 1", common.SafeUsername(md.Query("name"))).Scan(&r.ID, &privileges) if err != nil || ((privileges&uint64(common.UserPrivilegePublic)) == 0 && (md.User.UserPrivileges&common.AdminPrivilegeManageUsers == 0)) { return common.SimpleResponse(404, "That user could not be found!") @@ -323,7 +330,7 @@ func whereClauseUser(md common.MethodData, tableName string) (*common.CodeMessag } return nil, tableName + ".id = ?", id case md.Query("name") != "": - return nil, tableName + ".username = ?", md.Query("name") + return nil, tableName + ".username_safe = ?", common.SafeUsername(md.Query("name")) } a := common.SimpleResponse(400, "you need to pass either querystring parameters name or id") return &a, "", nil @@ -341,16 +348,18 @@ type lookupUser struct { // UserLookupGET does a quick lookup of users beginning with the passed // querystring value name. func UserLookupGET(md common.MethodData) common.CodeMessager { - name := strings.NewReplacer( + name := common.SafeUsername(md.Query("name")) + name = strings.NewReplacer( "%", "\\%", "_", "\\_", "\\", "\\\\", - ).Replace(md.Query("name")) + ).Replace(name) if name == "" { return common.SimpleResponse(400, "please provide an username to start searching") } name = "%" + name + "%" - rows, err := md.DB.Query("SELECT users.id, users.username FROM users WHERE username LIKE ? AND "+ + + rows, err := md.DB.Query("SELECT users.id, users.username FROM users WHERE username_safe LIKE ? AND "+ md.User.OnlyUserPublic(true)+" LIMIT 25", name) if err != nil { md.Err(err) @@ -358,7 +367,6 @@ func UserLookupGET(md common.MethodData) common.CodeMessager { } var r userLookupResponse - for rows.Next() { var l lookupUser err := rows.Scan(&l.ID, &l.Username)