require 'open-uri' module TaliaUtil # Collection of IO methods than can be mixed into other classes module IoHelper # Generic "open" method for files and urls. This won't choke on file:// URLs and # will do some extra escaping on the URL. # # *Usage*: # # open_generic('someurl.foo') do |io| # ... # end # # See open_from_url for an explanation of the options def open_generic(url, options = {}) url = file_url(url) # Even though open-uri would also open local files, we avoid to mangle # the URL in open_from_url if(File.exist?(url)) File.open(url) { |io| yield(io) } else open_from_url(url, options) { |io| yield(io) } end end # Will try to figure out the "base", which is the parent directory or path. # If the base is a directory, this will return the directory name, but if # it is an URL, this will return an URI object. def base_for(url) url = file_url(url) if(File.exist?(url)) file = File.expand_path(url) File.directory?(file) ? file : File.dirname(file) else uri = URI.parse(url) # Remove everything after the last '/' uri.path.gsub!(/\/[^\/]+\Z/, '/') uri.fragment = nil uri end end # Opens the given (web) URL, using URL encoding and necessary substitutions. # The user must pass a block which will receive the io object from # the url. # # The options may contain the http authentication information and such. See # the documentation for open-uri for more information. Example for options: # # :http_basic_authentication => [login, password] # # *Example*: # # open_from_url('http://foobar.com/', :http_basic_authentication => ['user', 'secret']) do |io| # ... # end def open_from_url(url, options = {}) # Encode the URI (the inner decode will save already-encoded URI and should # do nothing to non-encoded URIs) url = URI.encode(URI.decode(url)) url.gsub!(/\[/, '%5B') # URI class doesn't like unescaped brackets url.gsub!(/\]/, '%5D') open_args = [ url ] open_args << options if(options) begin open(*open_args) do |io| yield(io) end rescue Exception => e raise(IOError, "Error loading #{url} (when file: #{url}, open_args: [#{open_args.join(', ')}]) #{e}") end end # Get the "file url" for the given uri, stripping a possible file:// from the front def file_url(uri) uri.gsub(/\Afile:\/\//, '') end end # End modules end