require "arvados/keep"
require "uri"
-require "cgi"
class CollectionsController < ApplicationController
include ActionController::Live
return
end
- if Rails.configuration.keep_web_url
+ # If we are configured to use a keep-web server, just redirect to
+ # the appropriate URL.
+ if Rails.configuration.keep_web_url or
+ Rails.configuration.keep_web_download_url
opts = {}
if usable_token == params[:reader_token]
opts[:path_token] = usable_token
# to read the collection.
opts[:query_token] = usable_token
end
+ opts[:disposition] = params[:disposition] if params[:disposition]
return redirect_to keep_web_url(params[:uuid], params[:file], opts)
end
+ # No keep-web server available. Get the file data with arv-get,
+ # and serve it through Rails.
+
file_name = params[:file].andand.sub(/^(\.\/|\/|)/, './')
if file_name.nil? or not coll.manifest.has_file?(file_name)
return render_not_found
end
def keep_web_url(uuid_or_pdh, file, opts)
- fmt = {uuid_or_pdh: uuid_or_pdh.sub('+', '-')}
- uri = URI.parse(Rails.configuration.keep_web_url % fmt)
+ munged_id = uuid_or_pdh.sub('+', '-')
+ fmt = {uuid_or_pdh: munged_id}
+
+ tmpl = Rails.configuration.keep_web_url
+ if Rails.configuration.keep_web_download_url and
+ (!tmpl or opts[:disposition] == 'attachment')
+ # Prefer the attachment-only-host when we want an attachment
+ # (and when there is no preview link configured)
+ tmpl = Rails.configuration.keep_web_download_url
+ else
+ check_uri = URI.parse(tmpl % fmt)
+ if opts[:query_token] and
+ not check_uri.host.start_with?(munged_id + "--") and
+ not check_uri.host.start_with?(munged_id + ".")
+ # We're about to pass a token in the query string, but
+ # keep-web can't accept that safely at a single-origin URL
+ # template (unless it's -attachment-only-host).
+ tmpl = Rails.configuration.keep_web_download_url
+ if not tmpl
+ raise ArgumentError, "Download precluded by site configuration"
+ end
+ logger.warn("Using download link, even though inline content " \
+ "was requested: #{check_uri.to_s}")
+ end
+ end
+
+ if tmpl == Rails.configuration.keep_web_download_url
+ # This takes us to keep-web's -attachment-only-host so there is
+ # no need to add ?disposition=attachment.
+ opts.delete :disposition
+ end
+
+ uri = URI.parse(tmpl % fmt)
uri.path += '/' unless uri.path.end_with? '/'
if opts[:path_token]
uri.path += 't=' + opts[:path_token] + '/'
end
uri.path += '_/'
- uri.path += CGI::escape(file)
- if opts[:query_token]
- uri.query = 'api_token=' + CGI::escape(opts[:query_token])
+ uri.path += URI.escape(file)
+
+ query = Hash[URI.decode_www_form(uri.query || '')]
+ { query_token: 'api_token',
+ disposition: 'disposition' }.each do |opt, param|
+ if opts.include? opt
+ query[param] = opts[opt]
+ end
+ end
+ unless query.empty?
+ uri.query = URI.encode_www_form(query)
end
+
uri.to_s
end