Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-52523

Extended Choice Parameter broken by whitelisting change

    Details

    • Similar Issues:

      Description

      We just went thru a fair amount of effort to switch to Extended Choice Parameters as a replacement for Dynamic Parameters, to get scripted defaults in text-box input  (eg timestamp-derived filenames) while avoiding the security concerns of DP. So we sorta need this working.

      Meanwhile I'm playing with the workaround mechanism and hoping to make it work quickly. If not, I'll have to downgrade Jenkins again.

      Y'know, you REALLY should have implemented this change first in Warning/Deprecation mode, giving us a switch to turn on hard whitelisting when we had achieved a stable environment under the new rules. Oh well.

      Stack trace from a trivial Job which just accepts one value and echoes it back:

      java.lang.UnsupportedOperationException: Refusing to marshal com.cwctravel.hudson.plugins.extended_choice_parameter.ExtendedChoiceParameterDefinition for security reasons; see https://jenkins.io/redirect/class-filter/
       at hudson.util.XStream2$BlacklistedTypesConverter.marshal(XStream2.java:543)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:69)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:43)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:88)
       at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.writeItem(AbstractCollectionConverter.java:64)
       at com.thoughtworks.xstream.converters.collections.CollectionConverter.marshal(CollectionConverter.java:74)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:69)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:84)
       at hudson.util.RobustReflectionConverter.marshallField(RobustReflectionConverter.java:265)
       at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:252)
      Caused: java.lang.RuntimeException: Failed to serialize hudson.model.ParametersDefinitionProperty#parameterDefinitions for class hudson.model.ParametersDefinitionProperty
       at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:256)
       at hudson.util.RobustReflectionConverter$2.visit(RobustReflectionConverter.java:224)
       at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.visitSerializableFields(PureJavaReflectionProvider.java:138)
       at hudson.util.RobustReflectionConverter.doMarshal(RobustReflectionConverter.java:209)
       at hudson.util.RobustReflectionConverter.marshal(RobustReflectionConverter.java:150)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:69)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:43)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:88)
       at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.writeItem(AbstractCollectionConverter.java:64)
       at hudson.util.CopyOnWriteList$ConverterImpl.marshal(CopyOnWriteList.java:187)
       at hudson.util.XStream2$AssociatedConverterImpl.marshal(XStream2.java:461)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:69)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:84)
       at hudson.util.RobustReflectionConverter.marshallField(RobustReflectionConverter.java:265)
       at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:252)
      Caused: java.lang.RuntimeException: Failed to serialize hudson.model.Job#properties for class hudson.model.FreeStyleProject
       at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:256)
       at hudson.util.RobustReflectionConverter$2.visit(RobustReflectionConverter.java:224)
       at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.visitSerializableFields(PureJavaReflectionProvider.java:138)
       at hudson.util.RobustReflectionConverter.doMarshal(RobustReflectionConverter.java:209)
       at hudson.util.RobustReflectionConverter.marshal(RobustReflectionConverter.java:150)
       at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:69)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
       at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:43)
       at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:82)
       at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.marshal(AbstractTreeMarshallingStrategy.java:37)
       at com.thoughtworks.xstream.XStream.marshal(XStream.java:1026)
       at com.thoughtworks.xstream.XStream.marshal(XStream.java:1015)
       at com.thoughtworks.xstream.XStream.toXML(XStream.java:988)
       at hudson.XmlFile.write(XmlFile.java:193)
      Caused: java.io.IOException
       at hudson.XmlFile.write(XmlFile.java:200)
       at hudson.model.AbstractItem.save(AbstractItem.java:597)
       at hudson.model.Job.save(Job.java:191)
       at hudson.model.AbstractProject.save(AbstractProject.java:289)
       at hudson.BulkChange.commit(BulkChange.java:98)
       at hudson.model.Job.doConfigSubmit(Job.java:1351)
       at hudson.model.AbstractProject.doConfigSubmit(AbstractProject.java:772)
       at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
       at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
       at org.kohsuke.stapler.interceptor.RequirePOST$Processor.invoke(RequirePOST.java:77)
       at org.kohsuke.stapler.PreInvokeInterceptedFunction.invoke(PreInvokeInterceptedFunction.java:26)
       at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
       at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
       at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:129)
       at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
       at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
       at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
       at org.kohsuke.stapler.MetaClass$5.doDispatch(MetaClass.java:248)
       at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
       at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
       at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
       at org.kohsuke.stapler.MetaClass$5.doDispatch(MetaClass.java:248)
       at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
       at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
       at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
       at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
       at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
       at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:860)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
       at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
       at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
       at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
       at net.bull.javamelody.PluginMonitoringFilter.doFilter(PluginMonitoringFilter.java:88)
       at org.jvnet.hudson.plugins.monitoring.HudsonMonitoringFilter.doFilter(HudsonMonitoringFilter.java:114)
       at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:151)
       at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:157)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:99)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
       at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
       at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
       at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
       at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:90)
       at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:82)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
       at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
       at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
       at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
       at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
       at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
       at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
       at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
       at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
       at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
       at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
       at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
       at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
       at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
       at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
       at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
       at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
       at org.eclipse.jetty.server.Server.handle(Server.java:530)
       at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
       at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
       at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
       at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
       at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
       at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
       at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
       at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
       at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
       at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
       at java.lang.Thread.run(Thread.java:748) 

        Attachments

          Activity

          Hide
          keshlam Joseph Kesselman added a comment -

          #!/bin/bash
          #
          # Kluge to fix the Extended Choice Parameter.
          #
          # ECP's "text box" mode, for whatever reason, was hardcoded to use a
          # 200-pixel-wide entry box. Using absolute values in HTML rendering
          # sizes is almost always wrong; in this case it means the box will
          # be about 30 characters wide – painfully small if the parameter
          # value is intended to be a path.
          #
          # Luckily, this can be fixed by changing one text file inside the
          # plugin's jar, replacing that "width:200px" with "width:100%".
          # This value will use as much space as the parent rendering element
          # is willing to give it.
          #
          # Caveat: Pasting this into Jira may have glitched some line breaks...
          #
          # Debug trace, if desired
          #set -xv######################################################################function restart_server {
            if [ -z $USER ]; then
              USER=${jenkinsUser}
            fi
            if [ -z $PASSWORD ]; then
              PASSWORD=${jenkinsApiToken}
            fi

            if [ -z $USER -o -z $PASSWORD ]; then
              echo "User and/or password not provided. Please restart Jenkins manually to pick up modified jarfile."
          {{  else }}
              CRUMB=`curl -s -u ${USER}:${PASSWORD} "${JENKINS_URL}/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"`
              if [[ ${CRUMB} != "Jenkins-Crumb:"* ]]; then
                echo "Crumb not successfully retrieved; continuing without"
                CRUMB=""
              else
                CRUMB="-H $CRUMB"
              fi

              curl -s -X POST -u $USER:$PASSWORD $CRUMB ${JENKINS_URL}/safeRestart

              if [ $? -eq 0 ]; then
                echo "Restart requested. There will be a delay for quiescance before restart occurs."
              else
                 echo "User and password not accepted. Please restart Jenkins manually to pick up modified jarfile."
              fi

            fi
          }######################################################################

          # Default assumption: success
          {{rc=0 }}

          # Files to be patched: Jarfile, and path within it
          ecpJarfile=$JENKINS_HOME/plugins/extended-choice-parameter/WEB-INF/lib/extended-choice-parameter.jar
          textBox="com/cwctravel/hudson/plugins/extended_choice_parameter/ExtendedChoiceParameterDefinition/textboxContent.jelly"
          # Get a scratch space
          tmpdir=$(mktemp -d)
          cd $tmpdir
          # Unpack the jarfile for patching
          jar xvf $ecpJarfile
          rc=$?
          if [ $rc -ne 0 ]; then
             echo "Couldn't unpack $ecpJarfile, rc=$rc"
          else
            # Check whether this has already been fixed. (We can't count on
            # exit status of sed; it thinks "no match" on a global replace is
            # a successful operation.)
            grep "width:200px" $textBox
            rrc=$?
            if [ $rrc -ne 0 ]; then
              grep "width:100%" $textBox
              rc=$?
              if [ $rc -eq 0 ]; then
                 echo "Already patched"
              else
                 echo "width:200px not found, but not already patched"
                 echo "... this script may need to be updated."
              fi
            else
              # Patch the hardcoded value to full-width relative.
              # Note that sed s///g returns success even if no instances
              # were found
              sed -i "s/width:200px/width:100%/g" $textBox
              rc=$?
              if [ $rc -ne 0 ]; then
                 echo "Couldn't patch $textBox, rc=$rc"
              else
                 # Repack the jarfile, with error recovery
                 original=$(mktemp)
                 cp $ecpJarfile $original{{       }}
                 }}{{jar cvf $ecpJarfile META-INF/MANIFEST.MF *
                 rc=$?
                 if [ $rc -ne 0 ]; then
                    echo "Couldn't repack $ecpJarfile, rc=$rc"
                    mv $original $ecpJarfile
                 else
                    # Remove the temporary backup
                    rm $original
                    # Must do clean restart to pick up modified jarfile
                    restart_server
                 fi
              fi
            fi
          fi
          # Remove the scratch space
          cd ..
          rm -r $tmpdir{{# Return failure code, or 0 for success }}
          exit $rc

          Show
          keshlam Joseph Kesselman added a comment - #!/bin/bash # # Kluge to fix the Extended Choice Parameter. # # ECP's "text box" mode, for whatever reason, was hardcoded to use a # 200-pixel-wide entry box. Using absolute values in HTML rendering # sizes is almost always wrong; in this case it means the box will # be about 30 characters wide – painfully small if the parameter # value is intended to be a path. # # Luckily, this can be fixed by changing one text file inside the # plugin's jar, replacing that "width:200px" with "width:100%". # This value will use as much space as the parent rendering element # is willing to give it. # # Caveat: Pasting this into Jira may have glitched some line breaks... # # Debug trace, if desired #set -xv ###################################################################### function restart_server {   if [ -z $USER ]; then     USER=${jenkinsUser }   fi   if [ -z $PASSWORD ]; then     PASSWORD=${jenkinsApiToken }   fi   if [ -z $USER -o -z $PASSWORD ]; then     echo "User and/or password not provided. Please restart Jenkins manually to pick up modified jarfile." {{  else }}     CRUMB=`curl -s -u ${USER}:${PASSWORD} "${JENKINS_URL}/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"`     if [[ ${CRUMB} != "Jenkins-Crumb:"* ]]; then       echo "Crumb not successfully retrieved; continuing without"       CRUMB=""     else       CRUMB="-H $CRUMB"     fi     curl -s -X POST -u $USER:$PASSWORD $CRUMB ${JENKINS_URL}/safeRestart     if [ $? -eq 0 ]; then       echo "Restart requested. There will be a delay for quiescance before restart occurs."     else        echo "User and password not accepted. Please restart Jenkins manually to pick up modified jarfile."     fi   fi } ###################################################################### # Default assumption: success {{rc=0 }} # Files to be patched: Jarfile, and path within it ecpJarfile=$JENKINS_HOME/plugins/extended-choice-parameter/WEB-INF/lib/extended-choice-parameter.jar textBox="com/cwctravel/hudson/plugins/extended_choice_parameter/ExtendedChoiceParameterDefinition/textboxContent.jelly" # Get a scratch space tmpdir=$(mktemp -d) cd $tmpdir # Unpack the jarfile for patching jar xvf $ecpJarfile rc=$? if [ $rc -ne 0 ]; then    echo "Couldn't unpack $ecpJarfile, rc=$rc" else   # Check whether this has already been fixed. (We can't count on   # exit status of sed; it thinks "no match" on a global replace is   # a successful operation.)   grep "width:200px" $textBox   rrc=$?   if [ $rrc -ne 0 ]; then     grep "width:100%" $textBox     rc=$?     if [ $rc -eq 0 ]; then        echo "Already patched"     else        echo "width:200px not found, but not already patched"        echo "... this script may need to be updated."     fi   else     # Patch the hardcoded value to full-width relative.     # Note that sed s///g returns success even if no instances     # were found     sed -i "s/width:200px/width:100%/g" $textBox     rc=$?     if [ $rc -ne 0 ]; then        echo "Couldn't patch $textBox, rc=$rc"     else        # Repack the jarfile, with error recovery        original=$(mktemp)        cp $ecpJarfile $original {{       }}        }}{{jar cvf $ecpJarfile META-INF/MANIFEST.MF *        rc=$?        if [ $rc -ne 0 ]; then           echo "Couldn't repack $ecpJarfile, rc=$rc"           mv $original $ecpJarfile        else           # Remove the temporary backup           rm $original           # Must do clean restart to pick up modified jarfile           restart_server        fi     fi   fi fi # Remove the scratch space cd .. rm -r $tmpdir {{# Return failure code, or 0 for success }} exit $rc
          Hide
          keshlam Joseph Kesselman added a comment -

          .... Hm. That is assuming a jarfile rather than HPI. OK, I'm willing to believe it's my goof, then. Could have sworn otherwise.

          Of course what I really want is to get this trivial change made in the extension officially rather than patching my own copy. I didn't seem to be getting traction on that, though.

          Show
          keshlam Joseph Kesselman added a comment - .... Hm. That is assuming a jarfile rather than HPI. OK, I'm willing to believe it's my goof, then. Could have sworn otherwise. Of course what I really want is to get this trivial change made in the extension officially rather than patching my own copy. I didn't seem to be getting traction on that, though.
          Hide
          oleg_nenashev Oleg Nenashev added a comment -

          Joseph Kesselman https://github.com/jenkinsci/extended-choice-parameter-plugin does not seem to be actively maintained (vimil please correct me if I am wrong). If you are interested, you can request plugin ownership transfer. https://wiki.jenkins.io/display/JENKINS/Adopt+a+Plugin

           

           

          Show
          oleg_nenashev Oleg Nenashev added a comment - Joseph Kesselman   https://github.com/jenkinsci/extended-choice-parameter-plugin does not seem to be actively maintained ( vimil please correct me if I am wrong). If you are interested, you can request plugin ownership transfer. https://wiki.jenkins.io/display/JENKINS/Adopt+a+Plugin    
          Hide
          keshlam Joseph Kesselman added a comment - - edited

          Willing to take ownership at least for a while, if vimil has indeed abandoned it.

          Show
          keshlam Joseph Kesselman added a comment - - edited Willing to take ownership at least for a while, if vimil has indeed abandoned it.
          Hide
          vimil vimil added a comment -

          Send me a pull request and I can merge the change in.

          Show
          vimil vimil added a comment - Send me a pull request and I can merge the change in.

            People

            • Assignee:
              vimil vimil
              Reporter:
              keshlam Joseph Kesselman
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: