PageRenderTime 45ms CodeModel.GetById 27ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/Ruby/lib/ruby/1.8/uri/ftp.rb

http://github.com/agross/netopenspace
Ruby | 198 lines | 97 code | 22 blank | 79 comment | 15 complexity | 0a20367f152582a7420da61e441472f3 MD5 | raw file
  1#
  2# = uri/ftp.rb
  3#
  4# Author:: Akira Yamada <akira@ruby-lang.org>
  5# License:: You can redistribute it and/or modify it under the same term as Ruby.
  6# Revision:: $Id: ftp.rb 16085 2008-04-19 11:56:22Z knu $
  7#
  8
  9require 'uri/generic'
 10
 11module URI
 12
 13  #
 14  # FTP URI syntax is defined by RFC1738 section 3.2.
 15  #
 16  class FTP < Generic
 17    DEFAULT_PORT = 21
 18
 19    COMPONENT = [
 20      :scheme, 
 21      :userinfo, :host, :port,
 22      :path, :typecode
 23    ].freeze
 24    #
 25    # Typecode is "a", "i" or "d". 
 26    #
 27    # * "a" indicates a text file (the FTP command was ASCII)
 28    # * "i" indicates a binary file (FTP command IMAGE)
 29    # * "d" indicates the contents of a directory should be displayed
 30    #
 31    TYPECODE = ['a', 'i', 'd'].freeze
 32    TYPECODE_PREFIX = ';type='.freeze
 33
 34    def self.new2(user, password, host, port, path, 
 35                  typecode = nil, arg_check = true)
 36      typecode = nil if typecode.size == 0
 37      if typecode && !TYPECODE.include?(typecode)
 38        raise ArgumentError,
 39          "bad typecode is specified: #{typecode}"
 40      end
 41
 42      # do escape
 43
 44      self.new('ftp',
 45               [user, password], 
 46               host, port, nil, 
 47               typecode ? path + TYPECODE_PREFIX + typecode : path, 
 48               nil, nil, nil, arg_check)
 49    end
 50
 51    #
 52    # == Description
 53    #
 54    # Creates a new URI::FTP object from components, with syntax checking.  
 55    #
 56    # The components accepted are +userinfo+, +host+, +port+, +path+ and 
 57    # +typecode+.
 58    #
 59    # The components should be provided either as an Array, or as a Hash 
 60    # with keys formed by preceding the component names with a colon. 
 61    #
 62    # If an Array is used, the components must be passed in the order
 63    # [userinfo, host, port, path, typecode]
 64    #
 65    # If the path supplied is absolute, it will be escaped in order to
 66    # make it absolute in the URI. Examples:
 67    #
 68    #     require 'uri'
 69    #
 70    #     uri = URI::FTP.build(['user:password', 'ftp.example.com', nil, 
 71    #       '/path/file.> zip', 'i'])
 72    #     puts uri.to_s  ->  ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a
 73    #
 74    #     uri2 = URI::FTP.build({:host => 'ftp.example.com', 
 75    #       :path => 'ruby/src'})
 76    #     puts uri2.to_s  ->  ftp://ftp.example.com/ruby/src
 77    #
 78    def self.build(args)
 79
 80      # Fix the incoming path to be generic URL syntax
 81      # FTP path  ->  URL path
 82      # foo/bar       /foo/bar
 83      # /foo/bar      /%2Ffoo/bar
 84      #
 85      if args.kind_of?(Array)
 86        args[3] = '/' + args[3].sub(/^\//, '%2F')
 87      else
 88        args[:path] = '/' + args[:path].sub(/^\//, '%2F')
 89      end
 90
 91      tmp = Util::make_components_hash(self, args)
 92
 93      if tmp[:typecode]
 94        if tmp[:typecode].size == 1
 95          tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] 
 96        end
 97        tmp[:path] << tmp[:typecode]
 98      end
 99
100      return super(tmp)
101    end
102
103    #
104    # == Description
105    #
106    # Creates a new URI::FTP object from generic URL components with no
107    # syntax checking.
108    #
109    # Unlike build(), this method does not escape the path component as
110    # required by RFC1738; instead it is treated as per RFC2396.
111    #
112    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, 
113    # +opaque+, +query+ and +fragment+, in that order.
114    #
115    def initialize(*arg)
116      super(*arg)
117      @typecode = nil
118      tmp = @path.index(TYPECODE_PREFIX)
119      if tmp
120        typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
121        self.set_path(@path[0..tmp - 1])
122        
123        if arg[-1]
124          self.typecode = typecode
125        else
126          self.set_typecode(typecode)
127        end
128      end
129    end
130    attr_reader :typecode
131
132    def check_typecode(v)
133      if TYPECODE.include?(v)
134        return true
135      else
136        raise InvalidComponentError,
137          "bad typecode(expected #{TYPECODE.join(', ')}): #{v}"
138      end
139    end
140    private :check_typecode
141
142    def set_typecode(v)
143      @typecode = v
144    end
145    protected :set_typecode
146
147    def typecode=(typecode)
148      check_typecode(typecode)
149      set_typecode(typecode)
150      typecode
151    end
152
153    def merge(oth) # :nodoc:
154      tmp = super(oth)
155      if self != tmp
156        tmp.set_typecode(oth.typecode)
157      end
158
159      return tmp
160    end
161
162    # Returns the path from an FTP URI.
163    #
164    # RFC 1738 specifically states that the path for an FTP URI does not
165    # include the / which separates the URI path from the URI host. Example:
166    #
167    #     ftp://ftp.example.com/pub/ruby 
168    #
169    # The above URI indicates that the client should connect to 
170    # ftp.example.com then cd pub/ruby from the initial login directory.
171    #
172    # If you want to cd to an absolute directory, you must include an
173    # escaped / (%2F) in the path. Example:
174    #
175    #     ftp://ftp.example.com/%2Fpub/ruby
176    #
177    # This method will then return "/pub/ruby"
178    #
179    def path
180      return @path.sub(/^\//,'').sub(/^%2F/i,'/')
181    end
182
183    def to_s
184      save_path = nil
185      if @typecode
186        save_path = @path
187        @path = @path + TYPECODE_PREFIX + @typecode
188      end
189      str = super
190      if @typecode
191        @path = save_path
192      end
193
194      return str
195    end
196  end
197  @@schemes['FTP'] = FTP
198end