2019-05-19 13:23:03 +00:00
|
|
|
|
#!/usr/bin/python3
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
#
|
|
|
|
|
# script to emulate client khanat
|
|
|
|
|
#
|
|
|
|
|
# Copyright (C) 2019 AleaJactaEst
|
|
|
|
|
#
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
2019-05-30 17:22:22 +00:00
|
|
|
|
# Ex.: ./client.py --khanat-host 172.17.0.3 -d --size-buffer-file 10241024
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
# Modifier les droits pour les nouveaux joueurs (accès à tout)
|
|
|
|
|
# mysql -u root -e "use nel_ams_lib;UPDATE settings SET Value = 7 WHERE settings.Setting = 'Domain_Auto_Add';"
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import http.client
|
|
|
|
|
import crypt
|
|
|
|
|
import logging
|
2019-05-30 17:19:54 +00:00
|
|
|
|
import os
|
2019-05-19 13:23:03 +00:00
|
|
|
|
import os.path
|
|
|
|
|
import sys
|
|
|
|
|
import urllib.request
|
|
|
|
|
import urllib.parse
|
|
|
|
|
import tempfile
|
2019-10-24 17:45:24 +00:00
|
|
|
|
#from enum import IntEnum
|
|
|
|
|
#from ctypes import *
|
2019-05-19 13:23:03 +00:00
|
|
|
|
import re
|
|
|
|
|
import random
|
|
|
|
|
import lzma
|
2019-10-24 17:45:24 +00:00
|
|
|
|
#import socket
|
|
|
|
|
#import xml.etree.ElementTree as ET
|
|
|
|
|
#import hashlib
|
|
|
|
|
#import time
|
|
|
|
|
#import signal
|
|
|
|
|
#from tools import BitStream
|
|
|
|
|
#from tools import CCharacterSummary
|
|
|
|
|
#from tools import CBitSet
|
|
|
|
|
#from tools import getPowerOf2
|
|
|
|
|
#from tools import CFileChild
|
|
|
|
|
#from tools import CFileList
|
|
|
|
|
from tools import CFileContainer
|
|
|
|
|
#from tools import Enum
|
|
|
|
|
#from tools import World
|
|
|
|
|
#from tools import CActionFactory
|
|
|
|
|
#from tools import CSessionId
|
|
|
|
|
#from tools import CGenericMultiPartTemp
|
|
|
|
|
#from tools import CMainlandSummary
|
|
|
|
|
#from tools import CAction
|
|
|
|
|
#from tools import DecodeImpulse
|
|
|
|
|
#from tools import CImpulseDecoder
|
|
|
|
|
#from tools import CodeMsgXml
|
|
|
|
|
from tools import CPersistentDataRecord
|
|
|
|
|
from tools import ClientNetworkConnection
|
|
|
|
|
from tools import CStringManager
|
|
|
|
|
|
|
|
|
|
#INVALID_SLOT = 0xff
|
|
|
|
|
LOGGER = 'Client'
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
class ClientKhanat:
|
|
|
|
|
def __init__(self,
|
2019-05-30 17:19:54 +00:00
|
|
|
|
khanat_host,
|
|
|
|
|
khanat_port_login = 40916,
|
|
|
|
|
khanat_port_frontend = 47851,
|
2019-05-19 13:23:03 +00:00
|
|
|
|
login="tester",
|
|
|
|
|
password="tester",
|
|
|
|
|
clientApp="Lirria",
|
|
|
|
|
LanguageCode="fr",
|
|
|
|
|
url="/login/r2_login.php",
|
2019-05-19 13:29:43 +00:00
|
|
|
|
suffix = None,
|
2019-05-19 14:10:18 +00:00
|
|
|
|
download_patch = False,
|
2019-05-30 17:19:54 +00:00
|
|
|
|
show_patch_detail=False,
|
|
|
|
|
size_buffer_file=1024):
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
if suffix is None:
|
|
|
|
|
suffix = str(random.randrange(1, 9999))
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("suffix : %s" % suffix)
|
2019-05-19 13:29:43 +00:00
|
|
|
|
|
|
|
|
|
self.download_patch = download_patch
|
2019-05-19 14:10:18 +00:00
|
|
|
|
self.show_patch_detail = show_patch_detail
|
2019-05-30 17:19:54 +00:00
|
|
|
|
self.khanat_host = khanat_host
|
|
|
|
|
self.khanat_port_login = khanat_port_login
|
|
|
|
|
self.khanat_port_frontend = khanat_port_frontend
|
2019-05-19 13:23:03 +00:00
|
|
|
|
self.login = login + suffix
|
|
|
|
|
self.password = password
|
|
|
|
|
self.clientApp = clientApp
|
|
|
|
|
self.LanguageCode = LanguageCode
|
|
|
|
|
self.url = url
|
|
|
|
|
self.cookie, self.fsaddr, self.ringmainurl, self.fartp, self.stat, self.r2serverversion, self.r2backuppatchurl, self.r2patchurl = None, None, None, None, None, None, None, None
|
|
|
|
|
self.tempdir = tempfile.TemporaryDirectory(".khanat")
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("Temporary directory:%s" % self.tempdir)
|
|
|
|
|
self.khanat_idx = CPersistentDataRecord.CPersistentDataRecord()
|
2019-05-19 13:23:03 +00:00
|
|
|
|
self.UserAddr, self.UserKey, self.UserId = None, None, None
|
2019-10-24 17:45:24 +00:00
|
|
|
|
self.clientNetworkConnection = ClientNetworkConnection.ClientNetworkConnection(self.khanat_host, self.khanat_port_frontend, self.login)
|
2019-05-30 17:19:54 +00:00
|
|
|
|
self.size_buffer_file = size_buffer_file
|
2019-10-24 17:45:24 +00:00
|
|
|
|
self.cFileContainer = CFileContainer.CFileContainer()
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
def createAccount(self):
|
2019-05-30 17:19:54 +00:00
|
|
|
|
conn = http.client.HTTPConnection(host=self.khanat_host, port=self.khanat_port_login)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
cmd = "/ams/index.php?page=register"
|
|
|
|
|
headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
|
|
|
'Accept-Language' : 'en-US',
|
|
|
|
|
'Connection': 'keep-alive',
|
|
|
|
|
'DNT': '1',
|
|
|
|
|
'Cookie': 'PHPSESSID=lsoumn9f0ljgm3vo3hgjdead03',
|
2019-05-30 17:19:54 +00:00
|
|
|
|
'Host': self.khanat_host+':'+ str(self.khanat_port_login),
|
|
|
|
|
'Referer': 'http://' + self.khanat_host+':'+ str(self.khanat_port_login) + '/ams/index.php?page=register',
|
2019-05-19 13:23:03 +00:00
|
|
|
|
'Upgrade-Insecure-Requests': '1',
|
|
|
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20100101 Firefox/6.0',
|
2020-04-11 21:52:41 +00:00
|
|
|
|
'': 'application/x-www-form-urlencoded'}
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
|
|
|
|
params = urllib.parse.urlencode({'Username': self.login, 'Password': self.password, 'ConfirmPass': self.password, 'Email': self.login+'@khaganat.net', 'TaC': 'on', 'function': 'add_user'})
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("POST %s" % (cmd))
|
|
|
|
|
print( "host%s, port:%s" % (self.khanat_host, str(self.khanat_port_login)))
|
|
|
|
|
print("cmd:%s" % cmd)
|
|
|
|
|
print("params:%s" % params)
|
|
|
|
|
print("headers:%s" % headers)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
conn.request("POST", cmd, params, headers)
|
|
|
|
|
response = conn.getresponse()
|
|
|
|
|
if ( int(response.status) == 302 ):
|
|
|
|
|
conn.close()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("Account created : %s" % self.login)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
return
|
|
|
|
|
elif ( int(response.status) != 200 ):
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to create account (return code:" + str(response.status) + ")")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
ret = response.read()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
print("ret:%s" % ret)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
ret2 = ret.decode()
|
|
|
|
|
try:
|
|
|
|
|
state, comment = ret2.split(":", 2)
|
|
|
|
|
except:
|
|
|
|
|
state = 1
|
|
|
|
|
comment = ""
|
|
|
|
|
if int(state) != 1:
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to create account (state:" + state + ", comment:" + comment.strip() + ")")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
|
|
errordetected = False
|
|
|
|
|
for line in ret2.split('\n'):
|
2019-10-24 17:45:24 +00:00
|
|
|
|
m = re.search("(<strong>(?P<type>.*) Error</strong> )(?P<comment>[^.]+)", line)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
if m:
|
|
|
|
|
if m.group('comment') == 'Username ' + self.login + ' is in use':
|
|
|
|
|
continue
|
|
|
|
|
if m.group('comment') == 'Email is in use':
|
|
|
|
|
continue
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error('Impossible to create account: field:%s (%s)' % (m.group('type'), m.group('comment')))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
errordetected = True
|
|
|
|
|
if errordetected:
|
|
|
|
|
sys.exit(2)
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("Reuse account : %s" % self.login)
|
|
|
|
|
sys.exit(0)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
def connectR2(self):
|
2019-05-30 17:19:54 +00:00
|
|
|
|
conn = http.client.HTTPConnection(host=self.khanat_host, port=self.khanat_port_login)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
cmd = self.url + "?cmd=ask&cp=2&login=" + self.login + "&lg=" + self.LanguageCode
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("GET %s" % (cmd))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
conn.request("GET", cmd)
|
|
|
|
|
response = conn.getresponse()
|
|
|
|
|
if ( int(response.status) != 200 ):
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to get salt (return code:" + str(response.status) + ")")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
ret = response.read()
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
state, salt = ret.decode().split(":", 1)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
try:
|
|
|
|
|
state, salt = ret.decode(encoding='cp1252').split(":", 1)
|
|
|
|
|
except UnicodeDecodeError:
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to read output login")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
if int(state) != 1:
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to get salt (state:" + state + ")")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
cryptedPassword = crypt.crypt(self.password, salt)
|
|
|
|
|
|
2019-05-30 17:19:54 +00:00
|
|
|
|
conn = http.client.HTTPConnection(host=self.khanat_host, port=self.khanat_port_login)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
cmd = self.url + "?cmd=login&login=" + self.login + "&password=" + cryptedPassword + "&clientApplication=" + self.clientApp + "&cp=2" + "&lg=" + self.LanguageCode
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("GET %s" % (cmd))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
conn.request("GET", cmd)
|
|
|
|
|
response = conn.getresponse()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("%s %s" %(response.status, response.reason))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
ret = response.read()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug(ret)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
try:
|
|
|
|
|
line = ret.decode().split('\n')
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
try:
|
|
|
|
|
line = ret.decode(encoding='cp1252').split('\n')
|
|
|
|
|
except UnicodeDecodeError:
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error("Impossible to read output login")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug(line[0])
|
|
|
|
|
logging.getLogger(LOGGER).debug("line 0 '%s'" % line[0])
|
|
|
|
|
logging.getLogger(LOGGER).debug("line 1 '%s'" % line[1])
|
2019-05-19 13:23:03 +00:00
|
|
|
|
try:
|
|
|
|
|
state, self.cookie, self.fsaddr, self.ringmainurl, self.fartp, self.stat = line[0].split("#", 6)
|
|
|
|
|
except:
|
|
|
|
|
try:
|
|
|
|
|
state, self.cookie, self.fsaddr, self.ringmainurl, self.fartp = line[0].split("#", 5)
|
|
|
|
|
self.stat = 0
|
|
|
|
|
except:
|
|
|
|
|
state, error = line[0].split(":", 1)
|
|
|
|
|
|
|
|
|
|
if int(state) != 1:
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).error(error)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
|
|
self.r2serverversion, self.r2backuppatchurl, self.r2patchurl = line[1].split("#")
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("%s %s %s %s %s %s %s %s %s" % (state, self.cookie, self.fsaddr, self.ringmainurl, self.fartp, self.stat, self.r2serverversion, self.r2backuppatchurl, self.r2patchurl))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
self.UserAddr, self.UserKey, self.UserId = [ int(x, 16) for x in self.cookie.split('|') ]
|
|
|
|
|
|
|
|
|
|
conn.close()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("Login Ok")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
self.clientNetworkConnection.cookiesInit(self.UserAddr, self.UserKey, self.UserId)
|
|
|
|
|
|
|
|
|
|
def downloadFileUrl(self, source, dest):
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("Download %s (destination:%s)" % (source, dest))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
with urllib.request.urlopen(source) as conn :
|
|
|
|
|
header = conn.getheaders()
|
|
|
|
|
file_size = 0
|
|
|
|
|
for key, value in header:
|
|
|
|
|
if key == 'Content-Length':
|
|
|
|
|
file_size = int(value)
|
|
|
|
|
break
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("size:%d", file_size)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
file_size_dl = 0
|
2019-05-30 17:19:54 +00:00
|
|
|
|
block_size = self.size_buffer_file # 1024
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
with open(dest, 'wb') as fp:
|
|
|
|
|
while True:
|
|
|
|
|
buffer = conn.read(block_size)
|
|
|
|
|
if not buffer:
|
|
|
|
|
break
|
|
|
|
|
file_size_dl += len(buffer)
|
|
|
|
|
fp.write(buffer)
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("Download %s %10d [%6.2f%%]" % (source, file_size_dl, file_size_dl * 100. / file_size))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
fp.close()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("Downloaded %s (%d)" % (source, file_size))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
def getServerFile(self, name, bZipped = False, specifyDestName = None):
|
|
|
|
|
srcName = name
|
|
|
|
|
if specifyDestName:
|
|
|
|
|
dstName = specifyDestName
|
|
|
|
|
else:
|
|
|
|
|
dstName = os.path.basename(name)
|
|
|
|
|
if bZipped:
|
|
|
|
|
srcName += ".ngz"
|
|
|
|
|
dstName += ".ngz"
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("Download %s (destination:%s, zip:%d)" % (srcName, dstName, bZipped))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
dstName = os.path.join(self.tempdir.name, dstName)
|
|
|
|
|
self.downloadFileUrl( 'http://' + self.r2patchurl + '/' + srcName, dstName)
|
|
|
|
|
return dstName
|
|
|
|
|
|
|
|
|
|
def downloadAllPatch(self):
|
2019-05-19 13:29:43 +00:00
|
|
|
|
# TODO - check where client search file to download
|
2019-05-19 13:23:03 +00:00
|
|
|
|
for file in self.khanat_idx.CBNPFile:
|
|
|
|
|
tmp = self.getServerFile("%05d/%s.lzma" % (int(self.r2serverversion), file.FileName), False, "")
|
|
|
|
|
with lzma.open(tmp) as fin:
|
|
|
|
|
dstName = os.path.join(self.tempdir.name, file.FileName)
|
|
|
|
|
with open(dstName, "wb") as fout:
|
|
|
|
|
data = fin.read()
|
|
|
|
|
fout.write(data)
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("%s" % dstName)
|
2019-05-30 17:19:54 +00:00
|
|
|
|
os.remove(tmp)
|
|
|
|
|
# khanat-opennel-code/code/ryzom/client/src/login_patch.cpp # void CCheckThread::run ()
|
|
|
|
|
FilesToPatch = []
|
|
|
|
|
for file in self.khanat_idx.CBNPFile:
|
|
|
|
|
FilesToPatch.append(file)
|
|
|
|
|
# Here we got all the files to patch in FilesToPatch and all the versions that must be obtained Now we have to get the optional categories
|
|
|
|
|
OptionalCat = []
|
|
|
|
|
for category in self.khanat_idx.Categories:
|
|
|
|
|
if category._IsOptional:
|
|
|
|
|
for file in category._Files:
|
|
|
|
|
bAdded = False
|
|
|
|
|
for file2 in FilesToPatch:
|
|
|
|
|
if file2 == file:
|
|
|
|
|
OptionalCat.append(category._Name)
|
|
|
|
|
bAdded = True
|
|
|
|
|
break
|
|
|
|
|
if bAdded:
|
|
|
|
|
break
|
|
|
|
|
# For all categories that required an optional category if the cat required is present the category that reference it must be present
|
|
|
|
|
for category in self.khanat_idx.Categories:
|
|
|
|
|
if category._IsOptional and not len(category._CatRequired) == 0:
|
|
|
|
|
bFound = False
|
|
|
|
|
for cat in OptionalCat:
|
|
|
|
|
if category._Name == cat:
|
|
|
|
|
bFound = True
|
|
|
|
|
break
|
|
|
|
|
if bFound:
|
|
|
|
|
for cat in OptionalCat:
|
|
|
|
|
if category._CatRequired == cat:
|
|
|
|
|
OptionalCat.append(category._Name)
|
|
|
|
|
break
|
|
|
|
|
# Delete categories optional cat that are hidden
|
|
|
|
|
for category in self.khanat_idx.Categories:
|
|
|
|
|
if category._IsOptional and category._Hidden:
|
|
|
|
|
for cat in OptionalCat:
|
|
|
|
|
if category._Name == cat:
|
|
|
|
|
OptionalCat.remove(category._Name)
|
|
|
|
|
break
|
|
|
|
|
# Get all extract to category and check files inside the bnp with real files
|
|
|
|
|
for category in self.khanat_idx.Categories:
|
|
|
|
|
if len(category._UnpackTo) != 0:
|
|
|
|
|
for file in category._Files:
|
|
|
|
|
# TODO
|
|
|
|
|
# readHeader()
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def DownloadMinimum(self):
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).debug("-" * 80)
|
2019-05-30 17:19:54 +00:00
|
|
|
|
for file in self.khanat_idx.CBNPFile:
|
|
|
|
|
if file.FileName != "kh_server.bnp":
|
|
|
|
|
continue
|
|
|
|
|
tmp = self.getServerFile("%05d/%s.lzma" % (int(self.r2serverversion), file.FileName), False, "")
|
|
|
|
|
with lzma.open(tmp) as fin:
|
|
|
|
|
dstName = os.path.join(self.tempdir.name, file.FileName)
|
|
|
|
|
with open(dstName, "wb") as fout:
|
|
|
|
|
data = fin.read()
|
|
|
|
|
fout.write(data)
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("%s" % dstName)
|
2019-05-30 17:19:54 +00:00
|
|
|
|
os.remove(tmp)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
def Emulate(self):
|
|
|
|
|
self.createAccount()
|
|
|
|
|
self.connectR2()
|
|
|
|
|
# download patch
|
|
|
|
|
self.ryzomidx = self.getServerFile("%05d/ryzom_%05d.idx" % (int(self.r2serverversion), int(self.r2serverversion)), False, "")
|
|
|
|
|
self.khanat_idx.readFromBinFile(self.ryzomidx)
|
|
|
|
|
self.khanat_idx.CProductDescriptionForClient_apply()
|
|
|
|
|
# Show detail patch
|
2019-05-19 14:10:18 +00:00
|
|
|
|
if self.show_patch_detail:
|
|
|
|
|
self.khanat_idx.decrypt_token()
|
|
|
|
|
self.khanat_idx.show()
|
2019-05-19 13:23:03 +00:00
|
|
|
|
# Todo analyze patch and download if necessary or update if incremental - see category
|
|
|
|
|
# Download all file in patch - login_patch.cpp:2578 # void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP)
|
2019-05-19 13:29:43 +00:00
|
|
|
|
if self.download_patch:
|
|
|
|
|
self.downloadAllPatch()
|
2019-05-30 17:19:54 +00:00
|
|
|
|
else:
|
|
|
|
|
self.DownloadMinimum()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
self.cFileContainer = CFileContainer.CFileContainer()
|
2019-05-30 17:19:54 +00:00
|
|
|
|
self.cFileContainer.addSearchPath(self.tempdir.name)
|
2019-05-30 17:37:42 +00:00
|
|
|
|
msgRawXml = self.cFileContainer.getdata("msg.xml").decode()
|
|
|
|
|
databaseRawXml = self.cFileContainer.getdata("database.xml").decode()
|
|
|
|
|
self.clientNetworkConnection.EmulateFirst(msgRawXml, databaseRawXml)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
FORMAT = '%(asctime)-15s %(levelname)s %(filename)s:%(lineno)d %(message)s'
|
|
|
|
|
logging.basicConfig(format=FORMAT)
|
2019-10-24 17:45:24 +00:00
|
|
|
|
|
|
|
|
|
logger = []
|
|
|
|
|
logger.append(logging.getLogger(LOGGER))
|
|
|
|
|
#logger.append(logging.getLogger(CImpulseDecoder.LOGGER))
|
|
|
|
|
#logger.append(logging.getLogger(DecodeImpuls.LOGGER))
|
|
|
|
|
#logger.append(logging.getLogger(BitStream.LOGGER))
|
|
|
|
|
logger.append(logging.getLogger(CStringManager.LOGGER))
|
|
|
|
|
logger.append(logging.getLogger(CPersistentDataRecord.LOGGER))
|
|
|
|
|
logger.append(logging.getLogger(ClientNetworkConnection.LOGGER))
|
|
|
|
|
logger.append(logging.getLogger(LOGGER))
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
2019-05-30 17:19:54 +00:00
|
|
|
|
parser.add_argument("--khanat-host", help="khanat host to auhtenticate", default='localhost')
|
2019-05-19 13:23:03 +00:00
|
|
|
|
parser.add_argument("--suffix", help="define suffix")
|
|
|
|
|
parser.add_argument("-d", "--debug", help="show debug message", action='store_true')
|
2019-05-19 13:29:43 +00:00
|
|
|
|
parser.add_argument("-p", "--download-patch", help="show debug message", action='store_true')
|
2019-05-19 14:10:18 +00:00
|
|
|
|
parser.add_argument("-s", "--show-patch-detail", help="show debug message", action='store_true')
|
2019-05-30 17:19:54 +00:00
|
|
|
|
parser.add_argument("--size-buffer-file", help="size buffer to download file", type=int, default=1024)
|
|
|
|
|
parser.add_argument("--khanat-port-login", help="port http login", type=int, default=40916)
|
|
|
|
|
parser.add_argument("--khanat-port-frontend", help="port UDP frontend", type=int, default=47851)
|
|
|
|
|
|
2019-05-19 13:23:03 +00:00
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
|
level = logging.getLevelName('DEBUG')
|
|
|
|
|
else:
|
|
|
|
|
level = logging.getLevelName('INFO')
|
2019-10-24 17:45:24 +00:00
|
|
|
|
|
|
|
|
|
for logid in logger:
|
|
|
|
|
logid.setLevel(level)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
2019-05-30 17:19:54 +00:00
|
|
|
|
client = ClientKhanat(args.khanat_host, khanat_port_login=args.khanat_port_login, khanat_port_frontend=args.khanat_port_frontend, suffix=args.suffix, download_patch=args.download_patch, show_patch_detail=args.show_patch_detail, size_buffer_file=args.size_buffer_file)
|
2019-05-19 13:23:03 +00:00
|
|
|
|
client.Emulate()
|
2019-10-24 17:45:24 +00:00
|
|
|
|
logging.getLogger(LOGGER).info("End")
|
2019-05-19 13:23:03 +00:00
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2019-05-31 17:25:04 +00:00
|
|
|
|
#TestBitStream()
|
|
|
|
|
#TestCBitSet()
|
2019-05-19 14:10:18 +00:00
|
|
|
|
main()
|