├── hust-network.conf ├── upx.exe ├── requirements.txt ├── icon └── network.png ├── icon.qrc ├── systemd └── hust-network.service ├── README.md ├── .gitignore ├── HustNetwork.py ├── HustNetwork_GUI.py └── rc_icon.py /hust-network.conf: -------------------------------------------------------------------------------- 1 | {校园网用户名} 2 | {校园网密码} -------------------------------------------------------------------------------- /upx.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywang-wnlo/HustNetwork/HEAD/upx.exe -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyinstaller==6.3.0 2 | PySide6==6.6.1 3 | requests==2.31.0 4 | -------------------------------------------------------------------------------- /icon/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywang-wnlo/HustNetwork/HEAD/icon/network.png -------------------------------------------------------------------------------- /icon.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon/network.png 4 | 5 | -------------------------------------------------------------------------------- /systemd/hust-network.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=HUST Network Service 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | User={安装了python3环境的任意用户} 8 | Restart=on-failure 9 | RestartSec=5s 10 | ExecStart={HustNetwork.py的绝对路径} {hust-network.conf的绝对路径} 11 | ExecReload={HustNetwork.py的绝对路径} {hust-network.conf的绝对路径} 12 | LimitNOFILE=1048576 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HustNetwork 2 | 3 | 已毕业,无环境进行后续适配 4 | 5 | ## 功能 6 | 7 | 有库依赖,自动认证华科校园网,并支持断线重连,还有适用于 Window 的 GUI 版本 8 | 9 | ## 使用 10 | 11 | 无需在路由器上,任何(通过通过路由器的)接入校园网的设备均可运行 12 | 13 | ```bash 14 | python3 HustNetwork.py hust-network.conf 15 | python3 HustNetwork_GUI.py 16 | HustNetwork_GUI.exe 17 | ``` 18 | 19 | 其中 hust-network.conf 中内容依次为校园网账号和密码 20 | 21 | 程序需保持一直运行,推荐使用 screen 或者 systemctl 配置成 service 挂在后台 22 | 23 | ## 其他相关项目推荐 24 | 25 | - Rust 二进制文件:https://github.com/black-binary/hust-network-login 26 | - Shell 版本:https://github.com/jyi2ya/hust-network-login-sh 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/python,venv 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,venv 4 | 5 | ### Python ### 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | cover/ 58 | 59 | # Translations 60 | *.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | local_settings.py 66 | db.sqlite3 67 | db.sqlite3-journal 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | .pybuilder/ 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | # For a library or package, you might want to ignore these files since the code is 92 | # intended to run in multiple environments; otherwise, check them in: 93 | # .python-version 94 | 95 | # pipenv 96 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 97 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 98 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 99 | # install all needed dependencies. 100 | #Pipfile.lock 101 | 102 | # poetry 103 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 104 | # This is especially recommended for binary packages to ensure reproducibility, and is more 105 | # commonly ignored for libraries. 106 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 107 | #poetry.lock 108 | 109 | # pdm 110 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 111 | #pdm.lock 112 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 113 | # in version control. 114 | # https://pdm.fming.dev/#use-with-ide 115 | .pdm.toml 116 | 117 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 118 | __pypackages__/ 119 | 120 | # Celery stuff 121 | celerybeat-schedule 122 | celerybeat.pid 123 | 124 | # SageMath parsed files 125 | *.sage.py 126 | 127 | # Environments 128 | .env 129 | .venv 130 | env/ 131 | venv/ 132 | ENV/ 133 | env.bak/ 134 | venv.bak/ 135 | 136 | # Spyder project settings 137 | .spyderproject 138 | .spyproject 139 | 140 | # Rope project settings 141 | .ropeproject 142 | 143 | # mkdocs documentation 144 | /site 145 | 146 | # mypy 147 | .mypy_cache/ 148 | .dmypy.json 149 | dmypy.json 150 | 151 | # Pyre type checker 152 | .pyre/ 153 | 154 | # pytype static type analyzer 155 | .pytype/ 156 | 157 | # Cython debug symbols 158 | cython_debug/ 159 | 160 | # PyCharm 161 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 162 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 163 | # and can be added to the global gitignore or merged into this file. For a more nuclear 164 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 165 | #.idea/ 166 | 167 | ### venv ### 168 | # Virtualenv 169 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 170 | [Bb]in 171 | [Ii]nclude 172 | [Ll]ib 173 | [Ll]ib64 174 | [Ll]ocal 175 | [Ss]cripts 176 | pyvenv.cfg 177 | pip-selfcheck.json 178 | 179 | # End of https://www.toptal.com/developers/gitignore/api/python,venv 180 | 181 | -------------------------------------------------------------------------------- /HustNetwork.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import re 5 | import sys 6 | import time 7 | import math 8 | import subprocess 9 | 10 | import requests 11 | 12 | HUST_DNS = "202.114.0.242" 13 | OTHER_DNS = "223.5.5.5" 14 | 15 | 16 | class HustNetwork(object): 17 | def __init__(self, config_file): 18 | self._test_time = 60 19 | with open(config_file, 'r') as f: 20 | self._userId = f.readline().strip() 21 | self._password = f.readline().strip() 22 | self._auth_url = None 23 | self._referer = None 24 | self._origin = None 25 | # 认证过程中不要走系统代理 26 | self._proxies = { 27 | 'http': None, 28 | 'https': None, 29 | } 30 | self._encrypted_password = None 31 | 32 | def _ping(self, host): 33 | # 利用 ping 判断网络状态 34 | if sys.platform.lower() == "win32": 35 | cmd = f"ping -n 2 -w 1000 {host}" 36 | creation_flags = subprocess.CREATE_NO_WINDOW 37 | else: 38 | cmd = f"ping -c 2 -W 1 {host}" 39 | creation_flags = 0 40 | args = cmd.split(' ') 41 | th = subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, creationflags=creation_flags) 42 | return (th.wait() == 0) 43 | 44 | def _check_status(self): 45 | # 依次 ping 校园网 DNS 和 阿里云 DNS 46 | return self._ping(HUST_DNS) or self._ping(OTHER_DNS) 47 | 48 | def _get_auth_url(self): 49 | # 通过 http 的网站进行跳转 50 | test_url = "http://1.1.1.1" 51 | response = requests.get(test_url, proxies=self._proxies) 52 | response.encoding = 'utf8' 53 | 54 | # 获取跳转链接 55 | href = re.findall(r"href='(.+)'", response.text) 56 | self._referer = href[0] 57 | self._origin = self._referer.split("/eportal/")[0] 58 | self._auth_url = self._origin + "/eportal/InterFace.do?method=login" 59 | 60 | def _password_encrypt(self): 61 | page_info_url = self._origin + "/eportal/InterFace.do?method=pageInfo" 62 | data = { 63 | "queryString": self._referer 64 | } 65 | response = requests.post( 66 | page_info_url, data=data, proxies=self._proxies) 67 | response.encoding = 'utf8' 68 | result = response.json() 69 | 70 | self._publicKey_exponent = result["publicKeyExponent"] 71 | self._publicKey_modulus = result["publicKeyModulus"] 72 | return result["passwordEncrypt"] 73 | 74 | # 加密的模拟来源于 75 | # 1. https://blog.csdn.net/Kreeda/article/details/117965385 76 | # 2. https://www.cnblogs.com/himax/p/python_rsa_no_padding.html 77 | def _get_encrypted_password(self): 78 | if self._encrypted_password is None: 79 | # 加上通用的 mac string 80 | self._encrypted_password = self._password + ">111111111" 81 | e = int(self._publicKey_exponent, 16) 82 | m = int(self._publicKey_modulus, 16) 83 | # 16进制转10进制 84 | t = self._encrypted_password.encode('utf-8') 85 | # 字符串逆向并转换为bytes 86 | input_nr = int.from_bytes(t, byteorder='big') 87 | # 将字节转化成int型数字,如果没有标明进制,看做ascii码值 88 | crypt_nr = pow(input_nr, e, m) 89 | # 计算x的y次方,如果z在存在,则再对结果进行取模,其结果等效于pow(x,y) %z 90 | length = math.ceil(m.bit_length() / 8) 91 | # 取模数的比特长度(二进制长度),除以8将比特转为字节 92 | crypt_data = crypt_nr.to_bytes(length, byteorder='big') 93 | # 将密文转换为bytes存储(8字节),返回hex(16字节) 94 | self._encrypted_password = crypt_data.hex() 95 | return self._encrypted_password 96 | 97 | def _reconnection(self): 98 | time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 99 | print("[Log] [%s]" % (time_string), end=" ") 100 | print("锐捷掉线,尝试重连", end=" ") 101 | 102 | if self._auth_url is None: 103 | self._get_auth_url() 104 | 105 | # 组成 post 数据 106 | data = { 107 | "userId": self._userId, 108 | "password": self._password, 109 | "service": "", 110 | "queryString": self._referer.split("jsp?")[1], 111 | "operatorPwd": "", 112 | "operatorUserId": "", 113 | "validcode": "", 114 | "passwordEncrypt": "" 115 | } 116 | if self._password_encrypt(): 117 | data["password"] = self._get_encrypted_password() 118 | data["passwordEncrypt"] = "true" 119 | 120 | # 校园网认证 121 | headers = { 122 | "Host": self._origin.split("://")[1], 123 | "Origin": self._origin, 124 | "Referer": self._referer, 125 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36" 126 | } 127 | response = requests.post( 128 | self._auth_url, data=data, headers=headers, proxies=self._proxies) 129 | 130 | # 打印响应状态 131 | response.encoding = response.apparent_encoding 132 | result = response.json() 133 | print(result["result"], result["message"]) 134 | 135 | def run(self): 136 | while (True): 137 | if not self._check_status(): 138 | self._reconnection() 139 | time.sleep(self._test_time) 140 | 141 | 142 | if __name__ == "__main__": 143 | hustNetwork = HustNetwork(sys.argv[1]) 144 | while (True): 145 | try: 146 | hustNetwork.run() 147 | except Exception as e: 148 | time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 149 | print("[Exception] [%s]" % (time_string), end=" ") 150 | print(e) 151 | -------------------------------------------------------------------------------- /HustNetwork_GUI.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import re 6 | import sys 7 | import stat 8 | import time 9 | import math 10 | import shutil 11 | import subprocess 12 | 13 | import requests 14 | from PySide6 import QtCore, QtWidgets, QtGui 15 | import configparser 16 | import rc_icon 17 | 18 | 19 | def remove_readonly(func, path, _): 20 | "Clear the readonly bit and reattempt the removal" 21 | os.chmod(path, stat.S_IWRITE) 22 | func(path) 23 | 24 | 25 | class HustNetwork(QtCore.QThread): 26 | status_signal = QtCore.Signal(str) 27 | 28 | def __init__(self, username='', password='', ping_interval=15, ping_dns1='202.114.0.242', ping_dns2='223.5.5.5', config=None): 29 | super().__init__() 30 | if config is None: 31 | self._username = username 32 | self._password = password 33 | self._ping_interval = ping_interval 34 | self._ping_dns1 = ping_dns1 35 | self._ping_dns2 = ping_dns2 36 | else: 37 | self._username = config.get('network', 'username') 38 | self._password = config.get('network', 'password') 39 | self._ping_interval = config.getint('network', 'ping_interval') 40 | self._ping_dns1 = config.get('network', 'ping_dns1') 41 | self._ping_dns2 = config.get('network', 'ping_dns2') 42 | self._auth_url = None 43 | self._referer = None 44 | self._origin = None 45 | # 认证过程中不要走系统代理 46 | self._proxies = { 47 | 'http': None, 48 | 'https': None, 49 | } 50 | self._encrypted_password = None 51 | 52 | def _ping(self, host): 53 | # 利用 ping 判断网络状态 54 | if sys.platform.lower() == "win32": 55 | cmd = f"ping -n 2 -w 1000 {host}" 56 | creation_flags = subprocess.CREATE_NO_WINDOW 57 | else: 58 | cmd = f"ping -c 2 -W 1 {host}" 59 | creation_flags = 0 60 | args = cmd.split(' ') 61 | th = subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, creationflags=creation_flags) 62 | return (th.wait() == 0) 63 | 64 | def _check_status(self): 65 | # 默认情况依次 ping 校园网 DNS 和 阿里云 DNS 66 | return self._ping(self._ping_dns1) or self._ping(self._ping_dns2) 67 | 68 | def _get_auth_url(self): 69 | # 通过 http 的网站进行跳转 70 | test_url = "http://1.1.1.1" 71 | response = requests.get(test_url, proxies=self._proxies) 72 | response.encoding = 'utf8' 73 | 74 | # 获取跳转链接 75 | href = re.findall(r"href='(.+)'", response.text) 76 | self._referer = href[0] 77 | self._origin = self._referer.split("/eportal/")[0] 78 | self._auth_url = self._origin + "/eportal/InterFace.do?method=login" 79 | 80 | def _password_encrypt(self): 81 | page_info_url = self._origin + "/eportal/InterFace.do?method=pageInfo" 82 | data = { 83 | "queryString": self._referer 84 | } 85 | response = requests.post( 86 | page_info_url, data=data, proxies=self._proxies) 87 | response.encoding = 'utf8' 88 | result = response.json() 89 | 90 | self._publicKey_exponent = result["publicKeyExponent"] 91 | self._publicKey_modulus = result["publicKeyModulus"] 92 | return result["passwordEncrypt"] 93 | 94 | # 加密的模拟来源于 95 | # 1. https://blog.csdn.net/Kreeda/article/details/117965385 96 | # 2. https://www.cnblogs.com/himax/p/python_rsa_no_padding.html 97 | def _get_encrypted_password(self): 98 | if self._encrypted_password is None: 99 | # 加上通用的 mac string 100 | self._encrypted_password = self._password + ">111111111" 101 | e = int(self._publicKey_exponent, 16) 102 | m = int(self._publicKey_modulus, 16) 103 | # 16进制转10进制 104 | t = self._encrypted_password.encode('utf-8') 105 | # 字符串逆向并转换为bytes 106 | input_nr = int.from_bytes(t, byteorder='big') 107 | # 将字节转化成int型数字,如果没有标明进制,看做ascii码值 108 | crypt_nr = pow(input_nr, e, m) 109 | # 计算x的y次方,如果z在存在,则再对结果进行取模,其结果等效于pow(x,y) %z 110 | length = math.ceil(m.bit_length() / 8) 111 | # 取模数的比特长度(二进制长度),除以8将比特转为字节 112 | crypt_data = crypt_nr.to_bytes(length, byteorder='big') 113 | # 将密文转换为bytes存储(8字节),返回hex(16字节) 114 | self._encrypted_password = crypt_data.hex() 115 | return self._encrypted_password 116 | 117 | def _reconnection(self): 118 | if self._auth_url is None: 119 | self._get_auth_url() 120 | 121 | # 组成 post 数据 122 | data = { 123 | "userId": self._username, 124 | "password": self._password, 125 | "service": "", 126 | "queryString": self._referer.split("jsp?")[1], 127 | "operatorPwd": "", 128 | "operatorUserId": "", 129 | "validcode": "", 130 | "passwordEncrypt": "" 131 | } 132 | if self._password_encrypt(): 133 | data["password"] = self._get_encrypted_password() 134 | data["passwordEncrypt"] = "true" 135 | 136 | # 校园网认证 137 | headers = { 138 | "Host": self._origin.split("://")[1], 139 | "Origin": self._origin, 140 | "Referer": self._referer, 141 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36" 142 | } 143 | response = requests.post( 144 | self._auth_url, data=data, headers=headers, proxies=self._proxies) 145 | 146 | # 打印响应状态 147 | response.encoding = response.apparent_encoding 148 | result = response.json() 149 | if result["result"] == 'success': 150 | self.status_signal.emit("认证成功!") 151 | else: 152 | self.status_signal.emit(result["message"]) 153 | 154 | def run(self): 155 | while (True): 156 | try: 157 | ping_status = self._check_status() 158 | except Exception: 159 | self.status_signal.emit("网络异常!请检查网线接口连接情况") 160 | time.sleep(5) 161 | continue 162 | if not ping_status: 163 | try: 164 | self._reconnection() 165 | except Exception: 166 | self.status_signal.emit("连接失败!") 167 | else: 168 | self.status_signal.emit("已认证!") 169 | time.sleep(self._ping_interval) 170 | 171 | 172 | class HustNetworkGUI(QtWidgets.QWidget): 173 | def __init__(self): 174 | super().__init__() 175 | self.hustNetwork = None 176 | self.tray_msg = None 177 | 178 | self.setWindowTitle("华科校园网认证服务") 179 | self.setWindowIcon(QtGui.QIcon(":/icon/network.png")) 180 | self.setWindowFlags(QtCore.Qt.WindowType.WindowMinimizeButtonHint | 181 | QtCore.Qt.WindowType.WindowCloseButtonHint) 182 | 183 | self.layout = QtWidgets.QFormLayout(self) 184 | 185 | self.username = QtWidgets.QLineEdit() 186 | self.layout.addRow("校园网账号", self.username) 187 | 188 | self.password = QtWidgets.QLineEdit() 189 | self.password.setEchoMode(QtWidgets.QLineEdit.EchoMode.Password) 190 | self.layout.addRow("校园网密码", self.password) 191 | 192 | self.ping_interval = QtWidgets.QLineEdit("15") 193 | self.layout.addRow("断线重连间隔(s)", self.ping_interval) 194 | 195 | self.ping_dns1 = QtWidgets.QLineEdit("202.114.0.242") 196 | self.layout.addRow("ping 主机1", self.ping_dns1) 197 | self.ping_dns2 = QtWidgets.QLineEdit("223.5.5.5") 198 | self.layout.addRow("ping 主机2", self.ping_dns2) 199 | 200 | self.status = QtWidgets.QLabel("未运行") 201 | self.layout.addRow("当前状态", self.status) 202 | 203 | self.save_config = QtWidgets.QCheckBox("保存配置") 204 | self.save_config.setChecked(True) 205 | self.silent_start = QtWidgets.QCheckBox("静默启动") 206 | self.silent_start.setChecked(False) 207 | self.button = QtWidgets.QPushButton("开启服务") 208 | self.layout.addRow(self.save_config, self.silent_start) 209 | self.layout.addRow(self.button) 210 | 211 | if QtWidgets.QSystemTrayIcon.isSystemTrayAvailable(): 212 | self.create_tray_icon() 213 | self.tray_icon.show() 214 | 215 | self.button.clicked.connect(self.daemon_toggle) 216 | 217 | self.config = configparser.ConfigParser() 218 | if os.path.exists("config.ini"): 219 | self.config.read("config.ini") # 读取配置文件 220 | self.username.setText(self.config.get('network', 'username')) 221 | self.password.setText(self.config.get('network', 'password')) 222 | self.ping_interval.setText( 223 | self.config.get('network', 'ping_interval')) 224 | self.ping_dns1.setText(self.config.get('network', 'ping_dns1')) 225 | self.ping_dns2.setText(self.config.get('network', 'ping_dns2')) 226 | self.silent_start.setChecked( 227 | self.config.getboolean('normal', 'silent_start')) 228 | else: 229 | self.config['network'] = { 230 | 'username': '', 231 | 'password': '', 232 | 'ping_interval': '', 233 | 'ping_dns1': ''} 234 | self.config['normal'] = {'silent_start': ''} 235 | with open('config.ini', 'w') as f: 236 | self.config.write(f) 237 | 238 | # 删除旧的 _MEIxxxxxx 文件夹 239 | cur_dir = os.path.dirname(sys.argv[0]) 240 | mei_dirs = {} 241 | max_ctime = 0 242 | for file_name in os.listdir(cur_dir): 243 | if '_MEI' in file_name: 244 | mei_dir = os.path.join(cur_dir, file_name) 245 | if os.path.isdir(mei_dir): 246 | cur_ctime = os.path.getctime(mei_dir) 247 | mei_dirs[cur_ctime] = mei_dir 248 | max_ctime = max(max_ctime, cur_ctime) 249 | for ctime in mei_dirs: 250 | if ctime != max_ctime: 251 | shutil.rmtree(mei_dirs[ctime], onerror=remove_readonly) 252 | 253 | def tray_icon_activated(self, reason: QtWidgets.QSystemTrayIcon.ActivationReason): 254 | # 单击、双击均显示主窗口 255 | if reason == QtWidgets.QSystemTrayIcon.ActivationReason.DoubleClick: 256 | self.showNormal() 257 | elif reason == QtWidgets.QSystemTrayIcon.ActivationReason.Trigger: 258 | self.showNormal() 259 | 260 | def create_tray_icon(self): 261 | self.show_action = QtGui.QAction("显示", self) 262 | self.show_action.triggered.connect(self.showNormal) 263 | 264 | self.quit_action = QtGui.QAction("退出", self) 265 | self.quit_action.triggered.connect(qApp.quit) 266 | 267 | self.tray_icon_menu = QtWidgets.QMenu(self) 268 | self.tray_icon_menu.addAction(self.show_action) 269 | self.tray_icon_menu.addSeparator() 270 | self.tray_icon_menu.addAction(self.quit_action) 271 | 272 | self.tray_icon = QtWidgets.QSystemTrayIcon( 273 | QtGui.QIcon(":/icon/network.png"), self) 274 | self.tray_icon.setContextMenu(self.tray_icon_menu) 275 | self.tray_icon.setToolTip("华科校园网认证服务") 276 | 277 | self.tray_icon.activated.connect(self.tray_icon_activated) 278 | 279 | def closeEvent(self, event): 280 | # 服务运行后关闭时隐藏 281 | if not event.spontaneous() or not self.isVisible(): 282 | return 283 | if self.hustNetwork and QtWidgets.QSystemTrayIcon.isSystemTrayAvailable() and self.tray_icon.isVisible(): 284 | self.hide() 285 | self.tray_info("隐藏至系统托盘") 286 | event.ignore() 287 | 288 | def changeEvent(self, event): 289 | # 服务运行后最小化时隐藏 290 | if self.hustNetwork and self.windowState() == QtCore.Qt.WindowState.WindowMinimized: 291 | self.hide() 292 | self.tray_info("隐藏至系统托盘") 293 | QtWidgets.QWidget.changeEvent(self, event) 294 | 295 | @QtCore.Slot() 296 | def set_status(self, string: str): 297 | self.status.setText(string) 298 | 299 | @QtCore.Slot() 300 | def tray_info(self, string: str): 301 | if self.tray_msg != string: 302 | self.tray_msg = string 303 | self.tray_icon.showMessage("华科校园网认证服务", string) 304 | 305 | def save_to_confg_file(self): 306 | if self.save_config.isChecked(): 307 | self.config['network'] = { 308 | 'username': self.username.text(), 309 | 'password': self.password.text(), 310 | 'ping_interval': self.ping_interval.text(), 311 | 'ping_dns1': self.ping_dns1.text(), 312 | 'ping_dns2': self.ping_dns2.text()} 313 | self.config['normal'] = { 314 | 'silent_start': str(self.silent_start.isChecked())} 315 | with open('config.ini', 'w') as f: 316 | self.config.write(f) 317 | 318 | def start_auth_daemon(self): 319 | if self.save_config.isChecked(): 320 | self.hustNetwork = HustNetwork(config=self.config) 321 | else: 322 | self.hustNetwork = HustNetwork( 323 | self.username.text(), self.password.text(), int(self.ping_interval.text()), 324 | self.ping_dns1.text(), self.ping_dns2.text()) 325 | self.hustNetwork.status_signal.connect(self.set_status) 326 | self.hustNetwork.status_signal.connect(self.tray_info) 327 | self.hustNetwork.start() 328 | 329 | @QtCore.Slot() 330 | def daemon_toggle(self): 331 | if self.hustNetwork is None: 332 | self.save_to_confg_file() 333 | self.set_status("认证中...") 334 | self.start_auth_daemon() 335 | self.button.setText("停止服务") 336 | else: 337 | self.hustNetwork.terminate() 338 | self.hustNetwork.wait() 339 | del self.hustNetwork 340 | self.hustNetwork = None 341 | self.set_status("未运行") 342 | self.button.setText("开启服务") 343 | 344 | 345 | if __name__ == "__main__": 346 | app = QtWidgets.QApplication([]) 347 | 348 | if not QtWidgets.QSystemTrayIcon.isSystemTrayAvailable(): 349 | QtWidgets.QMessageBox.critical( 350 | None, "华科校园网认证服务", "该系统上不支持隐藏至系统托盘\n如需断线重连功能,认证完成后请勿关闭本程序") 351 | 352 | widget = HustNetworkGUI() 353 | widget.resize(250, 200) 354 | if widget.silent_start.isChecked(): 355 | widget.hide() 356 | widget.daemon_toggle() 357 | else: 358 | widget.show() 359 | 360 | sys.exit(app.exec()) 361 | -------------------------------------------------------------------------------- /rc_icon.py: -------------------------------------------------------------------------------- 1 | # Resource object code (Python 3) 2 | # Created by: object code 3 | # Created by: The Resource Compiler for Qt version 6.4.0 4 | # WARNING! All changes made in this file will be lost! 5 | 6 | from PySide6 import QtCore 7 | 8 | qt_resource_data = b"\ 9 | \x00\x00\x22\xfb\ 10 | \x89\ 11 | PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ 12 | \x00\x00\xc8\x00\x00\x00\xc8\x08\x06\x00\x00\x00\xadX\xae\x9e\ 13 | \x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ 14 | \x01\xc7o\xa8d\x00\x00\x00\x19tEXtSof\ 15 | tware\x00www.inksca\ 16 | pe.org\x9b\xee<\x1a\x00\x00 \x00ID\ 17 | ATx\x9c\xed\x9dyt\x1c\xc5\xb5\xff?\xd53\xa3\ 18 | \x19\xed\xbbl-\xde%\xbc\xe0\x0d/,\xc6\x10\xb3\x06\ 19 | \x02\xe1\xe5A 9\x84\x10\x02!\x90\x97@\xb0Y\xf2\ 20 | \xf2# d\x93\xf7H\xc0vX\x02\x81\x84\x00\x01B\ 21 | 0\xe6\xb4{\xc9\x88\xe7\xaf\xcd\xe5Df\xa5P\xed\ 47 | N\xe2\x99\xee\x02\x16\x9e?\x84\x0e\xbbmJT\x94@\ 48 | LX\xb6\x81,)\x98\xdf\xd1\xcdwZ;\xc9I\xc4\ 49 | \xaf\xca\x19\x10\xcb\xa6\xb4d\xee>}\x02K\xed\xb6'\ 50 | \xd1P\x02\xe9\x85\x95\x95L\xf7v\xf1HC\x1b\xa7\xf8\ 51 | u{\x87OV\x92\x99BkZ2\x7ft\xe7\xf0\xff\ 52 | \xd4\x10,4\x94@\x8eby%\x97vv\xf0\xeb\xc6\ 53 | 6\xc6\x0c\xe4\xaf\xc5\xed\xc2\x9f\x93\xc1_\x93\x04?\x9c\ 54 | =\x89&\xbb\xed\x89g\x94@\x80\xb5\xdb9\xbb\xa1\x9d\ 55 | \xdf5\xb5Q6\x98\xbe\x8e$\x17FN:\xaf\xbb5\ 56 | \xbe\xa7\x84\xd2;\x83Z \xab63\xa9\xd5\xc7\x8b\x0d\ 57 | m\x8c\x1f\xc4_\x03n\x17zn\x1aO\x9c5\x95\x9f\ 58 | \x00\x86\xdd\xf6\xc4\x13\x83R \xabV\x91\xecK\xe3\x99\ 59 | \x83\xcd|\xd3n\x17m<\x91\x9eL[~\x167\x9c\ 60 | 6\x8e\x17\xec\xb6%^\x18t\x02Y\xfe\x09\xd75\xb4\ 61 | \xf2Hg7\x1e\xbbm\x89G\x84\x80\xbc\x0c6\xa7\x0a\ 62 | .8\xfd$\xf6\xdbm\x8f\xdd\x0c\x1a\x81\xac\xdcLv\ 63 | G\x0f\xef4\xb42m\x90|\xe4\xa8\xf0\xb8\xf0\x0f\xc9\ 64 | \xe2\xbfgOd\xa1\xdd\xb6\xd8\xc9\xa0\x10\xc8\x8a\xcd|\ 65 | \xa3\xbe\x8d\x17\xe2\xa9\xd7(\xc8\x02_\x0f4\xc7\xf1\x12\ 66 | \x9e\x10\x90\x9f\xc5\x86|8k\xeaT\x9a\xed\xb6\xc7\x0e\ 67 | \x06\xba@\xc4\xbf7\xf2\xf2\xc1&.\x8d\xe5\xde\xa8p\ 68 | pjPV\x0cC\xb3\x03?\x1fj\x81\xfd\x0d\xd0\xd4\ 69 | n\xaf]f\xa4z\xe8\xcaO\xe3\xb2\xd3'\xf1\xa6\xdd\ 70 | \xb6\xf47\x03V \xebv\x90w\xb8\x8d\x0f\x1bZ\x19\ 71 | i\xb7-G\xc8\xcb\x80\xd2\x22HN:\xfe\x98_\x87\ 72 | \x96\x0e\xe8\xec\x86\x1e\x03Z\xda\xe3\xabwq:\x90\x85\ 73 | \xb9\xfc\xea\xcc\x13\xf9\xb9\xdd\xb6\xf4'\x03R \xab\xb7\ 74 | p\xfa\xc1V\xden\xf7\x92l\xb7-\x00\xa9\x1e(-\ 75 | \x84\x9c\xf4\xd0\xafih\x83M\xd5\xb1\xb3)\x12\x84\x80\ 76 | !Y\xbc{\xceT\xcee\x90\xb8\x83\x07\x9c@\x96m\ 77 | \xe5\x9aC\x8d<\xd9\xd3c\x7f0XF\x0a\x0c\xcb\x87\ 78 | \xfc\x8c\xc0\xc3\x15\x0e~\x03Vn\x81x\xfc\xf3d\xa7\ 79 | \xb17;\x95\xa9\xa7M\xa0\xd1n[b\xcd\x80\x12\xc8\ 80 | \xca\xad\xdcS{\x98r\xdd\xc6w\x9bC\x83\xfcL(\ 81 | \xca\x81\xcc\xd4\xe8\xda\xdaT\x03\x0d\xad\x96\x98e9\xe9\ 82 | \xc9\xb4\xe6e2y\xd6xv\xdbmK,\x190\x02\ 83 | yw#\x0f\xd55q\x93\x1d\x1f\xc7\xa9AVZ\xc0\ 84 | 3\x95\x97\x11\x10\x89\x15\x1cj\x81-q\xfc\xf8\xa5%\ 85 | \xd354\x83\x19\xa7L`\xab\xdd\xb6\xc4\x8a\x01!\x90\ 86 | w7\xf2\xc7\xba&\xbe\xdf_\x1f\xc5\xe9\x84tO\xa0\ 87 | \x87\xc8I\x0b\x0c\xa5\xc2\x1dB\x85\x824\xe0\xfdm\xd0\ 88 | \xa3[\xdf\xb6U\xa4$\xd1=t\x08\xa7\x9dV\xcaz\ 89 | \xbbm\x89\x05\x09/\x90e\x9bxl\x7f#7\x86\xfa\ 90 | 1\x84\x16x\xb8\x0d\x03t#\xf0\xf0\xe9\xc6\x17c}\ 91 | \xa7\x03\x10\xe0\xd2\x02B\xf0\xb8\xc0\xfd\xd9\xbf\x147\xa4\ 92 | y\xc0\xd3\x8b\x17*V\xec=\x0cUu\xfdw\xbfH\ 93 | \xf0$\xd1S\x90\xc9\x8c3&\xb2\xc9n[\xac&\xa1\ 94 | \x05\xf2\xee&~]\xd7\xc8\xed\xe1|\x84\xa2\x5c\x18[\ 95 | \x1c;\x9b\xacF\x1a\xb0f\x07t\xf9\xec\xb6\xc4\x9c\xe4\ 96 | $\xbc\x05\x05\x9c8\xbb\x8c]v\xdbb%\xb6{z\ 97 | \x22\xe5\xbdM\xfc<\x5cq\x08\x01#\x0bbgS,\ 98 | \x10\x1a\x8c\x1cb\xb7\x15}\xd3\xe5\xc3\xd3\xdc\xc8\xfa\x95\ 99 | \x9b\xc9\xb6\xdb\x16+IH\x81\xac\xae\xe4\xeb\x07\x9a\xf9\ 100 | e\xb8\x9d\xdf\xa8!\x81\xa1R\xa214\x1b\xb2\xd3\xec\ 101 | \xb6\xa2oZ:\xc9h\xf5\xb2e\xebV\xfaq\x10\x1a\ 102 | [\x12N k\xb63y_\x03\xaf\x84\x1b\x0a\x9b\x9f\ 103 | \x09#\x12\xac\xf78\x9a\xf1\xc3 )\x01\xb2\x985\xb5\ 104 | SX\xeb\xe5}\xbb\xed\xb0\x8a\x84\x12\xc8ku\xa4\x1c\ 105 | hb\x85\xd7\x17^\xc2\xbb\xacT\x187,VV\xf5\ 106 | \x0fn\x17L\x1a\x01Z\x02D\xaf\x1cna\xc6\xf2-\ 107 | sG\xc71\ 112 | \x86\x01\x07\x9ay\xee\xfd\xed\x14\xd9mK4$\x84\x9b\ 113 | \xf7\xfd\xad\xcc\xae\xadgy\xa8\xf3\x8e\xacT\x18[\x12\ 114 | X\xb7\x18\xa8t\xf9\xe0\x93\x1ah\xf7\xdam\x899\xb9\ 115 | \xe9T]0\x832\xbb\xed\x88\x94D\xe8A\x9c\x8d\xed\ 116 | \xfc=\x14qd\xa6\xc2\xe4\x91p\xd2\x98\x81-\x0e\x08\ 117 | l\x99\x9fQ\x06c\x0ac\xb3\x8ao\x15\x0dm\x94.\ 118 | \xfb\x84\x07\xec\xb6#R\xe2\xbe\x07Y\xb6\x89\x97\xf75\ 119 | pY\xb0\xe3\xc9I\x90\x9b\x09\x85\xd9\x81U\xee\xc1H\ 120 | \x97\x0fv\x1f\x82\x03M\xf1\xb9\xfb7\xc9\x85qB\x11\ 121 | \xe3\xa7\x8cN\xbc\xac\xf4q-\x90\x0f+\x99\xb5\xeb\x10\ 122 | +\x8f\xf4\x1e\x9f%i&\xcd\x03\xe9\xc9\x81\xb5\x81\xb4\ 123 | \xb8\x88\xf8\x88\x0f\xbc>8\xd8\x04\x07[\xa0#\xce\x86\ 124 | ^\xd9i\xd4|m&\xa3\xec\xb6#\x5c\xe2Z \x95\ 125 | \xb5\xac\xd6uNq9\x03^\xa8$WbN\xb8{\ 126 | \xfc\x817|C+\xf8\xfc\xe0v\x06v\xfe\x0e+\xb0\ 127 | n\xe7\xef\xb1tv\x07\x22\x12[:\xa0\xcd\x0b\xdd\xbe\ 128 | @\xd4\xa2\x9d\x14\xe7p\xd7\x9c)\xdck\xaf\x15\xe1\x11\ 129 | \xb7\x02\xd9\xd7\xc8\x15B\xf2\xa2\xddvD\xcb\x96jX\ 130 | \xbf3 \x8ccIN\x82\x99\xe3\x02a\xb8\xfd\x81_\ 131 | \x87\xee\x1e8\x12\x9f\xef\xd7\x03\xde\xa6\xb6.8\xdc\x12\ 132 | \xfb\x09\x7f\x8a\x1b\xdf\x984r&ON\x9cl\xf3q\ 133 | )\x90\x9a\x1a\ 134 | \x81\xca\xda\xbe\xcf\x9b^\x06S\xc6\xf4~L\xca\xfe\x9b\ 135 | \x84\xb7v\x06z\xba\xfa\x18\x06i\x15\xe6\xf0\xea\xd9S\ 136 | \xb84vw\xb0\x96\xb8\xf4b\xb9\xd3\xb9\x85\x04\x17G\ 137 | u]h\xe2\x00\xf8\xb8\x0a\x0e\x1f\x93T\xc7\xaf\xc3\xba\ 138 | *X\xb6\x19>\xd8\x16\xd8\xf2\xee\xef\xa5\x17\xb2\x92\x8c\ 139 | \x14\x9842\xf0\xcf\x15\xa3m-\xf5-|\xa3\xe1\x0f\ 140 | \x7f\xbc\x9a\xbb\xee\x08\xf2J\x88/\xe2\xae\x07\xd9\xd5D\ 141 | \xa6\xc7`\x17\x90c\xb7-\xd1\xf0\xf7\xd5\xc7?\xf4f\ 142 | \x8c\x1e\x0as\xa6~\xf1\xf3\xe1\x16\xf8\xe4\x98hB\xb7\ 143 | \x13\xa6\x8c\x82\xd4~pLt\xf7\xc0\xc6\xea\xd8L\xf6\ 144 | Gxw\xd5\xce^\xfdH\x09\xd0\x88\xe4#4>B\ 145 | \xc8\x0f\xe9\x11\x1fr\xef\xa2}\xd6\xdf1r\xe2n\xfb\ 146 | \x9bGg\x1e\x22\xb1\xc5!e\xf8\xc3\x94\xfa\x96/\xff\ 147 | \x9c\xd2\x8b\xcb\xba\xdb\x0f\xebw\xc1)cc\xf7\x86?\ 148 | \x82\xdb\x05\xd3\xc7\xc0\x86\xea\xc0\xd0\xcbJjSF\x95\ 149 | x\x93\xd2\x1b=\xbe\xb6\x1c\x04\xe7#9\x1f)\xc0\x01\ 150 | \x94\xcf\xdb\x85\xe0\x1d$\xaf\xa1e\xbeMy\xb9\xad\xfe\ 151 | \xb8\xb8\xeaAj\x9a\xc9J\xd2\xd9\x0d\xe1\xed\xb7\x8a7\ 152 | \xa4\x84\xa7\xdf\x0e\x04;\x85JF2|\xf3+_\xfe\ 153 | \xdd\xb6\xbd\x81\xb5\x8dc\x19Q\x10\xe8q\xfa\x03\xbf\x1e\ 154 | p2X=\x81\x1f\xddU\xb5\xe7\xb45\x8f\x0e\xef\xe3\ 155 | \xb4\x0e`\x19\x92\xa5\xf8\x92^\xe4\xbe\xfbZ\xfa8\xdf\ 156 | r\xe2j\x0e\xe2\xd6\xb9\x91\x04\x17\x07\x04&\xd5\xb9a\ 157 | \xe4\xc0\x02\xc8\xc9<\xfewcKzo\xa7?\xb7\x97\ 158 | 8\x1d\x819\x89\xd3\xe2\x1ekOZ\xe9\xb0\x1eWr\ 159 | _\x0f|*p\x11\x82\xc7q\xfb\xea\xb8g\xde\xb3\x94\ 160 | \xdfz\x16\xa2\xff\xf6\x0e\xc4M\x0f\xb2\x0e\x5c\x85\x0d\xec\ 161 | \x02J\xec\xb6\xc5\x0av\xd6\xc1{\x1bC?\xff\xa2S\ 162 | `H/\xb1xR\x06z\x91\xbd\xf5\x81\xf9\x80C\x0b\ 163 | \xc4\x86\xe4\xf7\x22\xa8X\xd2\xdb\x9c(Z\xc6\xb5l\xa8\ 164 | \x99\xbe\xfeO##\xb8t\x17\x88'\xd0z\x1e\xa3\xfc\ 165 | \xa1\x98&F\x8a\x1b\x81\xd45p\x95\x84g\xed\xb6\xc3\ 166 | J\x96o\x86\xaa\x10\xa6\x9cSKaZi\xdf\xe7\xe9\ 167 | F\xec\x16\x16Ca\xdb\x1e8`a\x0ak\xb7\xc3\xd0\ 168 | /{\xf7\x0e\x84aD\xba7\xb9\x09\xe4\x83t:\x1f\ 169 | \xe0\xfe\xfbc\xb2\xb6\x127C,)\xb9\xc1n\x1b\xac\ 170 | \xe6\x8c\x89\x815\x8e`[\xd3\xdd.8}bh\xe2\ 171 | \x00{\xc5\x01\x81\x05M+\x9d\x03\xdd\xba\xe6\xa8\x1ey\ 172 | F49\xb5\xb2A\xdcC\x8a\x7f\x07\xe5s\xbfk\x99\ 173 | aG\x11\x17=\xc8\xfez\xc6\x22\xd8\x06\x03\xb3\xda\x93\ 174 | \xd7\x07\xbb\x0fBC\x0bx\xfd\x81\x15\xf4\xfc,\x181\ 175 | \x04\x5cq\x1e\xd7q,\xb5\xf5\xf0\xa9\x85eu\xb2R\ 176 | 9x\xd1\x9b?\x9b\x86\xde3\x07\xc1\x1c`\x0eD\xbc\ 177 | =\xfeMt\xae\xb7\xd2U\x1c\x17\x02\xa9k\xe4\x01)\ 178 | \xb9\xd5n;\x14}cHX]\x19X'\xb1\x02\xa1\ 179 | AY\x11'\xcd,c\xc3\xe7\xbf\xbc\xeb\xf6Qh\xfa\ 180 | %\xc0\xe5\xc0,\xc2{q\xd6\x83\xf86\x15\x0b\xffe\ 181 | \x89}q \x10\xb1\xbf\x81\x1a\xa0/\x97\x9f\x22N\xd8\ 182 | \xdf\x00\xdb-\x5c\xce\x1b\x92\xc5\xd2sO\xe2?z=\ 183 | \xf8\x8b\xdbF\xe0\x90\xd7\x81q\x1d\x88Pw\xad\xf5\x80\ 184 | \xfc\x1e\x15\x8b\xa3\xae\xb5h\xbb@^\xfd\x97\xfemw\ 185 | \xb2\xf6BI\x01\xe4f\x89\xb8\x0e\xfeQ\x04\x90\x06|\ 186 | P\xd9\xfb\x06\xccH(+\xa2\xfa\xe4\xb1\x8c6=\xa9\ 187 | \xa2\xc2\x09\xcd\x17c\x88;\x80\xd3Bh\xd6\x00y5\ 188 | \x15\x8b\x9f\x8f\xc66\xdb\x05\xb2\xf0Y}\xed\xfamr\ 189 | &\x80;\x09\x8a\x0a\x04\xc5\x05\x82\xb2\x11\x82\xd2\xe1\x22\ 190 | \xe6+\xc6\x8a\xc8\xd8u \xb0\xb1\xd1\x0af\x8dG\xa6\ 191 | j\x94\x16\x14\x84\x98\x95\xb1\xe2\xd6\x8b1\xe4\x02`j\ 192 | \x1fgv#9\x8f\xf9\x8bVDj\x9b\xed\x02\xb9m\ 193 | \x91\xee=P/{\x0d\x90u9\xe1\x84\x91\x82\xf1\xa3\ 194 | \x05\x13\xc6h\xa4\xa5\xf4\xb7u\x8a`x}\xb0z{\ 195 | \xf4\x11\x8c\xa9\x1e8\xf9\x04\x00n.\xca\xe5\xe1\x90/\ 196 | \x14Bp\xd7\xdc\xeb\x11,\x22\xb0\xa0\x18\x8c}hr\ 197 | \x22\xe5\x8b#rP\xdb\xea8\x5c\xf2\x16g\x1el\xe8\ 198 | ]\x1c\x10\x084\xdaR%y\xf9-\x83{\x9f\xf0\xf3\ 199 | \xdck:\xbbjm\x9f3)\x08$\xf0\xb6\x22\xdb\xe3\ 200 | \x91Z\x8dRraX\x17J)\x99\xbf\xe8\x09\x0c9\ 201 | \x13\xd8brf1\x92\xf2H\xed\xb3U \x87\x9a\xf4\ 202 | \xff\x0a\xf5\x0dd\xe8\xb0i\xbb\xe4w/\xea\xfcn\x89\ 203 | \xce\xee\xfdJ(vS\x10\xe5j\xbe\x10_\x08D\x08\ 204 | \xe6\xd4\xd6FP2o\xc1\xe2mh\xda\x1c`]\xd0\ 205 | s\xa4\xb8\x91;\xe7\x16Fb\xa3\xcd\x02\xe1\xccH\xae\ 206 | \xdb\xb5W\xf2\xe8_t^~\xdb\xc0\xdbm\xb5U\x8a\ 207 | P\xc9\xcf\x0c\xb8i#\xa50\xfbK\xe9T\x93\x85\x87\ 208 | S#j\xa8\xfc\x81z\xba\x93\xce\x01\x82Uu\xf4\xe0\ 209 | \x14WE\xd2\xb4\x9d\x02\x11\x87\xebe\xc4y\xcb\xa5\x84\ 210 | \xb5\x9b\x0c\x16=\xe3\xa7\xf6\xa0\xeaM\xec\xc0\xe9\x80\xec\ 211 | \x08\xcb\xcc94\x18u\xec\x8ed\xc1\xe9\x11\x1bs\xdf\ 212 | }- \xae\x03\x82=\x0c\xff\x19I\xb3\xb6\x09d\xc9\ 213 | [\x9c\xd1\xd6\x19\xfd\xfd\x9b\xdb\xe0w/\xaa\xb9\x89]\ 214 | \x84\xbbk\xf9\x08eE\xc7'\xe3\x162\x0a\x81\x00T\ 215 | ,|\x17x#\xc8\xd1\x93\xa8\xa8\x08;\xeb\xbcm\x02\ 216 | ij3,\x8bK\xf6\xf5\xc0S\xaf\xea\xec?\xacD\ 217 | \xd2\xdfD2Q/\xca\x85\xc2\xdeB\xe2\x04'Gm\ 218 | \x90di\x90#\x1eh\x0e;=\x86=\x02\x997/\ 219 | 9\xb9q\xefYV6\xd9\xed\x83g\x97\x1a\x96m\x81\ 220 | P\x84F\xaa'\x90\x8e)TJ\xf2M+|\xe5\xec\ 221 | k\x8c2\xdc\xc1!\xcc2\x01d\x85\xdb\x5c\xff\x0b\xa4\ 222 | |\xde\xd7IgKr\xcba\xcb\x93\x8854K\xde\ 223 | \xffxP\xd4\xb7\x8f+rB\x98\x87$'\x05\xd2\xc2\ 224 | \x96\xf5\xe1K\x92z\xe8\x09\xca{\xc50\x82\xfb\xd6\xfc\ 225 | F\xd8[\xe2\xfbo\x9d:\xb0\x01\xedA\xe0\xeb\x00U\ 226 | \xdd\x051y\x92W|lp\xe6\x0c-\xee\xb3\x9f\x0f\ 227 | $\x86\x0f\x09,\xea\xb6v\x05\x16\x10{\xfc\x01\xef\x96\ 228 | \xc7\x15\xc8\x80\x99\x9b\x01\xf9\x19\xa1\xa5/\xd24&\x12\ 229 | |\x1e\xd17\x82\x93\x83L\xd3%=\xc9a\xaf\xfd\xc7\ 230 | ^ B\x08\xee\x9e{3\x1a\xff\x0b\x9f\xfb\xb9\x8d]\ 231 | ]\xf91\xe9\xbd::\xa1f\x9f\xa4t\xb8\xda\xd4\xd5\ 232 | \x1b\xcd\xad\xf0\xca;:=~\x98T&\x986A\xc3\ 233 | \x13e\xa2\xefT\xb7u\xc9\xef\xa4\xe8cO\x96\x197\ 234 | \xdc\xe0bhj\xb0\x9a$\xd5\x91\xc4\xb4\xc7V w\ 235 | \xde2\x84\xbb\xe7>\x05_^%\xf5k\xce\xfa\xae\x1e\ 236 | W\xcc\x0a\xa2\xed\xaaU\x02\x09\xc6\xdf\xde\xd5\xa9\xac\x0e\ 237 | \xbcbw\xee\x95\xfc\xf3\x03\x83935fO\xd3\xe2\ 238 | b\xdf\x9b\x90Q\xe4\xef\x1d\x9a\xf6\x03\x90\xbd\xcfp\x04\ 239 | \xefD\xd2d\xec\xe6 \xe5s/\xc4\xa9m\x84\xe3\xb7\ 240 | \x10x\x1di1M;\xd0\xd6\x1e\xcb\xd6\x13\x97\x86\x16\ 241 | \xc9\xd6\x9d_\x1e\x7fty\xe1\xcd\x15\x06\xbfz\xd2\xcf\ 242 | \x9a\xcd\x06\xba\xfdS\xb8\x91\x11]Uq\xcbp\x90\xf7\ 243 | \x05=.\xb5\x97#i66\x02)\xbf\xf5N\x10\xaf\ 244 | \x03\xbd.\x04\xb69\xb2b\xea\x8f\xf5\xf5(woo\ 245 | |\xba[\x06\xdd\x5c\xd8\xda\x0e\xff\xf7\x96\xc1\xe2?\xe9\ 246 | l\xa9\xb2\xf5\xfb\x0b\xbf\x8a\xfd\x15W80\xc4\x1f\x08\ 247 | \x9e\x11g\x0b\xf3\x17\xc6A\x0fr\xc3\x0d.\xca\xe7\xfd\ 248 | \x01\xe4\xbd\x98D\x81\xb5:3c\xea=KMQ\xc3\ 249 | \xab\xde\xa8\xde\xdb\xf7\x83\x7f\xa8A\xf2\xcc\xdft\x1e\xfd\ 250 | \x8bm\xfb\xddR\xc3\xda\x93%\x84`|\xc9c \xce\ 251 | \x0bz\x8e\xe4^\x22\xdc\xb6n\xdd\x83Zqs\x06C\ 252 | R_\x03\xae\xeb\xeb\xd4\x06Wl\x9a\xb9\x9f\x8a\xc5Q'\x22\x8c\ 270 | \xeeQ*\xbf\xf5[Hn49C\x22\xc5\x5c\xeeY\ 271 | x=\x0f=\xf4y\xe4F\x8fN\x18\xbbwBG\x08\ 272 | 8e\x92\xea=\xcc\x10\x02\xc6\x8e\x8c\xec\xcf\xbe\xef\x90\ 273 | d\xed'\xb1\xf7\x03K\x83\xde\xcb\xb1\xde}\xeb5\x18\ 274 | l\xa0\xafXt\xc1sh\x99fC\xaf\x90\x89|i\ 275 | \xa8\xe2\x8e\xa1 \x1f19\xc3\x0f\xfc\x80\xf9\x0b\x9f9\ 276 | \xee\x88\x8cM\x82\xb8\xd1\xc3D\xd8c\xec\xc1\xc8\x88B\ 277 | X\xbb9\xb2k\xdf\xfbHr\xca\xe4\x18W\xbd\x92|\ 278 | Y\x85\x15\xf3r\xd0y\x1c\xc17\xfb\xbeX\xbc\xc0\xd6\ 279 | \xbd\xd7\xb0d\x91%J\x8e\xbc\x071\xfc\x8f\x02yA\ 280 | \x8eJ\xe0\x07T,:^\x1c\x80&\x88I\xad\xa43\ 281 | \xa6\xa9\xb1U(\xb8\x93\x22\x7f\xba\x1b\x9a%{\x0f\xc4\ 282 | v.\x224\x02\xa3\x0d!\x04w\xdfz\x15\x06[B\ 283 | \x12\x87\xe0\x11\xb4\x8c\xabX\xb2\xc4\xb2\x81`d=H\ 284 | \xc5\xad\xb30\x8b\xd0\x92\xdc\xc3\xfc\xde\xc5\x01 4\xeb\ 285 | \x05\x92\x9b\x19\xc8~\xa2\xe8\x9b\xa6\xb6\xe8\x1e\xf0\xad;\ 286 | %\xc3\x0bc\xf7]\x0b\x03\x1f\x15\xb7L\xe6\xee\xb9\x8f\ 287 | \x80<#\x84K\xfcH\xf9s*\x16?`\xb5-\x91\ 288 | \xbdr\x0dy[\xf0\x83\xf2m\x16,^`v\xb9C\ 289 | \x13\x96G\x92\xcf:I%\x9d\x0b\x95\xcd;\xa2\x13H\ 290 | ,{\x10\xad\xab\x9d\x82\xa7\x17\xcc\xc5\xd0\xd6\x01\xa1\x88\ 291 | c\x1f\x92\xb3\x99o\xbd8 \x92\x1e\xa4\xe2\xb6<\xe0\ 292 | \xe2 G\xdb\xd0\xf4k\xfb\xf2;;\x1c\xd2\xd2JA\ 293 | n\x17\xcc\x9c\xa8\x86W\xa1\xf0\xf16\xc9\x9e\xba\xe8\x1e\ 294 | \xf0\xba\x18\xac\x89h\xdd]\xa4\xae_F\xda\x86\xe5\x08\ 295 | _\xf7\x95!]$y\x0b\x87\xe3\xbb\x94\xdfoQ\x0a\ 296 | \xbb\xe3\x09_ \xbaq>\x22\x88\x17J\x88\xc7)\x7f\ 297 | \xa8\xcf\xda\xaeIN\x1a\xc2\xbe\xaf\x09\xd3O\x8c~\xcb\ 298 | \xf6``K\x95\xe4\xa5\x7fF?\xe4Y\x80\xd3p\xac\x16\xc2\x1fuw\ 316 | /\x04L\x19;\xb8'\xe7\xed]\xf0\xe1f\x83\xcd;\ 317 | $\xfb\x0e\x05\x8f\xf7\xb0\x9aPb\xfe\x1dmM\xa4l\ 318 | ]K\xca\xd6\xb58\xdaz\xa9g\xdd7\x7fG3~\ 319 | A\xf9o6Er\xb1\x15D\x22\x90`\x05\xb8\xa60\ 320 | o^2\x8b\x16\xf59\xd3\xba\xeer\x1a\xd7}\x8a\xde\ 321 | \xdaNT\xa9\x15\x8a\x0b\x04\x19\x16$PNDj\x0f\ 322 | J\xd6n\x92\xac\xdbj\xd0\x13\x93eWs\x82-6\ 323 | \x0a]\xc7]\xbd\x85\xd4\xadkp\xef\xae\x8c,\xfd\xbb\ 324 | d\x19\x0eq'\xe5\x0b?\x88\xd2\xcc\xa8\x89`\x0e\x22\ 325 | 6 do\x05\x13SI\x17W\x03\x8f\x87\xd2Lv\ 326 | \xbahlm\x97\xf9a\xdf\xff(\xc6\x0e\xc2\x85\xc1\x9a\ 327 | }\x927V\x18\xd4\xec\xb37j\xd2}\xb4\x1fSJ\ 328 | \x92\xeav\x91\xbcc\x03\xc9\x9fnD\xeb\x8a,\x9a\xa1\ 329 | \xa7`\x18\xbe\xa1\xc3\x7f\x9ez\xd9e\xc1Cg\xfb\x99\ 330 | \xf0\x05\xe2\xd0\xdf\xc1\x086\xac\x91\xf7r\xe7\xdc\xa5\xfc\ 331 | rq]_\xcd\xa4\xa5\xb0\x0b\x88J e\x83(1\ 332 | CG',}Wg}e|\x84\x13\xbb]\x92\xa4\ 333 | \xba\xdd$Wm\xc0\xf3\xe9F\x1c\xed\x11.m\x09\x81\ 334 | w\xf88:\xa6\xcd\xa1{X\x19N\x9d\xa7\x22L\xf7\ 335 | \x1b\x13\x22+\xa0S>o\x130)\xc8\xd1\x8f\xd0\xf8\ 336 | *\xe5\x8b\x1a\xcd\x9ax\xf8\xcf\xc6\xc3k>1~\x12\ 337 | \xfe\xcd\x038\x1c0\xff'\xce\xb8\xc8\xc4\x11kv\xed\ 338 | \x95<\xff\x9aN[\x7fG\xf6\x1d\x83\x03\x83\x13D\x0d\ 339 | 3\xdd\xdb8'u\x13\x8e\xd6\x88\xe6\x15\x00H\x87\x93\ 340 | \xae\xf13h\x9f\xfa\x15\xfc9\x9f\xa7.8T\x94\xdb\ 341 | {\x1e\x03\xbb\x88\xec\xf1\x92\xdc\x87 X\xed\xb7\x19\x18\ 342 | |\xc0]w\x5c\xc4\x82_\xef\x0c\xd6DJ\x9a\xf1\x12\ 343 | \x10\xb1@\x8a\xf2\x07Gy\xb6\xb5\x9b\x0d^}\xc7\xbe\ 344 | l#\xa9t1Y\xabd\x9a\xa8d\xb2VI*]\ 345 | \xa0\x03\xad\x91\xb5\xa7\xa7f\xd09\xf14:&\x9f\x8e\ 346 | \x91|\xdc\x04rU\x94\xe6ZNd=\xc8\x15W8\ 347 | \x18_\xf2>p\x8a\xc9Y\xf5h\xf2\x06\xca\x17\xbf\x12\ 348 | \xec\x84\x1b\x16\xf8\xf5\x8e\xae\xc8\xf6\x83\xcd\x98\xa8q\xc5\ 349 | W\x07\xb6\x07\xeb\xc3\xcd\x06/\xbfm\xdd\xe2^(\x08\ 350 | $#\xc4~N\x14UL\xd5\xb6q\x82\xa8\xc1A\x94\ 351 | \xea\xd44\xbc#\xc6\xd39\xf1T\xbc#\xc6\x134\xa2\ 352 | MrGQ\x1e\xf7Gw3k\x89\xbcFa\xc5m\ 353 | \xe30\x8c\x0f\x01s?\x92\xe4\x1f8\xb8\x89\xf2EU\ 354 | \xc7\x1e\xba\xfbQ\xbdvWm\x90D_}p\xe1\x19\ 355 | \x1ag\x9ddY$\ 367 | \xb7\xbd\xeeR\x07cG\x0dL\x81\xbc\xfe\x9e\xc1{\x1f\ 368 | Y3\xe9H\x17\x1d\x94\x8a=\x94\xb2\x9b2m7\xa3\ 369 | E-\x1e\xac\x8d60\xdc\xc9x\xc7L\xa2\xabl*\ 370 | \xdd\xc3N\x08>\x842\xe7\xafE\xb9\x91U\x81\x8a%\ 371 | \xd1Os\xe7/|\x8e\x8a[[1\xe4\xb3\x04\xcfl\ 372 | w\x04\x0d!.\xc1\xe0\x12h\xde\x7f\xfd\xc6\xdb\x97\xb4\ 373 | e\xdc\xdc\xf3q\xeb\xb0\xb0c\xd4\xdd1K\xfb`/\ 374 | \xdenX\xbd12qd\x8a6F\x88\xfd\x8c`?\ 375 | #\xc4~Fj\xfb\x18J\xbd\xc5\x16\x060\x92S\xe9\ 376 | \x1e1\x9e\xae\xb2)t\x0f\x1f\x8btD\xf7(\x09\xc9\ 377 | \x9b\x16\x99f)\xd6\xd5I\x0f\xccI\x96\x10\xdc\xfd\x1b\ 378 | \x94\xc32\x9b\xcd\xf2\x04\xb6\xc82\xb6\x18ch7-\ 379 | {\x1d\xe0\xc6+\x1c\x8c\x1e\x80\xf9\xafVm\x0cx\xad\ 380 | \xccp\xe2\xa7H\x1c\xa6H\x1c\xfa\x92 \xac\x1c*\xf5\ 381 | \xc6>Y\xc0\xc7\xc6\x04f|s\x12\xb2xD\xa4=\ 382 | Eo\x18\x06\x0c/\xc9e\x9fU\x0dZ\x85u\x8e\xd2\ 383 | \xf2\x07*\xa9\xa8\x98\x81\xd1\xfa\x0b\x90?\x03B~\xc7\ 384 | \xe7\x8b&\xce\x16k8\x9b5H\x87\xa0F\x16Q)\ 385 | GSm\x94\xb0\x8ba\x1c\x94\xb9\xc7\xe5y\xf0\xd9\xb0\ 386 | \xbd\xa2?\xd8^\xfd\xc5\x0b+]tP$\x0eS\xc8\ 387 | !\x8a\xc4\xa1\xc0\xff\xc5A\xf2iF\x8b\xd6\xb3\x14\x02\ 388 | >\x5c\xec\x90#YoL`\xbd\x1c\xcf!\x99C\x8a\ 389 | \x07\xa6\x0f\xb3\xd8\xbf.XY\x92\x13\x7f\xe2\x00+{\ 390 | \x90\xa3\xa9\x98W\x8a\xc1\xaf\x89\xb0\xb2\xe8\xb1t\xe2\xa1\ 391 | F\x16S#\x8b9 \xf39@.'\x9d^\xc0\x94\ 392 | \x99\xd91N\xaf\x11[\xb4\xae\x0e\x1cmM8\xda\x1a\ 393 | q\xb64\xe1ho\xa4jc\x03\xd9F\x13y\xa2\x89\ 394 | \x14b\x9a\x04\xff8t4v\xca\xe1l\x95c\xd8j\ 395 | \x94\xf2\xa9\x1cA\xcf1\xef\xd0a\x85\x82\x9b\xae\xb4\xbc\ 396 | :\xd1\x8f\x8bry\xd4\xeaF\xad 6\x029\xc2\xdd\ 397 | \xb7MG\x18w\x02\xffA\x0c2\xc9K\xa7\x0b\x7fV\ 398 | \x1ezf\x1ezZ\x16FJ:zj\x06FJ\x1a\ 399 | zjf\xe0\xe7\xe44+\x87\x02\xa6\x08_7\x9a\xaf\ 400 | \x0b\xd1\xedE\xf3y\xd1\xba\xdaqt\xb4\xa2u\xb6\xa1\ 401 | u\xb6\x05\xfe\xdf\xd5\x8e\xa3\xb3\x15\xad\xa3\x0d\xe1\xb7\xb7\ 402 | \xa0\xa2\x8e\xc6\x1eY\xc4V9\x86mr\x0c\x95\xc6(\ 403 | \xbc}l\xca>\xebd\x8d\x0b\xcf\xb0\xee\xfb\x14\xd0\xe3\ 404 | \xd0\x19VP`m\x10\x9dU\xc4V G\xb8\xeb\xf6\ 405 | Q8\xf4k\x90\x5c\x03\x0c\x8f\xfd\x0d\xbf\x8ct\xb9\x91\ 406 | \xae$\x0cW\x12\xd2\x9d\x8c\xe1\xf2 ]IH\x97\x0b\ 407 | \x84@&\xf5\x9eL\x5c\xf2Y\x8az\xdd\x8f\xf0\x07\xbc\ 408 | \x8f\x9a\xaf;0b6\x0c4_\x17Z\xb7\x17\xe1\xeb\ 409 | D\xeb\xf6F\xb6s\xb5\x1fi\x95iT\xc9\xe1|*\ 410 | G\xf0)#\xd8e\x94\xe0\x0b}$\x0c\xc0\x8f\xbe\xe5\ 411 | `T\x89u\xbd\xb6\x84W\x8as\xb9\xcc\xb2\x06-\xa6\ 412 | \x7f\x04r\x84\x8a\x0a\x0dZ\xce\xc5\x90\xd7\x82\xb8\x04\xc2\ 413 | Hs\xaf\x08\x0b/n\xf6\xca\xa1\xd4\xc8bv\xcaa\ 414 | |*GrP\xe6F\xd5fz*\xdc\xf9C\xa7\xa5\ 415 | \x1d\xb2apQI~\x145\x09cL\xff\x0a\xe4h\ 416 | **<\xd02\x1b\x83s\x81s\x81\xe9\xf6\x18\x92\xf8\ 417 | t\x90\xcc>9\x84jYL\xb5QB\x0d%\xec\x93\ 418 | \x05\x96'\xb0\xbc`\xb6\xc6\xd9\xa7X:\x5c\xdd]\x94\ 419 | \xcb\x18\x02\xbb\xbb\xe2\x12\xfb\x04r,\xf7U\x94\xbe\xca\ 420 | \xd9\xdb\x0a:v;\xc7\x88=\x0c\x11\x0d\x08\x8b\xe2\xd6\ 421 | \x07\x02\x12A\x03Y\xd4\x19\xf9\xec\xa7\x80\xfd\xb2\x80:\ 422 | \x99O-Ch\x95\xb1\x8f\x1as9\x03\xbdG\x8a\x85\ 423 | }\xbe\x10\xdcR\x98\xc3\x83\xd6\xb5h=\xf1#\x10\xe0\ 424 | \xb1\x97\x8dg\xde\xff\xd8\xb8\x1a \x05/\xa3D-\xa3\ 425 | \xc5^F\x8bZFj\xb5\xe4\xd2\xd2/\xeeM\xbb\x90\ 426 | \x0e'\xf5z&\x87d6\xf5\x9f\xfd;@.u\xb2\ 427 | \x80\xfd2?\xec\xf9\x82\x95\xcc\x9a\xaa\xf1\x8ds,\xed\ 428 | =\x9a\x5c\x06\xc3\xf3\xf3\x89\xeb\x8a\x92q\xb5a||\ 429 | \x9e\xf6\xd3-\xe9\xc6w\x9a\xdbpt\xe2a\x8b,e\ 430 | \x8b,\x0d\x1c\xd4\x03\x0bd\x05\xa2\x91Bq\x98\xa1\xd4\ 431 | 3D\xd43Tk`tf\x1b\xee\xae\x16\x84\xaf\x7f\ 432 | \xdd\xa2\xe1`xR0R\xd21\xbe\xde\xbe\xe12|\ 450 | h\xfc\x08$5\x05\xbeu\x81f\xf5f\x85\xc3^\x07\ 451 | \x8b-m1\x86\xc4\x9d@\x00&\x14h\xd7\x15\x17\x88\ 452 | \xb0\xa3v\x1a[$\x0f?\xaf\xb3\xf2\xe3\xfe\x8d\xc2\xb3\ 453 | \x92\xb4\x94@)\x07\xbb\xd1\x1cp\xd5\xc5\x8e\xa8\xd2\x8b\ 454 | \xf6\x86\x94\xdc5:\x1bK\x93\x97\xc7\x92\xb8\x14\xc8\x9c\ 455 | 9\xf8\xc7\x96\x8a;\x22ys\xf5\xf8a\xe9\xbb\x06\xbf\ 456 | [\xa2s\xb8)1U2\xbc\xd0\xde\xfbk\x1a\x5cy\ 457 | \xa1\x831\xd6\xef\x96\xdeR\x9c\xc7\x93V7\x1aK\xe2\ 458 | R \x00\xd7^\xac\xfdv\xecHmO\xa4\xd7W\xd7\ 459 | J\x16>\xa3\xf3\xf2\xdb\x06\xcd\x11&\x18\xb0\x8b\xe1E\ 460 | \xf6\xf5 \x9a\x03\xae\xb8\xc0\xc1\xe4\xb1\x96\xdb \x85\xc1\ 461 | \x8f 6\xd5\xc5bE\xdc\x0a\x04\xa0(O\xbb\xc4\xe3\ 462 | \x8e|\xb5\xd0\xd0a\xed&\x83_\xfd\xd1\xcf\xab\xff2\ 463 | \xa8O\x90\x1e\xc5\xae\x89z\x8a\x07\xae\xbf\xcc\xc1\xb4\xf1\ 464 | \xd6\xdf_\xc0\xe3\x85\xf9\xac\xb0\xbc\xe1\x18\x13W\x0b\x85\ 465 | \xbd\xf1\xe8\x12\xe3\xc9\x0f6\x18\xd7Z\xd1\x96\x10P6\ 466 | B0\xeb$\x8d\xf1\xa3\xe2\xb7\x22\x95\xae\xc3]\x0f\xfb\ 467 | \xc3K\x10\x1d%\xa3\x8a\x05\xdf\xbaP\xb3|\xce\x01 \ 468 | \xa0\xae\xdb\xc1\x84\x91Y4[\xdex\x8c\x89{\x81\x00\ 469 | b\xfe\x13\xfa\xde\x1d5\x91e?\x09Ffz\xa0\xa6\ 470 | \xfa\xb4\x09\xf1Y>\xe1\x89\x97t\xaa\xf6\xc4\xfeo\xe3\ 471 | q\xc3y\xa7i\xcc\x9ef\xb9\xb7\xea\x08RJ\xbe^\ 472 | \x9c\xc7\xeb1i=\xc6\xc4\xdd:H/\xc8\xf1#\x1c\ 473 | s\x0e6\xf8+[\xda\xa2Kv}4-m\xf0\xef\ 474 | 5\x06\xff^\x13\x18\xd2L\x1b/\x98\ 496 | \x1eHH\x81\x00<\xff\x0f\xfd\xaa\x7f\xaf\x96\xcfv\xdb\ 497 | \x9c\xc9\xd5\xe3\x863\xa7k\x9c9\xa3\x1f&\xbd\xf1\xcf\ 498 | [u\xb9\x5c<\x1d\xecM\xd7b!\x09+\x10\x80\xc7\ 499 | ^6~\xb6z\xa3q\x9f\xd5%\x8e#!=\x15\xbe\ 500 | ~\x96\x83\xa9\xd6o\xd1H\x14V\xbb\x0c\xceK\x84 \ 501 | \xa8pHh\x81\x00<\xfe\x7fF\xc5\xea\x8d\xc6\xddv\ 502 | \x14\xb2\xec\x8dI'\x08.?\xdf1\xb8\x86]\x92\x8d\ 503 | ~\x17g\x0d\xcf$\xf2\x92SqJ\xc2\x0b\x04\xe0\xe9\ 504 | \xa5F\xf9\x8au\xc6=\xddq\xd2\xb1\xe7e\x09\xae\xf9\ 505 | \x86FA\xee\xa0\xe8M>\x92I\x5cP\x9cN\x83\xdd\ 506 | \x86\xc4\x82\x01!\x10\x80\xe7\xde0~\xba\xfc#cq\ 507 | \xa7\xd7\xe2\x5c7\x11\x92\xec\x81\x1f\x5c\xe6`X\x1c\x05\ 508 | @Y\x8e`\x85\x07.\xce\xc9\x89\xb4 [\xfc\x13\xd7\ 509 | \xbby\xc3\xe1\xaa\xafi\x0f\x9e~\x92vc\xb2'>\ 510 | r\x05uy\xe1\xc9Wt\xea\x9b\xe3\xc2\x9cX\xf0w\ 511 | \xd1\xcd\x05\x03Y\x1c0\x80z\x90#<\xfe\x92\xff\xbc\ 512 | m\xd5\xe2\xb5\xfaf\x19\x17\x15D\xf2\xb2\x047\x7f\xd7\ 513 | \x81'.\xac\xb1\x06)x\xa28\x87\x1f\x93`\xb1\x1d\ 514 | \x910\xe0\x04\x02\xb0t\x19\xa5\xeb*\xf5\xd5;\xf7D\ 515 | \x99k\xd3\x22\xa6O\x10|\xeb\xc2\xc4_U\x14\x01\xf7\ 516 | \xedm\x85\xb9