Source code for x2go.mimeboxactions

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

# Copyright (C) 2010-2020 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
#
# Python X2Go is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Python X2Go 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

"""\
For MIME box jobs there are currently three handling actions available:
:class:`x2go.mimeboxactions.X2GoMIMEboxActionOPEN`, :class:`x2go.mimeboxactions.X2GoMIMEboxActionOPENWITH` and :class:`x2go.mimeboxactions.X2GoMIMEboxActionSAVEAS`.

"""
__NAME__ = 'x2gomimeboxactions-pylib'

__package__ = 'x2go'
__name__    = 'x2go.mimeboxactions'

# modules
import os
import copy
import time

from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
if _X2GOCLIENT_OS in ("Windows"):
    import subprocess
    import win32api
else:
    from . import gevent_subprocess as subprocess
    from . import x2go_exceptions
    WindowsErrror = x2go_exceptions.WindowsError

# Python X2Go modules
from . import log
from . import x2go_exceptions

_MIMEBOX_ENV = os.environ.copy()


[docs]class X2GoMIMEboxAction(object): __name__ = 'NAME' __description__ = 'DESCRIPTION' def __init__(self, client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ This is a meta class and has no functionality as such. It is used as parent class by »real« X2Go MIME box actions. :param client_instance: the underlying :class:`x2go.client.X2GoClient` instance :type client_instance: ``obj`` :param logger: you can pass an :class:`x2go.log.X2GoLogger` object to the :class:`x2go.mimeboxactions.X2GoMIMEboxAction` constructor :type logger: ``obj`` :param loglevel: if no :class:`x2go.log.X2GoLogger` object has been supplied a new one will be constructed with the given loglevel :type loglevel: ``int`` """ if logger is None: self.logger = log.X2GoLogger(loglevel=loglevel) else: self.logger = copy.deepcopy(logger) self.logger.tag = __NAME__ # these get set from within the X2GoMIMEboxQueue class self.profile_name = 'UNKNOWN' self.session_name = 'UNKNOWN' self.client_instance = client_instance @property def name(self): """\ Return the X2Go MIME box action's name. :returns: MIME box action name :rtype: ``str`` """ return self.__name__ @property def description(self): """\ Return the X2Go MIME box action's description text. :returns: MIME box action's description :rtype: ``str`` """ return self.__description__ def _do_process(self, mimebox_file, mimebox_dir, ): """\ Perform the defined MIME box action (doing nothing in :class:`x2go.mimeboxactions.X2GoMIMEboxAction` parent class). :param mimebox_file: file name as placed in to the X2Go MIME box directory :type mimebox_file: ``str`` :param mimebox_dir: location of the X2Go session's MIME box directory :type mimebox_dir: ``str`` """ pass
[docs] def do_process(self, mimebox_file, mimebox_dir, ): """\ Wrapper method for the actual processing of MIME box actions. :param mimebox_file: file name as placed in to the X2Go MIME box directory :type mimebox_file: ``str`` :param mimebox_dir: location of the X2Go session's MIME box directory :type mimebox_dir: ``str`` """ mimebox_file = os.path.normpath(mimebox_file) mimebox_dir = os.path.normpath(mimebox_dir) self._do_process(mimebox_file, mimebox_dir)
[docs]class X2GoMIMEboxActionOPEN(X2GoMIMEboxAction): """\ MIME box action that opens incoming files in the system's default application. """ __name__= 'OPEN' __decription__= 'Open incoming file with local system\'s default application.' def __init__(self, client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ :param client_instance: the underlying :class:`x2go.client.X2GoClient` instance :type client_instance: ``obj`` :param logger: you can pass an :class:`x2go.log.X2GoLogger` object to the :class:`x2go.mimeboxactions.X2GoMIMEboxActionOPEN` constructor :type logger: ``obj`` :param loglevel: if no :class:`x2go.log.X2GoLogger` object has been supplied a new one will be constructed with the given loglevel :type loglevel: ``int`` """ self.client_instance = client_instance X2GoMIMEboxAction.__init__(self, logger=logger, loglevel=loglevel) def _do_process(self, mimebox_file, mimebox_dir, ): """\ Open an incoming MIME box file in the system's default application. :param mimebox_file: file name as placed in to the MIME box directory :type mimebox_file: ``str`` :param mimebox_dir: location of the X2Go session's MIME box directory :type mimebox_dir: ``str`` """ mimebox_file = os.path.normpath(mimebox_file) mimebox_dir = os.path.normpath(mimebox_dir) if _X2GOCLIENT_OS == "Windows": self.logger('opening incoming MIME box file with Python\'s os.startfile() command: %s' % mimebox_file, loglevel=log.loglevel_DEBUG) try: os.startfile(os.path.join(mimebox_dir, mimebox_file)) except WindowsError as win_err: if self.client_instance: self.client_instance.HOOK_mimeboxaction_error(mimebox_file, profile_name=self.profile_name, session_name=self.session_name, err_msg=str(win_err) ) else: self.logger('Encountered WindowsError: %s' % str(win_err), loglevel=log.loglevel_ERROR) time.sleep(20) else: cmd_line = [ 'xdg-open', os.path.join(mimebox_dir, mimebox_file), ] self.logger('opening MIME box file with command: %s' % ' '.join(cmd_line), loglevel=log.loglevel_DEBUG) subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=_MIMEBOX_ENV) time.sleep(20)
[docs]class X2GoMIMEboxActionOPENWITH(X2GoMIMEboxAction): """\ MIME box action that calls the system's ,,Open with...'' dialog on incoming files. Currently only properly implementable on Windows platforms. """ __name__= 'OPENWITH' __decription__= 'Evoke ,,Open with...\'\' dialog on incoming MIME box files.' def __init__(self, client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ :param client_instance: the underlying :class:`x2go.client.X2GoClient` instance :type client_instance: ``obj`` :param logger: you can pass an :class:`x2go.log.X2GoLogger` object to the :class:`x2go.mimeboxactions.X2GoMIMEboxActionOPENWITH` constructor :type logger: ``obj`` :param loglevel: if no :class:`x2go.log.X2GoLogger` object has been supplied a new one will be constructed with the given loglevel :type loglevel: ``int`` """ self.client_instance = client_instance X2GoMIMEboxAction.__init__(self, logger=logger, loglevel=loglevel) def _do_process(self, mimebox_file, mimebox_dir, ): """\ Open an incoming MIME box file in the system's default application. :param mimebox_file: file name as placed in to the MIME box directory :type mimebox_file: ``str`` :param mimebox_dir: location of the X2Go session's MIME box directory :type mimebox_dir: ``str`` """ mimebox_file = os.path.normpath(mimebox_file) mimebox_dir = os.path.normpath(mimebox_dir) if _X2GOCLIENT_OS == "Windows": self.logger('evoking Open-with dialog on incoming MIME box file: %s' % mimebox_file, loglevel=log.loglevel_DEBUG) win32api.ShellExecute ( 0, "open", "rundll32.exe", "shell32.dll,OpenAs_RunDLL %s" % os.path.join(mimebox_dir, mimebox_file), None, 0, ) time.sleep(20) else: self.logger('the evocation of the Open-with dialog box is currently not available on Linux, falling back to MIME box action OPEN', loglevel=log.loglevel_WARN) cmd_line = [ 'xdg-open', os.path.join(mimebox_dir, mimebox_file), ] self.logger('opening MIME box file with command: %s' % ' '.join(cmd_line), loglevel=log.loglevel_DEBUG) subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=_MIMEBOX_ENV) time.sleep(20)
[docs]class X2GoMIMEboxActionSAVEAS(X2GoMIMEboxAction): """\ MIME box action that allows saving incoming MIME box files to a local folder. What this MIME box actually does is calling a hook method in the :class:`x2go.client.X2GoClient` instance that can be hi-jacked by one of your application's methods which then can handle the ,,Save as...'' request. """ __name__ = 'SAVEAS' __decription__= 'Save incoming file as...' def __init__(self, client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ :param client_instance: an :class:`x2go.client.X2GoClient` instance, within your customized :class:`x2go.client.X2GoClient` make sure you have a ``HOOK_open_mimebox_saveas_dialog(filename=<str>)`` method defined that will actually handle the incoming mimebox file. :type client_instance: ``obj`` :param logger: you can pass an :class:`x2go.log.X2GoLogger` object to the :class:`x2go.mimeboxactions.X2GoMIMEboxActionSAVEAS` constructor :type logger: ``obj`` :param loglevel: if no :class:`x2go.log.X2GoLogger` object has been supplied a new one will be constructed with the given loglevel :type loglevel: ``int`` :raises X2GoMIMEboxActionException: if the client_instance has not been passed to the SAVEAS MIME box action """ if client_instance is None: raise x2go_exceptions.X2GoMIMEboxActionException('the SAVEAS MIME box action needs to know the X2GoClient instance (client=<instance>)') X2GoMIMEboxAction.__init__(self, client_instance=client_instance, logger=logger, loglevel=loglevel) def _do_process(self, mimebox_file, mimebox_dir): """\ Call an :class:`x2go.client.X2GoClient` hook method (``HOOK_open_mimebox_saveas_dialog``) that can handle the MIME box's SAVEAS action. :param mimebox_file: file name as placed in to the MIME box directory :type mimebox_file: ``str`` :param mimebox_dir: location of the X2Go session's MIME box directory :type mimebox_dir: ``str`` :param mimebox_file: PDF file name as placed in to the X2Go spool directory """ mimebox_file = os.path.normpath(mimebox_file) mimebox_dir = os.path.normpath(mimebox_dir) self.logger('Session %s (%s) is calling X2GoClient class hook method <client_instance>.HOOK_open_mimebox_saveas_dialog(%s)' % (self.session_name, self.profile_name, mimebox_file), loglevel=log.loglevel_NOTICE) self.client_instance.HOOK_open_mimebox_saveas_dialog(os.path.join(mimebox_dir, mimebox_file), profile_name=self.profile_name, session_name=self.session_name) time.sleep(60)