[med-svn] [mobyle] 02/08: Imported Upstream version 1.5.5+dfsg

Andreas Tille tille at debian.org
Fri May 20 21:22:48 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository mobyle.

commit d2c234cd5522e6eb8554244d821fc4374f1081a8
Author: Andreas Tille <tille at debian.org>
Date:   Fri May 20 22:57:04 2016 +0200

    Imported Upstream version 1.5.5+dfsg
---
 INSTALL                                     |   2 +-
 Local/mailTemplate.py                       | 150 +++++++++++++++-------------
 NEWS                                        |  13 ++-
 PKG-INFO                                    |   2 +-
 Src/Mobyle/Classes/Core.py                  |  67 ++++++++-----
 Src/Mobyle/CommandBuilder.py                |   7 +-
 Src/Mobyle/ConfigManager.py                 |   2 +-
 Src/Mobyle/Execution/DRMAA.py               |   5 +-
 Src/Mobyle/JobState.py                      |   2 +-
 Src/Mobyle/MobyleJob.py                     |  25 +++--
 Src/Mobyle/RunnerChild.py                   |  57 +++++------
 Src/Mobyle/Service.py                       |  27 +++--
 Src/Mobyle/Utils.py                         |  50 +++++++---
 Src/Portal/htdocs/MobylePortal/js/mobyle.js |   5 +-
 Src/Portal/htdocs/MobylePortal/xsl/job.xsl  |  18 ++--
 Tools/mob_log_rotate                        |   0
 Tools/mob_stat                              |  23 +++--
 setup.py                                    |   2 +-
 18 files changed, 268 insertions(+), 189 deletions(-)

diff --git a/INSTALL b/INSTALL
index 58d1a3a..2bf7563 100644
--- a/INSTALL
+++ b/INSTALL
@@ -126,7 +126,7 @@ cp Example/Local/Config/Config.template.py  Local/Config/Config.py
 
 In order to have a working installation, you need to edit the various configuration directives.
 The documentation describing the configuration of Mobyle and Apache is the configuration manual 
-Doc/Admin/configuration_guide.pdf.
+Doc/Admin/how_to_configure_mobyle.pdf.
 
 4.4 - Services descriptions deployment.
 ---------------------------------------
diff --git a/Local/mailTemplate.py b/Local/mailTemplate.py
index 244b475..c2d8a7e 100644
--- a/Local/mailTemplate.py
+++ b/Local/mailTemplate.py
@@ -1,6 +1,7 @@
+# -*- coding: utf-8 -*-
+
 #####################################################
-# Here are the different email templates sent to the user
-# Each template is structured as follows:
+# Here are the different email templates send to the user
 #
 # From:         required
 # Cc:           optional  
@@ -15,16 +16,16 @@
 
 ############################################################
 #
-# CONFIRM_SESSION email is sent to the user to confirm his 
+# CONFIRM_SESSION email is send to the user to confirm his 
 # registration. 
 # if config.AUTHENTICATED_SESSION = 'email'
 # 
 # the available keys are:
-# SENDER      : the email address which sends the mail as defined in the configuration
-# HELP        : the email of the Mobyle "hot line" as defined in the configuration
-# SERVER_NAME : the url of the Mobyle portal
-# CGI_URL     : the url of the portal cgi directory
-# ACTIVATING_KEY : the key which allows the user to activate its session 
+# SENDER      : the email address who send the mail as defined in config
+# HELP        : the email of the mobyle "hot line" as defined in config
+# SERVER_NAME : the url of the mobyle portal
+# CGI_URL     : the url of the portal cgi
+# ACTIVATING_KEY : the key which permit the user to acivate it's session 
 ###########################################################
 
 CONFIRM_SESSION = """
@@ -45,57 +46,77 @@ following link (or paste its URL in your favourite browser):
 
 ####################################################################
 #
-# RESULTS_TOOBIG email is sent to the user when a job is finished 
+# RESULTS_TOOBIG email is send to the user when a job is finished 
 # and the size of the results files is greater than Config.MAXMAILSIZE
 # 
 # the available keys are:
-# SENDER      : the email address which sends the mail as defined in the configuration 
-# HELP        : the email of the Mobyle "hot line" as defined in the configuration
-# SERVER_NAME : the url of the Mobyle portal
-# JOB_URL     : the url of the job
-# JOB_NAME    : the name of the service ex blast2 , clustalw-multialign
-# RESULTS_REMAIN : the number of days before the job is removed from the server, as defined in the configuration
+# SENDER      : the email address who send the mail as defined in config 
+# HELP        : the email of the mobyle "hot line" as defined in config
+# SERVER_NAME : the url of the mobyle portal
+# JOB_URL     : the job's url
+# JOB_NAME    : the name of the program ex blast2 , clustalw-multialing
+# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in config
 #
 ####################################################################
 
 RESULTS_TOOBIG = """
 From: %(SENDER)s
 Reply-To: %(SENDER)s
-Subject: Your %(JOB_NAME)s job is finished. Access your results
+Subject: your %(JOB_NAME)s job is finished. Access your results
 
 Your results are too big to be sent by email.
 They are accessible at the following address:
 %(JOB_URL)s
 
 Your results will be kept on our server for %(RESULTS_REMAIN)d days from now.
+
+You are using a free resource. Help us keeping it free, cite us:
+Mobyle: a new full web bioinformatics framework
+Bertrand Néron, Hervé Ménager, Corinne Maufrais, Nicolas Joly, Julien Maupetit,
+Sébastien Letort, Sébastien Carrere, Pierre Tuffery and Catherine Letondal.
+Bioinformatics (2009) 25 (22): 3005-3011. doi: 10.1093/bioinformatics/btp493
+
+Don't forget to cite also the authors of %(JOB_NAME)s.
+The references are available at the following address:
+http://mobyle.pasteur.fr/cgi-bin/portal.py#forms::%(JOB_NAME)s
 """
 
 
 ####################################################################
 #
-# RESULTS_FILES email is sent to the user when a job is finished 
+# RESULTS_FILES email is send to the user when a job is finished 
 # Config.OPT_EMAIl = False
 # 
 # the available keys are:
-# SENDER : the email address which sends the mail as defined in the configuration 
-# HELP   : the email of the mobyle "hot line" as defined in the configuration
+# SENDER : the email address who send the mail as defined in config 
+# HELP   : the email of the mobyle "hot line" as defined in config
 # SERVER_NAME : the url of the mobyle portal
-# JOB_URL     : the url of the job
-# JOB_NAME    : the name of the service ex blast2 , clustalw-multialign
-# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in the configuration
+# JOB_URL     : the job's url
+# JOB_NAME    : the name of the program ex blast2 , clustalw-multialing
+# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in config
 #
 ####################################################################
 
 RESULTS_FILES = """
 From: %(HELP)s
 Reply-To: %(SENDER)s
-Subject: Your %(JOB_NAME)s job is finished. Access your results
+Subject: your %(JOB_NAME)s job is finished. Access your results
 
 Your results are accessible at the following address:
 %(JOB_URL)s
 
 Your results will be kept on our server for %(RESULTS_REMAIN)d days from now.
 
+You are using a free resource. Help us keeping it free, cite us:
+Mobyle: a new full web bioinformatics framework
+Bertrand Néron, Hervé Ménager, Corinne Maufrais, Nicolas Joly, Julien Maupetit,
+Sébastien Letort, Sébastien Carrere, Pierre Tuffery and Catherine Letondal.
+Bioinformatics (2009) 25 (22): 3005-3011. doi: 10.1093/bioinformatics/btp493
+
+Don't forget to cite also the authors of %(JOB_NAME)s.
+The references are available at the following address:
+http://mobyle.pasteur.fr/cgi-bin/portal.py#forms::%(JOB_NAME)s
+
 An archive of your job is attached to this email. 
 It includes the index.xml file which is a summary of your job submission 
 (you can view it in your favorite web browser).
@@ -103,54 +124,64 @@ It includes the index.xml file which is a summary of your job submission
 
 ####################################################################
 #
-# RESULTS_NOTIFICATION email is sent to the user when a job is finished 
+# RESULTS_NOTIFICATION email is send to the user when a job is finished 
 # but the results files zipping failed.
 # 
 # the available keys are:
-# SENDER : the email address which sends the mail as defined in the configuration 
-# HELP   : the email of the mobyle "hot line" as defined in the configuration
+# SENDER : the email address who send the mail as defined in config 
+# HELP   : the email of the mobyle "hot line" as defined in config
 # SERVER_NAME : the url of the mobyle portal
-# JOB_URL     : the url of the job
-# JOB_NAME    : the name of the service ex blast2 , clustalw-multialign
-# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in the configuration
+# JOB_URL     : the job's url
+# JOB_NAME    : the name of the program ex blast2 , clustalw-multialing
+# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in config
 #
 ####################################################################
 
 RESULTS_NOTIFICATION = """
 From: %(HELP)s
 Reply-To: %(SENDER)s
-Subject: Your %(JOB_NAME)s job is finished. Access your results.
+Subject: your %(JOB_NAME)s job is finished. Access your results.
 
 Your results are accessible at the following address:
 %(JOB_URL)s
 
 Your results will be kept on our server for %(RESULTS_REMAIN)d days from now.
+
+You are using a free resource. Help us keeping it free, cite us:
+Mobyle: a new full web bioinformatics framework
+Bertrand Néron, Hervé Ménager, Corinne Maufrais, Nicolas Joly, Julien Maupetit,
+Sébastien Letort, Sébastien Carrere, Pierre Tuffery and Catherine Letondal.
+Bioinformatics (2009) 25 (22): 3005-3011. doi: 10.1093/bioinformatics/btp493
+
+Don't forget to cite also the authors of %(JOB_NAME)s.
+The references are available at the following address:
+http://mobyle.pasteur.fr/cgi-bin/portal.py#forms::%(JOB_NAME)s
 """
 
 ####################################################################
 #
-# LONG_JOB_NOTIFICATION email is sent to the user when a job is longer
+# LONG_JOB_NOTIFICATION email is send to the user when a job is longer
 # than Config.TIMEOUT
 # 
 # the available keys are:
-# SENDER   : the email address which sends the mail as defined in the configuration 
-# HELP     : the email of the mobyle "hot line" as defined in the configuration
+# SENDER   : the email address who send the mail as defined in config 
+# HELP     : the email of the mobyle "hot line" as defined in config
 # SERVER_NAME : the url of the mobyle portal
-# JOB_URL  : the url of the job
-# JOB_NAME : the name of the service ex blast2 , clustalw-multialign
+# JOB_URL  : the job's url
+# JOB_NAME : the name of the program ex blast2 , clustalw-multialing
 # JOB_KEY  : the unique key wich permit to identify a job
-# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in the configuration
+# RESULTS_REMAIN : the number of days before the jobs will be erase as defined in config
 #
 ####################################################################
 
 LONG_JOB_NOTIFICATION = """
 From: %(HELP)s
 Reply-To: %(SENDER)s
-Subject: Your job %(JOB_NAME)s/%(JOB_KEY)s is running.
+Subject: your job %(JOB_NAME)s/%(JOB_KEY)s is running.
 
 Your %(JOB_URL)s job is running on %(SERVER_NAME)s server.
-You will receive the results by email.
-You can access the results or check the job status at the following address:
+You'll receive the results by email.
+you could access to the results or check the job status at the following address:
 %(JOB_URL)s
 """
 
@@ -160,15 +191,15 @@ You can access the results or check the job status at the following address:
 # 
 # the available keys are:
 # USER     : the user email address
-# SENDER   : the email address which sends the mail as defined in the configuration 
-# HELP     : the email of the mobyle "hot line" as defined in the configuration
+# SENDER   : the email address who send the mail as defined in config 
+# HELP     : the email of the mobyle "hot line" as defined in config
 # MSG      : the message written by the USER 
 # SERVER_NAME   : the url of the mobyle portal
 # SESSION_ID    : the session unique identifier
 # SESSION_EMAIL : the user email store in the session
 # SESSION_ACTIVATED : if the session is activated
 # SESSION_AUTHENTICATED : if the session is authenticated
-# JOB_URL         : the url of the job
+# JOB_URL         : the job's url
 # JOB_DATE        : the date at which this job was launch
 # JOB_STATUS      : the mobyle job status ( finished, error ... )
 # JOB_ERROR_PARAM : if there is an error, the parameter name that provoke the error
@@ -200,19 +231,19 @@ Job information:
 
 ####################################################################
 #
-#  email is sent to the user as a receipt of its help demand
+#  email is send to the user as a receipt of its help demand
 # 
 # the available keys are:
 # USER     : the user email address
-# SENDER   : the email address which sends the mail as defined in the configuration 
-# HELP     : the email of the mobyle "hot line" as defined in the configuration
+# SENDER   : the email address who send the mail as defined in config 
+# HELP     : the email of the mobyle "hot line" as defined in config
 # MSG      : the message written by the USER 
 # SERVER_NAME   : the url of the mobyle portal
 # SESSION_ID    : the session unique identifier
 # SESSION_EMAIL : the user email store in the session
 # SESSION_ACTIVATED : if the session is activated
 # SESSION_AUTHENTICATED : if the session is authenticated
-# JOB_URL         : the url of the job
+# JOB_URL         : the job's url
 # JOB_DATE        : the date at which this job was launch
 # JOB_STATUS      : the mobyle job status ( finished, error ... )
 # JOB_ERROR_PARAM : if there is an error, the parameter name that provoke the error
@@ -224,8 +255,8 @@ From: %(HELP)s
 Reply-To: %(SENDER)s
 Subject: [mobyle help request receipt] help on job %(JOB_URL)s.
 
-We have received your help request (the message is included below). 
-We will try to answer it as soon as possible.
+We have received your help request (text received is included below). 
+We will try to answer as soon as possible.
 
 User Message:
 %(MSG)s
@@ -245,26 +276,3 @@ Job information:
 - error parameter: %(JOB_ERROR_PARAM)s
 - error message: %(JOB_ERROR_MSG)s
 """
-
-######################################################################
-#
-# email is sent by mobpasswd ( if -m option ) to notify the user of a 
-# password modification. 
-#
-# HELP          : the email of the mobyle "hot line" as defined in the configuration
-# SENDER        : the email address which sends the mail as defined in the configuration 
-# SERVER_NAME   : the url of the mobyle portal
-# PASSWD        : the new password
-#
-######################################################################
-
-NEW_PASSWD = """
-From: %(HELP)s
-Reply-To: %(SENDER)s
-Subject: [ %(SERVER_NAME)s ] new password.
-
-You have requested to change the password for your account on the
-%(SERVER_NAME)s server.
-
-Your new password is %(PASSWD)s
-"""
diff --git a/NEWS b/NEWS
index 426c291..cf84dde 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+CHANGES IN RELEASE 1.5.5
+
+* NEW: allow to display results files located inside a subdirectory.
+* NEW: allow to add a whole directory in zip results.
+* bug fix: the queue was not set properly when some nativespecification are provided.
+
+# Portal
+
+   * bug fix: do not display default interface if custom interface is defined.
+   * bug fix: correct the generated html for custom interfaces in job results page.
+
 CHANGES IN RELEASE 1.5.3
 
 # Portal
@@ -242,4 +253,4 @@ using OpenID, in order for them to avoid the management of a new Mobyle-specific
 password.
 
 # Google Analytics support: you can configure Mobyle to track users
-activity with a Google Analytics account.
\ No newline at end of file
+activity with a Google Analytics account.
diff --git a/PKG-INFO b/PKG-INFO
index efcd979..199d864 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: Mobyle
-Version: 1.5.3
+Version: 1.5.5
 Summary: UNKNOWN
 Home-page: https://projets.pasteur.fr/wiki/mobyle/
 Author: The Mobyle team
diff --git a/Src/Mobyle/Classes/Core.py b/Src/Mobyle/Classes/Core.py
index e4c8715..70d0b71 100644
--- a/Src/Mobyle/Classes/Core.py
+++ b/Src/Mobyle/Classes/Core.py
@@ -39,6 +39,8 @@ def safeMask( mask ):
     #we must work whit the same char set    
     mask = re.sub( "(;|`|$\(\s)+" , '_' , mask )
     mask = re.sub( "^.*[\\\]", "" ,  mask  )
+    mask = re.sub( "^/", "" ,  mask  )
+    mask = re.sub( "\.(\.)+", "" ,  mask  )
     return mask
 
 
@@ -350,8 +352,8 @@ class ChoiceDataType( StringDataType ):
 
 class MultipleChoiceDataType( StringDataType ):
 
-        
-    def convert( self , value , acceptedMobyleType , detectedMobyleType = None , paramFile= False ):
+
+    def convert( self , value , acceptedMobyleType , detectedMobyleType = None , paramFile= False, separator = None):
         """
         The MutipleChoiceDataType value are literals thus this method try to cast
         the value to a list of string.
@@ -359,38 +361,49 @@ class MultipleChoiceDataType( StringDataType ):
         @type value: list
         @param acceptedMobyleType: the MobyleType  accepted by this service parameter 
         @type acceptedMobyleType: L{MobyleType} instance
-        @param detectedMobyleType: the MobyleType discribing this data
+        @param detectedMobyleType: the MobyleType describing this data
         @type detectedMobyleType: L{MobyleType} instance
         @return: a string based on each selected value and joined by the separator.
         @rtype: String .
         @raise UserValueError: if the value can't be converted to a string.
-        """    
+        """
         if value is None:
             return ( None , acceptedMobyleType )
-        try:
-            values = [ str( elem ) for elem in value ]
-        except ValueError:
-            msg  = "this parameter is a MultipleChoice its all values must be Strings" %value 
-            raise UserValueError( msg = msg )
-        return ( values , acceptedMobyleType )
-    
+        sep = separator if separator is not None else ''
+        if hasattr( acceptedMobyleType , '_undefValue' ) and value == acceptedMobyleType._undefValue :
+            return ( None , acceptedMobyleType )
+        else:
+            try:
+                values = [ str( elem ) for elem in value ]
+            except ValueError:
+                msg  = "this parameter is a MultipleChoice its all values must be Strings" %value
+                raise UserValueError( msg = msg )
+            return ( sep.join(values) , acceptedMobyleType )
+
     def detect( self , value ):
         mt = MobyleType( self )
         return mt
-    
+
     def validate( self, param ):
         #values are stored as string in evaluator
         #the string is computed by service.setValue()
         #the string is return by getValue and used as is in ComandBuilder 
         userValues = param.getValue() #it's a string
+        if userValues is None:
+            return True
         sep = param.getSeparator()
+        #we must retransform the string in a list to check if each
+        #element is in the list of authorized values
+
         if sep == '':
             userValues = [ i for i in userValues ]
         else:
             userValues = userValues.split( sep )
+
         authorizedValues =  param.getVlistValues()
+        undef_value = param.getListUndefValue()
         for value in userValues:
-            if value not in authorizedValues :
+            if value not in authorizedValues and value != param.getListUndefValue():
                 msg = "the value %s is not allowed (allowed values: %s)" % (
                 str( value ) ,
                 str( param.getVlistValues() )
@@ -701,20 +714,20 @@ class AbstractTextDataType( AbstractFileDataType ):
                     raise MobyleError , msg
         else:
             try:
-                clean_content = self.cleanData( data )
-            except Exception, err :
+                clean_content = self.cleanData(data)
+            except Exception, err:
                 msg = "error when cleaning file : " + abs_DestFileName + str( err )
-                c_log.critical( msg , exc_info= True )
-                raise MobyleError , msg
+                c_log.critical(msg, exc_info=True)
+                raise MobyleError, msg
             try:
-                fh = open( abs_DestFileName , "w" )
-                fh.write( clean_content )
+                fh = open(abs_DestFileName, "w")
+                fh.write(clean_content)
                 fh.close()
-            except IOError , err:
-                msg = "error when creating file : " + abs_DestFileName + str( err )
-                raise MobyleError , msg
-        size = os.path.getsize( abs_DestFileName )
-        return os.path.basename( abs_DestFileName ) , size
+            except IOError, err:
+                msg = "error when creating file : " + abs_DestFileName + str(err)
+                raise MobyleError, msg
+        size = os.path.getsize(abs_DestFileName)
+        return os.path.basename(abs_DestFileName), size
 
 
 
@@ -821,14 +834,14 @@ class FilenameDataType( DataType ):
         """
         @param acceptedMobyleType: the MobyleType  accepted by this service parameter 
         @type acceptedMobyleType: L{MobyleType} instance
-        @param detectedMobyleType: the MobyleType discribing this data
+        @param detectedMobyleType: the MobyleType describing this data
         @type detectedMobyleType: L{MobyleType} instance
         """  
         if value is None:
             return ( None , acceptedMobyleType )
             #raise UserValueError( parameter = param , msg= " this parameter must be a String" )
-        fileName = safeFileName( value )
-        return ( fileName , acceptedMobyleType )
+        #fileName = safeFileName( value )
+        return ( value , acceptedMobyleType )
     
     def detect( self , value ):
         mt = MobyleType( self )
diff --git a/Src/Mobyle/CommandBuilder.py b/Src/Mobyle/CommandBuilder.py
index 6482cec..f93e4ce 100644
--- a/Src/Mobyle/CommandBuilder.py
+++ b/Src/Mobyle/CommandBuilder.py
@@ -247,7 +247,12 @@ class CommandBuilder:
                 continue
             else:
                 xmlEnv[ varEnv ] = envArg
-            
+        
+        for var, value in xmlEnv.items():
+            if value.startswith('()'):
+                msg = 'Bash vulnerabilty Exploitation: service unsafe check env %s'% var
+                c_log.critical("Security Error: %s : %s" % (service.getName(), msg))
+                raise MobyleError, msg              
         #trim multi espaces , ...
         self._commandLine = ' '.join( self._commandLine.split() )
         self._commandLine.strip()
diff --git a/Src/Mobyle/ConfigManager.py b/Src/Mobyle/ConfigManager.py
index f71235b..c57eeb0 100644
--- a/Src/Mobyle/ConfigManager.py
+++ b/Src/Mobyle/ConfigManager.py
@@ -58,7 +58,7 @@ class Config( object ):
     __metaclass__ = MetaSingleton
     
     def __init__(self):
-            self.__version = '1.5.3'
+            self.__version = '1.5.5'
             import Local.Config.Config
             import Local.Config.Execution
             #############################
diff --git a/Src/Mobyle/Execution/DRMAA.py b/Src/Mobyle/Execution/DRMAA.py
index 7b817cb..481a95a 100755
--- a/Src/Mobyle/Execution/DRMAA.py
+++ b/Src/Mobyle/Execution/DRMAA.py
@@ -109,10 +109,9 @@ class DRMAA(ExecutionSystem):
                 nativeSpecification = ''
                 if self.execution_config.nativeSpecification:
                     nativeSpecification = self.execution_config.nativeSpecification
-                elif queue:
+                if queue:
                     nativeSpecification = "%s -q %s" % ( nativeSpecification , queue )
-                if nativeSpecification:
-                    jt.nativeSpecification = nativeSpecification
+                jt.nativeSpecification = nativeSpecification
                 jt.blockEmail = True
                 drmJobid = drmaaSession.runJob( jt )
             except self.drmaa.errors , err :
diff --git a/Src/Mobyle/JobState.py b/Src/Mobyle/JobState.py
index 7562aa6..39940bd 100644
--- a/Src/Mobyle/JobState.py
+++ b/Src/Mobyle/JobState.py
@@ -733,7 +733,7 @@ class _abstractState( object ):
             attr[ 'size' ] = str( size )
             if fmt:
                 attr [ 'fmt' ] = fmt
-            self._addTextNode( outputNode , 'file' , os.path.basename( filename ) , attr = attr )
+            self._addTextNode(outputNode, 'file', filename, attr=attr)
               
                     
     def _createInOutNode( self , io , paramName , paramAttrs = {} ):
diff --git a/Src/Mobyle/MobyleJob.py b/Src/Mobyle/MobyleJob.py
index f85da9e..e379211 100644
--- a/Src/Mobyle/MobyleJob.py
+++ b/Src/Mobyle/MobyleJob.py
@@ -375,7 +375,7 @@ class MobyleJob:
             raise MobyleError , msg
         
         if self._debug > 1:
-            self.build_log.debug( "\n--------------------- MobyleJob set user value for " + paramName + "--------------------" )        
+            self.build_log.debug( "\n--------------------- MobyleJob set user value for " + paramName + "--------------------" )    
         if paramName in  self._service.getAllParameterNameByArgpos():
             parameter = self._service.getParameter( paramName )
             acceptedMobyleType = parameter.getType()
@@ -409,7 +409,12 @@ class MobyleJob:
                 oldValue = parameter.getValue()
                 try:
                     detectedMobyleType = dataType.detect( value )
-                    converted_value , convertedMobyleType = detectedMobyleType.convert( value , acceptedMobyleType )
+                    if dataType.getName()  == 'MultipleChoice':
+                        if isinstance(value, types.StringTypes):
+                            value = [value]
+                        converted_value , convertedMobyleType = detectedMobyleType.convert( value , acceptedMobyleType , separator = parameter.getSeparator())
+                    else:
+                        converted_value , convertedMobyleType = detectedMobyleType.convert( value , acceptedMobyleType)
                     parameter.setValue( converted_value )
                     if self._debug > 1:
                         try:
@@ -429,8 +434,9 @@ class MobyleJob:
                     else:
                         vdef , vdefMT = detectedMobyleType.convert( rawVdef , acceptedMobyleType )
                         if parameter.getType().getDataType().getName() == 'MultipleChoice':
-                            sep = parameter.getSeparator()
-                            vdef = sep.join( vdef)
+                            if vdef is not None:
+                                sep = parameter.getSeparator()
+                                vdef = sep.join( vdef)
                     if newValue == vdef :
                         if oldValue is not None and oldValue != vdef:
                             self.jobState.delInputData( paramName )
@@ -726,13 +732,18 @@ class MobyleJob:
                             'SERVER_PROTOCOL'     ,
                             'SERVER_SIGNATURE'    ,
                             'SERVER_SOFTWARE'     ,
-
-]:
+                            ]:
                 try:
                     del( os.environ[ envVar ])
                 except KeyError:
                     pass
-                    
+            for var in os.environ.keys():
+                if os.environ[var].startswith('()'):
+                    self.m_log.critical( "Security Error: %s/%s : unsafe var %s=%s : Bash vulnerabilty Exploitation'" % 
+                                         ( self._service.getName() , self._job.key, var, os.environ[var] ))
+                    self._logError(userMsg = "Mobyle internal server error")
+                    raise MobyleError, "Mobyle internal server error" 
+                
             self._validateParameters()
                     
             #do the controls specified in the Xml file
diff --git a/Src/Mobyle/RunnerChild.py b/Src/Mobyle/RunnerChild.py
index 05eff5a..258797f 100755
--- a/Src/Mobyle/RunnerChild.py
+++ b/Src/Mobyle/RunnerChild.py
@@ -118,7 +118,7 @@ class AsynchronJob:
                 for File in  glob.glob( mask ):
                     size = os.path.getsize( File )
                     if size != 0:
-                        resultsFiles.append(  ( str( File ) , size , None ) ) #we have not information about the output format 
+                        resultsFiles.append(( str( File ) , size , None )) #we have not information about the output format 
             if resultsFiles: 
                 self.results[ paramName ] = resultsFiles  #a list of tuple (string file name , int size ,  string format or None )
                 self.jobState.setOutputDataFile( paramName , resultsFiles )
@@ -128,30 +128,22 @@ class AsynchronJob:
             zipFileName = self.zipResults()
         except Exception :
             msg = "an error occured during the zipping results :\n\n"
-            rc_log.critical( "%s/%s : %s" %( self.serviceName , self.jobKey , msg ) , exc_info = True)
+            rc_log.critical( "%s/%s : %s" %(self.serviceName, self.jobKey, msg), exc_info=True)
             zipFileName = None
         if self.userEmail:
             if self.email_notify == 'auto':
                 # we test email_delay() to see if it is >= to 0, 
                 # as it seems that sometimes it is not >0.
-                if ( t1 - t0 ) >= _cfg.email_delay():
+                if self.email_notify == 'true' or ((t1 - t0) >= _cfg.email_delay()):
                     emailResults(_cfg,
-                                       self.userEmail,
-                                       registry ,
-                                       self.jobState.getID(),
-                                       self._dirPath ,
-                                       self.serviceName ,
-                                       self.jobKey ,
-                                      FileName = zipFileName )
-            elif self.email_notify == 'true':
-                emailResults( _cfg,
-                                   self.userEmail,
-                                   registry ,
-                                   self.jobState.getID(),
-                                   self._dirPath ,
-                                   self.serviceName ,
-                                   self.jobKey ,  
-                                   FileName = zipFileName )
+                                 self.userEmail,
+                                 registry,
+                                 self.jobState.getID(),
+                                 self._dirPath,
+                                 self.serviceName,
+                                 self.jobKey,
+                                 FileName=zipFileName)
+
             else:
                 pass    
 
@@ -184,10 +176,11 @@ class AsynchronJob:
     def zipResults(self ):    
         files2zip = []
 
-        for Files in self.results.values():
-            for File in Files:
-                files2zip.append( ( File[0] , os.path.basename( File[0]) ) ) #File is tuple (string file name , int size , string format or None )
-        
+        for result in self.results.values():
+            for file_ in result:
+                #file_ is tuple (string file name , int size , string format or None )
+                files2zip.append((file_[0], os.path.basename(file_[0]))) 
+                
         xsl_path = os.path.join( _cfg.portal_path() , "xsl" ,)
         jobXslPath = os.path.join( xsl_path , "job.xsl" ) 
         files2zip.append( ( jobXslPath , "job.xsl" ) )
@@ -212,8 +205,8 @@ class AsynchronJob:
         
         files2zip.append( ( os.path.join( self._dirPath , "index.xml") , "index.xml" ) )
         zipFileName = "%s_%s.zip" %(self.serviceName , self.jobKey )    
-        zip_filename = zipFiles( zipFileName , files2zip )
-        return  zip_filename    
+        zip_file = zipFiles( zipFileName , files2zip )
+        return  zip_file    
 
 if __name__ == '__main__':
     try:
@@ -235,11 +228,11 @@ if __name__ == '__main__':
     if userEmail is not None:
         userEmail = EmailAddress( userEmail  )
         
-    child = AsynchronJob( fromFather[ 'commandLine' ] , # string the unix command line
-                          fromFather[ 'dirPath' ] ,     # absolute path of the working directory
-                          fromFather[ 'serviceName' ] , # string 
-                          fromFather[ 'resultsMask'] ,  # 
-                          userEmail = userEmail  ,      # Net.EmailAddress to
-                          xmlEnv = fromFather[ 'xmlEnv' ] , #a dict
-                          email_notify = fromFather[ 'email_notify' ] #'true' , 'false' or 'auto'
+    child = AsynchronJob( fromFather['commandLine'],  # string the unix command line
+                          fromFather['dirPath'],      # absolute path of the working directory
+                          fromFather['serviceName'],  # string
+                          fromFather['resultsMask'],  #
+                          userEmail=userEmail,        # Net.EmailAddress to
+                          xmlEnv=fromFather['xmlEnv'],  # a dict
+                          email_notify=fromFather['email_notify']  # 'true' , 'false' or 'auto'
                           )
diff --git a/Src/Mobyle/Service.py b/Src/Mobyle/Service.py
index 7677b03..aaa4bc1 100644
--- a/Src/Mobyle/Service.py
+++ b/Src/Mobyle/Service.py
@@ -2891,15 +2891,17 @@ class Parameter( Para ):
         else:
             if value is not None:
                 if self._separator is not None:
+                    
                     #if separator is not None the Datatype is a MultipleDataType.
                     #the argument value is a list
                     #the value in the evaluator must be the final string
-                    value = self._separator.join( value )
+                    #value = self._separator.join( value )
+                    pass
                 self.getEvaluator().setVar( self.getName() ,  value  )
                 
             else:
                 self.getEvaluator().setVar( self.getName() , None )
-                
+            ev = self.getEvaluator()
 
     def setValueAsVdef( self ):
         """
@@ -2937,8 +2939,9 @@ class Parameter( Para ):
         if vdef is not None:
             convertedVdef , mt = self.convert( vdef , self.getType() )
             if self.getDataType().getName() == 'MultipleChoice':
-                sep = self.getSeparator()
-                convertedVdef = sep.join( convertedVdef )
+                if convertedVdef is not None:
+                    sep = self.getSeparator()
+                    convertedVdef = sep.join( convertedVdef )
             self.getEvaluator().setVar( self.getName() , convertedVdef )
             return convertedVdef
         else:
@@ -2979,8 +2982,13 @@ class Parameter( Para ):
         if self._paramfile:
             return self.getDataType().convert( value , acceptedMobyleType , detectedMobyleType = self , paramFile = True )
         else:
-            return self.getDataType().convert( value , acceptedMobyleType , detectedMobyleType = self )
-        
+            dt = self.getDataType()
+            if dt.getName() == 'MultipleChoice':
+                return dt.convert( value , acceptedMobyleType , detectedMobyleType = self, separator= self.getSeparator())
+            else:
+                return dt.convert( value , acceptedMobyleType , detectedMobyleType = self)
+            
+            
     def validate(self):
         return self.getDataType().validate( self )
         
@@ -4416,7 +4424,7 @@ class MobyleType(object):
     def getDataType( self ):
         return self.dataType
    
-    def convert(self , value , acceptedMobyleType , paramFile= False ):
+    def convert(self , value , acceptedMobyleType , paramFile= False, separator = None ):
         """
         convert the sequence contain in the file fileName in the rigth format
         throws an UnsupportedFormatError if the output format is not supported
@@ -4431,7 +4439,10 @@ class MobyleType(object):
         @rtype: ( string fileName , MobyleType instance )
         @raise UnSupportedFormatError: if the data cannot be converted in any suitable format
         """
-        outFileName , converted_mt =  self.dataType.convert(value , acceptedMobyleType , detectedMobyleType = self , paramFile = paramFile)
+        if separator is not None:
+            outFileName , converted_mt =  self.dataType.convert(value , acceptedMobyleType , detectedMobyleType = self , paramFile = paramFile, separator= separator)
+        else:
+            outFileName , converted_mt =  self.dataType.convert(value , acceptedMobyleType , detectedMobyleType = self , paramFile = paramFile)
         if self.bioTypes and converted_mt:
             converted_mt.bioTypes = [ b for b in self.bioTypes ]
         return outFileName , converted_mt
diff --git a/Src/Mobyle/Utils.py b/Src/Mobyle/Utils.py
index 12e23d2..6a0bc71 100644
--- a/Src/Mobyle/Utils.py
+++ b/Src/Mobyle/Utils.py
@@ -217,20 +217,18 @@ def killJob( jobID ):
 
 def safeFileName( fileName ):
     import string , re
-    
     if fileName in ( 'index.xml' , '.admin' , '.command' ,'.forChild.dump' ,'.session.xml'):
         raise UserValueError( msg = "value \"" + str( fileName ) + "\" is not allowed" )
     
     for car in fileName :
         if car not in string.printable : #we don't allow  non ascii char
             fileName = fileName.replace( car , '_')
-    
     #SECURITY: substitution of shell special characters
     fileName = re.sub( "[ ~%#\"\'<>&\*;$`\|()\[\]\{\}\?\s ]" , '_' , fileName )
-                  
     #SECURITY: transform an absolute path in relative path
     fileName = re.sub( "^.*[\\\]", "" , fileName )
-    
+    fileName = re.sub( "^/", "" ,  fileName  )
+    fileName = re.sub( "\.(\.)+", "" ,  fileName  )
     return fileName
 
 
@@ -253,7 +251,8 @@ def sizeFormat(bytes, precision=2):
     log = math.floor( math.log( bytes , 1024 ) )
     return "%.*f%s" % ( precision , bytes / math.pow(1024, log), [ 'bytes', 'KiB', 'MiB' , 'GiB' ][ int(log) ] )
 
-def zipFiles( zip_filename , files ):
+
+def zipFiles(zip_filename, files):
     """
     @param zip_filename: the absolute path to the archive to create
     @type zip_filename: string
@@ -267,8 +266,34 @@ def zipFiles( zip_filename , files ):
     from time import localtime
     from Mobyle.StatusManager import StatusManager
     
+    def compression_method(size):
+        if size > 0 and size < 10:
+            method = zipfile.ZIP_STORED
+        elif size >= 10:
+            method = zipfile.ZIP_DEFLATED
+        else:
+            #the file is empty we don't add it to this archive
+            method = None
+        return method
+
+    def expand_folder(folder):
+        files_2_add = []
+        folder_path, _ = folder
+        for dirpath, dirnames, filenames in os.walk(folder_path):
+            for f in filenames:
+                local_dir_path = dirpath[dirpath.find(os.path.basename(folder_path)):]
+                arc_filename = os.path.join(local_dir_path, f)
+                abs_path = os.path.abspath(os.path.join(dirpath, f))
+                files_2_add.append((abs_path, arc_filename))
+        return files_2_add
+
+
+    folder_2_expand = filter(lambda x : os.path.isdir(x[0]), files)
+    for folder in folder_2_expand:
+        files.extend(expand_folder(folder))
+    
     myZipFile = zipfile.ZipFile( zip_filename, "w", allowZip64 = True )
-    for filename , arc_filename in files:
+    for filename, arc_filename in files:
         if arc_filename == 'index.xml':
             from lxml import etree
             index_tree = etree.parse( filename )
@@ -288,15 +313,12 @@ def zipFiles( zip_filename , files ):
         except OSError , err:
             u_log.critical( "error during zipping files: %s"%(err) , exc_info = True)
             continue
-        if size > 0 and size < 10:
-            myZipFile.write( filename   , arc_filename , zipfile.ZIP_STORED )
-        elif size >= 10:  
-            myZipFile.write(filename, arc_filename, zipfile.ZIP_DEFLATED)
-        else:
-            #the file is empty we don't add it to this archive
-            pass   
+
+        method = compression_method(size)
+        if method is not None:
+            myZipFile.write(filename, arc_filename, method)
     myZipFile.close()
-    return  zip_filename
+    return zip_filename
 
 def emailHelpRequest( cfg, userEmail, registry, job_id, message, session, error_parameter, error_message ):
     from Mobyle.Net import Email, EmailAddress 
diff --git a/Src/Portal/htdocs/MobylePortal/js/mobyle.js b/Src/Portal/htdocs/MobylePortal/js/mobyle.js
index 8f3a913..25e54f8 100644
--- a/Src/Portal/htdocs/MobylePortal/js/mobyle.js
+++ b/Src/Portal/htdocs/MobylePortal/js/mobyle.js
@@ -3353,7 +3353,10 @@ var onFormParameterModification = function(source) {
       }
     }
   }
-  var value = form[formNameToTest].value || $A(form[formNameToTest]).pluck('value').reject(function(val) {return val == ''});
+  var value = '';
+  if(form[formNameToTest]){
+    value = form[formNameToTest].value || $A(form[formNameToTest]).pluck('value').reject(function(val) {return val == ''});
+  }
   value = (value == '') ? undefined : value;
   var defaultValue = parEl.readAttribute('data-default-value');
   defaultValue = (defaultValue == '') ? undefined : defaultValue;
diff --git a/Src/Portal/htdocs/MobylePortal/xsl/job.xsl b/Src/Portal/htdocs/MobylePortal/xsl/job.xsl
index 0ef70a4..26eea5a 100644
--- a/Src/Portal/htdocs/MobylePortal/xsl/job.xsl
+++ b/Src/Portal/htdocs/MobylePortal/xsl/job.xsl
@@ -203,10 +203,12 @@
         <xsl:apply-templates select="@*" />
 	<span class="prompt"><xsl:value-of select="//parameter[name/text()=$parametername]/prompt/text()" /></span>
         <xsl:apply-templates select="xhtml:*" mode="pre"/>
-        <!-- this part handles the display of results or parameter data which have no predefined custom <interface> tag -->        
-        <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/file" mode="dataProcessing"/>
-        <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/formattedFile" mode="dataProcessing"/>
-        <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/value" mode="dataProcessing"/>          
+        <xsl:if test="count(.//@*[contains(.,'data-url')])=0 and count(.//@*[contains(.,'data-value')])=0 and count(text()[contains(.,'data-url')])=0 and count(.//text()[contains(.,'data-value')])=0">
+            <!-- this part handles the display of results or parameter data which have no predefined custom <interface> tag -->        
+            <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/file" mode="dataProcessing"/>
+            <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/formattedFile" mode="dataProcessing"/>
+            <xsl:apply-templates select="$job/jobState/data/*[parameter/name=$parametername]/value" mode="dataProcessing"/>          
+        </xsl:if>
         </xsl:element>
     </xsl:if>
   </xsl:template>
@@ -217,14 +219,14 @@
     </xsl:copy>
   </xsl:template>
 
-  <xsl:template match="*[@*[ancestor::*[@data-parametername] and (contains(.,'data-url') or contains(.,'data-value'))]|text()[ancestor::*[@data-parametername] and (contains(.,'data-url') or contains(.,'data-value'))]]" mode="customInterface">
+  <xsl:template match="xhtml:*[@*[ancestor::*[@data-parametername] and (contains(.,'data-url') or contains(.,'data-value'))]|text()[ancestor::*[@data-parametername] and (contains(.,'data-url') or contains(.,'data-value'))]]" mode="pre">
     <!-- custom <interface> tag handling: setting the parameter name as a variable and then looping over all the values -->
     <xsl:variable name='parametername' select="ancestor-or-self::*[@data-parametername]/@data-parametername"/>
     <xsl:variable name='current' select="."/>
     <xsl:for-each select="$job/jobState/data/*[parameter/name=$parametername]/file/text()">
       <xsl:variable name="result-value" select="."/>      
       <xsl:element name="{local-name($current)}">
-        <xsl:apply-templates select="$current/@*|$current/node()|$current/text()" >
+        <xsl:apply-templates select="$current/@*|$current/node()|$current/text()" mode="pre">
           <xsl:with-param name="parametername" select="$parametername" />
           <xsl:with-param name="result-value" select="$result-value" />
         </xsl:apply-templates>
@@ -234,7 +236,7 @@
     <xsl:for-each select="$job/jobState/data/*[parameter/name=$parametername]/value/text()">
       <xsl:element name="{local-name($current)}">
         <xsl:variable name="result-value" select="."/>      
-        <xsl:apply-templates select="$current//@*|$current//node()|$current//text()" >
+        <xsl:apply-templates select="$current//@*|$current//node()|$current//text()" mode="pre">
           <xsl:with-param name="parametername" select="$parametername" />
           <xsl:with-param name="result-value" select="$result-value" />
         </xsl:apply-templates>
@@ -242,7 +244,7 @@
     </xsl:for-each>
   </xsl:template>
 
-  <xsl:template match="@*[contains(.,'data-url') or contains(.,'data-value')]" mode="customInterface">
+  <xsl:template match="@*[contains(.,'data-url') or contains(.,'data-value')]" mode="pre">
     <!-- custom <interface> tag handling in attribute values: replacing 'data-url' with the actual url of the data and 'data-value' with its actual value (=file name for files) -->
     <xsl:param name="parametername" />
     <xsl:param name="result-value" />
diff --git a/Tools/mob_log_rotate b/Tools/mob_log_rotate
old mode 100644
new mode 100755
diff --git a/Tools/mob_stat b/Tools/mob_stat
old mode 100644
new mode 100755
index 118b11c..fb7078a
--- a/Tools/mob_stat
+++ b/Tools/mob_stat
@@ -3,16 +3,7 @@
 
 from collections import namedtuple, defaultdict
 import gzip
-import os
-import sys
-MOBYLEHOME = None
-if os.environ.has_key('MOBYLEHOME'):
-    MOBYLEHOME = os.environ['MOBYLEHOME']
-if not MOBYLEHOME:
-    sys.exit('MOBYLEHOME must be defined in your environment if you want to send statistics by email')
-if (os.path.join(MOBYLEHOME, 'Src')) not in sys.path:
-    sys.path.append(os.path.join(MOBYLEHOME, 'Src'))
-    
+
 ###############
 #  Utilities  #
 ###############
@@ -114,7 +105,7 @@ def by_day(log):
 
 
 if __name__ == "__main__":
-    
+    import os
     import argparse
     parser = argparse.ArgumentParser(description = """parse mobyle access log 
 and generate a report
@@ -212,6 +203,16 @@ and generate a report
     # email the report to mobyle maintainers #
     ##########################################
     if args.email:
+        import sys
+        MOBYLEHOME = None
+        if os.environ.has_key('MOBYLEHOME'):
+            MOBYLEHOME = os.environ['MOBYLEHOME']
+        if not MOBYLEHOME:
+            sys.exit('MOBYLEHOME must be defined in your environment if you want to send statistics by email')
+        if (os.path.join(MOBYLEHOME, 'Src')) not in sys.path:
+            sys.path.append(os.path.join(MOBYLEHOME, 'Src'))
+        
+
         from Mobyle.ConfigManager import Config
         config = Config()
         from Mobyle.Net import EmailAddress , Email
diff --git a/setup.py b/setup.py
index 5963b99..1d01fbc 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ except:
 
 ## Basics ...
 package_nam = 'Mobyle'
-package_ver = '1.5.3'
+package_ver = '1.5.5'
 package_url = 'https://projets.pasteur.fr/wiki/mobyle/'
 package_aut = 'The Mobyle team'
 package_mel = 'mobyle at pasteur.fr'

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/mobyle.git



More information about the debian-med-commit mailing list