2014-01-21 59 views
4

我有兩個路徑:應用程序根路徑和目標路徑。確保目標路徑是應用程序根路徑的子項的最簡單方法是什麼?確定一個路徑是否在Ruby的另一個路徑下?

基本上我的服務器會顯示用戶提供的目標路徑。但我想限制我的服務器,所以只有應用程序根路徑下的文件是可顯示的。所以我想檢查目標路徑是否在根路徑下。

根路徑可以包含嵌套的目錄。

回答

3

另一種方式:

def child?(root, target) 
    raise ArgumentError, "target.size=#{target.size} < #{root.size} = root.size"\ 
    if target.size < root.size 

    target[0...root.size] == root && 
    (target.size == root.size || target[root.size] == ?/) 
end 

root = "/root/app" 

p child?(root, "/root/app/some/path") # => true 
p child?(root, "/root/apple")   # => false 
p child?(root, "/root/app")   # => true 
p child?(root, "/root")    # => ArgumentError: target.size = 5 < 9 = root.size 
2

怎麼樣一個正則表達式:

root = "/root/app/" 
target = "/root/app/some/path" 

target =~ /^#{root}/ 

你可以使用Pathname#realdirpath,如果需要的相對路徑轉換爲絕對路徑。

+0

嗯,我想這應該可以解決像主目錄或「東西〜/../../../ PWD 」。但我認爲這是可行的。 – lulalala

+0

我添加了一個註釋來使用路徑名方法來幫助 –

+3

如果目標是'「/ root/apple」'? – Max

2

或許有點效率低下,而且萬無一失

require 'find' 
Find.find(root).include?(target) 
1

您沒有提供任何的使用情況,因此,我認爲以下變量適用於你的情況

root = "/var/www/" 
target = "/var/www/logs/something/else.log" 

您可以使用正則表達式或更簡單String#start_with?

target.start_with?(root) 
+2

如果'target =「/ var/www/.../...怎麼辦/ etc/password「'?使用'File.realpath(target).start_with?(root)'更安全' –

+0

標題爲「路徑不是字符串」:https://robm.me.uk/ruby/2014/01/18/pathname.html –

0

爲了避免路徑注射可以使用File.path方法:

[21] pry(main)> path_1 = File.path(Rails.root.join('public', '../config/routes.rb')) 
=> "/project_path/config/routes.rb" 
[22] pry(main)> path_2 = File.path(Rails.root.join('public', 'robots.txt')) 
=> "/project_path/public/robots.txt" 
[24] pry(main)> path_1.include?(Rails.root.join('public').to_s) 
=> false 
[25] pry(main)> path_2.include?(Rails.root.join('public').to_s) 
=> true 
+0

這樣做實際上回答OP的問題? – RealCheeseLord

相關問題