# Path: subuserlib/classes/service.py
# class Service(UserOwnedObject):
#   __metaclass__ = abc.ABCMeta
# 
#   def __init__(self,user,subuser):
#     self.__subuser = subuser
#     UserOwnedObject.__init__(self,user)
# 
#   @abc.abstractmethod
#   def start(self,serviceStatus):
#     """
#     Start the service. Block untill the service has started. Returns a modified service status dictionary with any service specific properties set.
#     """
#     pass
# 
#   @abc.abstractmethod
#   def stop(self,serviceStatus):
#     """
#     Stop the service. Block untill the service has stopped.
#     """
#     pass
# 
#   @abc.abstractmethod
#   def cleanUp(self):
#     pass
# 
#   @abc.abstractmethod
#   def isRunning(self,serviceStatus):
#     """
#     Returns True if the services is running.
#     """
#     pass
# 
#   def getLockfileDir(self):
#     return os.path.join(self.user.config["lock-dir"],"services",self.__subuser.name)
# 
#   def getLockfilePath(self):
#     return os.path.join(self.getLockfileDir(),self.name+".json")
# 
#   def removeLockFile(self):
#     os.remove(self.getLockfilePath())
#     try:
#       os.rmdir(self.getLockfileDir())
#     except OSError:
#       pass
# 
#   def getLock(self):
#     try:
#       self.user.endUser.makedirs(self.getLockfileDir())
#     except OSError as exception:
#       if exception.errno != errno.EEXIST:
#         raise
#     while True:
#       try:
#         lockFd = open(self.getLockfilePath(),mode="r+")
#         break
#       except IOError:
#         self.user.endUser.create_file(self.getLockfilePath())
#     fcntl.flock(lockFd,fcntl.LOCK_EX)
#     return lockFd
# 
#   def addClient(self):
#     """
#     Increase the services client counter, starting the service if necessary. Blocks untill the service is ready to accept the new client.
#     """
#     with self.getLock() as lockFile:
#       try:
#         serviceStatus = json.load(lockFile, object_pairs_hook=OrderedDict)
#       except ValueError:
#         serviceStatus = {}
#         serviceStatus["client-counter"] = 0
#       if serviceStatus["client-counter"] == 0 or not self.isRunning(serviceStatus):
#         serviceStatus["client-counter"] = 0
#         serviceStatus = self.start(serviceStatus)
#       serviceStatus["client-counter"] = serviceStatus["client-counter"] + 1
#       lockFile.seek(0)
#       lockFile.truncate()
#       json.dump(serviceStatus,lockFile)
#       fcntl.flock(lockFile,fcntl.LOCK_UN)
# 
#   def removeClient(self):
#     """
#     Decrease the services client counter, stopping the service if no longer necessary.
#     """
#     noMoreClients = False
#     with self.getLock() as lockFile:
#       try:
#         lock_info = lockFile.read()
#         serviceStatus = json.loads(lock_info, object_pairs_hook=OrderedDict)
#       except ValueError as e:
#         sys.exit("Error in lock file. Failed to release lock:\n"+lock_info+"\n"+str(e))
#       serviceStatus["client-counter"] = serviceStatus["client-counter"] - 1
#       if serviceStatus["client-counter"] < 0:
#         raise RemoveClientException("The client-counter is already zero. Client cannot be removed! \n" + str(serviceStatus))
#       if serviceStatus["client-counter"] == 0:
#         self.stop(serviceStatus)
#         noMoreClients = True
#       lockFile.seek(0)
#       lockFile.truncate()
#       json.dump(serviceStatus,lockFile)
#       if noMoreClients:
#         self.removeLockFile()
#       fcntl.flock(lockFile,fcntl.LOCK_UN)
# 
#   def cleanUpIfNotRunning(self):
#     """
#     Check if running.
#     If not running, run cleanUp method.
#     """
#     with self.getLock() as lockFile:
#       try:
#         serviceStatus = json.load(lockFile, object_pairs_hook=OrderedDict)
#       except ValueError:
#         serviceStatus = {}
#         serviceStatus["client-counter"] = 0
#       if serviceStatus["client-counter"] == 0 or not self.isRunning(serviceStatus):
#         self.cleanUp()
#         self.removeLockFile()
#       fcntl.flock(lockFile,fcntl.LOCK_UN)


import os
import time
import shutil
import errno
import sys
import hashlib
import subuserlib.verify
import subuserlib.subuser
from subuserlib.classes.service import Service
from collections import OrderedDict
    from subuserlib.classes.permissionsAccepters.acceptPermissionsAtCLI import AcceptPermissionsAtCLI
An x11 bridge provides a secure/firewalled link between a desktop application and the host x11 server. In this case, we use XPRA to do the bridging.

::.

  -------------                      -------------
  |desktop app| <--/tmp/.X11-unix--> |xpra server|    Untrusted
  -------------                      -------------
                                           ^
                                           | ~/.xpra
                                           v
  -------------                       -------------
  | host      |  <--/tmp/.X11-unix--> |xpra client|   Trusted
  -------------                       -------------

This configuration involves 3 containers.

1) contains the untrusted desktop application
2) contains an untrusted xpra server
3) contains a trusted xpra client

I up-to-date version of xpra can be used, xpra need not be installed on the host.

"""

#external imports
#internal imports

class XpraX11Bridge(Service):
  def __init__(self,user,subuser):
    self.subuser = subuser

# Path: subuserlib/classes/service.py
# class Service(UserOwnedObject):
#   __metaclass__ = abc.ABCMeta
# 
#   def __init__(self,user,subuser):
#     self.__subuser = subuser
#     UserOwnedObject.__init__(self,user)
# 
#   @abc.abstractmethod
#   def start(self,serviceStatus):
#     """
#     Start the service. Block untill the service has started. Returns a modified service status dictionary with any service specific properties set.
#     """
#     pass
# 
#   @abc.abstractmethod
#   def stop(self,serviceStatus):
#     """
#     Stop the service. Block untill the service has stopped.
#     """
#     pass
# 
#   @abc.abstractmethod
#   def cleanUp(self):
#     pass
# 
#   @abc.abstractmethod
#   def isRunning(self,serviceStatus):
#     """
#     Returns True if the services is running.
#     """
#     pass
# 
#   def getLockfileDir(self):
#     return os.path.join(self.user.config["lock-dir"],"services",self.__subuser.name)
# 
#   def getLockfilePath(self):
#     return os.path.join(self.getLockfileDir(),self.name+".json")
# 
#   def removeLockFile(self):
#     os.remove(self.getLockfilePath())
#     try:
#       os.rmdir(self.getLockfileDir())
#     except OSError:
#       pass
# 
#   def getLock(self):
#     try:
#       self.user.endUser.makedirs(self.getLockfileDir())
#     except OSError as exception:
#       if exception.errno != errno.EEXIST:
#         raise
#     while True:
#       try:
#         lockFd = open(self.getLockfilePath(),mode="r+")
#         break
#       except IOError:
#         self.user.endUser.create_file(self.getLockfilePath())
#     fcntl.flock(lockFd,fcntl.LOCK_EX)
#     return lockFd
# 
#   def addClient(self):
#     """
#     Increase the services client counter, starting the service if necessary. Blocks untill the service is ready to accept the new client.
#     """
#     with self.getLock() as lockFile:
#       try:
#         serviceStatus = json.load(lockFile, object_pairs_hook=OrderedDict)
#       except ValueError:
#         serviceStatus = {}
#         serviceStatus["client-counter"] = 0
#       if serviceStatus["client-counter"] == 0 or not self.isRunning(serviceStatus):
#         serviceStatus["client-counter"] = 0
#         serviceStatus = self.start(serviceStatus)
#       serviceStatus["client-counter"] = serviceStatus["client-counter"] + 1
#       lockFile.seek(0)
#       lockFile.truncate()
#       json.dump(serviceStatus,lockFile)
#       fcntl.flock(lockFile,fcntl.LOCK_UN)
# 
#   def removeClient(self):
#     """
#     Decrease the services client counter, stopping the service if no longer necessary.
#     """
#     noMoreClients = False
#     with self.getLock() as lockFile:
#       try:
#         lock_info = lockFile.read()
#         serviceStatus = json.loads(lock_info, object_pairs_hook=OrderedDict)
#       except ValueError as e:
#         sys.exit("Error in lock file. Failed to release lock:\n"+lock_info+"\n"+str(e))
#       serviceStatus["client-counter"] = serviceStatus["client-counter"] - 1
#       if serviceStatus["client-counter"] < 0:
#         raise RemoveClientException("The client-counter is already zero. Client cannot be removed! \n" + str(serviceStatus))
#       if serviceStatus["client-counter"] == 0:
#         self.stop(serviceStatus)
#         noMoreClients = True
#       lockFile.seek(0)
#       lockFile.truncate()
#       json.dump(serviceStatus,lockFile)
#       if noMoreClients:
#         self.removeLockFile()
#       fcntl.flock(lockFile,fcntl.LOCK_UN)
# 
#   def cleanUpIfNotRunning(self):
#     """
#     Check if running.
#     If not running, run cleanUp method.
#     """
#     with self.getLock() as lockFile:
#       try:
#         serviceStatus = json.load(lockFile, object_pairs_hook=OrderedDict)
#       except ValueError:
#         serviceStatus = {}
#         serviceStatus["client-counter"] = 0
#       if serviceStatus["client-counter"] == 0 or not self.isRunning(serviceStatus):
#         self.cleanUp()
#         self.removeLockFile()
#       fcntl.flock(lockFile,fcntl.LOCK_UN)


# Path: subuserlib/classes/subuserSubmodules/run/x11Bridge.py
import os
import time
import shutil
import errno
import sys
import hashlib
import subuserlib.verify
import subuserlib.subuser
from subuserlib.classes.service import Service
from collections import OrderedDict
    from subuserlib.classes.permissionsAccepters.acceptPermissionsAtCLI import AcceptPermissionsAtCLI

An x11 bridge provides a secure/firewalled link between a desktop application and the host x11 server. In this case, we use XPRA to do the bridging.

::.

  -------------                      -------------
  |desktop app| <--/tmp/.X11-unix--> |xpra server|    Untrusted
  -------------                      -------------
                                           ^
                                           | ~/.xpra
                                           v
  -------------                       -------------
  | host      |  <--/tmp/.X11-unix--> |xpra client|   Trusted
  -------------                       -------------

This configuration involves 3 containers.

1) contains the untrusted desktop application
2) contains an untrusted xpra server
3) contains a trusted xpra client

I up-to-date version of xpra can be used, xpra need not be installed on the host.

"""

#external imports
#internal imports

class XpraX11Bridge(Service):
  def __init__(self,user,subuser):
    self.subuser = subuser

    Service.__init__(self,user,subuser)