galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
December 2014
- 2 participants
- 245 discussions
commit/galaxy-central: jmchilton: Merged in dannon/galaxy-central/stable (pull request #596)
by commits-noreply@bitbucket.org 09 Dec '14
by commits-noreply@bitbucket.org 09 Dec '14
09 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3e7adbbe91a0/
Changeset: 3e7adbbe91a0
Branch: stable
User: jmchilton
Date: 2014-12-09 14:31:53+00:00
Summary: Merged in dannon/galaxy-central/stable (pull request #596)
[STABLE] Grafts of next-stable commits for security release.
Affected #: 12 files
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/web/framework/helpers/__init__.py
--- a/lib/galaxy/web/framework/helpers/__init__.py
+++ b/lib/galaxy/web/framework/helpers/__init__.py
@@ -3,13 +3,13 @@
"""
import time
-from cgi import escape
from datetime import datetime, timedelta
from galaxy import eggs
from galaxy.util import hash_util
from galaxy.util.json import dumps
eggs.require( "MarkupSafe" ) #required by WebHelpers
eggs.require( "WebHelpers" )
+from markupsafe import escape
from webhelpers import date
from webhelpers.html.tags import stylesheet_link, javascript_link
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -11,8 +11,7 @@
from galaxy.util.sanitize_html import sanitize_html
from galaxy.util.json import loads
from galaxy.web.base.controller import BaseUIController, ERROR, SUCCESS, url_for, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesExtendedMetadataMixin
-from galaxy.web.framework.helpers import grids, iff, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, iff, time_ago, to_unicode, escape
from galaxy.tools.errors import EmailErrorReporter
eggs.require( "Paste" )
@@ -510,7 +509,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
# Error checking.
@@ -939,9 +938,12 @@
"""
Show the parameters used for an HDA
"""
- hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ try:
+ hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ except ValueError:
+ hda = None
if not hda:
- raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
+ raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % escape( str( dataset_id ) ) )
if not self._can_access_dataset( trans, hda ):
return trans.show_error_message( "You are not allowed to access this dataset" )
@@ -973,7 +975,10 @@
params_objects = job.get_param_values( trans.app, ignore_errors=False )
except:
params_objects = job.get_param_values( trans.app, ignore_errors=True )
- upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ), trans, update_values=False ) #use different param_objects here, since we want to display original values as much as possible
+ # use different param_objects in the following line, since we want to display original values as much as possible
+ upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ),
+ trans,
+ update_values=False )
has_parameter_errors = True
except:
pass
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -17,7 +17,7 @@
from galaxy.web.base.controller import ExportsHistoryMixin
from galaxy.web.base.controller import ImportsHistoryMixin
from galaxy.web.base.controller import ERROR, INFO, SUCCESS, WARNING
-from galaxy.web.framework.helpers import grids, iff, time_ago
+from galaxy.web.framework.helpers import grids, iff, time_ago, escape
log = logging.getLogger( __name__ )
@@ -1234,7 +1234,7 @@
else:
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/search.py
--- a/lib/galaxy/webapps/galaxy/controllers/search.py
+++ b/lib/galaxy/webapps/galaxy/controllers/search.py
@@ -1,4 +1,3 @@
-
"""
Contains a basic search interface for Galaxy
"""
@@ -8,7 +7,13 @@
log = logging.getLogger( __name__ )
+
class SearchController( BaseUIController ):
+
@web.expose
def index(self, trans):
- return trans.fill_template( "search/index.mako")
+ """
+ Not ready for human consumption, yet. Power users can still use the
+ search API.
+ """
+ return trans.show_message("Sorry, the search interface isn't quite ready for use, yet.")
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -15,8 +15,8 @@
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import is_hashable
-from galaxy.web import error
-from galaxy.web import url_for
+from galaxy.web import error, url_for
+from galaxy.web.framework.helpers import escape
from galaxy.web.base.controller import BaseUIController
import tool_shed.util.shed_util_common as suc
@@ -57,7 +57,7 @@
return trans.response.send_redirect( url_for( controller="root", action="welcome" ) )
# When the tool form is initially loaded, the received kwd will not include a 'refresh'
# entry (which only is included when another option is selected in the tool_version_select_field),
- # so the default selected option should be the most recent version of the tool. The following
+ # so the default selected option should be the most recent version of the tool. The following
# check will mae sure this occurs.
refreshed_on_change = kwd.get( 'refresh', False )
tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
@@ -69,7 +69,7 @@
log.error( "index called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if tool.require_login and not trans.user:
message = "You must be logged in to use this tool."
status = "info"
@@ -290,7 +290,7 @@
log.error( "data_source_redirect called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if isinstance( tool, DataSourceTool ):
link = url_for( tool.action, **tool.get_static_param_values( trans ) )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -605,8 +605,8 @@
else:
refresh_frames = [ 'masthead' ]
trans.handle_user_logout( logout_all=logout_all )
- message = 'You have been logged out.<br>You can log in again, <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
- ( escape( trans.request.referer ), url_for( '/' ) )
+ message = 'You have been logged out.<br>To log in again <a target="_top" href="%s">go to the home page</a>.' % \
+ ( url_for( '/' ) )
if biostar.biostar_logged_in( trans ):
biostar_url = biostar.biostar_logout( trans )
if biostar_url:
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -9,7 +9,7 @@
from galaxy import model, web
from galaxy.model.item_attrs import UsesAnnotations, UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesVisualizationMixin
-from galaxy.web.framework.helpers import time_ago, grids
+from galaxy.web.framework.helpers import time_ago, grids, escape
from galaxy import util
from galaxy.datatypes.interval import Bed
from galaxy.util.json import loads
@@ -123,7 +123,7 @@
# or_( "metadata like '%%\"dbkey\": [\"?\"]%%'", "metadata like '%%\"dbkey\": \"?\"%%'" ) \
# )
# )
-
+
class HistoryColumn( grids.GridColumn ):
""" Column for filtering by history id. """
@@ -360,7 +360,7 @@
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
def list( self, trans, *args, **kwargs ):
-
+
# Handle operation
if 'operation' in kwargs and 'id' in kwargs:
session = trans.sa_session
@@ -388,7 +388,7 @@
kwargs[ 'embedded' ] = True
grid = self._user_list_grid( trans, *args, **kwargs )
return trans.fill_template( "visualization/list.mako", embedded_grid=grid, shared_by_others=shared_by_others )
-
+
#
# -- Functions for operating on visualizations. --
#
@@ -459,7 +459,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % web.url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -22,8 +22,7 @@
from galaxy.web import error, url_for
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesStoredWorkflowMixin
from galaxy.web.framework.formbuilder import form
-from galaxy.web.framework.helpers import grids, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, time_ago, to_unicode, escape
from galaxy.workflow.modules import WorkflowModuleInjector
from galaxy.workflow.modules import MissingToolException
from galaxy.workflow.modules import module_factory, is_tool_module_type
@@ -389,7 +388,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -45,7 +45,7 @@
<script>
Raven.config('${app.config.sentry_dsn_public}').install();
%if trans.user:
- Raven.setUser( { email: "${trans.user.email}" } );
+ Raven.setUser( { email: "${trans.user.email | h}" } );
%endif
</script>
%endif
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/refresh_frames.mako
--- a/templates/refresh_frames.mako
+++ b/templates/refresh_frames.mako
@@ -21,7 +21,7 @@
## Refresh masthead == user changes (backward compatibility)
if ( parent.user_changed ) {
%if trans.user:
- parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} );
+ parent.user_changed( "${trans.user.email | h }", ${int( app.config.is_admin_user( trans.user ) )} );
%else:
parent.user_changed( null, false );
%endif
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/search/index.mako
--- a/templates/search/index.mako
+++ b/templates/search/index.mako
@@ -1,52 +1,112 @@
-
<%inherit file="/webapps/galaxy/base_panels.mako"/>
-<%namespace file="/search/search.mako" import="search_init" />
-<%namespace file="/search/search.mako" import="search_dialog" /><%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
- self.active_view="shared"
- self.overlay_visible=False
-%>
+ <%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.message_box_visible=False
+ self.active_view="shared"
+ self.overlay_visible=False
+ %></%def><%def name="stylesheets()">
-${parent.stylesheets()}
-<style>
-.searchResult {
- border-style:dashed;
- border-width:1px;
- margin: 5px;
-}
-</style>
+ ${parent.stylesheets()}
+ <style>
+ .searchResult {
+ border-style:dashed;
+ border-width:1px;
+ margin: 5px;
+ }
+ </style>
+</%def>
+
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js(
+ "libs/jquery/jquery",
+ )}
+ <script type="text/javascript">
+
+ function search_format_output(doc) {
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ return a;
+ }
+
+ function doSearch(query) {
+ if (query.length > 1) {
+ var url = "/api/search";
+ $.ajax({
+ type : 'POST',
+ url: url,
+ data: JSON.stringify({"query" : query }),
+ contentType : 'application/json',
+ dataType : 'json',
+ success : function(data) {
+ var p = $("#output");
+ p.empty();
+ _.each(data.results, function(doc){
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ p.append(b);
+ });
+ }
+ });
+ }
+ };
+
+
+ var queryURL = function (query) {
+ var url = "/api/search" + encodeURIComponent(query);
+ url = url + "&field=" + $("#searchFields").val();
+ if ($("#fileType").val() != "All") {
+ url = url + "&type=" + $("#fileType").val()
+ }
+ return url;
+ }
+
+ $(document).ready( function() {
+ $("#search_button").click(function() {
+ doSearch($("#search_text").val());
+ });
+ $('#search_text').keyup(function(e){
+ if(e.keyCode == 13) {
+ doSearch($("#search_text").val());
+ }
+ });
+ doSearch($("#search_text").val());
+ });
+ </script></%def>
+
<%def name="center_panel()">
-${search_init()}
-<script type="text/javascript">
-var search_format_output = function(doc) {
- var div_class = "historyItem";
- var a = $("<div class='" + div_class + "'>")
- a.append($("<div>").append(doc['model_class']));
- b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
- if ('misc_blurb' in doc) {
- b.append( $("<div>").append(doc["misc_blurb"]) );
- }
- if ('peek' in doc) {
- b.append( $("<pre class='peek'>").append( doc["peek"]) );
- }
- return a;
-}
+ <div id="search_box" style="margin: 20px;">
+ <input type="text" id="search_text" size="90"/>
+ </div>
+ <div style="margin: 20px;">
+ <input type="button" id="search_button" value="Search"/>
+ </div>
+ <div id="output"></div>
-</script>
-<div style="overflow: auto; height: 100%">
-${search_dialog("search_format_output")}
-</div></%def>
-
-
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/webapps/galaxy/cloud/run.mako
--- a/templates/webapps/galaxy/cloud/run.mako
+++ /dev/null
@@ -1,41 +0,0 @@
-<%inherit file="/webapps/galaxy/base_panels.mako"/>
-
-<%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.active_view="shared"
- self.message_box_visible=False
-%>
-</%def>
-
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%;">
- <div class="page-container" style="padding: 10px;">
- <h2>Launching a Galaxy Cloud Instance</h2>
-%if error:
- <p>${error}</p>
-%elif instance:
- %if kp_material:
- <h3>Very Important Key Pair Information</h3>
- <p>A new key pair named '${kp_name}' has been created in your AWS
- account and will be used to access this instance via ssh. It is
- <strong>very important</strong> that you save the following private key
- as it is not saved on this Galaxy instance and will be permanently lost
- once you leave this page. To do this, save the following key block as
- a plain text file named '${kp_name}'.</p>
- <pre>${kp_material}</pre>
- %endif
- <p>The instance '${instance.id} has been successfully launched using the
- '${instance.image_id}' AMI.<br/> Access it at <a
- href="http://${instance.public_dns_name}">http://${instance.public_dns_name}</a></p>
- <p>SSH access is available using your private key '${kp_name}'.</p>
-%else:
- <p> Unknown failure, no instance. Please refer to your AWS console at <a
- href="https://console.aws.amazon.com">https://console.aws.amazon.com</a></p>
-%endif
- </div>
- </div>
-</%def>
-
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
11 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c759bf3e94af/
Changeset: c759bf3e94af
Branch: stable
User: dannon
Date: 2014-11-25 19:26:52+00:00
Summary: Prevent XSS in unknown tool display, update to actually use show_error_message instead of replying with plain text.
Affected #: 2 files
diff -r 8e45b1cefba16727d4d3a7d0dceaaaf1ef400a0c -r c759bf3e94af92d7889ce847fe319bd0592f70e5 lib/galaxy/web/framework/helpers/__init__.py
--- a/lib/galaxy/web/framework/helpers/__init__.py
+++ b/lib/galaxy/web/framework/helpers/__init__.py
@@ -3,13 +3,13 @@
"""
import time
-from cgi import escape
from datetime import datetime, timedelta
from galaxy import eggs
from galaxy.util import hash_util
from galaxy.util.json import dumps
eggs.require( "MarkupSafe" ) #required by WebHelpers
eggs.require( "WebHelpers" )
+from markupsafe import escape
from webhelpers import date
from webhelpers.html.tags import stylesheet_link, javascript_link
diff -r 8e45b1cefba16727d4d3a7d0dceaaaf1ef400a0c -r c759bf3e94af92d7889ce847fe319bd0592f70e5 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -15,8 +15,8 @@
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import is_hashable
-from galaxy.web import error
-from galaxy.web import url_for
+from galaxy.web import error, url_for
+from galaxy.web.framework.helpers import escape
from galaxy.web.base.controller import BaseUIController
import tool_shed.util.shed_util_common as suc
@@ -57,7 +57,7 @@
return trans.response.send_redirect( url_for( controller="root", action="welcome" ) )
# When the tool form is initially loaded, the received kwd will not include a 'refresh'
# entry (which only is included when another option is selected in the tool_version_select_field),
- # so the default selected option should be the most recent version of the tool. The following
+ # so the default selected option should be the most recent version of the tool. The following
# check will mae sure this occurs.
refreshed_on_change = kwd.get( 'refresh', False )
tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
@@ -69,7 +69,7 @@
log.error( "index called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if tool.require_login and not trans.user:
message = "You must be logged in to use this tool."
status = "info"
https://bitbucket.org/galaxy/galaxy-central/commits/6a27c440865c/
Changeset: 6a27c440865c
Branch: stable
User: dannon
Date: 2014-11-25 19:31:55+00:00
Summary: Another instance of tool_id reflected xss (in data_source_redirect).
Affected #: 1 file
diff -r c759bf3e94af92d7889ce847fe319bd0592f70e5 -r 6a27c440865cdb38241b4e49664e594c719dcd2f lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -290,7 +290,7 @@
log.error( "data_source_redirect called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if isinstance( tool, DataSourceTool ):
link = url_for( tool.action, **tool.get_static_param_values( trans ) )
https://bitbucket.org/galaxy/galaxy-central/commits/705e13dd0567/
Changeset: 705e13dd0567
Branch: stable
User: dannon
Date: 2014-11-25 20:14:25+00:00
Summary: Referer-in-okmessage reflective xss fix
Affected #: 4 files
diff -r 6a27c440865cdb38241b4e49664e594c719dcd2f -r 705e13dd05674a8f35771c3b86fc221842e371e9 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -11,8 +11,7 @@
from galaxy.util.sanitize_html import sanitize_html
from galaxy.util.json import loads
from galaxy.web.base.controller import BaseUIController, ERROR, SUCCESS, url_for, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesExtendedMetadataMixin
-from galaxy.web.framework.helpers import grids, iff, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, iff, time_ago, to_unicode, escape
from galaxy.tools.errors import EmailErrorReporter
eggs.require( "Paste" )
@@ -510,7 +509,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
# Error checking.
diff -r 6a27c440865cdb38241b4e49664e594c719dcd2f -r 705e13dd05674a8f35771c3b86fc221842e371e9 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -17,7 +17,7 @@
from galaxy.web.base.controller import ExportsHistoryMixin
from galaxy.web.base.controller import ImportsHistoryMixin
from galaxy.web.base.controller import ERROR, INFO, SUCCESS, WARNING
-from galaxy.web.framework.helpers import grids, iff, time_ago
+from galaxy.web.framework.helpers import grids, iff, time_ago, escape
log = logging.getLogger( __name__ )
@@ -1232,7 +1232,7 @@
else:
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
diff -r 6a27c440865cdb38241b4e49664e594c719dcd2f -r 705e13dd05674a8f35771c3b86fc221842e371e9 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -9,7 +9,7 @@
from galaxy import model, web
from galaxy.model.item_attrs import UsesAnnotations, UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesVisualizationMixin
-from galaxy.web.framework.helpers import time_ago, grids
+from galaxy.web.framework.helpers import time_ago, grids, escape
from galaxy import util
from galaxy.datatypes.interval import Bed
from galaxy.util.json import loads
@@ -123,7 +123,7 @@
# or_( "metadata like '%%\"dbkey\": [\"?\"]%%'", "metadata like '%%\"dbkey\": \"?\"%%'" ) \
# )
# )
-
+
class HistoryColumn( grids.GridColumn ):
""" Column for filtering by history id. """
@@ -360,7 +360,7 @@
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
def list( self, trans, *args, **kwargs ):
-
+
# Handle operation
if 'operation' in kwargs and 'id' in kwargs:
session = trans.sa_session
@@ -388,7 +388,7 @@
kwargs[ 'embedded' ] = True
grid = self._user_list_grid( trans, *args, **kwargs )
return trans.fill_template( "visualization/list.mako", embedded_grid=grid, shared_by_others=shared_by_others )
-
+
#
# -- Functions for operating on visualizations. --
#
@@ -459,7 +459,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % web.url_for( '/' )
diff -r 6a27c440865cdb38241b4e49664e594c719dcd2f -r 705e13dd05674a8f35771c3b86fc221842e371e9 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -22,8 +22,7 @@
from galaxy.web import error, url_for
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesStoredWorkflowMixin
from galaxy.web.framework.formbuilder import form
-from galaxy.web.framework.helpers import grids, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, time_ago, to_unicode, escape
from galaxy.workflow.modules import WorkflowModuleInjector
from galaxy.workflow.modules import MissingToolException
from galaxy.workflow.modules import module_factory, is_tool_module_type
@@ -389,7 +388,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
https://bitbucket.org/galaxy/galaxy-central/commits/b6ee4c07d0ab/
Changeset: b6ee4c07d0ab
Branch: stable
User: dannon
Date: 2014-11-25 20:14:58+00:00
Summary: Referer-in-logout reflective xss fix.
Affected #: 1 file
diff -r 705e13dd05674a8f35771c3b86fc221842e371e9 -r b6ee4c07d0abb03f1d017c7756a59606594a88a2 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -605,8 +605,8 @@
else:
refresh_frames = [ 'masthead' ]
trans.handle_user_logout( logout_all=logout_all )
- message = 'You have been logged out.<br>You can log in again, <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
- ( escape( trans.request.referer ), url_for( '/' ) )
+ message = 'You have been logged out.<br>To log in again <a target="_top" href="%s">go to the home page</a>.' % \
+ ( url_for( '/' ) )
if biostar.biostar_logged_in( trans ):
biostar_url = biostar.biostar_logout( trans )
if biostar_url:
https://bitbucket.org/galaxy/galaxy-central/commits/925ce4a5eb77/
Changeset: 925ce4a5eb77
Branch: stable
User: dannon
Date: 2014-12-04 16:51:46+00:00
Summary: Remove unused cloud/run.mako; all functionality is rolled into cloud/index.
Affected #: 1 file
diff -r b6ee4c07d0abb03f1d017c7756a59606594a88a2 -r 925ce4a5eb7730dffad81391e2e0caff5d764fac templates/webapps/galaxy/cloud/run.mako
--- a/templates/webapps/galaxy/cloud/run.mako
+++ /dev/null
@@ -1,41 +0,0 @@
-<%inherit file="/webapps/galaxy/base_panels.mako"/>
-
-<%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.active_view="shared"
- self.message_box_visible=False
-%>
-</%def>
-
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%;">
- <div class="page-container" style="padding: 10px;">
- <h2>Launching a Galaxy Cloud Instance</h2>
-%if error:
- <p>${error}</p>
-%elif instance:
- %if kp_material:
- <h3>Very Important Key Pair Information</h3>
- <p>A new key pair named '${kp_name}' has been created in your AWS
- account and will be used to access this instance via ssh. It is
- <strong>very important</strong> that you save the following private key
- as it is not saved on this Galaxy instance and will be permanently lost
- once you leave this page. To do this, save the following key block as
- a plain text file named '${kp_name}'.</p>
- <pre>${kp_material}</pre>
- %endif
- <p>The instance '${instance.id} has been successfully launched using the
- '${instance.image_id}' AMI.<br/> Access it at <a
- href="http://${instance.public_dns_name}">http://${instance.public_dns_name}</a></p>
- <p>SSH access is available using your private key '${kp_name}'.</p>
-%else:
- <p> Unknown failure, no instance. Please refer to your AWS console at <a
- href="https://console.aws.amazon.com">https://console.aws.amazon.com</a></p>
-%endif
- </div>
- </div>
-</%def>
-
https://bitbucket.org/galaxy/galaxy-central/commits/58b1fe20c936/
Changeset: 58b1fe20c936
Branch: stable
User: dannon
Date: 2014-12-04 17:05:07+00:00
Summary: Don't trust user email rendered into page unescaped for Raven.
Affected #: 1 file
diff -r 925ce4a5eb7730dffad81391e2e0caff5d764fac -r 58b1fe20c93603b62becc2b669fe9e4e380c40c5 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -45,7 +45,7 @@
<script>
Raven.config('${app.config.sentry_dsn_public}').install();
%if trans.user:
- Raven.setUser( { email: "${trans.user.email}" } );
+ Raven.setUser( { email: "${trans.user.email | h}" } );
%endif
</script>
%endif
https://bitbucket.org/galaxy/galaxy-central/commits/bb90975b564a/
Changeset: bb90975b564a
Branch: stable
User: dannon
Date: 2014-12-04 18:10:37+00:00
Summary: Catch ValueError and actually log it instead of blowing up w/ invalid dataset_id. Raise httpexception.
Affected #: 1 file
diff -r 58b1fe20c93603b62becc2b669fe9e4e380c40c5 -r bb90975b564a98a98cd215ae3a29771ea9dbc31c lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -938,9 +938,12 @@
"""
Show the parameters used for an HDA
"""
- hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ try:
+ hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ except ValueError:
+ hda = None
if not hda:
- raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
+ raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % escape( str( dataset_id ) ) )
if not self._can_access_dataset( trans, hda ):
return trans.show_error_message( "You are not allowed to access this dataset" )
@@ -972,7 +975,10 @@
params_objects = job.get_param_values( trans.app, ignore_errors=False )
except:
params_objects = job.get_param_values( trans.app, ignore_errors=True )
- upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ), trans, update_values=False ) #use different param_objects here, since we want to display original values as much as possible
+ # use different param_objects in the following line, since we want to display original values as much as possible
+ upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ),
+ trans,
+ update_values=False )
has_parameter_errors = True
except:
pass
https://bitbucket.org/galaxy/galaxy-central/commits/9612d9eedace/
Changeset: 9612d9eedace
Branch: stable
User: dannon
Date: 2014-12-04 20:23:35+00:00
Summary: Fix search to work for at least datasets, hdas, etc.
Affected #: 1 file
diff -r bb90975b564a98a98cd215ae3a29771ea9dbc31c -r 9612d9eedace3e2a9f6eb752228d5a6e651737cb templates/search/index.mako
--- a/templates/search/index.mako
+++ b/templates/search/index.mako
@@ -1,52 +1,112 @@
-
<%inherit file="/webapps/galaxy/base_panels.mako"/>
-<%namespace file="/search/search.mako" import="search_init" />
-<%namespace file="/search/search.mako" import="search_dialog" /><%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
- self.active_view="shared"
- self.overlay_visible=False
-%>
+ <%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.message_box_visible=False
+ self.active_view="shared"
+ self.overlay_visible=False
+ %></%def><%def name="stylesheets()">
-${parent.stylesheets()}
-<style>
-.searchResult {
- border-style:dashed;
- border-width:1px;
- margin: 5px;
-}
-</style>
+ ${parent.stylesheets()}
+ <style>
+ .searchResult {
+ border-style:dashed;
+ border-width:1px;
+ margin: 5px;
+ }
+ </style>
+</%def>
+
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js(
+ "libs/jquery/jquery",
+ )}
+ <script type="text/javascript">
+
+ function search_format_output(doc) {
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ return a;
+ }
+
+ function doSearch(query) {
+ if (query.length > 1) {
+ var url = "/api/search";
+ $.ajax({
+ type : 'POST',
+ url: url,
+ data: JSON.stringify({"query" : query }),
+ contentType : 'application/json',
+ dataType : 'json',
+ success : function(data) {
+ var p = $("#output");
+ p.empty();
+ _.each(data.results, function(doc){
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ p.append(b);
+ });
+ }
+ });
+ }
+ };
+
+
+ var queryURL = function (query) {
+ var url = "/api/search" + encodeURIComponent(query);
+ url = url + "&field=" + $("#searchFields").val();
+ if ($("#fileType").val() != "All") {
+ url = url + "&type=" + $("#fileType").val()
+ }
+ return url;
+ }
+
+ $(document).ready( function() {
+ $("#search_button").click(function() {
+ doSearch($("#search_text").val());
+ });
+ $('#search_text').keyup(function(e){
+ if(e.keyCode == 13) {
+ doSearch($("#search_text").val());
+ }
+ });
+ doSearch($("#search_text").val());
+ });
+ </script></%def>
+
<%def name="center_panel()">
-${search_init()}
-<script type="text/javascript">
-var search_format_output = function(doc) {
- var div_class = "historyItem";
- var a = $("<div class='" + div_class + "'>")
- a.append($("<div>").append(doc['model_class']));
- b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
- if ('misc_blurb' in doc) {
- b.append( $("<div>").append(doc["misc_blurb"]) );
- }
- if ('peek' in doc) {
- b.append( $("<pre class='peek'>").append( doc["peek"]) );
- }
- return a;
-}
+ <div id="search_box" style="margin: 20px;">
+ <input type="text" id="search_text" size="90"/>
+ </div>
+ <div style="margin: 20px;">
+ <input type="button" id="search_button" value="Search"/>
+ </div>
+ <div id="output"></div>
-</script>
-<div style="overflow: auto; height: 100%">
-${search_dialog("search_format_output")}
-</div></%def>
-
-
https://bitbucket.org/galaxy/galaxy-central/commits/5e4d8a48320f/
Changeset: 5e4d8a48320f
Branch: stable
User: dannon
Date: 2014-12-04 20:27:19+00:00
Summary: Disable search interface for right now -- I made it not broken in the previous commit, but nobody should be using this yet.
Affected #: 1 file
diff -r 9612d9eedace3e2a9f6eb752228d5a6e651737cb -r 5e4d8a48320fb516ea8695bfdfdedc1960594f84 lib/galaxy/webapps/galaxy/controllers/search.py
--- a/lib/galaxy/webapps/galaxy/controllers/search.py
+++ b/lib/galaxy/webapps/galaxy/controllers/search.py
@@ -1,4 +1,3 @@
-
"""
Contains a basic search interface for Galaxy
"""
@@ -8,7 +7,13 @@
log = logging.getLogger( __name__ )
+
class SearchController( BaseUIController ):
+
@web.expose
def index(self, trans):
- return trans.fill_template( "search/index.mako")
+ """
+ Not ready for human consumption, yet. Power users can still use the
+ search API.
+ """
+ return trans.show_message("Sorry, the search interface isn't quite ready for use, yet.")
https://bitbucket.org/galaxy/galaxy-central/commits/fdc7863699d2/
Changeset: fdc7863699d2
Branch: stable
User: dannon
Date: 2014-12-08 22:16:21+00:00
Summary: One more place we shouldn't trust user_email.
Affected #: 1 file
diff -r 5e4d8a48320fb516ea8695bfdfdedc1960594f84 -r fdc7863699d233e2b44d6d42f47dfaaa97e0d80e templates/refresh_frames.mako
--- a/templates/refresh_frames.mako
+++ b/templates/refresh_frames.mako
@@ -21,7 +21,7 @@
## Refresh masthead == user changes (backward compatibility)
if ( parent.user_changed ) {
%if trans.user:
- parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} );
+ parent.user_changed( "${trans.user.email | h }", ${int( app.config.is_admin_user( trans.user ) )} );
%else:
parent.user_changed( null, false );
%endif
https://bitbucket.org/galaxy/galaxy-central/commits/3e7adbbe91a0/
Changeset: 3e7adbbe91a0
Branch: stable
User: jmchilton
Date: 2014-12-09 14:31:53+00:00
Summary: Merged in dannon/galaxy-central/stable (pull request #596)
[STABLE] Grafts of next-stable commits for security release.
Affected #: 12 files
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/web/framework/helpers/__init__.py
--- a/lib/galaxy/web/framework/helpers/__init__.py
+++ b/lib/galaxy/web/framework/helpers/__init__.py
@@ -3,13 +3,13 @@
"""
import time
-from cgi import escape
from datetime import datetime, timedelta
from galaxy import eggs
from galaxy.util import hash_util
from galaxy.util.json import dumps
eggs.require( "MarkupSafe" ) #required by WebHelpers
eggs.require( "WebHelpers" )
+from markupsafe import escape
from webhelpers import date
from webhelpers.html.tags import stylesheet_link, javascript_link
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -11,8 +11,7 @@
from galaxy.util.sanitize_html import sanitize_html
from galaxy.util.json import loads
from galaxy.web.base.controller import BaseUIController, ERROR, SUCCESS, url_for, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesExtendedMetadataMixin
-from galaxy.web.framework.helpers import grids, iff, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, iff, time_ago, to_unicode, escape
from galaxy.tools.errors import EmailErrorReporter
eggs.require( "Paste" )
@@ -510,7 +509,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
# Error checking.
@@ -939,9 +938,12 @@
"""
Show the parameters used for an HDA
"""
- hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ try:
+ hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) )
+ except ValueError:
+ hda = None
if not hda:
- raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
+ raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % escape( str( dataset_id ) ) )
if not self._can_access_dataset( trans, hda ):
return trans.show_error_message( "You are not allowed to access this dataset" )
@@ -973,7 +975,10 @@
params_objects = job.get_param_values( trans.app, ignore_errors=False )
except:
params_objects = job.get_param_values( trans.app, ignore_errors=True )
- upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ), trans, update_values=False ) #use different param_objects here, since we want to display original values as much as possible
+ # use different param_objects in the following line, since we want to display original values as much as possible
+ upgrade_messages = tool.check_and_update_param_values( job.get_param_values( trans.app, ignore_errors=True ),
+ trans,
+ update_values=False )
has_parameter_errors = True
except:
pass
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -17,7 +17,7 @@
from galaxy.web.base.controller import ExportsHistoryMixin
from galaxy.web.base.controller import ImportsHistoryMixin
from galaxy.web.base.controller import ERROR, INFO, SUCCESS, WARNING
-from galaxy.web.framework.helpers import grids, iff, time_ago
+from galaxy.web.framework.helpers import grids, iff, time_ago, escape
log = logging.getLogger( __name__ )
@@ -1234,7 +1234,7 @@
else:
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/search.py
--- a/lib/galaxy/webapps/galaxy/controllers/search.py
+++ b/lib/galaxy/webapps/galaxy/controllers/search.py
@@ -1,4 +1,3 @@
-
"""
Contains a basic search interface for Galaxy
"""
@@ -8,7 +7,13 @@
log = logging.getLogger( __name__ )
+
class SearchController( BaseUIController ):
+
@web.expose
def index(self, trans):
- return trans.fill_template( "search/index.mako")
+ """
+ Not ready for human consumption, yet. Power users can still use the
+ search API.
+ """
+ return trans.show_message("Sorry, the search interface isn't quite ready for use, yet.")
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -15,8 +15,8 @@
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import is_hashable
-from galaxy.web import error
-from galaxy.web import url_for
+from galaxy.web import error, url_for
+from galaxy.web.framework.helpers import escape
from galaxy.web.base.controller import BaseUIController
import tool_shed.util.shed_util_common as suc
@@ -57,7 +57,7 @@
return trans.response.send_redirect( url_for( controller="root", action="welcome" ) )
# When the tool form is initially loaded, the received kwd will not include a 'refresh'
# entry (which only is included when another option is selected in the tool_version_select_field),
- # so the default selected option should be the most recent version of the tool. The following
+ # so the default selected option should be the most recent version of the tool. The following
# check will mae sure this occurs.
refreshed_on_change = kwd.get( 'refresh', False )
tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
@@ -69,7 +69,7 @@
log.error( "index called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if tool.require_login and not trans.user:
message = "You must be logged in to use this tool."
status = "info"
@@ -290,7 +290,7 @@
log.error( "data_source_redirect called with tool id '%s' but no such tool exists", tool_id )
trans.log_event( "Tool id '%s' does not exist" % tool_id )
trans.response.status = 404
- return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+ return trans.show_error_message("Tool '%s' does not exist." % ( escape(tool_id) ))
if isinstance( tool, DataSourceTool ):
link = url_for( tool.action, **tool.get_static_param_values( trans ) )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -605,8 +605,8 @@
else:
refresh_frames = [ 'masthead' ]
trans.handle_user_logout( logout_all=logout_all )
- message = 'You have been logged out.<br>You can log in again, <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
- ( escape( trans.request.referer ), url_for( '/' ) )
+ message = 'You have been logged out.<br>To log in again <a target="_top" href="%s">go to the home page</a>.' % \
+ ( url_for( '/' ) )
if biostar.biostar_logged_in( trans ):
biostar_url = biostar.biostar_logout( trans )
if biostar_url:
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -9,7 +9,7 @@
from galaxy import model, web
from galaxy.model.item_attrs import UsesAnnotations, UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesVisualizationMixin
-from galaxy.web.framework.helpers import time_ago, grids
+from galaxy.web.framework.helpers import time_ago, grids, escape
from galaxy import util
from galaxy.datatypes.interval import Bed
from galaxy.util.json import loads
@@ -123,7 +123,7 @@
# or_( "metadata like '%%\"dbkey\": [\"?\"]%%'", "metadata like '%%\"dbkey\": \"?\"%%'" ) \
# )
# )
-
+
class HistoryColumn( grids.GridColumn ):
""" Column for filtering by history id. """
@@ -360,7 +360,7 @@
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
def list( self, trans, *args, **kwargs ):
-
+
# Handle operation
if 'operation' in kwargs and 'id' in kwargs:
session = trans.sa_session
@@ -388,7 +388,7 @@
kwargs[ 'embedded' ] = True
grid = self._user_list_grid( trans, *args, **kwargs )
return trans.fill_template( "visualization/list.mako", embedded_grid=grid, shared_by_others=shared_by_others )
-
+
#
# -- Functions for operating on visualizations. --
#
@@ -459,7 +459,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % web.url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -22,8 +22,7 @@
from galaxy.web import error, url_for
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesStoredWorkflowMixin
from galaxy.web.framework.formbuilder import form
-from galaxy.web.framework.helpers import grids, time_ago
-from galaxy.web.framework.helpers import to_unicode
+from galaxy.web.framework.helpers import grids, time_ago, to_unicode, escape
from galaxy.workflow.modules import WorkflowModuleInjector
from galaxy.workflow.modules import MissingToolException
from galaxy.workflow.modules import module_factory, is_tool_module_type
@@ -389,7 +388,7 @@
# Set referer message.
referer = trans.request.referer
if referer is not "":
- referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ referer_message = "<a href='%s'>return to the previous page</a>" % escape(referer)
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -45,7 +45,7 @@
<script>
Raven.config('${app.config.sentry_dsn_public}').install();
%if trans.user:
- Raven.setUser( { email: "${trans.user.email}" } );
+ Raven.setUser( { email: "${trans.user.email | h}" } );
%endif
</script>
%endif
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/refresh_frames.mako
--- a/templates/refresh_frames.mako
+++ b/templates/refresh_frames.mako
@@ -21,7 +21,7 @@
## Refresh masthead == user changes (backward compatibility)
if ( parent.user_changed ) {
%if trans.user:
- parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} );
+ parent.user_changed( "${trans.user.email | h }", ${int( app.config.is_admin_user( trans.user ) )} );
%else:
parent.user_changed( null, false );
%endif
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/search/index.mako
--- a/templates/search/index.mako
+++ b/templates/search/index.mako
@@ -1,52 +1,112 @@
-
<%inherit file="/webapps/galaxy/base_panels.mako"/>
-<%namespace file="/search/search.mako" import="search_init" />
-<%namespace file="/search/search.mako" import="search_dialog" /><%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
- self.active_view="shared"
- self.overlay_visible=False
-%>
+ <%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.message_box_visible=False
+ self.active_view="shared"
+ self.overlay_visible=False
+ %></%def><%def name="stylesheets()">
-${parent.stylesheets()}
-<style>
-.searchResult {
- border-style:dashed;
- border-width:1px;
- margin: 5px;
-}
-</style>
+ ${parent.stylesheets()}
+ <style>
+ .searchResult {
+ border-style:dashed;
+ border-width:1px;
+ margin: 5px;
+ }
+ </style>
+</%def>
+
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js(
+ "libs/jquery/jquery",
+ )}
+ <script type="text/javascript">
+
+ function search_format_output(doc) {
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ return a;
+ }
+
+ function doSearch(query) {
+ if (query.length > 1) {
+ var url = "/api/search";
+ $.ajax({
+ type : 'POST',
+ url: url,
+ data: JSON.stringify({"query" : query }),
+ contentType : 'application/json',
+ dataType : 'json',
+ success : function(data) {
+ var p = $("#output");
+ p.empty();
+ _.each(data.results, function(doc){
+ var div_class = "historyItem";
+ var a = $("<div class='" + div_class + "'>")
+ a.append($("<div>").append(doc['model_class']));
+ b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
+ if ('misc_blurb' in doc) {
+ b.append( $("<div>").append(doc["misc_blurb"]) );
+ }
+ if ('peek' in doc) {
+ b.append( $("<pre class='peek'>").append( doc["peek"]) );
+ }
+ p.append(b);
+ });
+ }
+ });
+ }
+ };
+
+
+ var queryURL = function (query) {
+ var url = "/api/search" + encodeURIComponent(query);
+ url = url + "&field=" + $("#searchFields").val();
+ if ($("#fileType").val() != "All") {
+ url = url + "&type=" + $("#fileType").val()
+ }
+ return url;
+ }
+
+ $(document).ready( function() {
+ $("#search_button").click(function() {
+ doSearch($("#search_text").val());
+ });
+ $('#search_text').keyup(function(e){
+ if(e.keyCode == 13) {
+ doSearch($("#search_text").val());
+ }
+ });
+ doSearch($("#search_text").val());
+ });
+ </script></%def>
+
<%def name="center_panel()">
-${search_init()}
-<script type="text/javascript">
-var search_format_output = function(doc) {
- var div_class = "historyItem";
- var a = $("<div class='" + div_class + "'>")
- a.append($("<div>").append(doc['model_class']));
- b = a.append( $("<div class='historyItemTitle'><a href='/file/" + doc['id'] + "'>" + doc['name'] + "</a></div>") );
- if ('misc_blurb' in doc) {
- b.append( $("<div>").append(doc["misc_blurb"]) );
- }
- if ('peek' in doc) {
- b.append( $("<pre class='peek'>").append( doc["peek"]) );
- }
- return a;
-}
+ <div id="search_box" style="margin: 20px;">
+ <input type="text" id="search_text" size="90"/>
+ </div>
+ <div style="margin: 20px;">
+ <input type="button" id="search_button" value="Search"/>
+ </div>
+ <div id="output"></div>
-</script>
-<div style="overflow: auto; height: 100%">
-${search_dialog("search_format_output")}
-</div></%def>
-
-
diff -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 -r 3e7adbbe91a06d30a96e7a7101707e040376aba1 templates/webapps/galaxy/cloud/run.mako
--- a/templates/webapps/galaxy/cloud/run.mako
+++ /dev/null
@@ -1,41 +0,0 @@
-<%inherit file="/webapps/galaxy/base_panels.mako"/>
-
-<%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.active_view="shared"
- self.message_box_visible=False
-%>
-</%def>
-
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%;">
- <div class="page-container" style="padding: 10px;">
- <h2>Launching a Galaxy Cloud Instance</h2>
-%if error:
- <p>${error}</p>
-%elif instance:
- %if kp_material:
- <h3>Very Important Key Pair Information</h3>
- <p>A new key pair named '${kp_name}' has been created in your AWS
- account and will be used to access this instance via ssh. It is
- <strong>very important</strong> that you save the following private key
- as it is not saved on this Galaxy instance and will be permanently lost
- once you leave this page. To do this, save the following key block as
- a plain text file named '${kp_name}'.</p>
- <pre>${kp_material}</pre>
- %endif
- <p>The instance '${instance.id} has been successfully launched using the
- '${instance.image_id}' AMI.<br/> Access it at <a
- href="http://${instance.public_dns_name}">http://${instance.public_dns_name}</a></p>
- <p>SSH access is available using your private key '${kp_name}'.</p>
-%else:
- <p> Unknown failure, no instance. Please refer to your AWS console at <a
- href="https://console.aws.amazon.com">https://console.aws.amazon.com</a></p>
-%endif
- </div>
- </div>
-</%def>
-
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
09 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/511fbb67b820/
Changeset: 511fbb67b820
User: jmchilton
Date: 2014-12-09 14:17:25+00:00
Summary: Merge next-stable.
Affected #: 44 files
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-acb2548443ae42d39ef200d035ccc0481d6b930c latest_2014.10.06
+782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 latest_2014.10.06
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/security/validate_user_input.py
--- a/lib/galaxy/security/validate_user_input.py
+++ b/lib/galaxy/security/validate_user_input.py
@@ -1,3 +1,9 @@
+"""
+Utilities for validating inputs related to user objects.
+
+The validate_* methods in this file return simple messages that do not contain
+user inputs - so these methods do not need to be escaped.
+"""
import logging
import re
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -67,6 +67,7 @@
from galaxy.util.template import fill_template
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
+from galaxy.web.framework.helpers import escape
from galaxy.model.item_attrs import Dictifiable
from galaxy.model import Workflow
from tool_shed.util import common_util
@@ -791,7 +792,7 @@
success = True
# Make sure the tool is actually loaded.
if tool_id not in self.tools_by_id:
- return None, False, "No tool with id %s" % tool_id
+ return None, False, "No tool with id %s" % escape( tool_id )
else:
tool = self.tools_by_id[ tool_id ]
tarball_files = []
@@ -902,7 +903,7 @@
replace the old tool.
"""
if tool_id not in self.tools_by_id:
- message = "No tool with id %s" % tool_id
+ message = "No tool with id %s" % escape( tool_id )
status = 'error'
else:
old_tool = self.tools_by_id[ tool_id ]
@@ -939,7 +940,7 @@
Attempt to remove the tool identified by 'tool_id'.
"""
if tool_id not in self.tools_by_id:
- message = "No tool with id %s" % tool_id
+ message = "No tool with id %s" % escape( tool_id )
status = 'error'
else:
tool = self.tools_by_id[ tool_id ]
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -1,6 +1,10 @@
+import logging
from galaxy.util import listify
from copy import deepcopy
+log = logging.getLogger( __name__ )
+
+
class FilterFactory( object ):
"""
An instance of this class is responsible for filtering the list
@@ -37,17 +41,21 @@
elif name == 'toolbox_label_filters':
category = "label"
if category:
- self.__init_filters( category, user_filters, filters )
+ validate = getattr( trans.app.config, 'user_%s_filters' % category, [] )
+ self.__init_filters( category, user_filters, filters, validate=validate )
else:
if kwds.get( "trackster", False ):
filters[ "tool" ].append( _has_trackster_conf )
return filters
- def __init_filters( self, key, filters, toolbox_filters ):
+ def __init_filters( self, key, filters, toolbox_filters, validate=None ):
for filter in filters:
- filter_function = self.__build_filter_function( filter )
- toolbox_filters[ key ].append( filter_function )
+ if validate is None or filter in validate or filter in self.default_filters:
+ filter_function = self.__build_filter_function( filter )
+ toolbox_filters[ key ].append( filter_function )
+ else:
+ log.warning( "Refusing to load %s filter '%s' which is not defined in config", key, filter )
return toolbox_filters
def __build_filter_function( self, filter_name ):
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -1664,7 +1664,8 @@
stored.user = trans.user
stored.published = publish
if data[ 'annotation' ]:
- self.add_item_annotation( trans.sa_session, stored.user, stored, data[ 'annotation' ] )
+ annotation = sanitize_html( data[ 'annotation' ], 'utf-8', 'text/html' )
+ self.add_item_annotation( trans.sa_session, stored.user, stored, annotation )
# Persist
trans.sa_session.add( stored )
@@ -2571,6 +2572,8 @@
def set_public_username( self, trans, id, username, **kwargs ):
""" Set user's public username and delegate to sharing() """
user = trans.get_user()
+ # message from validate_publicname does not contain input, no need
+ # to escape.
message = validate_publicname( trans, username, user )
if message:
return trans.fill_template( '/sharing_base.mako', item=self.get_item( trans, id ), message=message, status='error' )
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/web/form_builder.py
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -563,7 +563,7 @@
html += '<input name="__switch_default__" type="hidden" value="%s" />' % self.default_field
options = []
for name, delegate_field in self.delegate_fields.items():
- field = dumps( delegate_field.to_dict() )
+ field = escape( dumps( delegate_field.to_dict() ) )
option = " '%s': %s" % ( name, field )
options.append( option )
html += '<script>$(document).ready( function() {\nvar switchOptions = {\n'
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -718,7 +718,9 @@
for husa in husas:
trans.sa_session.delete( husa )
if not deleted_sharing_relation:
- message = "History '%s' does not seem to be shared with user '%s'" % ( history.name, user.email )
+ history_name = escape( history.name )
+ user_email = escape( user.email )
+ message = "History '%s' does not seem to be shared with user '%s'" % ( history_name, user_email )
return trans.fill_template( '/sharing_base.mako', item=history,
message=message, status='error' )
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/webapps/galaxy/controllers/mobile.py
--- a/lib/galaxy/webapps/galaxy/controllers/mobile.py
+++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py
@@ -1,60 +1,71 @@
+from galaxy import web
from galaxy.web.base.controller import *
+
class Mobile( BaseUIController ):
+
@web.expose
def index( self, trans, **kwargs ):
- return trans.fill_template( "mobile/index.mako" )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # return trans.fill_template( "mobile/index.mako" )
@web.expose
def history_list( self, trans ):
- return trans.fill_template( "mobile/history/list.mako" )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # return trans.fill_template( "mobile/history/list.mako" )
@web.expose
def history_detail( self, trans, id ):
- history = trans.sa_session.query( trans.app.model.History ).get( id )
- assert history.user == trans.user
- return trans.fill_template( "mobile/history/detail.mako", history=history )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # history = trans.sa_session.query( trans.app.model.History ).get( id )
+ # assert history.user == trans.user
+ # return trans.fill_template( "mobile/history/detail.mako", history=history )
@web.expose
def dataset_detail( self, trans, id ):
- dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
- assert dataset.history.user == trans.user
- return trans.fill_template( "mobile/dataset/detail.mako", dataset=dataset )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
+ # assert dataset.history.user == trans.user
+ # return trans.fill_template( "mobile/dataset/detail.mako", dataset=dataset )
@web.expose
def dataset_peek( self, trans, id ):
- dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
- assert dataset.history.user == trans.user
- return trans.fill_template( "mobile/dataset/peek.mako", dataset=dataset )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
+ # assert dataset.history.user == trans.user
+ # return trans.fill_template( "mobile/dataset/peek.mako", dataset=dataset )
@web.expose
def settings( self, trans, email=None, password=None ):
- message = None
- if email is not None and password is not None:
- if email == "":
- self.__logout( trans )
- message = "Logged out"
- else:
- error = self.__login( trans, email, password )
- message = error or "Login changed"
- return trans.fill_template( "mobile/settings.mako", message=message )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # message = None
+ # if email is not None and password is not None:
+ # if email == "":
+ # self.__logout( trans )
+ # message = "Logged out"
+ # else:
+ # error = self.__login( trans, email, password )
+ # message = error or "Login changed"
+ # return trans.fill_template( "mobile/settings.mako", message=message )
def __logout( self, trans ):
- trans.log_event( "User logged out" )
- trans.handle_user_logout()
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # trans.log_event( "User logged out" )
+ # trans.handle_user_logout()
def __login( self, trans, email="", password="" ):
- error = password_error = None
- user = trans.sa_session.query( model.User ).filter_by( email = email ).first()
- if not user:
- error = "No such user (please note that login is case sensitive)"
- elif user.deleted:
- error = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
- elif user.external:
- error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
- elif not user.check_password( password ):
- error = "Invalid password"
- else:
- trans.handle_user_login( user )
- trans.log_event( "User logged in" )
- return error
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # error = password_error = None
+ # user = trans.sa_session.query( model.User ).filter_by( email = email ).first()
+ # if not user:
+ # error = "No such user (please note that login is case sensitive)"
+ # elif user.deleted:
+ # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
+ # elif user.external:
+ # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
+ # elif not user.check_password( password ):
+ # error = "Invalid password"
+ # else:
+ # trans.handle_user_login( user )
+ # trans.log_event( "User logged in" )
+ # return error
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -500,14 +500,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a page with yourself" )
elif trans.sa_session.query( model.PageUserShareAssociation ) \
.filter_by( user=other, page=page ).count() > 0:
mtype = "error"
- msg = ( "Page already shared with '%s'" % email )
+ msg = ( "Page already shared with '%s'" % escape( email ) )
else:
share = model.PageUserShareAssociation()
share.page = page
@@ -516,7 +516,9 @@
session.add( share )
self.create_item_slug( session, page )
session.flush()
- trans.set_message( "Page '%s' shared with user '%s'" % ( page.title, other.email ) )
+ page_title = escape( page.title )
+ other_email = escape( other.email )
+ trans.set_message( "Page '%s' shared with user '%s'" % ( page_title, other_email ) )
return trans.response.send_redirect( url_for( controller='page', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message = msg,
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -535,14 +535,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a visualization with yourself" )
elif trans.sa_session.query( model.VisualizationUserShareAssociation ) \
.filter_by( user=other, visualization=visualization ).count() > 0:
mtype = "error"
- msg = ( "Visualization already shared with '%s'" % email )
+ msg = ( "Visualization already shared with '%s'" % escape( email ) )
else:
share = model.VisualizationUserShareAssociation()
share.visualization = visualization
@@ -551,7 +551,9 @@
session.add( share )
self.create_item_slug( session, visualization )
session.flush()
- trans.set_message( "Visualization '%s' shared with user '%s'" % ( visualization.title, other.email ) )
+ viz_title = escape( visualization.title )
+ other_email = escape( other.email )
+ trans.set_message( "Visualization '%s' shared with user '%s'" % ( viz_title, other_email ) )
return trans.response.send_redirect( web.url_for(controller='visualization', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message = msg,
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -310,14 +310,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a workflow with yourself" )
elif trans.sa_session.query( model.StoredWorkflowUserShareAssociation ) \
.filter_by( user=other, stored_workflow=stored ).count() > 0:
mtype = "error"
- msg = ( "Workflow already shared with '%s'" % email )
+ msg = ( "Workflow already shared with '%s'" % escape( email ) )
else:
share = model.StoredWorkflowUserShareAssociation()
share.stored_workflow = stored
@@ -325,7 +325,7 @@
session = trans.sa_session
session.add( share )
session.flush()
- trans.set_message( "Workflow '%s' shared with user '%s'" % ( stored.name, other.email ) )
+ trans.set_message( "Workflow '%s' shared with user '%s'" % ( escape( stored.name ), escape( other.email ) ) )
return trans.response.send_redirect( url_for( controller='workflow', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message=msg,
@@ -415,7 +415,7 @@
stored.latest_workflow.name = san_new_name
trans.sa_session.flush()
# For current workflows grid:
- trans.set_message( "Workflow renamed to '%s'." % new_name )
+ trans.set_message( "Workflow renamed to '%s'." % san_new_name )
return self.list( trans )
# For new workflows grid:
#message = "Workflow renamed to '%s'." % new_name
@@ -535,7 +535,7 @@
session.add( new_stored )
session.flush()
# Display the management page
- trans.set_message( 'Created new workflow with name "%s"' % new_stored.name )
+ trans.set_message( 'Created new workflow with name "%s"' % escape( new_stored.name ) )
return self.list( trans )
@web.expose
@@ -582,7 +582,7 @@
trans.sa_session.add( stored )
trans.sa_session.flush()
# Display the management page
- trans.set_message( "Workflow '%s' deleted" % stored.name )
+ trans.set_message( "Workflow '%s' deleted" % escape( stored.name ) )
return self.list( trans )
@web.expose
@@ -1089,7 +1089,7 @@
message += "Imported, but this workflow contains cycles. "
status = "error"
else:
- message += "Workflow <b>%s</b> imported successfully. " % workflow.name
+ message += "Workflow <b>%s</b> imported successfully. " % escape( workflow.name )
if missing_tool_tups:
if trans.user_is_admin():
# A required tool is not available in the local Galaxy instance.
@@ -1103,7 +1103,7 @@
message += "You can likely install the required tools from one of the Galaxy tool sheds listed below.<br/>"
for missing_tool_tup in missing_tool_tups:
missing_tool_id, missing_tool_name, missing_tool_version = missing_tool_tup
- message += "<b>Tool name</b> %s, <b>id</b> %s, <b>version</b> %s<br/>" % ( missing_tool_name, missing_tool_id, missing_tool_version )
+ message += "<b>Tool name</b> %s, <b>id</b> %s, <b>version</b> %s<br/>" % ( escape( missing_tool_name ), escape( missing_tool_id ), escape( missing_tool_version ) )
message += "<br/>"
for shed_name, shed_url in trans.app.tool_shed_registry.tool_sheds.items():
if shed_url.endswith( '/' ):
@@ -1113,7 +1113,7 @@
url += '&tool_id='
for missing_tool_tup in missing_tool_tups:
missing_tool_id = missing_tool_tup[0]
- url += '%s,' % missing_tool_id
+ url += '%s,' % escape( missing_tool_id )
message += '<a href="%s">%s</a><br/>' % ( url, shed_name )
status = 'error'
if installed_repository_file or tool_shed_url:
@@ -1133,13 +1133,13 @@
pass
if tool_shed_url:
# We've received the textual representation of a workflow from a Galaxy tool shed.
- message = "Workflow <b>%s</b> imported successfully." % workflow.name
+ message = "Workflow <b>%s</b> imported successfully." % escape( workflow.name )
url = '%s/workflow/view_workflow?repository_metadata_id=%s&workflow_name=%s&message=%s' % \
( tool_shed_url, repository_metadata_id, encoding_util.tool_shed_encode( workflow_name ), message )
return trans.response.send_redirect( url )
elif installed_repository_file:
# The workflow was read from a file included with an installed tool shed repository.
- message = "Workflow <b>%s</b> imported successfully." % workflow.name
+ message = "Workflow <b>%s</b> imported successfully." % escape( workflow.name )
if cntrller == 'api':
return status, message
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
@@ -1184,7 +1184,7 @@
# Index page with message
workflow_id = trans.security.encode_id( stored_workflow.id )
return trans.show_message( 'Workflow "%s" created from current history. You can <a href="%s" target="_parent">edit</a> or <a href="%s">run</a> the workflow.' %
- ( workflow_name, url_for( controller='workflow', action='editor', id=workflow_id ),
+ ( escape( workflow_name ), url_for( controller='workflow', action='editor', id=workflow_id ),
url_for( controller='workflow', action='run', id=workflow_id ) ) )
@web.expose
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/embed_base.mako
--- a/templates/embed_base.mako
+++ b/templates/embed_base.mako
@@ -51,7 +51,7 @@
</div><h4><a class="toggle-embed" href="${display_href}" title="Show or hide ${item_display_name} content">Galaxy ${get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h}</a></h4>
%if hasattr( item, "annotation") and item.annotation:
- <div class="annotation">${item.annotation}</div>
+ <div class="annotation">${item.annotation | h}</div>
%endif
## Use a hidden var to store the ajax URL for getting an item's content.
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/ind_share_base.mako
--- a/templates/ind_share_base.mako
+++ b/templates/ind_share_base.mako
@@ -91,7 +91,7 @@
Email address of user to share with
</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="email" value="${email}" size="40">
+ <input type="text" name="email" value="${email | h}" size="40"></div><div style="clear: both"></div></div>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/user/dbkeys.mako
--- a/templates/user/dbkeys.mako
+++ b/templates/user/dbkeys.mako
@@ -148,7 +148,7 @@
Processing
% endif
</td>
- <td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key}" /><input type="submit" name="delete" value="Delete" /></form></td>
+ <td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key | h}" /><input type="submit" name="delete" value="Delete" /></form></td></tr>
% endfor
</table>
@@ -194,7 +194,7 @@
<div style="clear: both; padding-bottom: 0.5em"></div><select id="fasta_input" name="dataset_id">
%for dataset in fasta_hdas:
- <option value="${trans.security.encode_id( dataset.id )}">${dataset.hid}: ${dataset.name}</option>
+ <option value="${trans.security.encode_id( dataset.id )}">${dataset.hid | h}: ${dataset.name | h}</option>
%endfor
</select><input type="file" id="len_file_input" name="len_file" /></input>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/user/openid_associate.mako
--- a/templates/user/openid_associate.mako
+++ b/templates/user/openid_associate.mako
@@ -48,13 +48,13 @@
The following OpenIDs will be associated with the account chosen or created below.
<ul>
%for openid in openids:
- <li>${openid.openid}</li>
+ <li>${openid.openid | h}</li>
%endfor
</ul></div>
%else:
<div>
- The OpenID <strong>${openids[0].openid}</strong> will be associated with the account chosen or created.
+ The OpenID <strong>${openids[0].openid | h}</strong> will be associated with the account chosen or created.
</div>
%endif
<br/>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/user/toolbox_filters.mako
--- a/templates/user/toolbox_filters.mako
+++ b/templates/user/toolbox_filters.mako
@@ -15,7 +15,7 @@
%if tool_filters or section_filters or label_filters:
<div class="toolForm">
- <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
+ <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller )}" method="post" >
% if tool_filters:
<div class="toolFormTitle">Edit ToolBox filters :: Tools</div><div class="toolFormBody">
@@ -87,5 +87,5 @@
</form></div>
%else:
- ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )}
+ ${render_msg( 'No filters available. Contact your system administrator or check your configuration file.', 'info' )}
%endif
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/user/username.mako
--- a/templates/user/username.mako
+++ b/templates/user/username.mako
@@ -1,4 +1,9 @@
<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
<% is_admin = cntrller == 'admin' and trans.user_is_admin() %>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/root/tool_menu.mako
--- a/templates/webapps/galaxy/root/tool_menu.mako
+++ b/templates/webapps/galaxy/root/tool_menu.mako
@@ -82,7 +82,7 @@
%if t.user.stored_workflow_menu_entries:
%for m in t.user.stored_workflow_menu_entries:
<div class="toolTitle">
- <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(m.stored_workflow_id) )}" target="galaxy_main">${ util.unicodify( m.stored_workflow.name ) }</a>
+ <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(m.stored_workflow_id) )}" target="galaxy_main">${ util.unicodify( m.stored_workflow.name ) | h}</a></div>
%endfor
%endif
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/tool_executed.mako
--- a/templates/webapps/galaxy/tool_executed.mako
+++ b/templates/webapps/galaxy/tool_executed.mako
@@ -61,7 +61,7 @@
${jobs_str} been successfully added to the queue - resulting in the following ${datasets_str}:
</p>
%for _, data in out_data:
- <div style="padding: 10px"><b> ${data.hid}: ${data.name}</b></div>
+ <div style="padding: 10px"><b> ${data.hid}: ${data.name | h}</b></div>
%endfor
<p>
@@ -83,7 +83,7 @@
<ul><!-- Styling on this list is a little flat. Consider identing these error messages. -->
%for job_error in job_errors:
- <li><b>${job_error}</b></li>
+ <li><b>${job_error | h}</b></li>
%endfor
</ul></div>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/visualization/phyloviz.mako
--- a/templates/webapps/galaxy/visualization/phyloviz.mako
+++ b/templates/webapps/galaxy/visualization/phyloviz.mako
@@ -180,7 +180,6 @@
<%def name="center_panel()">
-
<div class="unified-panel-header" unselectable="on"><div class="unified-panel-header-inner"><div style="float:left;" id="title"></div>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/configure_menu.mako
--- a/templates/webapps/galaxy/workflow/configure_menu.mako
+++ b/templates/webapps/galaxy/workflow/configure_menu.mako
@@ -1,4 +1,5 @@
<%inherit file="/webapps/galaxy/base_panels.mako"/>
+<%page expression_filter="h"/><%def name="init()"><%
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/display.mako
--- a/templates/webapps/galaxy/workflow/display.mako
+++ b/templates/webapps/galaxy/workflow/display.mako
@@ -40,7 +40,7 @@
<%def name="row_for_param( param, value, other_values, prefix, step )"><% cls = "form-row" %><div class="${cls}">
- <label>${param.get_label()}</label>
+ <label>${param.get_label() | h}</label><div>
%if isinstance( param, DataToolParameter ) or isinstance( param, DataCollectionToolParameter ):
%if ( prefix + param.name ) in step.input_connections_by_name:
@@ -93,19 +93,19 @@
%><div class="toolForm">
%if tool:
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name | h}</div><div class="toolFormBody">
${do_inputs( tool.inputs, step.state.inputs, "", step )}
</div>
%else:
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: Unknown Tool with id '${step.tool_id}'</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: Unknown Tool with id '${step.tool_id | h}'</div>
%endif
</div>
%else:
## TODO: always input dataset?
<% module = step.module %><div class="toolForm">
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name}</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name | h}</div><div class="toolFormBody">
${do_inputs( module.get_runtime_inputs(), step.state.inputs, "", step )}
</div>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/list.mako
--- a/templates/webapps/galaxy/workflow/list.mako
+++ b/templates/webapps/galaxy/workflow/list.mako
@@ -94,7 +94,7 @@
<% workflow = association.stored_workflow %><tr><td>
- <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name )}</a>
+ <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a></td><td>${workflow.user.email}</td><td>${len(workflow.latest_workflow.steps)}</td>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/list_for_run.mako
--- a/templates/webapps/galaxy/workflow/list_for_run.mako
+++ b/templates/webapps/galaxy/workflow/list_for_run.mako
@@ -23,7 +23,7 @@
%for i, workflow in enumerate( workflows ):
<tr><td>
- <a href="${h.url_for(controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name )}</a>
+ <a href="${h.url_for(controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a><a id="wf-${i}-popup" class="popup-arrow" style="display: none;">▼</a></td><td>${len(workflow.latest_workflow.steps)}</td>
@@ -51,10 +51,10 @@
<% workflow = association.stored_workflow %><tr><td>
- <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name}</a>
+ <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a><a id="shared-${i}-popup" class="popup-arrow" style="display: none;">▼</a></td>
- <td>${workflow.user.email}</td>
+ <td>${workflow.user.email | h}</td><td>${len(workflow.latest_workflow.steps)}</td></tr>
%endfor
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/missing_tools.mako
--- a/templates/webapps/galaxy/workflow/missing_tools.mako
+++ b/templates/webapps/galaxy/workflow/missing_tools.mako
@@ -1,6 +1,6 @@
<%inherit file="/base.mako"/>
-<h2>Cannot run workflow "${h.to_unicode( workflow.name )}"</h2>
+<h2>Cannot run workflow "${h.to_unicode( workflow.name ) | h}"</h2>
%if workflow.annotation:
<div class="workflow-annotation">${workflow.annotation}</div>
@@ -11,7 +11,7 @@
<strong>This workflow utilizes tools which are unavailable, and cannot be run. Enable the tools listed below, or <a href="${h.url_for(controller='workflow', action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">edit the workflow</a> to correct these errors.</strong><br/><ul>
%for i, tool in enumerate( missing_tools ):
- <li>${tool}</li>
+ <li>${tool | h}</li>
%endfor
</ul></div>
\ No newline at end of file
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/myexp_export.mako
--- a/templates/webapps/galaxy/workflow/myexp_export.mako
+++ b/templates/webapps/galaxy/workflow/myexp_export.mako
@@ -9,7 +9,7 @@
## Generate request.
<?xml version="1.0"?><workflow>
- <title>${workflow_name}</title>
+ <title>${workflow_name | h}</title><description>${workflow_description}</description><type>Galaxy</type><content encoding="base64" type="binary">
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/rename.mako
--- a/templates/webapps/galaxy/workflow/rename.mako
+++ b/templates/webapps/galaxy/workflow/rename.mako
@@ -15,7 +15,7 @@
%endif
<div class="toolForm">
- <div class="toolFormTitle">Rename workflow '${stored.name}'</div>
+ <div class="toolFormTitle">Rename workflow '${stored.name | h}'</div><div class="toolFormBody"><form action="${h.url_for(controller='workflow', action='rename', id=trans.security.encode_id(stored.id) )}" method="POST"><div class="form-row">
@@ -23,7 +23,7 @@
New name
</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="new_name" value="${stored.name}" size="40">
+ <input type="text" name="new_name" value="${stored.name | h}" size="40"></div><div style="clear: both"></div></div>
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -372,7 +372,7 @@
<% cls = "form-row" %>
%endif
<div class="${cls}">
- <label>${param.get_label()}</label>
+ <label>${param.get_label() | h}</label><div>
%if isinstance( param, DataToolParameter ) or isinstance( param, DataCollectionToolParameter ):
%if ( prefix + param.name ) in step.input_connections_by_name:
@@ -444,7 +444,7 @@
%else:
<span class="workflow_parameters"><span class="uneditable_field">
- ${param.value_to_display_text( value, app )}
+ ${param.value_to_display_text( value, app ) | h}
</span><span class="editable_field"><span class="editable">
@@ -474,7 +474,7 @@
<span class="action-button" id="hide_all_tool_body">Collapse</span></div>
-<h2>Running workflow "${h.to_unicode( workflow.name )}"</h2>
+<h2>Running workflow "${h.to_unicode( workflow.name ) | h}"</h2>
%if has_upgrade_messages:
<div class="warningmessage">
@@ -574,6 +574,7 @@
<%
pja_ss_all = []
for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
+ pja_ss = h.escape( pja_ss )
for rematch in re.findall('\$\{.+?\}', pja_ss):
pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
pja_ss_all.append(pja_ss)
@@ -586,7 +587,7 @@
%else:
<div class="toolForm"><div class="toolFormTitle">
- <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
+ <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name | h}</span>
% if step.annotations:
<div class="step-annotation">${step.annotations[0].annotation}</div>
% endif
diff -r 8d8bce91a289e040d47f9b757aae4051a0501743 -r 511fbb67b820735128ee02e526fb6873beaa961e templates/webapps/galaxy/workflow/run_complete.mako
--- a/templates/webapps/galaxy/workflow/run_complete.mako
+++ b/templates/webapps/galaxy/workflow/run_complete.mako
@@ -1,4 +1,5 @@
<%inherit file="/base.mako"/>
+<%page expression_filter="h"/><div class="donemessagelarge">
%if scheduled:
@@ -7,7 +8,7 @@
<div class="workflow-invocation-complete">
%if invocation['new_history']:
<p>These datasets will appear in a new history:
- <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False )}">
+ <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False ) | n}">
'${h.to_unicode(invocation['new_history'].name)}'.
</a></p>
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
09 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ac30ccd5cd1e/
Changeset: ac30ccd5cd1e
Branch: next-stable
User: jmchilton
Date: 2014-12-09 14:14:54+00:00
Summary: Merge stable.
Affected #: 42 files
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-acb2548443ae42d39ef200d035ccc0481d6b930c latest_2014.10.06
+782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 latest_2014.10.06
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/security/validate_user_input.py
--- a/lib/galaxy/security/validate_user_input.py
+++ b/lib/galaxy/security/validate_user_input.py
@@ -1,3 +1,9 @@
+"""
+Utilities for validating inputs related to user objects.
+
+The validate_* methods in this file return simple messages that do not contain
+user inputs - so these methods do not need to be escaped.
+"""
import logging
import re
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -67,6 +67,7 @@
from galaxy.util.template import fill_template
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
+from galaxy.web.framework.helpers import escape
from galaxy.model.item_attrs import Dictifiable
from galaxy.model import Workflow
from tool_shed.util import common_util
@@ -791,7 +792,7 @@
success = True
# Make sure the tool is actually loaded.
if tool_id not in self.tools_by_id:
- return None, False, "No tool with id %s" % tool_id
+ return None, False, "No tool with id %s" % escape( tool_id )
else:
tool = self.tools_by_id[ tool_id ]
tarball_files = []
@@ -902,7 +903,7 @@
replace the old tool.
"""
if tool_id not in self.tools_by_id:
- message = "No tool with id %s" % tool_id
+ message = "No tool with id %s" % escape( tool_id )
status = 'error'
else:
old_tool = self.tools_by_id[ tool_id ]
@@ -939,7 +940,7 @@
Attempt to remove the tool identified by 'tool_id'.
"""
if tool_id not in self.tools_by_id:
- message = "No tool with id %s" % tool_id
+ message = "No tool with id %s" % escape( tool_id )
status = 'error'
else:
tool = self.tools_by_id[ tool_id ]
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -1,6 +1,10 @@
+import logging
from galaxy.util import listify
from copy import deepcopy
+log = logging.getLogger( __name__ )
+
+
class FilterFactory( object ):
"""
An instance of this class is responsible for filtering the list
@@ -37,17 +41,21 @@
elif name == 'toolbox_label_filters':
category = "label"
if category:
- self.__init_filters( category, user_filters, filters )
+ validate = getattr( trans.app.config, 'user_%s_filters' % category, [] )
+ self.__init_filters( category, user_filters, filters, validate=validate )
else:
if kwds.get( "trackster", False ):
filters[ "tool" ].append( _has_trackster_conf )
return filters
- def __init_filters( self, key, filters, toolbox_filters ):
+ def __init_filters( self, key, filters, toolbox_filters, validate=None ):
for filter in filters:
- filter_function = self.__build_filter_function( filter )
- toolbox_filters[ key ].append( filter_function )
+ if validate is None or filter in validate or filter in self.default_filters:
+ filter_function = self.__build_filter_function( filter )
+ toolbox_filters[ key ].append( filter_function )
+ else:
+ log.warning( "Refusing to load %s filter '%s' which is not defined in config", key, filter )
return toolbox_filters
def __build_filter_function( self, filter_name ):
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -1664,7 +1664,8 @@
stored.user = trans.user
stored.published = publish
if data[ 'annotation' ]:
- self.add_item_annotation( trans.sa_session, stored.user, stored, data[ 'annotation' ] )
+ annotation = sanitize_html( data[ 'annotation' ], 'utf-8', 'text/html' )
+ self.add_item_annotation( trans.sa_session, stored.user, stored, annotation )
# Persist
trans.sa_session.add( stored )
@@ -2571,6 +2572,8 @@
def set_public_username( self, trans, id, username, **kwargs ):
""" Set user's public username and delegate to sharing() """
user = trans.get_user()
+ # message from validate_publicname does not contain input, no need
+ # to escape.
message = validate_publicname( trans, username, user )
if message:
return trans.fill_template( '/sharing_base.mako', item=self.get_item( trans, id ), message=message, status='error' )
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/web/form_builder.py
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -563,7 +563,7 @@
html += '<input name="__switch_default__" type="hidden" value="%s" />' % self.default_field
options = []
for name, delegate_field in self.delegate_fields.items():
- field = dumps( delegate_field.to_dict() )
+ field = escape( dumps( delegate_field.to_dict() ) )
option = " '%s': %s" % ( name, field )
options.append( option )
html += '<script>$(document).ready( function() {\nvar switchOptions = {\n'
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -718,7 +718,9 @@
for husa in husas:
trans.sa_session.delete( husa )
if not deleted_sharing_relation:
- message = "History '%s' does not seem to be shared with user '%s'" % ( history.name, user.email )
+ history_name = escape( history.name )
+ user_email = escape( user.email )
+ message = "History '%s' does not seem to be shared with user '%s'" % ( history_name, user_email )
return trans.fill_template( '/sharing_base.mako', item=history,
message=message, status='error' )
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/webapps/galaxy/controllers/mobile.py
--- a/lib/galaxy/webapps/galaxy/controllers/mobile.py
+++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py
@@ -1,60 +1,71 @@
+from galaxy import web
from galaxy.web.base.controller import *
+
class Mobile( BaseUIController ):
+
@web.expose
def index( self, trans, **kwargs ):
- return trans.fill_template( "mobile/index.mako" )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # return trans.fill_template( "mobile/index.mako" )
@web.expose
def history_list( self, trans ):
- return trans.fill_template( "mobile/history/list.mako" )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # return trans.fill_template( "mobile/history/list.mako" )
@web.expose
def history_detail( self, trans, id ):
- history = trans.sa_session.query( trans.app.model.History ).get( id )
- assert history.user == trans.user
- return trans.fill_template( "mobile/history/detail.mako", history=history )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # history = trans.sa_session.query( trans.app.model.History ).get( id )
+ # assert history.user == trans.user
+ # return trans.fill_template( "mobile/history/detail.mako", history=history )
@web.expose
def dataset_detail( self, trans, id ):
- dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
- assert dataset.history.user == trans.user
- return trans.fill_template( "mobile/dataset/detail.mako", dataset=dataset )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
+ # assert dataset.history.user == trans.user
+ # return trans.fill_template( "mobile/dataset/detail.mako", dataset=dataset )
@web.expose
def dataset_peek( self, trans, id ):
- dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
- assert dataset.history.user == trans.user
- return trans.fill_template( "mobile/dataset/peek.mako", dataset=dataset )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
+ # assert dataset.history.user == trans.user
+ # return trans.fill_template( "mobile/dataset/peek.mako", dataset=dataset )
@web.expose
def settings( self, trans, email=None, password=None ):
- message = None
- if email is not None and password is not None:
- if email == "":
- self.__logout( trans )
- message = "Logged out"
- else:
- error = self.__login( trans, email, password )
- message = error or "Login changed"
- return trans.fill_template( "mobile/settings.mako", message=message )
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # message = None
+ # if email is not None and password is not None:
+ # if email == "":
+ # self.__logout( trans )
+ # message = "Logged out"
+ # else:
+ # error = self.__login( trans, email, password )
+ # message = error or "Login changed"
+ # return trans.fill_template( "mobile/settings.mako", message=message )
def __logout( self, trans ):
- trans.log_event( "User logged out" )
- trans.handle_user_logout()
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # trans.log_event( "User logged out" )
+ # trans.handle_user_logout()
def __login( self, trans, email="", password="" ):
- error = password_error = None
- user = trans.sa_session.query( model.User ).filter_by( email = email ).first()
- if not user:
- error = "No such user (please note that login is case sensitive)"
- elif user.deleted:
- error = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
- elif user.external:
- error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
- elif not user.check_password( password ):
- error = "Invalid password"
- else:
- trans.handle_user_login( user )
- trans.log_event( "User logged in" )
- return error
+ return trans.response.send_redirect( web.url_for(controller='root', action='index' ) )
+ # error = password_error = None
+ # user = trans.sa_session.query( model.User ).filter_by( email = email ).first()
+ # if not user:
+ # error = "No such user (please note that login is case sensitive)"
+ # elif user.deleted:
+ # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
+ # elif user.external:
+ # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
+ # elif not user.check_password( password ):
+ # error = "Invalid password"
+ # else:
+ # trans.handle_user_login( user )
+ # trans.log_event( "User logged in" )
+ # return error
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -500,14 +500,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a page with yourself" )
elif trans.sa_session.query( model.PageUserShareAssociation ) \
.filter_by( user=other, page=page ).count() > 0:
mtype = "error"
- msg = ( "Page already shared with '%s'" % email )
+ msg = ( "Page already shared with '%s'" % escape( email ) )
else:
share = model.PageUserShareAssociation()
share.page = page
@@ -516,7 +516,9 @@
session.add( share )
self.create_item_slug( session, page )
session.flush()
- trans.set_message( "Page '%s' shared with user '%s'" % ( page.title, other.email ) )
+ page_title = escape( page.title )
+ other_email = escape( other.email )
+ trans.set_message( "Page '%s' shared with user '%s'" % ( page_title, other_email ) )
return trans.response.send_redirect( url_for( controller='page', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message = msg,
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -535,14 +535,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a visualization with yourself" )
elif trans.sa_session.query( model.VisualizationUserShareAssociation ) \
.filter_by( user=other, visualization=visualization ).count() > 0:
mtype = "error"
- msg = ( "Visualization already shared with '%s'" % email )
+ msg = ( "Visualization already shared with '%s'" % escape( email ) )
else:
share = model.VisualizationUserShareAssociation()
share.visualization = visualization
@@ -551,7 +551,9 @@
session.add( share )
self.create_item_slug( session, visualization )
session.flush()
- trans.set_message( "Visualization '%s' shared with user '%s'" % ( visualization.title, other.email ) )
+ viz_title = escape( visualization.title )
+ other_email = escape( other.email )
+ trans.set_message( "Visualization '%s' shared with user '%s'" % ( viz_title, other_email ) )
return trans.response.send_redirect( web.url_for(controller='visualization', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message = msg,
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -310,14 +310,14 @@
.first()
if not other:
mtype = "error"
- msg = ( "User '%s' does not exist" % email )
+ msg = ( "User '%s' does not exist" % escape( email ) )
elif other == trans.get_user():
mtype = "error"
msg = ( "You cannot share a workflow with yourself" )
elif trans.sa_session.query( model.StoredWorkflowUserShareAssociation ) \
.filter_by( user=other, stored_workflow=stored ).count() > 0:
mtype = "error"
- msg = ( "Workflow already shared with '%s'" % email )
+ msg = ( "Workflow already shared with '%s'" % escape( email ) )
else:
share = model.StoredWorkflowUserShareAssociation()
share.stored_workflow = stored
@@ -325,7 +325,7 @@
session = trans.sa_session
session.add( share )
session.flush()
- trans.set_message( "Workflow '%s' shared with user '%s'" % ( stored.name, other.email ) )
+ trans.set_message( "Workflow '%s' shared with user '%s'" % ( escape( stored.name ), escape( other.email ) ) )
return trans.response.send_redirect( url_for( controller='workflow', action='sharing', id=id ) )
return trans.fill_template( "/ind_share_base.mako",
message=msg,
@@ -436,7 +436,7 @@
stored.latest_workflow.name = san_new_name
trans.sa_session.flush()
# For current workflows grid:
- trans.set_message( "Workflow renamed to '%s'." % new_name )
+ trans.set_message( "Workflow renamed to '%s'." % san_new_name )
return self.list( trans )
# For new workflows grid:
#message = "Workflow renamed to '%s'." % new_name
@@ -556,7 +556,7 @@
session.add( new_stored )
session.flush()
# Display the management page
- trans.set_message( 'Created new workflow with name "%s"' % new_stored.name )
+ trans.set_message( 'Created new workflow with name "%s"' % escape( new_stored.name ) )
return self.list( trans )
@web.expose
@@ -603,7 +603,7 @@
trans.sa_session.add( stored )
trans.sa_session.flush()
# Display the management page
- trans.set_message( "Workflow '%s' deleted" % stored.name )
+ trans.set_message( "Workflow '%s' deleted" % escape( stored.name ) )
return self.list( trans )
@web.expose
@@ -1110,7 +1110,7 @@
message += "Imported, but this workflow contains cycles. "
status = "error"
else:
- message += "Workflow <b>%s</b> imported successfully. " % workflow.name
+ message += "Workflow <b>%s</b> imported successfully. " % escape( workflow.name )
if missing_tool_tups:
if trans.user_is_admin():
# A required tool is not available in the local Galaxy instance.
@@ -1124,7 +1124,7 @@
message += "You can likely install the required tools from one of the Galaxy tool sheds listed below.<br/>"
for missing_tool_tup in missing_tool_tups:
missing_tool_id, missing_tool_name, missing_tool_version = missing_tool_tup
- message += "<b>Tool name</b> %s, <b>id</b> %s, <b>version</b> %s<br/>" % ( missing_tool_name, missing_tool_id, missing_tool_version )
+ message += "<b>Tool name</b> %s, <b>id</b> %s, <b>version</b> %s<br/>" % ( escape( missing_tool_name ), escape( missing_tool_id ), escape( missing_tool_version ) )
message += "<br/>"
for shed_name, shed_url in trans.app.tool_shed_registry.tool_sheds.items():
if shed_url.endswith( '/' ):
@@ -1134,7 +1134,7 @@
url += '&tool_id='
for missing_tool_tup in missing_tool_tups:
missing_tool_id = missing_tool_tup[0]
- url += '%s,' % missing_tool_id
+ url += '%s,' % escape( missing_tool_id )
message += '<a href="%s">%s</a><br/>' % ( url, shed_name )
status = 'error'
if installed_repository_file or tool_shed_url:
@@ -1154,13 +1154,13 @@
pass
if tool_shed_url:
# We've received the textual representation of a workflow from a Galaxy tool shed.
- message = "Workflow <b>%s</b> imported successfully." % workflow.name
+ message = "Workflow <b>%s</b> imported successfully." % escape( workflow.name )
url = '%s/workflow/view_workflow?repository_metadata_id=%s&workflow_name=%s&message=%s' % \
( tool_shed_url, repository_metadata_id, encoding_util.tool_shed_encode( workflow_name ), message )
return trans.response.send_redirect( url )
elif installed_repository_file:
# The workflow was read from a file included with an installed tool shed repository.
- message = "Workflow <b>%s</b> imported successfully." % workflow.name
+ message = "Workflow <b>%s</b> imported successfully." % escape( workflow.name )
if cntrller == 'api':
return status, message
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
@@ -1205,7 +1205,7 @@
# Index page with message
workflow_id = trans.security.encode_id( stored_workflow.id )
return trans.show_message( 'Workflow "%s" created from current history. You can <a href="%s" target="_parent">edit</a> or <a href="%s">run</a> the workflow.' %
- ( workflow_name, url_for( controller='workflow', action='editor', id=workflow_id ),
+ ( escape( workflow_name ), url_for( controller='workflow', action='editor', id=workflow_id ),
url_for( controller='workflow', action='run', id=workflow_id ) ) )
@web.expose
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/embed_base.mako
--- a/templates/embed_base.mako
+++ b/templates/embed_base.mako
@@ -51,7 +51,7 @@
</div><h4><a class="toggle-embed" href="${display_href}" title="Show or hide ${item_display_name} content">Galaxy ${get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h}</a></h4>
%if hasattr( item, "annotation") and item.annotation:
- <div class="annotation">${item.annotation}</div>
+ <div class="annotation">${item.annotation | h}</div>
%endif
## Use a hidden var to store the ajax URL for getting an item's content.
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/ind_share_base.mako
--- a/templates/ind_share_base.mako
+++ b/templates/ind_share_base.mako
@@ -91,7 +91,7 @@
Email address of user to share with
</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="email" value="${email}" size="40">
+ <input type="text" name="email" value="${email | h}" size="40"></div><div style="clear: both"></div></div>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/user/dbkeys.mako
--- a/templates/user/dbkeys.mako
+++ b/templates/user/dbkeys.mako
@@ -148,7 +148,7 @@
Processing
% endif
</td>
- <td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key}" /><input type="submit" name="delete" value="Delete" /></form></td>
+ <td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key | h}" /><input type="submit" name="delete" value="Delete" /></form></td></tr>
% endfor
</table>
@@ -194,7 +194,7 @@
<div style="clear: both; padding-bottom: 0.5em"></div><select id="fasta_input" name="dataset_id">
%for dataset in fasta_hdas:
- <option value="${trans.security.encode_id( dataset.id )}">${dataset.hid}: ${dataset.name}</option>
+ <option value="${trans.security.encode_id( dataset.id )}">${dataset.hid | h}: ${dataset.name | h}</option>
%endfor
</select><input type="file" id="len_file_input" name="len_file" /></input>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/user/openid_associate.mako
--- a/templates/user/openid_associate.mako
+++ b/templates/user/openid_associate.mako
@@ -48,13 +48,13 @@
The following OpenIDs will be associated with the account chosen or created below.
<ul>
%for openid in openids:
- <li>${openid.openid}</li>
+ <li>${openid.openid | h}</li>
%endfor
</ul></div>
%else:
<div>
- The OpenID <strong>${openids[0].openid}</strong> will be associated with the account chosen or created.
+ The OpenID <strong>${openids[0].openid | h}</strong> will be associated with the account chosen or created.
</div>
%endif
<br/>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/user/toolbox_filters.mako
--- a/templates/user/toolbox_filters.mako
+++ b/templates/user/toolbox_filters.mako
@@ -15,7 +15,7 @@
%if tool_filters or section_filters or label_filters:
<div class="toolForm">
- <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
+ <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller )}" method="post" >
% if tool_filters:
<div class="toolFormTitle">Edit ToolBox filters :: Tools</div><div class="toolFormBody">
@@ -87,5 +87,5 @@
</form></div>
%else:
- ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )}
+ ${render_msg( 'No filters available. Contact your system administrator or check your configuration file.', 'info' )}
%endif
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/user/username.mako
--- a/templates/user/username.mako
+++ b/templates/user/username.mako
@@ -1,4 +1,9 @@
<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
<% is_admin = cntrller == 'admin' and trans.user_is_admin() %>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/root/tool_menu.mako
--- a/templates/webapps/galaxy/root/tool_menu.mako
+++ b/templates/webapps/galaxy/root/tool_menu.mako
@@ -82,7 +82,7 @@
%if t.user.stored_workflow_menu_entries:
%for m in t.user.stored_workflow_menu_entries:
<div class="toolTitle">
- <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(m.stored_workflow_id) )}" target="galaxy_main">${ util.unicodify( m.stored_workflow.name ) }</a>
+ <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(m.stored_workflow_id) )}" target="galaxy_main">${ util.unicodify( m.stored_workflow.name ) | h}</a></div>
%endfor
%endif
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/tool_executed.mako
--- a/templates/webapps/galaxy/tool_executed.mako
+++ b/templates/webapps/galaxy/tool_executed.mako
@@ -61,7 +61,7 @@
${jobs_str} been successfully added to the queue - resulting in the following ${datasets_str}:
</p>
%for _, data in out_data:
- <div style="padding: 10px"><b> ${data.hid}: ${data.name}</b></div>
+ <div style="padding: 10px"><b> ${data.hid}: ${data.name | h}</b></div>
%endfor
<p>
@@ -83,7 +83,7 @@
<ul><!-- Styling on this list is a little flat. Consider identing these error messages. -->
%for job_error in job_errors:
- <li><b>${job_error}</b></li>
+ <li><b>${job_error | h}</b></li>
%endfor
</ul></div>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/visualization/phyloviz.mako
--- a/templates/webapps/galaxy/visualization/phyloviz.mako
+++ b/templates/webapps/galaxy/visualization/phyloviz.mako
@@ -180,7 +180,6 @@
<%def name="center_panel()">
-
<div class="unified-panel-header" unselectable="on"><div class="unified-panel-header-inner"><div style="float:left;" id="title"></div>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/configure_menu.mako
--- a/templates/webapps/galaxy/workflow/configure_menu.mako
+++ b/templates/webapps/galaxy/workflow/configure_menu.mako
@@ -1,4 +1,5 @@
<%inherit file="/webapps/galaxy/base_panels.mako"/>
+<%page expression_filter="h"/><%def name="init()"><%
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/display.mako
--- a/templates/webapps/galaxy/workflow/display.mako
+++ b/templates/webapps/galaxy/workflow/display.mako
@@ -40,7 +40,7 @@
<%def name="row_for_param( param, value, other_values, prefix, step )"><% cls = "form-row" %><div class="${cls}">
- <label>${param.get_label()}</label>
+ <label>${param.get_label() | h}</label><div>
%if isinstance( param, DataToolParameter ) or isinstance( param, DataCollectionToolParameter ):
%if ( prefix + param.name ) in step.input_connections_by_name:
@@ -93,19 +93,19 @@
%><div class="toolForm">
%if tool:
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name | h}</div><div class="toolFormBody">
${do_inputs( tool.inputs, step.state.inputs, "", step )}
</div>
%else:
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: Unknown Tool with id '${step.tool_id}'</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: Unknown Tool with id '${step.tool_id | h}'</div>
%endif
</div>
%else:
## TODO: always input dataset?
<% module = step.module %><div class="toolForm">
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name}</div>
+ <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name | h}</div><div class="toolFormBody">
${do_inputs( module.get_runtime_inputs(), step.state.inputs, "", step )}
</div>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/list.mako
--- a/templates/webapps/galaxy/workflow/list.mako
+++ b/templates/webapps/galaxy/workflow/list.mako
@@ -94,7 +94,7 @@
<% workflow = association.stored_workflow %><tr><td>
- <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name )}</a>
+ <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a></td><td>${workflow.user.email}</td><td>${len(workflow.latest_workflow.steps)}</td>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/list_for_run.mako
--- a/templates/webapps/galaxy/workflow/list_for_run.mako
+++ b/templates/webapps/galaxy/workflow/list_for_run.mako
@@ -36,7 +36,7 @@
%for i, workflow in enumerate( workflows ):
<tr><td>
- <a href="${h.url_for(controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name )}</a>
+ <a href="${h.url_for(controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a><a id="wf-${i}-popup" class="popup-arrow" style="display: none;">▼</a></td><td>${len(workflow.latest_workflow.steps)}</td>
@@ -64,10 +64,10 @@
<% workflow = association.stored_workflow %><tr><td>
- <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name}</a>
+ <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a><a id="shared-${i}-popup" class="popup-arrow" style="display: none;">▼</a></td>
- <td>${workflow.user.email}</td>
+ <td>${workflow.user.email | h}</td><td>${len(workflow.latest_workflow.steps)}</td></tr>
%endfor
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/missing_tools.mako
--- a/templates/webapps/galaxy/workflow/missing_tools.mako
+++ b/templates/webapps/galaxy/workflow/missing_tools.mako
@@ -1,6 +1,6 @@
<%inherit file="/base.mako"/>
-<h2>Cannot run workflow "${h.to_unicode( workflow.name )}"</h2>
+<h2>Cannot run workflow "${h.to_unicode( workflow.name ) | h}"</h2>
%if workflow.annotation:
<div class="workflow-annotation">${workflow.annotation}</div>
@@ -11,7 +11,7 @@
<strong>This workflow utilizes tools which are unavailable, and cannot be run. Enable the tools listed below, or <a href="${h.url_for(controller='workflow', action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">edit the workflow</a> to correct these errors.</strong><br/><ul>
%for i, tool in enumerate( missing_tools ):
- <li>${tool}</li>
+ <li>${tool | h}</li>
%endfor
</ul></div>
\ No newline at end of file
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/myexp_export.mako
--- a/templates/webapps/galaxy/workflow/myexp_export.mako
+++ b/templates/webapps/galaxy/workflow/myexp_export.mako
@@ -9,7 +9,7 @@
## Generate request.
<?xml version="1.0"?><workflow>
- <title>${workflow_name}</title>
+ <title>${workflow_name | h}</title><description>${workflow_description}</description><type>Galaxy</type><content encoding="base64" type="binary">
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/rename.mako
--- a/templates/webapps/galaxy/workflow/rename.mako
+++ b/templates/webapps/galaxy/workflow/rename.mako
@@ -15,7 +15,7 @@
%endif
<div class="toolForm">
- <div class="toolFormTitle">Rename workflow '${stored.name}'</div>
+ <div class="toolFormTitle">Rename workflow '${stored.name | h}'</div><div class="toolFormBody"><form action="${h.url_for(controller='workflow', action='rename', id=trans.security.encode_id(stored.id) )}" method="POST"><div class="form-row">
@@ -23,7 +23,7 @@
New name
</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="new_name" value="${stored.name}" size="40">
+ <input type="text" name="new_name" value="${stored.name | h}" size="40"></div><div style="clear: both"></div></div>
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -372,7 +372,7 @@
<% cls = "form-row" %>
%endif
<div class="${cls}">
- <label>${param.get_label()}</label>
+ <label>${param.get_label() | h}</label><div>
%if isinstance( param, DataToolParameter ) or isinstance( param, DataCollectionToolParameter ):
%if ( prefix + param.name ) in step.input_connections_by_name:
@@ -444,7 +444,7 @@
%else:
<span class="workflow_parameters"><span class="uneditable_field">
- ${param.value_to_display_text( value, app )}
+ ${param.value_to_display_text( value, app ) | h}
</span><span class="editable_field"><span class="editable">
@@ -474,7 +474,7 @@
<span class="action-button" id="hide_all_tool_body">Collapse</span></div>
-<h2>Running workflow "${h.to_unicode( workflow.name )}"</h2>
+<h2>Running workflow "${h.to_unicode( workflow.name ) | h}"</h2>
%if has_upgrade_messages:
<div class="warningmessage">
@@ -574,6 +574,7 @@
<%
pja_ss_all = []
for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
+ pja_ss = h.escape( pja_ss )
for rematch in re.findall('\$\{.+?\}', pja_ss):
pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
pja_ss_all.append(pja_ss)
@@ -586,7 +587,7 @@
%else:
<div class="toolForm"><div class="toolFormTitle">
- <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
+ <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name | h}</span>
% if step.annotations:
<div class="step-annotation">${step.annotations[0].annotation}</div>
% endif
diff -r 49ef0cdbf45acca661900c22869f33cd01536ecf -r ac30ccd5cd1e285390706592a0b005f79456cbac templates/webapps/galaxy/workflow/run_complete.mako
--- a/templates/webapps/galaxy/workflow/run_complete.mako
+++ b/templates/webapps/galaxy/workflow/run_complete.mako
@@ -1,4 +1,5 @@
<%inherit file="/base.mako"/>
+<%page expression_filter="h"/><div class="donemessagelarge">
%if scheduled:
@@ -7,7 +8,7 @@
<div class="workflow-invocation-complete">
%if invocation['new_history']:
<p>These datasets will appear in a new history:
- <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False )}">
+ <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False ) | n}">
'${h.to_unicode(invocation['new_history'].name)}'.
</a></p>
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Update tag latest_2014.10.06 for changeset 782cf1a1f6b5
by commits-noreply@bitbucket.org 09 Dec '14
by commits-noreply@bitbucket.org 09 Dec '14
09 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3e3ac0894aba/
Changeset: 3e3ac0894aba
Branch: stable
User: natefoo
Date: 2014-12-09 14:00:15+00:00
Summary: Update tag latest_2014.10.06 for changeset 782cf1a1f6b5
Affected #: 1 file
diff -r 782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 -r 3e3ac0894aba44bba95bce6dd6833e639e01f890 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-8e45b1cefba16727d4d3a7d0dceaaaf1ef400a0c latest_2014.10.06
+782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 latest_2014.10.06
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: martenson: show wrapper versions and requirement versions in the toolform header
by commits-noreply@bitbucket.org 08 Dec '14
by commits-noreply@bitbucket.org 08 Dec '14
08 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8d8bce91a289/
Changeset: 8d8bce91a289
User: martenson
Date: 2014-12-08 22:07:58+00:00
Summary: show wrapper versions and requirement versions in the toolform header
Affected #: 1 file
diff -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 -r 8d8bce91a289e040d47f9b757aae4051a0501743 templates/webapps/galaxy/tool_form.mako
--- a/templates/webapps/galaxy/tool_form.mako
+++ b/templates/webapps/galaxy/tool_form.mako
@@ -353,10 +353,25 @@
%if tool.has_multiple_pages:
<div class="toolFormTitle">${tool.name} (step ${tool_state.page+1} of ${tool.npages})
%elif not tool_version_select_field:
- <div class="toolFormTitle">${tool.name} (version ${tool.version})
+ <div class="toolFormTitle">${tool.name} (Galaxy tool version ${tool.version})
%else:
<div class="toolFormTitle">${tool.name} ${tool_version_select_field.get_html()}
%endif
+ ## Show information button with underlying requirements and their versions
+ %if tool.requirements:
+ <a href="#" class="icon-btn" title="Underlying versions" tabindex="0" data-toggle="popover" data-placement="bottom" data-content=
+ "
+ %for i, requirement in enumerate( tool.requirements ):
+ ${ requirement.name } v ${ requirement.version } ${ '' if i + 1 == len( tool.requirements ) else ' | ' }
+ %endfor
+ "
+ onclick="$(function () {
+ $( '[ data-toggle=\'popover\' ]' ).popover();
+ $( this ).popover( 'show' );
+ })">
+ <span class="fa fa-info-circle"></span>
+ </a>
+ %endif
<span class="pull-right">
%if trans.app.config.biostar_url:
@@ -442,4 +457,4 @@
<div id="citations"></div>
%endif
-</div>
\ No newline at end of file
+</div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Merged in carlfeberhard/carlfeberhard-galaxy-central-stable/stable (pull request #600)
by commits-noreply@bitbucket.org 08 Dec '14
by commits-noreply@bitbucket.org 08 Dec '14
08 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/782cf1a1f6b5/
Changeset: 782cf1a1f6b5
Branch: stable
User: dannon
Date: 2014-12-08 22:06:25+00:00
Summary: Merged in carlfeberhard/carlfeberhard-galaxy-central-stable/stable (pull request #600)
[STABLE] Fix to 04a072e to use the correct mako method in the masthead.
Affected #: 1 file
diff -r 07404a82972d877b5529fffaeb3e7e05b69a02a3 -r 782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -1,4 +1,4 @@
-<%namespace file="/galaxy_client_app.mako" import="get_user_json" />
+<%namespace file="/galaxy_client_app.mako" import="get_user_dict" />
## masthead head generator
<%def name="load(active_view = None)">
@@ -34,7 +34,7 @@
'requests' : bool(trans.user and (trans.user.requests or trans.app.security_agent.get_accessible_request_types(trans, trans.user))),
'email' : trans.user.email if (trans.user) else "",
'valid' : bool(trans.user != None),
- 'json' : get_user_json()
+ 'json' : get_user_dict()
}
}
%>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/030db20e2f4f/
Changeset: 030db20e2f4f
Branch: stable
User: carlfeberhard
Date: 2014-12-08 21:47:33+00:00
Summary: Fix to 04a072e: use proper mako dict method instead of printing json string
Affected #: 1 file
diff -r 374e94196a14673993540a60d446addc6b1780a0 -r 030db20e2f4f15d63f622ccdd224d65214cb8d7a templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -1,4 +1,4 @@
-<%namespace file="/galaxy_client_app.mako" import="get_user_json" />
+<%namespace file="/galaxy_client_app.mako" import="get_user_dict" />
## masthead head generator
<%def name="load(active_view = None)">
@@ -34,7 +34,7 @@
'requests' : bool(trans.user and (trans.user.requests or trans.app.security_agent.get_accessible_request_types(trans, trans.user))),
'email' : trans.user.email if (trans.user) else "",
'valid' : bool(trans.user != None),
- 'json' : get_user_json()
+ 'json' : get_user_dict()
}
}
%>
https://bitbucket.org/galaxy/galaxy-central/commits/782cf1a1f6b5/
Changeset: 782cf1a1f6b5
Branch: stable
User: dannon
Date: 2014-12-08 22:06:25+00:00
Summary: Merged in carlfeberhard/carlfeberhard-galaxy-central-stable/stable (pull request #600)
[STABLE] Fix to 04a072e to use the correct mako method in the masthead.
Affected #: 1 file
diff -r 07404a82972d877b5529fffaeb3e7e05b69a02a3 -r 782cf1a1f6b56f8a9c0b3e5e9ffd29fd93b16ce3 templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -1,4 +1,4 @@
-<%namespace file="/galaxy_client_app.mako" import="get_user_json" />
+<%namespace file="/galaxy_client_app.mako" import="get_user_dict" />
## masthead head generator
<%def name="load(active_view = None)">
@@ -34,7 +34,7 @@
'requests' : bool(trans.user and (trans.user.requests or trans.app.security_agent.get_accessible_request_types(trans, trans.user))),
'email' : trans.user.email if (trans.user) else "",
'valid' : bool(trans.user != None),
- 'json' : get_user_json()
+ 'json' : get_user_dict()
}
}
%>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Client build: modularize mode-button plugin from ui.js; update history/multi-view.js and history/view.mako
by commits-noreply@bitbucket.org 08 Dec '14
by commits-noreply@bitbucket.org 08 Dec '14
08 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8e98c3d9b9a8/
Changeset: 8e98c3d9b9a8
User: carlfeberhard
Date: 2014-12-08 21:34:09+00:00
Summary: Client build: modularize mode-button plugin from ui.js; update history/multi-view.js and history/view.mako
Affected #: 10 files
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 client/galaxy/scripts/jq-plugins/ui/mode-button.js
--- /dev/null
+++ b/client/galaxy/scripts/jq-plugins/ui/mode-button.js
@@ -0,0 +1,191 @@
+// from: https://raw.githubusercontent.com/umdjs/umd/master/jqueryPlugin.js
+// Uses AMD or browser globals to create a jQuery plugin.
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ //TODO: So...this turns out to be an all or nothing thing. If I load jQuery in the define below, it will
+ // (of course) wipe the old jquery *and all the plugins loaded into it*. So the define below *is still
+ // relying on jquery being loaded globally* in order to preserve plugins.
+ define([], factory);
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+
+}(function () {
+
+ /** Multi 'mode' button (or any element really) that changes the html
+ * contents of itself when clicked. Pass in an ordered list of
+ * objects with 'html' and (optional) onclick functions.
+ *
+ * When clicked in a particular node, the onclick function will
+ * be called (with the element as this) and the element will
+ * switch to the next mode, replacing its html content with
+ * that mode's html.
+ *
+ * If there is no next mode, the element will switch back to
+ * the first mode.
+ * @example:
+ * $( '.myElement' ).modeButton({
+ * modes : [
+ * {
+ * mode: 'bler',
+ * html: '<h5>Bler</h5>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'red' );
+ * }
+ * },
+ * {
+ * mode: 'bloo',
+ * html: '<h4>Bloo</h4>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'blue' );
+ * }
+ * },
+ * {
+ * mode: 'blah',
+ * html: '<h3>Blah</h3>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'grey' );
+ * }
+ * },
+ * ]
+ * });
+ * $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
+ */
+ /** constructor */
+ function ModeButton( element, options ){
+ this.currModeIndex = 0;
+ return this._init( element, options );
+ }
+
+ /** html5 data key to store this object inside an element */
+ ModeButton.prototype.DATA_KEY = 'mode-button';
+ /** default options */
+ ModeButton.prototype.defaults = {
+ switchModesOnClick : true
+ };
+
+ // ---- private interface
+ /** set up options, intial mode, and the click handler */
+ ModeButton.prototype._init = function _init( element, options ){
+ //console.debug( 'ModeButton._init:', element, options );
+ options = options || {};
+ this.$element = $( element );
+ this.options = $.extend( true, {}, this.defaults, options );
+ if( !options.modes ){
+ throw new Error( 'ModeButton requires a "modes" array' );
+ }
+
+ var modeButton = this;
+ this.$element.click( function _ModeButtonClick( event ){
+ // call the curr mode fn
+ modeButton.callModeFn();
+ // inc the curr mode index
+ if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
+ // set the element html
+ $( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
+ });
+ return this.reset();
+ };
+ /** increment the mode index to the next in the array, looping back to zero if at the last */
+ ModeButton.prototype._incModeIndex = function _incModeIndex(){
+ this.currModeIndex += 1;
+ if( this.currModeIndex >= this.options.modes.length ){
+ this.currModeIndex = 0;
+ }
+ return this;
+ };
+ /** get the mode index in the modes array for the given key (mode name) */
+ ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
+ for( var i=0; i<this.options.modes.length; i+=1 ){
+ if( this.options.modes[ i ].mode === modeKey ){ return i; }
+ }
+ throw new Error( 'mode not found: ' + modeKey );
+ };
+ /** set the current mode to the one with the given index and set button html */
+ ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
+ var newMode = this.options.modes[ index ];
+ if( !newMode ){
+ throw new Error( 'mode index not found: ' + index );
+ }
+ this.currModeIndex = index;
+ if( newMode.html ){
+ this.$element.html( newMode.html );
+ }
+ return this;
+ };
+
+ // ---- public interface
+ /** get the current mode object (not just the mode name) */
+ ModeButton.prototype.currentMode = function currentMode(){
+ return this.options.modes[ this.currModeIndex ];
+ };
+ /** return the mode key of the current mode */
+ ModeButton.prototype.current = function current(){
+ // sugar for returning mode name
+ return this.currentMode().mode;
+ };
+ /** get the mode with the given modeKey or the current mode if modeKey is undefined */
+ ModeButton.prototype.getMode = function getMode( modeKey ){
+ if( !modeKey ){ return this.currentMode(); }
+ return this.options.modes[( this._getModeIndex( modeKey ) )];
+ };
+ /** T/F if the button has the given mode */
+ ModeButton.prototype.hasMode = function hasMode( modeKey ){
+ try {
+ return !!this.getMode( modeKey );
+ } catch( err ){}
+ return false;
+ };
+ /** set the current mode to the mode with the given name */
+ ModeButton.prototype.setMode = function setMode( modeKey ){
+ return this._setModeByIndex( this._getModeIndex( modeKey ) );
+ };
+ /** reset to the initial mode */
+ ModeButton.prototype.reset = function reset(){
+ this.currModeIndex = 0;
+ if( this.options.initialMode ){
+ this.currModeIndex = this._getModeIndex( this.options.initialMode );
+ }
+ return this._setModeByIndex( this.currModeIndex );
+ };
+ /** manually call the click handler of the given mode */
+ ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
+ var modeFn = this.getMode( modeKey ).onclick;
+ if( modeFn && $.type( modeFn === 'function' ) ){
+ // call with the element as context (std jquery pattern)
+ return modeFn.call( this.$element.get(0) );
+ }
+ return undefined;
+ };
+
+ // as jq plugin
+ $.fn.modeButton = function $modeButton( options ){
+ if( !this.size() ){ return this; }
+
+ //TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
+ if( $.type( options ) === 'object' ){
+ return this.map( function(){
+ var $this = $( this );
+ $this.data( 'mode-button', new ModeButton( $this, options ) );
+ return this;
+ });
+ }
+
+ var $first = $( this[0] ),
+ button = $first.data( 'mode-button' );
+
+ if( !button ){
+ throw new Error( 'modeButton needs an options object or string name of a function' );
+ }
+
+ if( button && $.type( options ) === 'string' ){
+ var fnName = options;
+ if( button && $.type( button[ fnName ] ) === 'function' ){
+ return button[ fnName ].apply( button, $.makeArray( arguments ).slice( 1 ) );
+ }
+ }
+ return button;
+ };
+
+}));
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 client/galaxy/scripts/mvc/history/multi-panel.js
--- a/client/galaxy/scripts/mvc/history/multi-panel.js
+++ b/client/galaxy/scripts/mvc/history/multi-panel.js
@@ -2,7 +2,8 @@
"mvc/history/history-model",
"mvc/history/history-panel-edit",
"mvc/base-mvc",
- "utils/ajax-queue"
+ "utils/ajax-queue",
+ "jq-plugins/ui/mode-button"
], function( HISTORY_MODEL, HPANEL_EDIT, baseMVC, ajaxQueue ){
window.HISTORY_MODEL = HISTORY_MODEL;
//==============================================================================
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 client/galaxy/scripts/mvc/ui.js
--- a/client/galaxy/scripts/mvc/ui.js
+++ b/client/galaxy/scripts/mvc/ui.js
@@ -749,184 +749,3 @@
}
});
}());
-
-
-//==============================================================================
-(function(){
- /** Multi 'mode' button (or any element really) that changes the html
- * contents of itself when clicked. Pass in an ordered list of
- * objects with 'html' and (optional) onclick functions.
- *
- * When clicked in a particular node, the onclick function will
- * be called (with the element as this) and the element will
- * switch to the next mode, replacing its html content with
- * that mode's html.
- *
- * If there is no next mode, the element will switch back to
- * the first mode.
- * @example:
- * $( '.myElement' ).modeButton({
- * modes : [
- * {
- * mode: 'bler',
- * html: '<h5>Bler</h5>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'red' );
- * }
- * },
- * {
- * mode: 'bloo',
- * html: '<h4>Bloo</h4>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'blue' );
- * }
- * },
- * {
- * mode: 'blah',
- * html: '<h3>Blah</h3>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'grey' );
- * }
- * },
- * ]
- * });
- * $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
- */
- /** constructor */
- function ModeButton( element, options ){
- this.currModeIndex = 0;
- return this._init( element, options );
- }
-
- /** html5 data key to store this object inside an element */
- ModeButton.prototype.DATA_KEY = 'mode-button';
- /** default options */
- ModeButton.prototype.defaults = {
- switchModesOnClick : true
- };
-
- // ---- private interface
- /** set up options, intial mode, and the click handler */
- ModeButton.prototype._init = function _init( element, options ){
- //console.debug( 'ModeButton._init:', element, options );
- options = options || {};
- this.$element = $( element );
- this.options = jQuery.extend( true, {}, this.defaults, options );
- if( !options.modes ){
- throw new Error( 'ModeButton requires a "modes" array' );
- }
-
- var modeButton = this;
- this.$element.click( function _ModeButtonClick( event ){
- // call the curr mode fn
- modeButton.callModeFn();
- // inc the curr mode index
- if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
- // set the element html
- $( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
- });
- return this.reset();
- };
- /** increment the mode index to the next in the array, looping back to zero if at the last */
- ModeButton.prototype._incModeIndex = function _incModeIndex(){
- this.currModeIndex += 1;
- if( this.currModeIndex >= this.options.modes.length ){
- this.currModeIndex = 0;
- }
- return this;
- };
- /** get the mode index in the modes array for the given key (mode name) */
- ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
- for( var i=0; i<this.options.modes.length; i+=1 ){
- if( this.options.modes[ i ].mode === modeKey ){ return i; }
- }
- throw new Error( 'mode not found: ' + modeKey );
- };
- /** set the current mode to the one with the given index and set button html */
- ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
- var newMode = this.options.modes[ index ];
- if( !newMode ){
- throw new Error( 'mode index not found: ' + index );
- }
- this.currModeIndex = index;
- if( newMode.html ){
- this.$element.html( newMode.html );
- }
- return this;
- };
-
- // ---- public interface
- /** get the current mode object (not just the mode name) */
- ModeButton.prototype.currentMode = function currentMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- /** return the mode key of the current mode */
- ModeButton.prototype.current = function current(){
- // sugar for returning mode name
- return this.currentMode().mode;
- };
- /** get the mode with the given modeKey or the current mode if modeKey is undefined */
- ModeButton.prototype.getMode = function getMode( modeKey ){
- if( !modeKey ){ return this.currentMode(); }
- return this.options.modes[( this._getModeIndex( modeKey ) )];
- };
- /** T/F if the button has the given mode */
- ModeButton.prototype.hasMode = function hasMode( modeKey ){
- try {
- return !!this.getMode( modeKey );
- } catch( err ){}
- return false;
- };
- /** set the current mode to the mode with the given name */
- ModeButton.prototype.setMode = function setMode( modeKey ){
- return this._setModeByIndex( this._getModeIndex( modeKey ) );
- };
- /** reset to the initial mode */
- ModeButton.prototype.reset = function reset(){
- this.currModeIndex = 0;
- if( this.options.initialMode ){
- this.currModeIndex = this._getModeIndex( this.options.initialMode );
- }
- return this._setModeByIndex( this.currModeIndex );
- };
- /** manually call the click handler of the given mode */
- ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
- var modeFn = this.getMode( modeKey ).onclick;
- if( modeFn && jQuery.type( modeFn === 'function' ) ){
- // call with the element as context (std jquery pattern)
- return modeFn.call( this.$element.get(0) );
- }
- return undefined;
- };
-
- // as jq plugin
- jQuery.fn.extend({
- modeButton : function $modeButton( options ){
- if( !this.size() ){ return this; }
-
- //TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
- if( jQuery.type( options ) === 'object' ){
- return this.map( function(){
- var $this = $( this );
- $this.data( 'mode-button', new ModeButton( $this, options ) );
- return this;
- });
- }
-
- var $first = $( this[0] ),
- button = $first.data( 'mode-button' );
-
- if( !button ){
- throw new Error( 'modeButton needs an options object or string name of a function' );
- }
-
- if( button && jQuery.type( options ) === 'string' ){
- var fnName = options;
- if( button && jQuery.type( button[ fnName ] ) === 'function' ){
- return button[ fnName ].apply( button, jQuery.makeArray( arguments ).slice( 1 ) );
- }
- }
- return button;
- }
- });
-}());
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/jq-plugins/ui/mode-button.js
--- /dev/null
+++ b/static/scripts/jq-plugins/ui/mode-button.js
@@ -0,0 +1,191 @@
+// from: https://raw.githubusercontent.com/umdjs/umd/master/jqueryPlugin.js
+// Uses AMD or browser globals to create a jQuery plugin.
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ //TODO: So...this turns out to be an all or nothing thing. If I load jQuery in the define below, it will
+ // (of course) wipe the old jquery *and all the plugins loaded into it*. So the define below *is still
+ // relying on jquery being loaded globally* in order to preserve plugins.
+ define([], factory);
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+
+}(function () {
+
+ /** Multi 'mode' button (or any element really) that changes the html
+ * contents of itself when clicked. Pass in an ordered list of
+ * objects with 'html' and (optional) onclick functions.
+ *
+ * When clicked in a particular node, the onclick function will
+ * be called (with the element as this) and the element will
+ * switch to the next mode, replacing its html content with
+ * that mode's html.
+ *
+ * If there is no next mode, the element will switch back to
+ * the first mode.
+ * @example:
+ * $( '.myElement' ).modeButton({
+ * modes : [
+ * {
+ * mode: 'bler',
+ * html: '<h5>Bler</h5>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'red' );
+ * }
+ * },
+ * {
+ * mode: 'bloo',
+ * html: '<h4>Bloo</h4>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'blue' );
+ * }
+ * },
+ * {
+ * mode: 'blah',
+ * html: '<h3>Blah</h3>',
+ * onclick : function(){
+ * $( 'body' ).css( 'background-color', 'grey' );
+ * }
+ * },
+ * ]
+ * });
+ * $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
+ */
+ /** constructor */
+ function ModeButton( element, options ){
+ this.currModeIndex = 0;
+ return this._init( element, options );
+ }
+
+ /** html5 data key to store this object inside an element */
+ ModeButton.prototype.DATA_KEY = 'mode-button';
+ /** default options */
+ ModeButton.prototype.defaults = {
+ switchModesOnClick : true
+ };
+
+ // ---- private interface
+ /** set up options, intial mode, and the click handler */
+ ModeButton.prototype._init = function _init( element, options ){
+ //console.debug( 'ModeButton._init:', element, options );
+ options = options || {};
+ this.$element = $( element );
+ this.options = $.extend( true, {}, this.defaults, options );
+ if( !options.modes ){
+ throw new Error( 'ModeButton requires a "modes" array' );
+ }
+
+ var modeButton = this;
+ this.$element.click( function _ModeButtonClick( event ){
+ // call the curr mode fn
+ modeButton.callModeFn();
+ // inc the curr mode index
+ if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
+ // set the element html
+ $( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
+ });
+ return this.reset();
+ };
+ /** increment the mode index to the next in the array, looping back to zero if at the last */
+ ModeButton.prototype._incModeIndex = function _incModeIndex(){
+ this.currModeIndex += 1;
+ if( this.currModeIndex >= this.options.modes.length ){
+ this.currModeIndex = 0;
+ }
+ return this;
+ };
+ /** get the mode index in the modes array for the given key (mode name) */
+ ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
+ for( var i=0; i<this.options.modes.length; i+=1 ){
+ if( this.options.modes[ i ].mode === modeKey ){ return i; }
+ }
+ throw new Error( 'mode not found: ' + modeKey );
+ };
+ /** set the current mode to the one with the given index and set button html */
+ ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
+ var newMode = this.options.modes[ index ];
+ if( !newMode ){
+ throw new Error( 'mode index not found: ' + index );
+ }
+ this.currModeIndex = index;
+ if( newMode.html ){
+ this.$element.html( newMode.html );
+ }
+ return this;
+ };
+
+ // ---- public interface
+ /** get the current mode object (not just the mode name) */
+ ModeButton.prototype.currentMode = function currentMode(){
+ return this.options.modes[ this.currModeIndex ];
+ };
+ /** return the mode key of the current mode */
+ ModeButton.prototype.current = function current(){
+ // sugar for returning mode name
+ return this.currentMode().mode;
+ };
+ /** get the mode with the given modeKey or the current mode if modeKey is undefined */
+ ModeButton.prototype.getMode = function getMode( modeKey ){
+ if( !modeKey ){ return this.currentMode(); }
+ return this.options.modes[( this._getModeIndex( modeKey ) )];
+ };
+ /** T/F if the button has the given mode */
+ ModeButton.prototype.hasMode = function hasMode( modeKey ){
+ try {
+ return !!this.getMode( modeKey );
+ } catch( err ){}
+ return false;
+ };
+ /** set the current mode to the mode with the given name */
+ ModeButton.prototype.setMode = function setMode( modeKey ){
+ return this._setModeByIndex( this._getModeIndex( modeKey ) );
+ };
+ /** reset to the initial mode */
+ ModeButton.prototype.reset = function reset(){
+ this.currModeIndex = 0;
+ if( this.options.initialMode ){
+ this.currModeIndex = this._getModeIndex( this.options.initialMode );
+ }
+ return this._setModeByIndex( this.currModeIndex );
+ };
+ /** manually call the click handler of the given mode */
+ ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
+ var modeFn = this.getMode( modeKey ).onclick;
+ if( modeFn && $.type( modeFn === 'function' ) ){
+ // call with the element as context (std jquery pattern)
+ return modeFn.call( this.$element.get(0) );
+ }
+ return undefined;
+ };
+
+ // as jq plugin
+ $.fn.modeButton = function $modeButton( options ){
+ if( !this.size() ){ return this; }
+
+ //TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
+ if( $.type( options ) === 'object' ){
+ return this.map( function(){
+ var $this = $( this );
+ $this.data( 'mode-button', new ModeButton( $this, options ) );
+ return this;
+ });
+ }
+
+ var $first = $( this[0] ),
+ button = $first.data( 'mode-button' );
+
+ if( !button ){
+ throw new Error( 'modeButton needs an options object or string name of a function' );
+ }
+
+ if( button && $.type( options ) === 'string' ){
+ var fnName = options;
+ if( button && $.type( button[ fnName ] ) === 'function' ){
+ return button[ fnName ].apply( button, $.makeArray( arguments ).slice( 1 ) );
+ }
+ }
+ return button;
+ };
+
+}));
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/mvc/history/multi-panel.js
--- a/static/scripts/mvc/history/multi-panel.js
+++ b/static/scripts/mvc/history/multi-panel.js
@@ -2,7 +2,8 @@
"mvc/history/history-model",
"mvc/history/history-panel-edit",
"mvc/base-mvc",
- "utils/ajax-queue"
+ "utils/ajax-queue",
+ "jq-plugins/ui/mode-button"
], function( HISTORY_MODEL, HPANEL_EDIT, baseMVC, ajaxQueue ){
window.HISTORY_MODEL = HISTORY_MODEL;
//==============================================================================
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -749,184 +749,3 @@
}
});
}());
-
-
-//==============================================================================
-(function(){
- /** Multi 'mode' button (or any element really) that changes the html
- * contents of itself when clicked. Pass in an ordered list of
- * objects with 'html' and (optional) onclick functions.
- *
- * When clicked in a particular node, the onclick function will
- * be called (with the element as this) and the element will
- * switch to the next mode, replacing its html content with
- * that mode's html.
- *
- * If there is no next mode, the element will switch back to
- * the first mode.
- * @example:
- * $( '.myElement' ).modeButton({
- * modes : [
- * {
- * mode: 'bler',
- * html: '<h5>Bler</h5>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'red' );
- * }
- * },
- * {
- * mode: 'bloo',
- * html: '<h4>Bloo</h4>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'blue' );
- * }
- * },
- * {
- * mode: 'blah',
- * html: '<h3>Blah</h3>',
- * onclick : function(){
- * $( 'body' ).css( 'background-color', 'grey' );
- * }
- * },
- * ]
- * });
- * $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
- */
- /** constructor */
- function ModeButton( element, options ){
- this.currModeIndex = 0;
- return this._init( element, options );
- }
-
- /** html5 data key to store this object inside an element */
- ModeButton.prototype.DATA_KEY = 'mode-button';
- /** default options */
- ModeButton.prototype.defaults = {
- switchModesOnClick : true
- };
-
- // ---- private interface
- /** set up options, intial mode, and the click handler */
- ModeButton.prototype._init = function _init( element, options ){
- //console.debug( 'ModeButton._init:', element, options );
- options = options || {};
- this.$element = $( element );
- this.options = jQuery.extend( true, {}, this.defaults, options );
- if( !options.modes ){
- throw new Error( 'ModeButton requires a "modes" array' );
- }
-
- var modeButton = this;
- this.$element.click( function _ModeButtonClick( event ){
- // call the curr mode fn
- modeButton.callModeFn();
- // inc the curr mode index
- if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
- // set the element html
- $( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
- });
- return this.reset();
- };
- /** increment the mode index to the next in the array, looping back to zero if at the last */
- ModeButton.prototype._incModeIndex = function _incModeIndex(){
- this.currModeIndex += 1;
- if( this.currModeIndex >= this.options.modes.length ){
- this.currModeIndex = 0;
- }
- return this;
- };
- /** get the mode index in the modes array for the given key (mode name) */
- ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
- for( var i=0; i<this.options.modes.length; i+=1 ){
- if( this.options.modes[ i ].mode === modeKey ){ return i; }
- }
- throw new Error( 'mode not found: ' + modeKey );
- };
- /** set the current mode to the one with the given index and set button html */
- ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
- var newMode = this.options.modes[ index ];
- if( !newMode ){
- throw new Error( 'mode index not found: ' + index );
- }
- this.currModeIndex = index;
- if( newMode.html ){
- this.$element.html( newMode.html );
- }
- return this;
- };
-
- // ---- public interface
- /** get the current mode object (not just the mode name) */
- ModeButton.prototype.currentMode = function currentMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- /** return the mode key of the current mode */
- ModeButton.prototype.current = function current(){
- // sugar for returning mode name
- return this.currentMode().mode;
- };
- /** get the mode with the given modeKey or the current mode if modeKey is undefined */
- ModeButton.prototype.getMode = function getMode( modeKey ){
- if( !modeKey ){ return this.currentMode(); }
- return this.options.modes[( this._getModeIndex( modeKey ) )];
- };
- /** T/F if the button has the given mode */
- ModeButton.prototype.hasMode = function hasMode( modeKey ){
- try {
- return !!this.getMode( modeKey );
- } catch( err ){}
- return false;
- };
- /** set the current mode to the mode with the given name */
- ModeButton.prototype.setMode = function setMode( modeKey ){
- return this._setModeByIndex( this._getModeIndex( modeKey ) );
- };
- /** reset to the initial mode */
- ModeButton.prototype.reset = function reset(){
- this.currModeIndex = 0;
- if( this.options.initialMode ){
- this.currModeIndex = this._getModeIndex( this.options.initialMode );
- }
- return this._setModeByIndex( this.currModeIndex );
- };
- /** manually call the click handler of the given mode */
- ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
- var modeFn = this.getMode( modeKey ).onclick;
- if( modeFn && jQuery.type( modeFn === 'function' ) ){
- // call with the element as context (std jquery pattern)
- return modeFn.call( this.$element.get(0) );
- }
- return undefined;
- };
-
- // as jq plugin
- jQuery.fn.extend({
- modeButton : function $modeButton( options ){
- if( !this.size() ){ return this; }
-
- //TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
- if( jQuery.type( options ) === 'object' ){
- return this.map( function(){
- var $this = $( this );
- $this.data( 'mode-button', new ModeButton( $this, options ) );
- return this;
- });
- }
-
- var $first = $( this[0] ),
- button = $first.data( 'mode-button' );
-
- if( !button ){
- throw new Error( 'modeButton needs an options object or string name of a function' );
- }
-
- if( button && jQuery.type( options ) === 'string' ){
- var fnName = options;
- if( button && jQuery.type( button[ fnName ] ) === 'function' ){
- return button[ fnName ].apply( button, jQuery.makeArray( arguments ).slice( 1 ) );
- }
- }
- return button;
- }
- });
-}());
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/packed/jq-plugins/ui/mode-button.js
--- /dev/null
+++ b/static/scripts/packed/jq-plugins/ui/mode-button.js
@@ -0,0 +1,1 @@
+(function(a){if(typeof define==="function"&&define.amd){define([],a)}else{a(jQuery)}}(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=$.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&$.type(o==="function")){return o.call(this.$element.get(0))}return undefined};$.fn.modeButton=function k(n){if(!this.size()){return this}if($.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&$.type(n)==="string"){var q=n;if(o&&$.type(o[q])==="function"){return o[q].apply(o,$.makeArray(arguments).slice(1))}}return o}}));
\ No newline at end of file
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/packed/mvc/history/multi-panel.js
--- a/static/scripts/packed/mvc/history/multi-panel.js
+++ b/static/scripts/packed/mvc/history/multi-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue"],function(d,l,z,a){window.HISTORY_MODEL=d;function g(H,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return H.copy()}var F=H.get("name"),C="Copy of '"+F+"'";function D(J){if(!J){if(!Galaxy.modal.$("#invalid-title").size()){var I=$("<p/>").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(I)}return false}return J}function G(I){var J=$('<p><span class="fa fa-spinner fa-spin"></span> Copying history...</p>').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(J);H.copy(true,I).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['<label for="copy-modal-title">',_l("Enter a title for the copied history"),":","</label><br />",'<input id="copy-modal-title" class="form-control" style="width: 100%" value="',C,'" />'].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:function(){var I=Galaxy.modal.$("#copy-modal-title").val();if(!D(I)){return}G(I)}}},E));$("#copy-modal-title").focus().select()}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($('<span class="fa fa-spinner fa-spin"></span><i>loading datasets...</i>')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(E<C){return false}if(F>D){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(D){D=D||{};var C=['<div class="panel-controls clear flex-row">',this.controlsLeftTemplate(),'<div class="pull-right">','<button class="delete-history btn btn-default">',D.deleted?_l("Undelete"):_l("Delete"),"</button>",'<button class="copy-history btn btn-default">',_l("Copy"),"</button>","</div>","</div>",'<div class="inner flex-row flex-column-container">','<div id="history-',D.id,'" class="history-column history-panel flex-column"></div>',"</div>"].join("");return $(C)},controlsLeftTemplate:function(){return(this.currentHistory)?['<div class="pull-left">','<button class="create-new btn btn-default">',_l("Create new"),"</button> ","</div>"].join(""):['<div class="pull-left">','<button class="switch-to btn btn-default">',_l("Switch to"),"</button>","</div>"].join("")},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history.btn":function(){var C=this,D;if(this.model.get("deleted")){D=this.model.undelete()}else{D=this.model._delete()}D.fail(function(G,E,F){alert(_l("Could not delete the history")+":\n"+F)}).done(function(E){C.render()})},"click .copy-history.btn":"copy"},copy:function s(){g(this.model)},toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({initialize:function c(C){C=C||{};this.log(this+".init",C);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){C=C||this.order;var E=this.currentHistoryId;switch(C){case"name":this.collection.comparator=function(F){return[F.id!==E,F.get("name").toLowerCase()]};break;case"size":this.collection.comparator=function(F){return[F.id!==E,F.get("size")]};break;default:this.collection.comparator=function(F){return[F.id!==E,Date(F.get("update_time"))]}}this.collection.sort(D);return this.collection},setOrder:function(C){if(["update","name","size"].indexOf(C)===-1){C="update"}this.order=C;this.sortCollection();return this},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(C){var D=this;D.listenTo(C,{"in-view":D.queueHdaFetch});D.listenTo(C.panel,{"view:draggable:dragstart":function(H,F,E,G){D._dropData=JSON.parse(H.dataTransfer.getData("text"));D.currentColumnDropTargetOn()},"view:draggable:dragend":function(H,F,E,G){D._dropData=null;D.currentColumnDropTargetOff()},"droptarget:drop":function(G,H,F){var I=D._dropData.filter(function(J){return(_.isObject(J)&&J.id&&J.model_class==="HistoryDatasetAssociation")});D._dropData=null;var E=new a.NamedAjaxQueue();I.forEach(function(J){E.add({name:"copy-"+J.id,fn:function(){return F.model.contents.copy(J.id)}})});E.start();E.done(function(J){F.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.template(C.options));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},template:function w(C){C=C||{};var D=[];if(this.options.headerHeight){D=D.concat(['<div class="loading-overlay flex-row"><div class="loading-overlay-message">loading...</div></div>','<div class="header flex-column-container">','<div class="header-control header-control-left flex-column">','<button class="done btn btn-default">',_l("Done"),"</button>",'<button class="include-deleted btn btn-default"></button>','<div class="order btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',_l("Order histories by")+'... <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="javascript:void(0);" class="order-update">',_l("Time of last update"),"</a></li>",'<li><a href="javascript:void(0);" class="order-name">',_l("Name"),"</a></li>",'<li><a href="javascript:void(0);" class="order-size">',_l("Size"),"</a></li>","</ul>","</div>",'<div id="search-histories" class="header-search"></div>',"</div>",'<div class="header-control header-control-center flex-column">','<div class="header-info">',"</div>","</div>",'<div class="header-control header-control-right flex-column">','<div id="search-datasets" class="header-search"></div>','<button id="toggle-deleted" class="btn btn-default">',_l("Include deleted datasets"),"</button>",'<button id="toggle-hidden" class="btn btn-default">',_l("Include hidden datasets"),"</button>","</div>","</div>"])}D=D.concat(['<div class="outer-middle flex-row flex-row-container">','<div class="middle flex-column-container flex-row"></div>',"</div>",'<div class="footer flex-column-container">',"</div>"]);return $(D.join(""))},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){this.$(".header .header-info").text(C)},events:{"click .done.btn":function(){window.location="/"},"click .create-new.btn":"create","click .order .order-update":function(C){this.setOrder("update")},"click .order .order-name":function(C){this.setOrder("name")},"click .order .order-size":function(C){this.setOrder("size")}},includeDeletedHistories:function(){window.location+=(/\?/.test(window.location.toString()))?("&"):("?")+"include_deleted_histories=True"},excludeDeletedHistories:function(){window.location=window.location.toString().replace(/[&\?]include_deleted_histories=True/g,"")},setUpBehaviors:function(){var D=this;D.$(".include-deleted").modeButton({initialMode:this.collection.includeDeleted?"exclude":"include",switchModesOnClick:false,modes:[{mode:"include",html:_l("Include deleted histories"),onclick:_.bind(D.includeDeletedHistories,D)},{mode:"exclude",html:_l("Exclude deleted histories"),onclick:_.bind(D.excludeDeletedHistories,D)}]});D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});D.$("#toggle-deleted").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude deleted datasets")},{mode:"include",html:_l("Include deleted datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowDeleted(E,false)},F*200)})});D.$("#toggle-hidden").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude hidden datasets")},{mode:"include",html:_l("Include hidden datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowHidden(E,false)},F*200)})});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTargetOff()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"}});return{MultiPanelColumns:m}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue","jq-plugins/ui/mode-button"],function(d,l,z,a){window.HISTORY_MODEL=d;function g(H,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return H.copy()}var F=H.get("name"),C="Copy of '"+F+"'";function D(J){if(!J){if(!Galaxy.modal.$("#invalid-title").size()){var I=$("<p/>").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(I)}return false}return J}function G(I){var J=$('<p><span class="fa fa-spinner fa-spin"></span> Copying history...</p>').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(J);H.copy(true,I).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['<label for="copy-modal-title">',_l("Enter a title for the copied history"),":","</label><br />",'<input id="copy-modal-title" class="form-control" style="width: 100%" value="',C,'" />'].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:function(){var I=Galaxy.modal.$("#copy-modal-title").val();if(!D(I)){return}G(I)}}},E));$("#copy-modal-title").focus().select()}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($('<span class="fa fa-spinner fa-spin"></span><i>loading datasets...</i>')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(E<C){return false}if(F>D){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(D){D=D||{};var C=['<div class="panel-controls clear flex-row">',this.controlsLeftTemplate(),'<div class="pull-right">','<button class="delete-history btn btn-default">',D.deleted?_l("Undelete"):_l("Delete"),"</button>",'<button class="copy-history btn btn-default">',_l("Copy"),"</button>","</div>","</div>",'<div class="inner flex-row flex-column-container">','<div id="history-',D.id,'" class="history-column history-panel flex-column"></div>',"</div>"].join("");return $(C)},controlsLeftTemplate:function(){return(this.currentHistory)?['<div class="pull-left">','<button class="create-new btn btn-default">',_l("Create new"),"</button> ","</div>"].join(""):['<div class="pull-left">','<button class="switch-to btn btn-default">',_l("Switch to"),"</button>","</div>"].join("")},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history.btn":function(){var C=this,D;if(this.model.get("deleted")){D=this.model.undelete()}else{D=this.model._delete()}D.fail(function(G,E,F){alert(_l("Could not delete the history")+":\n"+F)}).done(function(E){C.render()})},"click .copy-history.btn":"copy"},copy:function s(){g(this.model)},toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({initialize:function c(C){C=C||{};this.log(this+".init",C);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){C=C||this.order;var E=this.currentHistoryId;switch(C){case"name":this.collection.comparator=function(F){return[F.id!==E,F.get("name").toLowerCase()]};break;case"size":this.collection.comparator=function(F){return[F.id!==E,F.get("size")]};break;default:this.collection.comparator=function(F){return[F.id!==E,Date(F.get("update_time"))]}}this.collection.sort(D);return this.collection},setOrder:function(C){if(["update","name","size"].indexOf(C)===-1){C="update"}this.order=C;this.sortCollection();return this},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(C){var D=this;D.listenTo(C,{"in-view":D.queueHdaFetch});D.listenTo(C.panel,{"view:draggable:dragstart":function(H,F,E,G){D._dropData=JSON.parse(H.dataTransfer.getData("text"));D.currentColumnDropTargetOn()},"view:draggable:dragend":function(H,F,E,G){D._dropData=null;D.currentColumnDropTargetOff()},"droptarget:drop":function(G,H,F){var I=D._dropData.filter(function(J){return(_.isObject(J)&&J.id&&J.model_class==="HistoryDatasetAssociation")});D._dropData=null;var E=new a.NamedAjaxQueue();I.forEach(function(J){E.add({name:"copy-"+J.id,fn:function(){return F.model.contents.copy(J.id)}})});E.start();E.done(function(J){F.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.template(C.options));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},template:function w(C){C=C||{};var D=[];if(this.options.headerHeight){D=D.concat(['<div class="loading-overlay flex-row"><div class="loading-overlay-message">loading...</div></div>','<div class="header flex-column-container">','<div class="header-control header-control-left flex-column">','<button class="done btn btn-default">',_l("Done"),"</button>",'<button class="include-deleted btn btn-default"></button>','<div class="order btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',_l("Order histories by")+'... <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="javascript:void(0);" class="order-update">',_l("Time of last update"),"</a></li>",'<li><a href="javascript:void(0);" class="order-name">',_l("Name"),"</a></li>",'<li><a href="javascript:void(0);" class="order-size">',_l("Size"),"</a></li>","</ul>","</div>",'<div id="search-histories" class="header-search"></div>',"</div>",'<div class="header-control header-control-center flex-column">','<div class="header-info">',"</div>","</div>",'<div class="header-control header-control-right flex-column">','<div id="search-datasets" class="header-search"></div>','<button id="toggle-deleted" class="btn btn-default">',_l("Include deleted datasets"),"</button>",'<button id="toggle-hidden" class="btn btn-default">',_l("Include hidden datasets"),"</button>","</div>","</div>"])}D=D.concat(['<div class="outer-middle flex-row flex-row-container">','<div class="middle flex-column-container flex-row"></div>',"</div>",'<div class="footer flex-column-container">',"</div>"]);return $(D.join(""))},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){this.$(".header .header-info").text(C)},events:{"click .done.btn":function(){window.location="/"},"click .create-new.btn":"create","click .order .order-update":function(C){this.setOrder("update")},"click .order .order-name":function(C){this.setOrder("name")},"click .order .order-size":function(C){this.setOrder("size")}},includeDeletedHistories:function(){window.location+=(/\?/.test(window.location.toString()))?("&"):("?")+"include_deleted_histories=True"},excludeDeletedHistories:function(){window.location=window.location.toString().replace(/[&\?]include_deleted_histories=True/g,"")},setUpBehaviors:function(){var D=this;D.$(".include-deleted").modeButton({initialMode:this.collection.includeDeleted?"exclude":"include",switchModesOnClick:false,modes:[{mode:"include",html:_l("Include deleted histories"),onclick:_.bind(D.includeDeletedHistories,D)},{mode:"exclude",html:_l("Exclude deleted histories"),onclick:_.bind(D.excludeDeletedHistories,D)}]});D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});D.$("#toggle-deleted").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude deleted datasets")},{mode:"include",html:_l("Include deleted datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowDeleted(E,false)},F*200)})});D.$("#toggle-hidden").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude hidden datasets")},{mode:"include",html:_l("Include hidden datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowHidden(E,false)},F*200)})});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTargetOff()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"}});return{MultiPanelColumns:m}});
\ No newline at end of file
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";a.parent().find(".loading-indicator").remove();b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){var b=window._l||function(d){return d};function a(k,q){var e=27,n=13,d=$(k),f=true,h={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(r){},minSearchLen:0,escWillClear:true,oninit:function(){}};function j(r){var s=$(this).parent().children("input");s.focus().val("").trigger("clear:searchInput");q.onclear()}function p(s,r){$(this).trigger("search:searchInput",r);if(typeof q.onfirstsearch==="function"&&f){f=false;q.onfirstsearch(r)}else{q.onsearch(r)}}function g(){return['<input type="text" name="',q.name,'" placeholder="',q.placeholder,'" ','class="search-query ',q.classes,'" ',"/>"].join("")}function m(){return $(g()).focus(function(r){$(this).select()}).keyup(function(s){s.preventDefault();s.stopPropagation();if(!$(this).val()){$(this).blur()}if(s.which===e&&q.escWillClear){j.call(this,s)}else{var r=$(this).val();if((s.which===n)||(q.minSearchLen&&r.length>=q.minSearchLen)){p.call(this,s,r)}else{if(!r.length){j.call(this,s)}}}}).on("change",function(r){p.call(this,r,$(this).val())}).val(q.initialVal)}function l(){return $(['<span class="search-clear fa fa-times-circle" ','title="',b("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(r){j.call(this,r)})}function o(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',b("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function i(){d.find(".search-loading").toggle();d.find(".search-clear").toggle()}if(jQuery.type(q)==="string"){if(q==="toggle-loading"){i()}return d}if(jQuery.type(q)==="object"){q=jQuery.extend(true,{},h,q)}return d.addClass("search-input").prepend([m(),l(),o()])}jQuery.fn.extend({searchInput:function c(d){return this.each(function(){return a(this,d)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){return o.call(this.$element.get(0))}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";a.parent().find(".loading-indicator").remove();b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){var b=window._l||function(d){return d};function a(k,q){var e=27,n=13,d=$(k),f=true,h={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(r){},minSearchLen:0,escWillClear:true,oninit:function(){}};function j(r){var s=$(this).parent().children("input");s.focus().val("").trigger("clear:searchInput");q.onclear()}function p(s,r){$(this).trigger("search:searchInput",r);if(typeof q.onfirstsearch==="function"&&f){f=false;q.onfirstsearch(r)}else{q.onsearch(r)}}function g(){return['<input type="text" name="',q.name,'" placeholder="',q.placeholder,'" ','class="search-query ',q.classes,'" ',"/>"].join("")}function m(){return $(g()).focus(function(r){$(this).select()}).keyup(function(s){s.preventDefault();s.stopPropagation();if(!$(this).val()){$(this).blur()}if(s.which===e&&q.escWillClear){j.call(this,s)}else{var r=$(this).val();if((s.which===n)||(q.minSearchLen&&r.length>=q.minSearchLen)){p.call(this,s,r)}else{if(!r.length){j.call(this,s)}}}}).on("change",function(r){p.call(this,r,$(this).val())}).val(q.initialVal)}function l(){return $(['<span class="search-clear fa fa-times-circle" ','title="',b("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(r){j.call(this,r)})}function o(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',b("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function i(){d.find(".search-loading").toggle();d.find(".search-clear").toggle()}if(jQuery.type(q)==="string"){if(q==="toggle-loading"){i()}return d}if(jQuery.type(q)==="object"){q=jQuery.extend(true,{},h,q)}return d.addClass("search-input").prepend([m(),l(),o()])}jQuery.fn.extend({searchInput:function c(d){return this.each(function(){return a(this,d)})}})}());
\ No newline at end of file
diff -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 -r 8e98c3d9b9a8bc3cabff60c67367fbaf5b328320 templates/webapps/galaxy/history/view.mako
--- a/templates/webapps/galaxy/history/view.mako
+++ b/templates/webapps/galaxy/history/view.mako
@@ -65,8 +65,7 @@
## ----------------------------------------------------------------------------
<%def name="javascripts()">
-${parent.javascripts()}
-
+ ${parent.javascripts()}
</%def>
## ----------------------------------------------------------------------------
@@ -144,7 +143,7 @@
window.location = "${ switch_to_url }";
}
});
-
+
$( '#import' ).modeButton({
switchModesOnClick : false,
initialMode : "${ 'with_deleted' if show_deleted else 'without_deleted' }",
@@ -175,8 +174,16 @@
({ location: 'mvc/history/history-panel', className: 'HistoryPanel' });
require.config({
- baseUrl : "${h.url_for( '/static/scripts' )}"
- })([ 'mvc/user/user-model', panelToUse.location, 'utils/localization' ], function( user, panelMod, _l ){
+ baseUrl : "${h.url_for( '/static/scripts' )}",
+ paths : {
+ 'jquery' : 'libs/jquery/jquery'
+ }
+ })([
+ 'mvc/user/user-model',
+ panelToUse.location,
+ 'utils/localization',
+ 'jq-plugins/ui/mode-button'
+ ], function( user, panelMod, _l ){
$(function(){
setUpBehaviors();
if( hasMasthead ){
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/39b03ce9d101/
Changeset: 39b03ce9d101
User: guerler
Date: 2014-12-08 20:34:11+00:00
Summary: Security fixes for assigned templates
Affected #: 4 files
diff -r 864fdca5b06e6f15040298a316746448d09cdb40 -r 39b03ce9d101f7177c51342172ba9bab540ee257 templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
--- a/templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
@@ -1,5 +1,5 @@
<%inherit file="/tracks/history_select_grid.mako"/><%def name="title()">
- <h2>History '${grid.get_current_item( trans, **kwargs ).name}'</h2>
+ <h2>History '${grid.get_current_item( trans, **kwargs ).name | h}'</h2></%def>
diff -r 864fdca5b06e6f15040298a316746448d09cdb40 -r 39b03ce9d101f7177c51342172ba9bab540ee257 templates/webapps/galaxy/tracks/index.mako
--- a/templates/webapps/galaxy/tracks/index.mako
+++ /dev/null
@@ -1,38 +0,0 @@
-<form id="form" method="POST">
- <div class="form-row">
- <label for="dbkey">Browser name:</label>
- <div class="form-row-input">
- <input type="text" name="title" id="title" value="Unnamed Browser"></input>
- </div>
- <div style="clear: both;"></div>
- </div>
- <div class="form-row">
- <label for="dbkey">Reference genome build (dbkey): </label>
- <div class="form-row-input">
- <select name="dbkey" id="dbkey" refresh_on_change="true">
- %for tmp_dbkey in dbkey_set:
- <option value="${tmp_dbkey}"
- %if tmp_dbkey == dbkey:
- selected="selected"
- %endif
- >${tmp_dbkey}</option>
- %endfor
- </select>
- </div>
- <div style="clear: both;"></div>
- </div>
- <div class="form-row">
- <label for="dataset_ids">Datasets to visualize: (${", ".join(available_tracks)} files are supported)</label>
- %for dataset_id, (dataset_ext, dataset_name) in datasets.iteritems():
- <div>
- <input type="checkbox" id="${dataset_id}" name="dataset_ids" value="${dataset_id}" />
- <label style="display:inline; font-weight: normal" for="${dataset_id}">[${dataset_ext}] ${dataset_name}</label>
- </div>
- %endfor
-
- <div style="clear: both;"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="browse" value="Browse"/>
- </div>
-</form>
diff -r 864fdca5b06e6f15040298a316746448d09cdb40 -r 39b03ce9d101f7177c51342172ba9bab540ee257 templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
--- a/templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
@@ -2,7 +2,7 @@
<%namespace file='/library/common/browse_library.mako' import="render_content, grid_javascripts" /><%def name="title()">
- <h2>History '${grid.get_current_item( trans, **kwargs ).name}'</h2>
+ <h2>History '${grid.get_current_item( trans, **kwargs ).name | h}'</h2></%def>
${select_header()}
diff -r 864fdca5b06e6f15040298a316746448d09cdb40 -r 39b03ce9d101f7177c51342172ba9bab540ee257 templates/webapps/galaxy/visualization/phyloviz.mako
--- a/templates/webapps/galaxy/visualization/phyloviz.mako
+++ b/templates/webapps/galaxy/visualization/phyloviz.mako
@@ -196,7 +196,7 @@
<p>Select a tree to view:
<select id="phylovizNexSelector">
% for tree, index in data["trees"]:
- <option value="${index}">${tree}</option>
+ <option value="${index | h}">${tree | h}</option>
% endfor
</select></p>
https://bitbucket.org/galaxy/galaxy-central/commits/0fb0c56af3cf/
Changeset: 0fb0c56af3cf
User: guerler
Date: 2014-12-08 20:38:01+00:00
Summary: Parameters: Handle missing context
Affected #: 1 file
diff -r 39b03ce9d101f7177c51342172ba9bab540ee257 -r 0fb0c56af3cf25bb8c3bb366d34c6aedcbb9df14 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -767,7 +767,10 @@
if self.options:
return self.options.get_options( trans, other_values )
elif self.dynamic_options:
- return eval( self.dynamic_options, self.tool.code_namespace, other_values )
+ try:
+ return eval( self.dynamic_options, self.tool.code_namespace, other_values )
+ except Exception:
+ return []
else:
return self.static_options
@@ -779,7 +782,10 @@
if self.options:
return map( _get_UnvalidatedValue_value, set( v for _, v, _ in self.options.get_options( trans, other_values ) ) )
elif self.dynamic_options:
- return set( v for _, v, _ in eval( self.dynamic_options, self.tool.code_namespace, other_values ) )
+ try:
+ return set( v for _, v, _ in eval( self.dynamic_options, self.tool.code_namespace, other_values ) )
+ except Exception:
+ return set()
else:
return self.legal_values
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0