lib/prawn/svg/loaders/file.rb in prawn-svg-0.23.0 vs lib/prawn/svg/loaders/file.rb in prawn-svg-0.23.1

- old
+ new

@@ -1,32 +1,58 @@ +# +# Load a file from disk. +# +# WINDOWS +# ======= +# Windows is supported, but must use URLs in the modern structure like: +# file:///x:/path/to/the/file.png +# or as a relative path: +# directory/file.png +# or as an absolute path from the current drive: +# /path/to/the/file.png +# +# Ruby's URI parser does not like backslashes, nor can it handle filenames as URLs starting +# with a drive letter as it thinks you're giving it a scheme. +# +# URL ENCODING +# ============ +# This module assumes the URL that is passed in has been URL-encoded. If for some reason +# you're passing in a filename that hasn't been taken from an XML document's attribute, +# you will want to URL encode it before you pass it in. +# module Prawn::SVG::Loaders class File attr_reader :root_path def initialize(root_path) + if root_path.empty? + raise ArgumentError, "An empty string is not a valid root path. Use '.' if you want the current working directory." + end + @root_path = ::File.expand_path(root_path) raise ArgumentError, "#{root_path} is not a directory" unless Dir.exist?(@root_path) end def from_url(url) uri = build_uri(url) if uri && uri.scheme.nil? && uri.path - path = build_absolute_path(uri.path) - load_file(path) + load_file(uri.path) elsif uri && uri.scheme == 'file' assert_valid_file_uri!(uri) - load_file(uri.path) + path = windows? ? fix_windows_path(uri.path) : uri.path + load_file(path) end end private def load_file(path) - path = ::File.expand_path(path) + path = URI.decode(path) + path = build_absolute_and_expand_path(path) assert_valid_path!(path) assert_file_exists!(path) IO.read(path) end @@ -36,21 +62,21 @@ rescue URI::InvalidURIError end end def assert_valid_path!(path) - if !path.start_with?("#{root_path}/") + # TODO : case sensitive comparison, but it's going to be a bit of a headache + # making it dependent on whether the file system is case sensitive or not. + # Leaving it like this until it's a problem for someone. + + if !path.start_with?("#{root_path}#{::File::SEPARATOR}") raise Prawn::SVG::UrlLoader::Error, "file path is not inside the root path of #{root_path}" end end - def build_absolute_path(path) - if path[0] == "/" - path - else - "#{root_path}/#{path}" - end + def build_absolute_and_expand_path(path) + ::File.expand_path(path, root_path) end def assert_valid_file_uri!(uri) if uri.host raise Prawn::SVG::UrlLoader::Error, "prawn-svg does not suport file: URLs with a host. Your URL probably doesn't start with three slashes, and it should." @@ -59,8 +85,20 @@ def assert_file_exists!(path) if !::File.exist?(path) raise Prawn::SVG::UrlLoader::Error, "File #{path} does not exist" end + end + + def fix_windows_path(path) + if matches = path.match(%r(\A/[a-z]:/)i) + path[1..-1] + else + path + end + end + + def windows? + !!(RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/) end end end