Added comprehensive encoding handling to support both player-level encoding choices as well as global multiple encodings through the settings file.

This commit is contained in:
Griatch 2010-10-03 19:11:43 +00:00
parent 7904916dba
commit 745df8356f
5 changed files with 69 additions and 34 deletions

View file

@ -506,14 +506,8 @@ class ObjectDB(TypedObject):
# This is an important function that must always work. # This is an important function that must always work.
# we use a different __getattribute__ to avoid recursive loops. # we use a different __getattribute__ to avoid recursive loops.
if from_obj: if object.__getattribute__(self, 'player'):
try: object.__getattribute__(self, 'player').msg(message, markup)
from_obj.at_msg_send(message, self)
except Exception:
pass
if self.at_msg_receive(message, from_obj):
for session in object.__getattribute__(self, 'sessions'):
session.msg(message, markup)
def emit_to(self, message, from_obj=None): def emit_to(self, message, from_obj=None):
"Deprecated. Alias for msg" "Deprecated. Alias for msg"

View file

@ -253,19 +253,15 @@ class PlayerDB(TypedObject):
def msg(self, message, from_obj=None, markup=True): def msg(self, message, from_obj=None, markup=True):
""" """
This duplicates the same-named method on the Character. This is the main route for sending data to the user.
It forwards messages to the character or uses
the session messaging directly.
""" """
if self.character:
self.character.msg(message, from_obj)
else:
if from_obj: if from_obj:
try: try:
from_obj.at_msg_send(message, self) from_obj.at_msg_send(message, self)
except Exception: except Exception:
pass pass
if self.at_msg_receive(message, from_obj): if self.character:
if self.character.at_msg_receive(message, from_obj):
for session in object.__getattribute__(self, 'sessions'): for session in object.__getattribute__(self, 'sessions'):
session.msg(message, markup) session.msg(message, markup)

View file

@ -16,6 +16,8 @@ from src.utils import reloads
from src.utils import logger from src.utils import logger
from src.utils import utils from src.utils import utils
ENCODINGS = settings.ENCODINGS
class SessionProtocol(StatefulTelnetProtocol): class SessionProtocol(StatefulTelnetProtocol):
""" """
This class represents a player's session. Each player This class represents a player's session. Each player
@ -71,6 +73,7 @@ class SessionProtocol(StatefulTelnetProtocol):
self.name = None self.name = None
self.uid = None self.uid = None
self.logged_in = False self.logged_in = False
self.encoding = "utf-8"
# The time the user last issued a command. # The time the user last issued a command.
self.cmd_last = time.time() self.cmd_last = time.time()
@ -103,11 +106,29 @@ class SessionProtocol(StatefulTelnetProtocol):
So we take the user input and pass it to the Player and their currently So we take the user input and pass it to the Player and their currently
connected character. connected character.
""" """
if self.encoding:
try: try:
raw_string = utils.to_unicode(raw_string) raw_string = utils.to_unicode(raw_string, encoding=self.encoding)
except Exception, e: self.execute_cmd(raw_string)
self.sendLine(str(e))
return return
except Exception, e:
err = str(e)
print err
pass
# malformed/wrong encoding defined on player-try some defaults
for encoding in ENCODINGS:
try:
raw_string = utils.to_unicode(raw_string, encoding=encoding)
err = None
break
except Exception, e:
err = str(e)
continue
if err:
self.sendLine(err)
else:
self.execute_cmd(raw_string) self.execute_cmd(raw_string)
def msg(self, message, markup=True): def msg(self, message, markup=True):
@ -120,11 +141,26 @@ class SessionProtocol(StatefulTelnetProtocol):
colors, but could also be html tags for colors, but could also be html tags for
web connections etc. web connections etc.
""" """
if self.encoding:
try: try:
message = utils.to_str(message) message = utils.to_str(message, encoding=self.encoding)
except Exception, e: self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
self.sendLine(str(e))
return return
except Exception:
pass
# malformed/wrong encoding defined on player - try some defaults
for encoding in ENCODINGS:
try:
message = utils.to_str(message, encoding=encoding)
err = None
break
except Exception, e:
err = str(e)
continue
if err:
self.sendLine(err)
else:
self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup)) self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
def get_character(self): def get_character(self):
@ -228,6 +264,8 @@ class SessionProtocol(StatefulTelnetProtocol):
self.name = user.username self.name = user.username
self.logged_in = True self.logged_in = True
self.conn_time = time.time() self.conn_time = time.time()
if player.db.encoding:
self.encoding = player.db.encoding
if not settings.ALLOW_MULTISESSION: if not settings.ALLOW_MULTISESSION:
# disconnect previous sessions. # disconnect previous sessions.

View file

@ -70,6 +70,12 @@ IMPORT_MUX_HELP = False
# thrown off by sending the empty system command 'idle' to the server # thrown off by sending the empty system command 'idle' to the server
# at regular intervals. # at regular intervals.
IDLE_TIMEOUT = 3600 IDLE_TIMEOUT = 3600
# The set of encodings tried. A Player object may set an attribute "encoding" on
# itself to match the client used. If not set, or wrong encoding is
# given, this list is tried, in order, aborting on the first match.
# Add sets for languages/regions your players are likely to use.
# (see http://en.wikipedia.org/wiki/Character_encoding)
ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"]
################################################### ###################################################
# Evennia Database config # Evennia Database config

View file

@ -273,7 +273,7 @@ class Attribute(SharedMemoryModel):
such as dhango model instances, cannot be directly stored/pickled such as dhango model instances, cannot be directly stored/pickled
in an attribute, so we have to be clever about it. in an attribute, so we have to be clever about it.
Types of objects and how they are handled: Types of objects and how they are handled:
* str - stored directly in field * str - s5Atored directly in field
* django model object - store its dbref in field * django model object - store its dbref in field
* any other python structure - pickle in field * any other python structure - pickle in field
@ -813,7 +813,8 @@ class TypedObject(SharedMemoryModel):
""" """
Returns all attributes defined on the object. Returns all attributes defined on the object.
""" """
return [attr for attr in self.objattribute_set.all()] attr_set_all = eval("self.%s_set.all()" % (self.attribute_model_name.lower()))
return [attr for attr in attr_set_all]
def attr(self, attribute_name=None, value=None, delete=False): def attr(self, attribute_name=None, value=None, delete=False):
""" """