| 190 | |
| 191 | |
| 192 | class ConfigApp(tornado.web.Application): |
| 193 | |
| 194 | def __init__(self): |
| 195 | # generate a new auth token using UUID |
| 196 | self.access_token = uuid.uuid4().hex |
| 197 | settings = { |
| 198 | "access_token": self.access_token, # our custom setting |
| 199 | "login_url": "/version", |
| 200 | "debug": True |
| 201 | } |
| 202 | handlers = [ |
| 203 | (r"/(.*\.html|config.js)", tornado.web.StaticFileHandler, {"path": current_ime_config_dir}), |
| 204 | (r"/(.*\.htm)", tornado.web.StaticFileHandler, {"path": os.path.join(current_dir, "config")}), |
| 205 | (r"/((css|fonts|images|js)/.*)", tornado.web.StaticFileHandler, {"path": os.path.join(current_dir, "config")}), |
| 206 | (r"/(icon.ico)", tornado.web.StaticFileHandler, {"path": current_ime_dir}), |
| 207 | (r"/(version.txt)", tornado.web.StaticFileHandler, {"path": os.path.join(current_dir, "../../")}), |
| 208 | (r"/config", ConfigHandler), # main configuration handler |
| 209 | (r"/keep_alive", KeepAliveHandler), # keep the api server alive |
| 210 | (r"/login/(.*)", LoginHandler) # authentication |
| 211 | ] |
| 212 | super().__init__(handlers, **settings) |
| 213 | self.timeout_handler = None |
| 214 | self.port = 0 |
| 215 | |
| 216 | def launch_browser(self, tool_name): |
| 217 | user_html = """<html> |
| 218 | <form id="auth" action="http://127.0.0.1:{PORT}/login/{PAGE_NAME}" method="POST"> |
| 219 | <input type="hidden" name="token" value="{TOKEN}"> |
| 220 | </form> |
| 221 | <script type="text/javascript"> |
| 222 | document.getElementById("auth").submit(); |
| 223 | </script> |
| 224 | </html>""".format(PORT=self.port, PAGE_NAME=tool_name, TOKEN=self.access_token) |
| 225 | # use a local html file to send access token to our service via http POST for authentication. |
| 226 | os.makedirs(localdata_dir, exist_ok=True) |
| 227 | filename = os.path.join(localdata_dir, "launch_{}.html".format(tool_name)) |
| 228 | |
| 229 | with open(filename, "w") as f: |
| 230 | f.write(user_html) |
| 231 | os.startfile(filename) |
| 232 | |
| 233 | def run(self, tool_name): |
| 234 | # find a port number that's available |
| 235 | random.seed() |
| 236 | while True: |
| 237 | port = random.randint(1025, 65535) |
| 238 | try: |
| 239 | self.listen(port, "127.0.0.1") |
| 240 | break |
| 241 | except OSError: # it's possible that the port we want to use is already in use |
| 242 | continue |
| 243 | self.port = port |
| 244 | |
| 245 | self.launch_browser(tool_name) |
| 246 | |
| 247 | # setup the main event loop |
| 248 | loop = tornado.ioloop.IOLoop.current() |
| 249 | self.timeout_handler = loop.call_later(SERVER_TIMEOUT, self.quit) |