diff options
Diffstat (limited to 'app/controllers/concerns/internal_redirect.rb')
-rw-r--r-- | app/controllers/concerns/internal_redirect.rb | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/app/controllers/concerns/internal_redirect.rb b/app/controllers/concerns/internal_redirect.rb new file mode 100644 index 00000000000..7409b2e89a5 --- /dev/null +++ b/app/controllers/concerns/internal_redirect.rb @@ -0,0 +1,35 @@ +module InternalRedirect + extend ActiveSupport::Concern + + def safe_redirect_path(path) + return unless path + # Verify that the string starts with a `/` but not a double `/`. + return unless path =~ %r{^/\w.*$} + + uri = URI(path) + # Ignore anything path of the redirect except for the path, querystring and, + # fragment, forcing the redirect within the same host. + full_path_for_uri(uri) + rescue URI::InvalidURIError + nil + end + + def safe_redirect_path_for_url(url) + return unless url + + uri = URI(url) + safe_redirect_path(full_path_for_uri(uri)) if host_allowed?(uri) + rescue URI::InvalidURIError + nil + end + + def host_allowed?(uri) + uri.host == request.host && + uri.port == request.port + end + + def full_path_for_uri(uri) + path_with_query = [uri.path, uri.query].compact.join('?') + [path_with_query, uri.fragment].compact.join("#") + end +end |