Skip to content

Commit

Permalink
Merge pull request #362 from Rackover/sanitize_name
Browse files Browse the repository at this point in the history
Filtering non-latin letters in game names
  • Loading branch information
Rackover authored Oct 31, 2018
2 parents cfa7d74 + e29d899 commit 0216f87
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion server/gameconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ async def handle_action(self, command, args):
replace("'", '')
self.game.map_file_path = 'maps/{}.zip'.format(self.game.map_scenario_path.split('/')[2])
elif option_key == 'Title':
self.game.name = option_value
self.game.name = self.game.sanitize_name(option_value)

self._mark_dirty()

Expand Down
12 changes: 11 additions & 1 deletion server/games/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import time
import functools
import re
from collections import defaultdict
import asyncio
from typing import Union
Expand Down Expand Up @@ -122,7 +123,7 @@ def __init__(self, id, game_service, game_stats_service,
self.visibility = VisibilityState.PUBLIC
self.max_players = 12
self.host = host
self.name = name
self.name = self.sanitize_name(name)
self.map_id = None
self.map_file_path = 'maps/%s.zip' % map
self.map_scenario_path = None
Expand Down Expand Up @@ -617,6 +618,7 @@ async def update_game_stats(self):
# Write out the game_stats record.
# In some cases, games can be invalidated while running: we check for those cases when
# the game ends and update this record as appropriate.

await cursor.execute("INSERT INTO game_stats(id, gameType, gameMod, `host`, mapId, gameName, validity)"
"VALUES(%s, %s, %s, %s, %s, %s, %s)",
(self.id,
Expand Down Expand Up @@ -663,6 +665,14 @@ async def update_game_player_stats(self):
def getGamemodVersion(self):
return self.game_service.game_mode_versions[self.game_mode]

"""
Replaces sequences of non-latin characters with an underscore and truncates the string to 128 characters
Avoids the game name to crash the mysql INSERT query by being longer than the column's max size or by
containing non-latin1 characters
"""
def sanitize_name(self, name):
return re.sub('[^\x20-\xFF]+', '_', name)[0:128]

async def mark_invalid(self, new_validity_state: ValidityState):
self._logger.info("Marked as invalid because: %s", repr(new_validity_state))
self.validity = new_validity_state
Expand Down
2 changes: 1 addition & 1 deletion server/ladder_service.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async def start_game(self, player1, player2):

# Host is player 1
game.host = player1
game.name = str(player1.login + " Vs " + player2.login)
game.name = game.sanitize_name(str(player1.login + " Vs " + player2.login))

game.set_player_option(player1.id, 'StartSpot', 1)
game.set_player_option(player2.id, 'StartSpot', 2)
Expand Down
12 changes: 11 additions & 1 deletion tests/unit_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,16 @@ async def test_on_game_end_calls_rate_game_with_two_players(game):

assert game.validity is ValidityState.VALID

async def test_name_sanitization(game):
await game.clear_data()
game.state = GameState.LOBBY
game.name = game.sanitize_name("卓☻иAâé~<1000")
try:
game.name.encode('utf-16-be').decode('ascii')
except UnicodeDecodeError:
pass

assert(game.name == "_Aâé~<1000")

async def test_to_dict(game, create_player):
await game.clear_data()
Expand All @@ -430,7 +440,7 @@ async def test_to_dict(game, create_player):
"visibility": VisibilityState.to_string(game.visibility),
"password_protected": game.password is not None,
"uid": game.id,
"title": game.name,
"title": game.sanitize_name(game.name),
"state": 'playing',
"featured_mod": game.game_mode,
"featured_mod_versions": game.getGamemodVersion(),
Expand Down
2 changes: 1 addition & 1 deletion tests/unit_tests/test_gameconnection.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ async def test_handle_action_GameResult_calls_add_result(game, game_connection):

async def test_handle_action_GameOption_change_name(game, game_connection):
await game_connection.handle_action('GameOption', ['Title', 'All welcome'])
assert game.name == 'All welcome'
assert game.name == game.sanitize_name('All welcome')

async def test_json_stats(game_connection, game_stats_service, players, game):
game_stats_service.process_game_stats = mock.Mock()
Expand Down

0 comments on commit 0216f87

Please sign in to comment.