Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-01-02 11:43:10 +0300
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-01-14 14:48:15 +0300
commita3191463b60c8ded25a2898d5e5520ae4aff1114 (patch)
tree3b566fdd59145e2ea314f8054a650c03a4ab5155 /lib/gitlab
parent3de8a4620a70c886c815576dc0a30a745cbb8ccb (diff)
Add path sanitization to `StringPath`
[ci skip]
Diffstat (limited to 'lib/gitlab')
-rw-r--r--lib/gitlab/string_path.rb39
1 files changed, 27 insertions, 12 deletions
diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb
index ad68a8ff2d6..8310564646e 100644
--- a/lib/gitlab/string_path.rb
+++ b/lib/gitlab/string_path.rb
@@ -5,15 +5,12 @@ module Gitlab
# This is IO-operations safe class, that does similar job to
# Ruby's Pathname but without the risk of accessing filesystem.
#
- # TODO, better support for '../' and './'
- #
class StringPath
attr_reader :path, :universe
def initialize(path, universe, metadata = [])
- @path = prepare(path)
- @universe = universe.map { |entry| prepare(entry) }
- @universe << './' unless @universe.include?('./')
+ @path = sanitize(path)
+ @universe = universe.map { |entry| sanitize(entry) }
@metadata = metadata
end
@@ -60,15 +57,16 @@ module Gitlab
def descendants
return [] unless directory?
- children = @universe.select { |entry| entry =~ /^#{@path}.+/ }
- children.map { |path| new(path) }
+ select { |entry| entry =~ /^#{@path}.+/ }
end
def children
return [] unless directory?
return @children if @children
- children = @universe.select { |entry| entry =~ %r{^#{@path}[^/]+/?$} }
- @children = children.map { |path| new(path) }
+
+ @children = select do |entry|
+ self.class.child?(@path, entry)
+ end
end
def directories
@@ -104,9 +102,26 @@ module Gitlab
self.class.new(path, @universe)
end
- def prepare(path)
- return path if path =~ %r{^(/|\.|\.\.)}
- path.dup.prepend('./')
+ def select
+ selected = @universe.select { |entry| yield entry }
+ selected.map { |path| new(path) }
+ end
+
+ def sanitize(path)
+ self.class.sanitize(path)
+ end
+
+ def self.sanitize(path)
+ # It looks like Pathname#new doesn't touch a file system,
+ # neither Pathname#cleanpath does, so it is, hopefully, filesystem safe
+
+ clean = Pathname.new(path).cleanpath.to_s
+ raise ArgumentError, 'Invalid path' if clean.start_with?('../')
+ clean + (path.end_with?('/') ? '/' : '')
+ end
+
+ def self.child?(path, entry)
+ entry =~ %r{^#{path}[^/\s]+/?$}
end
end
end