Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2# This file is part of Xpra. 

3# Copyright (C) 2020 Antoine Martin <antoine@xpra.org> 

4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 

5# later version. See the file COPYING for details. 

6 

7import io 

8from contextlib import redirect_stdout, redirect_stderr 

9 

10from xpra.util import typedict 

11from xpra.scripts.config import TRUE_OPTIONS 

12from xpra.server.source.stub_source_mixin import StubSourceMixin 

13from xpra.log import Logger 

14 

15log = Logger("exec") 

16 

17 

18class ShellMixin(StubSourceMixin): 

19 

20 @classmethod 

21 def is_needed(cls, caps : typedict) -> bool: 

22 return caps.boolget("shell", False) 

23 

24 def __init__(self, *_args): 

25 self._server = None 

26 self.shell_enabled = False 

27 self.saved_logging_handler = None 

28 self.log_records = [] 

29 self.log_thread = None 

30 

31 def init_from(self, protocol, server): 

32 self._server = server 

33 try: 

34 options = protocol._conn.options 

35 shell = options.get("shell", "") 

36 self.shell_enabled = shell.lower() in TRUE_OPTIONS 

37 except AttributeError: 

38 options = {} 

39 self.shell_enabled = False 

40 log("init_from(%s, %s) shell_enabled(%s)=%s", protocol, server, options, self.shell_enabled) 

41 

42 def get_caps(self) -> dict: 

43 return {"shell" : self.shell_enabled} 

44 

45 def get_info(self) -> dict: 

46 return {"shell" : self.shell_enabled} 

47 

48 def shell_exec(self, code): 

49 stdout, stderr = self.do_shell_exec(code) 

50 log("shell_exec(%s) stdout=%r", code, stdout) 

51 log("shell_exec(%s) stderr=%r", code, stderr) 

52 if stdout is not None: 

53 self.send("shell-reply", 1, stdout) 

54 if stderr: 

55 self.send("shell-reply", 2, stderr) 

56 return stdout, stderr 

57 

58 def do_shell_exec(self, code): 

59 log("shell_exec(%r)", code) 

60 try: 

61 assert self.shell_enabled, "shell support is not available with this connection" 

62 _globals = { 

63 "connection" : self, 

64 "server" : self._server, 

65 "log" : log, 

66 } 

67 stdout = io.StringIO() 

68 stderr = io.StringIO() 

69 with redirect_stdout(stdout): 

70 with redirect_stderr(stderr): 

71 exec(code, _globals, {}) 

72 return stdout.getvalue().encode("utf8"), stderr.getvalue().encode("utf8") 

73 except Exception as e: 

74 log("shell_exec(..)", exc_info=True) 

75 log.error("Error running %r:", code) 

76 log.error(" %s", e) 

77 return None, str(e)