mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-05-06 05:26:33 -05:00
Sake: Sanitize Mii info returned from mkw FriendInfo
This commit is contained in:
parent
4dbe2a7678
commit
2770b46ab7
|
|
@ -453,6 +453,34 @@ func isPlayerInfoValid(playerInfoString string) (string, bool) {
|
|||
return fixedPlayerInfoString, true
|
||||
}
|
||||
|
||||
func filterMarioKartWiiFriendInfo(value string, isOwner bool) (string, string) {
|
||||
// Clear personal info from the Mii data before sending to the client. This
|
||||
// cannot be done before inserting into the database because the client
|
||||
// expects the server to return the exact copy of what it has previously updated.
|
||||
if isOwner {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
|
||||
binaryData, err := base64.StdEncoding.DecodeString(value)
|
||||
if err != nil {
|
||||
// Shouldn't happen after validation
|
||||
panic(err)
|
||||
}
|
||||
// Only change if the Mii checksum is valid
|
||||
if len(binaryData) < 0x4C {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
|
||||
mii := common.RawMiiFromBytes(binaryData)
|
||||
if mii.CalculateMiiCRC() != 0 {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
|
||||
mii = mii.ClearMiiInfo()
|
||||
binaryData = append(mii.Data[:], binaryData[len(mii.Data):]...)
|
||||
return base64.StdEncoding.EncodeToString(binaryData), ResultSuccess
|
||||
}
|
||||
|
||||
func getMultipartBoundary(contentType string) string {
|
||||
startIndex := strings.Index(contentType, "boundary=")
|
||||
if startIndex == -1 {
|
||||
|
|
|
|||
|
|
@ -306,6 +306,14 @@ func getMyRecords(moduleName string, profileId uint32, gameInfo common.GameInfo,
|
|||
}}
|
||||
}
|
||||
|
||||
table := GetTable(gameInfo.Name, request.TableID)
|
||||
if table != nil && table.Reserved {
|
||||
logging.Error(moduleName, "Attempt to get my records from reserved table", aurora.Cyan(request.TableID))
|
||||
return StorageResponseBody{GetMyRecordsResponse: &StorageGetMyRecordsResponse{
|
||||
GetMyRecordsResult: ResultTableNotFound,
|
||||
}}
|
||||
}
|
||||
|
||||
records, err := database.GetSakeRecords(pool, ctx, gameInfo.GameID, []int32{int32(profileId)}, request.TableID, nil, request.Fields.Fields, request.Filter)
|
||||
if err != nil {
|
||||
logging.Error(moduleName, "Failed to get sake records from the database:", err)
|
||||
|
|
@ -319,9 +327,10 @@ func getMyRecords(moduleName string, profileId uint32, gameInfo common.GameInfo,
|
|||
}}
|
||||
}
|
||||
|
||||
responseValues, result := fillResponseValues(moduleName, profileId, table, records, request)
|
||||
response := StorageGetMyRecordsResponse{
|
||||
GetMyRecordsResult: ResultSuccess,
|
||||
Values: fillResponseValues(records, request),
|
||||
GetMyRecordsResult: result,
|
||||
Values: responseValues,
|
||||
}
|
||||
logging.Info(moduleName, "Returning", aurora.Cyan(len(records)), "records from table", aurora.Cyan(request.TableID), "for profile", aurora.Cyan(profileId))
|
||||
|
||||
|
|
@ -462,9 +471,10 @@ func searchForRecords(moduleName string, profileId uint32, gameInfo common.GameI
|
|||
records = records[:request.Max]
|
||||
}
|
||||
|
||||
responseValues, result := fillResponseValues(moduleName, profileId, table, records, request)
|
||||
response := StorageSearchForRecordsResponse{
|
||||
SearchForRecordsResult: "Success",
|
||||
Values: fillResponseValues(records, request),
|
||||
SearchForRecordsResult: result,
|
||||
Values: responseValues,
|
||||
}
|
||||
logging.Info(moduleName, "Found", aurora.Cyan(len(records)), "records in table", aurora.Cyan(request.TableID), "for profile", aurora.Cyan(profileId), "with filter", aurora.Cyan(request.Filter))
|
||||
|
||||
|
|
@ -502,12 +512,18 @@ func getInputFields(moduleName string, request StorageRequestData, table *SakeTa
|
|||
logging.Error(moduleName, "Invalid value for field", aurora.Cyan(field.Name).String()+":", aurora.Cyan(value))
|
||||
return nil, result
|
||||
}
|
||||
var result string
|
||||
sakeField.Value, result = table.FilterFieldFromClient(field.Name, value)
|
||||
if result != ResultSuccess {
|
||||
logging.Error(moduleName, "Failed to filter from client value for field", aurora.Cyan(field.Name), ":", aurora.Cyan(result))
|
||||
return nil, result
|
||||
}
|
||||
fields[field.Name] = sakeField
|
||||
}
|
||||
return fields, ResultSuccess
|
||||
}
|
||||
|
||||
func fillResponseValues(records []database.SakeRecord, request StorageRequestData) StorageResponseValues {
|
||||
func fillResponseValues(moduleName string, profileId uint32, table *SakeTable, records []database.SakeRecord, request StorageRequestData) (StorageResponseValues, string) {
|
||||
var response StorageResponseValues
|
||||
for _, record := range records {
|
||||
valueArray := StorageArrayOfRecordValue{}
|
||||
|
|
@ -536,14 +552,21 @@ func fillResponseValues(records []database.SakeRecord, request StorageRequestDat
|
|||
}
|
||||
if fieldValue == nil {
|
||||
valueArray.RecordValues = append(valueArray.RecordValues, StorageRecordValue{Value: nil})
|
||||
} else {
|
||||
value := fillValue(fieldValue.Type, fieldValue.Value)
|
||||
valueArray.RecordValues = append(valueArray.RecordValues, StorageRecordValue{Value: &value})
|
||||
continue
|
||||
}
|
||||
|
||||
var result string
|
||||
fieldValue.Value, result = table.FilterFieldFromDatabase(field, fieldValue.Value, record.OwnerId == int32(profileId))
|
||||
if result != ResultSuccess {
|
||||
logging.Error(moduleName, "Failed to filter to client value for field", aurora.Cyan(field), ":", aurora.Cyan(result))
|
||||
return StorageResponseValues{}, result
|
||||
}
|
||||
value := fillValue(fieldValue.Type, fieldValue.Value)
|
||||
valueArray.RecordValues = append(valueArray.RecordValues, StorageRecordValue{Value: &value})
|
||||
}
|
||||
response.ArrayOfRecordValue = append(response.ArrayOfRecordValue, valueArray)
|
||||
}
|
||||
return response
|
||||
return response, ResultSuccess
|
||||
}
|
||||
|
||||
func fillValue(valueType database.SakeFieldType, value string) StorageValue {
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ type SakeFieldDefinition struct {
|
|||
// Optional function for custom validation.
|
||||
IsValidFunc func(value string) bool
|
||||
// Optional function for custom filtering. This function receives the value from the client AFTER validation, before inserting into the database.
|
||||
FilterFromClientFunc func(value string) (string, error)
|
||||
FilterFromClientFunc func(value string, isOwner bool) (string, string)
|
||||
// Optional function for custom filtering. This function receives the value from the database before sending to the client.
|
||||
FilterFromDatabaseFunc func(value string) (string, error)
|
||||
FilterFromDatabaseFunc func(value string, isOwner bool) (string, string)
|
||||
}
|
||||
|
||||
type SakeTable struct {
|
||||
|
|
@ -113,7 +113,8 @@ var TableDefinitions = map[string]SakeTable{
|
|||
Hardened: false, // To allow modding extra fields
|
||||
Fields: map[string]SakeFieldDefinition{
|
||||
"info": {
|
||||
Type: database.SakeFieldTypeBinaryData,
|
||||
Type: database.SakeFieldTypeBinaryData,
|
||||
FilterFromDatabaseFunc: filterMarioKartWiiFriendInfo,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -387,3 +388,34 @@ func (t *SakeTable) CheckValidField(fieldName string, field database.SakeField)
|
|||
}
|
||||
return ResultSuccess
|
||||
}
|
||||
|
||||
func (t *SakeTable) FilterFieldFromClient(fieldName string, value string) (string, string) {
|
||||
if t == nil || t.Fields == nil {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
fieldDef, exists := t.Fields[fieldName]
|
||||
if !exists {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
if fieldDef.FilterFromClientFunc == nil {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
return fieldDef.FilterFromClientFunc(value, true)
|
||||
}
|
||||
|
||||
func (t *SakeTable) FilterFieldFromDatabase(fieldName string, value string, isOwner bool) (string, string) {
|
||||
if t == nil || t.Fields == nil {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
fieldDef, exists := t.Fields[fieldName]
|
||||
if !exists {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
if fieldDef.FilterFromDatabaseFunc == nil {
|
||||
return value, ResultSuccess
|
||||
}
|
||||
if t.OwnerType != OwnerTypeProfile {
|
||||
isOwner = false
|
||||
}
|
||||
return fieldDef.FilterFromDatabaseFunc(value, isOwner)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user