def _handle_sasl_auth(self, xml): try: saslauth = base64.b64decode(xml.text).decode("utf-8").split("/") username = saslauth[0] username = saslauth[0].split("\x00")[1] authcode = "" self.uid = username if len(saslauth) > 1: resource = saslauth[1] self.clientresource = resource elif len(saslauth[0].split("\x00")) > 2: resource = saslauth[0].split("\x00")[2] self.clientresource = resource if len(saslauth) > 2: authcode = saslauth[2] if self.devclass: # if there is a devclass it is a bot bumper.bot_add(self.uid, self.uid, self.devclass, "atom", "eco-legacy") self.type = self.BOT xmppserverlog.info("bot authenticated SN: {}".format(self.uid)) # Send response self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>' ) # Success # Client authenticated, move to next state self._set_state("INIT") else: auth = False if bumper.check_authcode(self.uid, authcode): auth = True elif bumper.use_auth == False: auth = True if auth: self.type = self.CONTROLLER bumper.client_add(self.uid, "bumper", self.clientresource) xmppserverlog.info("client authenticated {}".format( self.uid)) # Client authenticated, move to next state self._set_state("INIT") # Send response self.send( '<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>' ) # Success else: # Failed to authenticate self.send( '<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>' ) # Fail except Exception as e: xmppserverlog.exception("{}".format(e))
async def test_devmgr(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing confserver = create_confserver() client = await aiohttp_client(create_app) bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1") # Test PollSCResult postbody = {"td": "PollSCResult"} resp = await client.post("/api/iot/devmanager.do", json=postbody) assert resp.status == 200 text = await resp.text() test_resp = json.loads(text) assert test_resp["ret"] == "ok" # Test HasUnreadMsg postbody = {"td": "HasUnreadMsg"} resp = await client.post("/api/iot/devmanager.do", json=postbody) assert resp.status == 200 text = await resp.text() test_resp = json.loads(text) assert test_resp["ret"] == "ok" assert test_resp["unRead"] == False # Test BotCommand bumper.bot_add("sn_1234", "did_1234", "dev_1234", "res_1234", "eco-ng") bumper.bot_set_mqtt("did_1234", True) postbody = {"toId": "did_1234"} # Test return get status command_getstatus_resp = { "id": "resp_1234", "resp": "<ctl ret='ok' status='idle'/>", "ret": "ok", } bumper.mqtt_helperbot.send_command = mock.MagicMock( return_value=async_return(command_getstatus_resp)) resp = await client.post("/api/iot/devmanager.do", json=postbody) assert resp.status == 200 text = await resp.text() test_resp = json.loads(text) assert test_resp["ret"] == "ok" # Test return fail timeout command_timeout_resp = { "id": "resp_1234", "errno": "timeout", "ret": "fail" } bumper.mqtt_helperbot.send_command = mock.MagicMock( return_value=async_return(command_timeout_resp)) resp = await client.post("/api/iot/devmanager.do", json=postbody) assert resp.status == 200 text = await resp.text() test_resp = json.loads(text) assert test_resp["ret"] == "fail"
async def test_login(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing client = await aiohttp_client(create_app) # Test without user resp = await client.get("/v1/private/us/en/dev_1234/ios/1/0/0/user/login") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["code"] == bumper.RETURN_API_SUCCESS assert "accessToken" in jsonresp["data"] assert "uid" in jsonresp["data"] assert "username" in jsonresp["data"] remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing # Test global_e without user resp = await client.get("/v1/private/us/en/dev_1234/global_e/1/0/0/user/login") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["code"] == bumper.RETURN_API_SUCCESS assert "accessToken" in jsonresp["data"] assert "uid" in jsonresp["data"] assert "username" in jsonresp["data"] # Add a user to db and test with existing users bumper.user_add("testuser") resp = await client.get("/v1/private/us/en/dev_1234/ios/1/0/0/user/login") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["code"] == bumper.RETURN_API_SUCCESS assert "accessToken" in jsonresp["data"] assert "uid" in jsonresp["data"] assert "username" in jsonresp["data"] # Add a bot to db that will be added to user bumper.bot_add("sn_123", "did_123", "dev_123", "res_123", "com_123") resp = await client.get("/v1/private/us/en/dev_1234/ios/1/0/0/user/login") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["code"] == bumper.RETURN_API_SUCCESS assert "accessToken" in jsonresp["data"] assert "uid" in jsonresp["data"] assert "username" in jsonresp["data"]
def test_bot_db(): bumper.db = "tests/tmp.db" # Set db location for testing bumper.bot_add("sn_123", "did_123", "dev_123", "res_123", "co_123") assert_true(bumper.bot_get("did_123")) # Test that bot was added to db bumper.bot_set_nick("did_123", "nick_123") assert_equals(bumper.bot_get("did_123")["nick"], "nick_123") # Test that nick was added to bot bumper.bot_set_mqtt("did_123", True) assert_true(bumper.bot_get("did_123") ["mqtt_connection"]) # Test that mqtt was set True for bot bumper.bot_set_xmpp("did_123", True) assert_true(bumper.bot_get("did_123") ["xmpp_connection"]) # Test that xmpp was set True for bot bumper.bot_remove("did_123") assert_false(bumper.bot_get("did_123")) # Test that bot is no longer in db
async def test_getUserAccountInfo(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing bumper.user_add("testuser") bumper.user_add_device("testuser", "dev_1234") bumper.user_add_token("testuser", "token_1234") bumper.user_add_authcode("testuser", "token_1234", "auth_1234") bumper.user_add_bot("testuser", "did_1234") bumper.bot_add("sn_1234", "did_1234", "class_1234", "res_1234", "com_1234") client = await aiohttp_client(create_app) resp = await client.get( "/v1/private/us/en/dev_1234/global_e/1/0/0/user/getUserAccountInfo") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["code"] == "0000" assert jsonresp["msg"] == "操作成功" assert jsonresp["data"]["userName"] == "fusername_testuser"
def test_login(): if os.path.exists("tests/tmp.db"): os.remove("tests/tmp.db") # Remove existing db bumper.db = "tests/tmp.db" # Set db location for testing loop = asyncio.get_event_loop() client = TestClient(TestServer(app), loop=loop) loop.run_until_complete(client.start_server()) root = "http://{}".format(confserver.address) async def test_handle_login(): resp = await client.get( "/1/private/us/en/dev_1234/ios/1/0/0/user/login") assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) if jsonresp: assert jsonresp["code"] == bumper.RETURN_API_SUCCESS assert "accessToken" in jsonresp["data"] assert "uid" in jsonresp["data"] assert "username" in jsonresp["data"] else: assert jsonresp # Test loop.run_until_complete(test_handle_login()) # Add a user to db and test with existing users bumper.user_add("testuser") # Test loop.run_until_complete(test_handle_login()) # Add a bot to db that will be added to user bumper.bot_add("sn_123", "did_123", "dev_123", "res_123", "com_123") # Test loop.run_until_complete(test_handle_login()) loop.run_until_complete( client.close()) # Close test server after all tests are done
async def test_appsvr_api(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing client = await aiohttp_client(create_app) # Test GetGlobalDeviceList postbody = { "aliliving": False, "appVer": "1.1.6", "auth": { "realm": "ecouser.net", "resource": "ECOGLOBLEac5ae987", "token": "token_1234", "userid": "testuser", "with": "users", }, "channel": "google_play", "defaultLang": "en", "lang": "en", "platform": "Android", "todo": "GetGlobalDeviceList", "userid": "testuser", } resp = await client.post("/api/appsvr/app.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["ret"] == "ok" bumper.bot_add("sn_1234", "did_1234", "ls1ok3", "res_1234", "eco-ng") # Test again with bot added resp = await client.post("/api/appsvr/app.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["ret"] == "ok"
async def test_lg_logs(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing bumper.bot_add("sn_1234", "did_1234", "ls1ok3", "res_1234", "eco-ng") bumper.bot_set_mqtt("did_1234", True) confserver = create_confserver() client = await aiohttp_client(create_app) bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1") # Test return get status command_getstatus_resp = { "id": "resp_1234", "resp": "<ctl ret='ok' status='idle'/>", "ret": "ok", } bumper.mqtt_helperbot.send_command = mock.MagicMock( return_value=async_return(command_getstatus_resp) ) # Test GetGlobalDeviceList postbody = { "auth": { "realm": "ecouser.net", "resource": "ECOGLOBLEac5ae987", "token": "token_1234", "userid": "testuser", "with": "users", }, "did": "did_1234", "resource": "res_1234", "td": "GetCleanLogs", } resp = await client.post("/api/lg/log.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["ret"] == "ok"
async def authenticate(self, *args, **kwargs): authenticated = False try: session = kwargs.get("session", None) username = session.username password = session.password client_id = session.client_id if "@" in client_id: didsplit = str(client_id).split("@") if not ( # if ecouser or bumper aren't in details it is a bot "ecouser" in didsplit[1] or "bumper" in didsplit[1]): tmpbotdetail = str(didsplit[1]).split("/") bumper.bot_add( username, didsplit[0], tmpbotdetail[0], tmpbotdetail[1], "eco-ng", ) mqttserverlog.info( f"Bumper Authentication Success - Bot - SN: {username} - DID: {didsplit[0]} - Class: {tmpbotdetail[0]}" ) authenticated = True else: tmpclientdetail = str(didsplit[1]).split("/") userid = didsplit[0] realm = tmpclientdetail[0] resource = tmpclientdetail[1] if userid == "helperbot": mqttserverlog.info( f"Bumper Authentication Success - Helperbot: {client_id}" ) authenticated = True else: auth = False if bumper.check_authcode(didsplit[0], password): auth = True elif bumper.use_auth == False: auth = True if auth: bumper.client_add(userid, realm, resource) mqttserverlog.info( f"Bumper Authentication Success - Client - Username: {username} - ClientID: {client_id}" ) authenticated = True else: authenticated = False # Check for File Auth if username and not authenticated: # If there is a username and it isn't already authenticated hash = self._users.get(username, None) if hash: # If there is a matching entry in passwd, check hash authenticated = pwd_context.verify(password, hash) if authenticated: mqttserverlog.info( f"File Authentication Success - Username: {username} - ClientID: {client_id}" ) else: mqttserverlog.info( f"File Authentication Failed - Username: {username} - ClientID: {client_id}" ) else: mqttserverlog.info( f"File Authentication Failed - No Entry for Username: {username} - ClientID: {client_id}" ) except Exception as e: mqttserverlog.exception("Session: {} - {}".format( (kwargs.get("session", None)), e)) authenticated = False # Check for allow anonymous allow_anonymous = self.auth_config.get("allow-anonymous", True) if allow_anonymous and not authenticated: # If anonymous auth is allowed and it isn't already authenticated authenticated = True self.context.logger.debug( f"Anonymous Authentication Success: config allows anonymous - Username: {username}" ) mqttserverlog.info( f"Anonymous Authentication Success: config allows anonymous - Username: {username}" ) return authenticated
async def test_postUsersAPI(aiohttp_client): remove_existing_db() bumper.db = "tests/tmp.db" # Set db location for testing client = await aiohttp_client(create_app) # Test FindBest postbody = {"todo": "FindBest", "service": "EcoMsgNew"} resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test EcoUpdate postbody = {"todo": "FindBest", "service": "EcoUpdate"} resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test loginByItToken - Uses the authcode bumper.user_add("testuser") bumper.user_add_device("testuser", "dev_1234") bumper.user_add_token("testuser", "token_1234") bumper.user_add_authcode("testuser", "token_1234", "auth_1234") bumper.user_add_bot("testuser", "did_1234") bumper.bot_add("sn_1234", "did_1234", "class_1234", "res_1234", "com_1234") # Test postbody = { "country": "US", "last": "", "realm": "ecouser.net", "resource": "dev_1234", "todo": "loginByItToken", "token": "auth_1234", "userId": "testuser", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test as EcoVacs Home (global_e) postbody = { "country": "US", "edition": "ECOGLOBLE", "last": "", "org": "ECOWW", "resource": "dev_1234", "todo": "loginByItToken", "token": "auth_1234", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test as EcoVacs Home (global_e) & Post Form postbody = { "country": "US", "edition": "ECOGLOBLE", "last": "", "org": "ECOWW", "resource": "dev_1234", "todo": "loginByItToken", "token": "auth_1234", } resp = await client.post("/api/users/user.do", data=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test GetDeviceList postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "GetDeviceList", "userid": "testuser", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test SetDeviceNick postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "SetDeviceNick", "nick": "botnick", "did": "did_1234", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test AddOneDevice - Same as set nick for some bots postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "AddOneDevice", "nick": "botnick", "did": "did_1234", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok" # Test DeleteOneDevice - remove bot postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "DeleteOneDevice", "did": "did_1234", } resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) assert jsonresp["result"] == "ok"
async def authenticate(self, *args, **kwargs): if not self.auth_config: # auth config section not found self.context.logger.warning( "'auth' section not found in context configuration" ) return False allow_anonymous = self.auth_config.get( "allow-anonymous", True ) # allow anonymous by default if allow_anonymous: authenticated = True self.context.logger.debug("Authentication success: config allows anonymous") else: try: session = kwargs.get("session", None) username = session.username password = session.password client_id = session.client_id didsplit = str(client_id).split("@") # If this isn't a fake user (fuid) then add as a bot if not ( str(didsplit[0]).startswith("fuid") or str(didsplit[0]).startswith("helper") ): tmpbotdetail = str(didsplit[1]).split("/") bumper.bot_add( username, didsplit[0], tmpbotdetail[0], tmpbotdetail[1], "eco-ng", ) mqttserverlog.debug( "new bot authenticated SN: {} DID: {}".format( username, didsplit[0] ) ) authenticated = True else: tmpclientdetail = str(didsplit[1]).split("/") userid = didsplit[0] realm = tmpclientdetail[0] resource = tmpclientdetail[1] if userid == "helper1": authenticated = True else: auth = False if bumper.check_authcode(didsplit[0], password): auth = True elif bumper.use_auth == False: auth = True if auth: bumper.client_add(userid, realm, resource) mqttserverlog.debug( "client authenticated {}".format(userid) ) authenticated = True else: authenticated = False except Exception as e: mqttserverlog.exception("Session: {} - {}".format((kwargs.get("session", None)),e)) authenticated = False return authenticated
def test_devmgr(): if os.path.exists("tests/tmp.db"): os.remove("tests/tmp.db") # Remove existing db bumper.db = "tests/tmp.db" # Set db location for testing loop = asyncio.get_event_loop() client = TestClient(TestServer(app), loop=loop) loop.run_until_complete(client.start_server()) root = "http://{}".format(confserver.address) async def test_devmanager(postbody=None, command=False): resp = await client.post("/api/iot/devmanager.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) if jsonresp: if not command: assert jsonresp["ret"] == "ok" else: if "ret" in jsonresp: if jsonresp["ret"] == "ok": assert jsonresp["resp"] else: assert jsonresp["errno"] else: assert jsonresp # Test PollSCResult postbody = {"td": "PollSCResult"} # Test loop.run_until_complete(test_devmanager(postbody, command=False)) # Test BotCommand bumper.bot_add("sn_1234", "did_1234", "dev_1234", "res_1234", "eco-ng") bumper.bot_set_mqtt("did_1234", True) postbody = {"toId": "did_1234"} # Test return get status command_getstatus_resp = { "id": "resp_1234", "resp": "<ctl ret='ok' status='idle'/>", "ret": "ok" } confserver.helperbot.send_command = mock.MagicMock( return_value=async_return(command_getstatus_resp)) # Test loop.run_until_complete(test_devmanager(postbody, command=True)) # Test return fail timeout command_timeout_resp = { "id": "resp_1234", "errno": "timeout", "ret": "fail" } confserver.helperbot.send_command = mock.MagicMock( return_value=async_return(command_timeout_resp)) # Test loop.run_until_complete(test_devmanager(postbody, command=True)) # Set bot not on mqtt bumper.bot_set_mqtt("did_1234", False) confserver.helperbot.send_command = mock.MagicMock( return_value=async_return(command_getstatus_resp)) # Test loop.run_until_complete(test_devmanager(postbody, command=True)) loop.run_until_complete( client.close()) # Close test server after all tests are done
def test_postUsersAPI(): if os.path.exists("tests/tmp.db"): os.remove("tests/tmp.db") # Remove existing db bumper.db = "tests/tmp.db" # Set db location for testing loop = asyncio.get_event_loop() client = TestClient(TestServer(app), loop=loop) loop.run_until_complete(client.start_server()) root = "http://{}".format(confserver.address) async def test_handle_postUsersApi(postbody=None): resp = await client.post("/api/users/user.do", json=postbody) assert resp.status == 200 text = await resp.text() jsonresp = json.loads(text) if jsonresp: assert jsonresp["result"] == "ok" else: assert jsonresp # Test FindBest postbody = {"todo": "FindBest", "service": "EcoMsgNew"} # Test loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test EcoUpdate postbody = {"todo": "FindBest", "service": "EcoUpdate"} # Test loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test loginByItToken - Uses the authcode bumper.user_add("testuser") bumper.user_add_device("testuser", "dev_1234") bumper.user_add_token("testuser", "token_1234") bumper.user_add_authcode("testuser", "token_1234", "auth_1234") bumper.user_add_bot("testuser", "did_1234") bumper.bot_add("sn_1234", "did_1234", "class_1234", "res_1234", "com_1234") # Test postbody = { "country": "US", "last": "", "realm": "ecouser.net", "resource": "dev_1234", "todo": "loginByItToken", "token": "auth_1234", "userId": "testuser", } loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test GetDeviceList postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "GetDeviceList", "userid": "testuser", } loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test SetDeviceNick postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "SetDeviceNick", "nick": "botnick", "did": "did_1234", } loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test AddOneDevice - Same as set nick for some bots postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "AddOneDevice", "nick": "botnick", "did": "did_1234", } loop.run_until_complete(test_handle_postUsersApi(postbody)) # Test DeleteOneDevice - remove bot postbody = { "auth": { "realm": "ecouser.net", "resource": "dev_1234", "token": "token_1234", "userid": "testuser", "with": "users", }, "todo": "DeleteOneDevice", "did": "did_1234", } loop.run_until_complete(test_handle_postUsersApi(postbody)) loop.run_until_complete( client.close()) # Close test server after all tests are done
def _handle_iq_auth(self, data): try: xml = ET.fromstring(data.decode("utf-8")) ctl = xml[0][0] xmppserverlog.info("IQ AUTH XML: {}".format(xml)) # Received username and auth tag, send username/password requirement if ( xml.get("type") == "get" and "auth}username" in ctl.tag and self.type == self.UNKNOWN ): self.send( '<iq type="result" id="{}"><query xmlns="jabber:iq:auth"><username/><password/></query></iq>'.format( xml.get("id") ) ) # Received username, password, resource - Handle auth here and return pass or fail if ( xml.get("type") == "set" and "auth}username" in ctl.tag and self.type == self.UNKNOWN ): xmlauth = xml[0].getchildren() # uid = "" password = "" resource = "" for aitem in xmlauth: if "username" in aitem.tag: self.uid = aitem.text elif "password" in aitem.tag: password = aitem.text.split("/")[2] authcode = password elif "resource" in aitem.tag: self.clientresource = aitem.text resource = self.clientresource if not self.uid.startswith("fuid"): # Need sample data to see details here bumper.bot_add("", self.uid, "", resource, "eco-legacy") xmppserverlog.info("bot authenticated {}".format(self.uid)) # Client authenticated, move to next state self._set_state("INIT") # Successful auth self.send('<iq type="result" id="{}"/>'.format(xml.get("id"))) else: auth = False if bumper.check_authcode(self.uid, authcode): auth = True elif bumper.use_auth == False: auth = True if auth: bumper.client_add(self.uid, "bumper", self.clientresource) xmppserverlog.debug("client authenticated {}".format(self.uid)) # Client authenticated, move to next state self._set_state("INIT") # Successful auth self.send('<iq type="result" id="{}"/>'.format(xml.get("id"))) else: # Failed auth self.send( '<iq type="error" id="{}"><error code="401" type="auth"><not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format( xml.get("id") ) ) except ET.ParseError as e: if "no element found" in e.msg: xmppserverlog.debug( "xml parse error - {} - {}".format(data.decode("utf-8"), e) ) elif "not well-formed (invalid token)" in e.msg: xmppserverlog.debug( "xml parse error - {} - {}".format(data.decode("utf-8"), e) ) else: xmppserverlog.debug( "xml parse error - {} - {}".format(data.decode("utf-8"), e) ) except Exception as e: xmppserverlog.exception("{}".format(e))