opal 0.3.15 → 0.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +8 -2
  3. data/README.md +1 -1
  4. data/Rakefile +51 -57
  5. data/bin/opal +50 -2
  6. data/{runtime/corelib → core}/alpha.rb +6 -1
  7. data/{runtime/corelib → core}/array.rb +38 -42
  8. data/{runtime/corelib → core}/basic_object.rb +6 -17
  9. data/core/boolean.rb +40 -0
  10. data/core/class.rb +69 -0
  11. data/{runtime/corelib → core}/comparable.rb +0 -0
  12. data/core/debug.js +59 -0
  13. data/core/debug.rb +35 -0
  14. data/core/dir.rb +90 -0
  15. data/core/enumerable.rb +331 -0
  16. data/core/enumerator.rb +126 -0
  17. data/core/error.rb +40 -0
  18. data/{runtime/corelib → core}/file.rb +6 -3
  19. data/core/gemlib.rb +30 -0
  20. data/{runtime/corelib → core}/hash.rb +37 -35
  21. data/{runtime/corelib → core}/io.rb +0 -0
  22. data/{runtime/corelib → core}/kernel.rb +26 -21
  23. data/{runtime/corelib → core}/load_order +2 -5
  24. data/{runtime/corelib → core}/match_data.rb +2 -4
  25. data/core/module.rb +204 -0
  26. data/{runtime/corelib → core}/nil_class.rb +1 -7
  27. data/{runtime/corelib → core}/numeric.rb +9 -13
  28. data/core/object.rb +17 -0
  29. data/{runtime/corelib → core}/proc.rb +2 -13
  30. data/{runtime/corelib → core}/range.rb +19 -7
  31. data/{runtime/corelib → core}/rational.rb +0 -0
  32. data/{runtime/corelib → core}/regexp.rb +2 -6
  33. data/core/runtime.js +672 -0
  34. data/{runtime/corelib → core}/string.rb +25 -9
  35. data/{runtime/corelib → core}/struct.rb +0 -0
  36. data/core/time.rb +111 -0
  37. data/{runtime/corelib → core}/top_self.rb +0 -0
  38. data/{runtime/spec → core_spec}/README.md +0 -0
  39. data/{runtime/spec → core_spec}/core/array/allocate_spec.rb +0 -0
  40. data/{runtime/spec → core_spec}/core/array/append_spec.rb +0 -0
  41. data/{runtime/spec → core_spec}/core/array/assoc_spec.rb +0 -0
  42. data/{runtime/spec → core_spec}/core/array/at_spec.rb +0 -0
  43. data/{runtime/spec → core_spec}/core/array/clear_spec.rb +0 -0
  44. data/{runtime/spec → core_spec}/core/array/collect_spec.rb +0 -0
  45. data/{runtime/spec → core_spec}/core/array/compact_spec.rb +0 -0
  46. data/{runtime/spec → core_spec}/core/array/concat_spec.rb +0 -0
  47. data/{runtime/spec → core_spec}/core/array/constructor_spec.rb +0 -0
  48. data/{runtime/spec → core_spec}/core/array/count_spec.rb +0 -0
  49. data/{runtime/spec → core_spec}/core/array/delete_at_spec.rb +0 -0
  50. data/{runtime/spec → core_spec}/core/array/delete_if_spec.rb +0 -0
  51. data/{runtime/spec → core_spec}/core/array/delete_spec.rb +0 -0
  52. data/{runtime/spec → core_spec}/core/array/each_index_spec.rb +0 -0
  53. data/{runtime/spec → core_spec}/core/array/each_spec.rb +0 -0
  54. data/{runtime/spec → core_spec}/core/array/element_reference_spec.rb +0 -0
  55. data/{runtime/spec → core_spec}/core/array/element_set_spec.rb +0 -0
  56. data/{runtime/spec → core_spec}/core/array/empty_spec.rb +0 -0
  57. data/{runtime/spec → core_spec}/core/array/eql_spec.rb +0 -0
  58. data/{runtime/spec → core_spec}/core/array/equal_value_spec.rb +0 -0
  59. data/{runtime/spec → core_spec}/core/array/fetch_spec.rb +0 -0
  60. data/{runtime/spec → core_spec}/core/array/first_spec.rb +0 -0
  61. data/{runtime/spec → core_spec}/core/array/fixtures/classes.rb +0 -0
  62. data/{runtime/spec → core_spec}/core/array/flatten_spec.rb +0 -0
  63. data/{runtime/spec → core_spec}/core/array/include_spec.rb +0 -0
  64. data/{runtime/spec → core_spec}/core/array/insert_spec.rb +0 -0
  65. data/{runtime/spec → core_spec}/core/array/last_spec.rb +0 -0
  66. data/{runtime/spec → core_spec}/core/array/length_spec.rb +0 -0
  67. data/{runtime/spec → core_spec}/core/array/map_spec.rb +0 -0
  68. data/{runtime/spec → core_spec}/core/array/plus_spec.rb +0 -0
  69. data/{runtime/spec → core_spec}/core/array/pop_spec.rb +0 -0
  70. data/{runtime/spec → core_spec}/core/array/push_spec.rb +0 -0
  71. data/{runtime/spec → core_spec}/core/array/rassoc_spec.rb +0 -0
  72. data/{runtime/spec → core_spec}/core/array/reject_spec.rb +0 -0
  73. data/{runtime/spec → core_spec}/core/array/replace_spec.rb +0 -0
  74. data/{runtime/spec → core_spec}/core/array/reverse_each_spec.rb +0 -0
  75. data/{runtime/spec → core_spec}/core/array/reverse_spec.rb +0 -0
  76. data/{runtime/spec → core_spec}/core/array/shared/collect.rb +0 -0
  77. data/{runtime/spec → core_spec}/core/array/shared/eql.rb +0 -0
  78. data/{runtime/spec → core_spec}/core/array/shared/length.rb +0 -0
  79. data/{runtime/spec → core_spec}/core/array/shared/replace.rb +0 -0
  80. data/{runtime/spec → core_spec}/core/class/new_spec.rb +0 -0
  81. data/{runtime/spec → core_spec}/core/enumerable/all_spec.rb +0 -0
  82. data/{runtime/spec → core_spec}/core/enumerable/any_spec.rb +0 -0
  83. data/{runtime/spec → core_spec}/core/enumerable/collect_spec.rb +0 -0
  84. data/{runtime/spec → core_spec}/core/enumerable/count_spec.rb +0 -0
  85. data/{runtime/spec → core_spec}/core/enumerable/detect_spec.rb +0 -0
  86. data/{runtime/spec → core_spec}/core/enumerable/find_spec.rb +0 -0
  87. data/core_spec/core/enumerable/first_spec.rb +3 -0
  88. data/{runtime/spec → core_spec}/core/enumerable/fixtures/classes.rb +0 -0
  89. data/{runtime/spec → core_spec}/core/enumerable/shared/collect.rb +0 -0
  90. data/{runtime/spec → core_spec}/core/enumerable/shared/entries.rb +0 -0
  91. data/{runtime/spec → core_spec}/core/enumerable/shared/find.rb +0 -0
  92. data/core_spec/core/enumerable/shared/take.rb +31 -0
  93. data/{runtime/spec → core_spec}/core/enumerable/to_a_spec.rb +0 -0
  94. data/{runtime/spec → core_spec}/core/false/and_spec.rb +0 -0
  95. data/{runtime/spec → core_spec}/core/false/inspect_spec.rb +0 -0
  96. data/{runtime/spec → core_spec}/core/false/or_spec.rb +0 -0
  97. data/{runtime/spec → core_spec}/core/false/to_s_spec.rb +0 -0
  98. data/{runtime/spec → core_spec}/core/false/xor_spec.rb +0 -0
  99. data/{runtime/spec → core_spec}/core/hash/allocate_spec.rb +0 -0
  100. data/{runtime/spec → core_spec}/core/hash/assoc_spec.rb +0 -0
  101. data/{runtime/spec → core_spec}/core/hash/clear_spec.rb +0 -0
  102. data/{runtime/spec → core_spec}/core/hash/clone_spec.rb +0 -0
  103. data/{runtime/spec → core_spec}/core/hash/default_spec.rb +0 -0
  104. data/{runtime/spec → core_spec}/core/hash/delete_if_spec.rb +0 -0
  105. data/{runtime/spec → core_spec}/core/hash/element_reference_spec.rb +0 -0
  106. data/{runtime/spec → core_spec}/core/hash/element_set_spec.rb +0 -0
  107. data/{runtime/spec → core_spec}/core/hash/new_spec.rb +0 -0
  108. data/{runtime/spec → core_spec}/core/matchdata/to_a_spec.rb +0 -0
  109. data/{runtime/spec → core_spec}/core/nil/and_spec.rb +0 -0
  110. data/{runtime/spec → core_spec}/core/nil/inspect_spec.rb +0 -0
  111. data/{runtime/spec → core_spec}/core/nil/nil_spec.rb +0 -0
  112. data/{runtime/spec → core_spec}/core/nil/or_spec.rb +0 -0
  113. data/{runtime/spec → core_spec}/core/nil/to_a_spec.rb +0 -0
  114. data/{runtime/spec → core_spec}/core/nil/to_f_spec.rb +0 -0
  115. data/{runtime/spec → core_spec}/core/nil/to_i_spec.rb +0 -0
  116. data/{runtime/spec → core_spec}/core/nil/to_s_spec.rb +0 -0
  117. data/{runtime/spec → core_spec}/core/nil/xor_spec.rb +0 -0
  118. data/{runtime/spec → core_spec}/core/numeric/equal_value_spec.rb +0 -0
  119. data/{runtime/spec → core_spec}/core/object/is_a_spec.rb +0 -0
  120. data/{runtime/spec → core_spec}/core/object/shared/kind_of.rb +0 -0
  121. data/{runtime/spec → core_spec}/core/regexp/match_spec.rb +0 -0
  122. data/{runtime/spec → core_spec}/core/regexp/shared/match.rb +0 -0
  123. data/{runtime/spec → core_spec}/core/symbol/to_proc_spec.rb +0 -0
  124. data/{runtime/spec → core_spec}/core/true/and_spec.rb +0 -0
  125. data/{runtime/spec → core_spec}/core/true/inspect_spec.rb +0 -0
  126. data/{runtime/spec → core_spec}/core/true/or_spec.rb +0 -0
  127. data/{runtime/spec → core_spec}/core/true/to_s_spec.rb +0 -0
  128. data/{runtime/spec → core_spec}/core/true/xor_spec.rb +0 -0
  129. data/{runtime/spec → core_spec}/language/alias_spec.rb +0 -0
  130. data/{runtime/spec → core_spec}/language/and_spec.rb +0 -0
  131. data/{runtime/spec → core_spec}/language/array_spec.rb +0 -0
  132. data/{runtime/spec → core_spec}/language/block_spec.rb +0 -0
  133. data/{runtime/spec → core_spec}/language/break_spec.rb +0 -0
  134. data/{runtime/spec → core_spec}/language/case_spec.rb +0 -0
  135. data/{runtime/spec → core_spec}/language/defined_spec.rb +0 -0
  136. data/{runtime/spec → core_spec}/language/ensure_spec.rb +0 -0
  137. data/{runtime/spec → core_spec}/language/fixtures/block.rb +0 -0
  138. data/{runtime/spec → core_spec}/language/fixtures/break.rb +0 -0
  139. data/{runtime/spec → core_spec}/language/fixtures/defined.rb +0 -0
  140. data/{runtime/spec → core_spec}/language/fixtures/ensure.rb +0 -0
  141. data/{runtime/spec → core_spec}/language/fixtures/next.rb +0 -0
  142. data/{runtime/spec → core_spec}/language/fixtures/send.rb +0 -0
  143. data/{runtime/spec → core_spec}/language/fixtures/super.rb +0 -0
  144. data/{runtime/spec → core_spec}/language/hash_spec.rb +0 -0
  145. data/{runtime/spec → core_spec}/language/if_spec.rb +0 -0
  146. data/{runtime/spec → core_spec}/language/loop_spec.rb +0 -0
  147. data/{runtime/spec → core_spec}/language/next_spec.rb +0 -0
  148. data/{runtime/spec → core_spec}/language/or_spec.rb +0 -0
  149. data/{runtime/spec → core_spec}/language/predefined_spec.rb +0 -0
  150. data/{runtime/spec → core_spec}/language/regexp/interpolation_spec.rb +8 -0
  151. data/{runtime/spec → core_spec}/language/regexp_spec.rb +0 -0
  152. data/{runtime/spec → core_spec}/language/send_spec.rb +0 -0
  153. data/{runtime/spec → core_spec}/language/string_spec.rb +0 -0
  154. data/{runtime/spec → core_spec}/language/super_spec.rb +0 -0
  155. data/{runtime/spec → core_spec}/language/symbol_spec.rb +0 -0
  156. data/{runtime/spec → core_spec}/language/undef_spec.rb +0 -0
  157. data/{runtime/spec → core_spec}/language/unless_spec.rb +0 -0
  158. data/{runtime/spec → core_spec}/language/until_spec.rb +0 -0
  159. data/core_spec/language/variables_spec.rb +112 -0
  160. data/{runtime/spec → core_spec}/language/versions/hash_1.9.rb +0 -0
  161. data/{runtime/spec → core_spec}/language/while_spec.rb +0 -0
  162. data/{runtime/spec → core_spec}/opal/opal/defined_spec.rb +0 -0
  163. data/{runtime/spec → core_spec}/opal/opal/function_spec.rb +0 -0
  164. data/{runtime/spec → core_spec}/opal/opal/native_spec.rb +0 -0
  165. data/{runtime/spec → core_spec}/opal/opal/null_spec.rb +0 -0
  166. data/{runtime/spec → core_spec}/opal/opal/number_spec.rb +0 -0
  167. data/{runtime/spec → core_spec}/opal/opal/object_spec.rb +0 -0
  168. data/{runtime/spec → core_spec}/opal/opal/string_spec.rb +0 -0
  169. data/{runtime/spec → core_spec}/opal/opal/typeof_spec.rb +0 -0
  170. data/{runtime/spec → core_spec}/opal/opal/undefined_spec.rb +0 -0
  171. data/{runtime/spec → core_spec}/opal/true/case_compare_spec.rb +0 -0
  172. data/{runtime/spec → core_spec}/opal/true/class_spec.rb +0 -0
  173. data/{docs/spec_runner.html → core_spec/release_runner.html} +4 -3
  174. data/core_spec/runner.html +16 -0
  175. data/core_spec/spec_helper.rb +23 -0
  176. data/lib/opal.rb +85 -2
  177. data/lib/opal/builder.rb +129 -46
  178. data/lib/opal/context.rb +47 -26
  179. data/lib/opal/dependency_builder.rb +113 -14
  180. data/lib/opal/environment.rb +40 -45
  181. data/lib/opal/parser/grammar.rb +2296 -2254
  182. data/lib/opal/parser/grammar.y +27 -8
  183. data/lib/opal/parser/lexer.rb +12 -3
  184. data/lib/opal/parser/parser.rb +117 -30
  185. data/lib/opal/parser/scope.rb +2 -2
  186. data/lib/opal/version.rb +1 -1
  187. data/opal.gemspec +3 -8
  188. data/spec/grammar/masgn_spec.rb +37 -0
  189. metadata +177 -227
  190. data/index.html +0 -434
  191. data/lib/opal/command.rb +0 -73
  192. data/runtime/README.md +0 -25
  193. data/runtime/corelib/boolean.rb +0 -44
  194. data/runtime/corelib/class.rb +0 -43
  195. data/runtime/corelib/complex.rb +0 -2
  196. data/runtime/corelib/dir.rb +0 -29
  197. data/runtime/corelib/enumerable.rb +0 -316
  198. data/runtime/corelib/enumerator.rb +0 -80
  199. data/runtime/corelib/error.rb +0 -25
  200. data/runtime/corelib/module.rb +0 -171
  201. data/runtime/corelib/native.rb +0 -50
  202. data/runtime/corelib/object.rb +0 -21
  203. data/runtime/corelib/time.rb +0 -196
  204. data/runtime/gemlib/alpha.rb +0 -5
  205. data/runtime/gemlib/kernel.rb +0 -17
  206. data/runtime/gemlib/load_order +0 -2
  207. data/runtime/kernel/class.js +0 -256
  208. data/runtime/kernel/debug.js +0 -42
  209. data/runtime/kernel/init.js +0 -114
  210. data/runtime/kernel/load_order +0 -5
  211. data/runtime/kernel/loader.js +0 -151
  212. data/runtime/kernel/runtime.js +0 -414
  213. data/runtime/spec/language/variables_spec.rb +0 -28
  214. data/runtime/spec/library/stringscanner/scan_spec.rb +0 -36
  215. data/runtime/spec/opal/forwardable/def_instance_delegator_spec.rb +0 -49
  216. data/runtime/spec/spec_helper.rb +0 -25
  217. data/runtime/stdlib/base64.rb +0 -91
  218. data/runtime/stdlib/date.rb +0 -4
  219. data/runtime/stdlib/dev.rb +0 -171
  220. data/runtime/stdlib/forwardable.rb +0 -33
  221. data/runtime/stdlib/optparse.rb +0 -0
  222. data/runtime/stdlib/pp.rb +0 -6
  223. data/runtime/stdlib/racc/parser.rb +0 -159
  224. data/runtime/stdlib/rbconfig.rb +0 -0
  225. data/runtime/stdlib/si.rb +0 -17
  226. data/runtime/stdlib/strscan.rb +0 -53
  227. data/runtime/stdlib/uri.rb +0 -111
  228. data/runtime/stdlib/uri/common.rb +0 -1014
  229. data/runtime/stdlib/uri/ftp.rb +0 -261
  230. data/runtime/stdlib/uri/generic.rb +0 -1599
  231. data/runtime/stdlib/uri/http.rb +0 -106
  232. data/runtime/stdlib/uri/https.rb +0 -22
  233. data/runtime/stdlib/uri/ldap.rb +0 -260
  234. data/runtime/stdlib/uri/ldaps.rb +0 -20
  235. data/runtime/stdlib/uri/mailto.rb +0 -280
  236. data/spec/builder/output_path_spec.rb +0 -50
@@ -1,261 +0,0 @@
1
- # = uri/ftp.rb
2
- #
3
- # Author:: Akira Yamada <akira@ruby-lang.org>
4
- # License:: You can redistribute it and/or modify it under the same term as Ruby.
5
- # Revision:: $Id$
6
- #
7
- # See URI for general documentation
8
- #
9
-
10
- require 'uri/generic'
11
-
12
- module URI
13
-
14
- #
15
- # FTP URI syntax is defined by RFC1738 section 3.2.
16
- #
17
- # This class will be redesigned because of difference of implementations;
18
- # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
19
- # is a good summary about the de facto spec.
20
- # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04
21
- #
22
- class FTP < Generic
23
- # A Default port of 21 for URI::FTP
24
- DEFAULT_PORT = 21
25
-
26
- #
27
- # An Array of the available components for URI::FTP
28
- #
29
- COMPONENT = [
30
- :scheme,
31
- :userinfo, :host, :port,
32
- :path, :typecode
33
- ].freeze
34
-
35
- #
36
- # Typecode is "a", "i" or "d".
37
- #
38
- # * "a" indicates a text file (the FTP command was ASCII)
39
- # * "i" indicates a binary file (FTP command IMAGE)
40
- # * "d" indicates the contents of a directory should be displayed
41
- #
42
- TYPECODE = ['a', 'i', 'd'].freeze
43
-
44
- # Typecode prefix
45
- # ';type='
46
- TYPECODE_PREFIX = ';type='.freeze
47
-
48
- # alternate initialization
49
- # Creates a new URI::FTP object.
50
- #
51
- # Unlike build(), this method does not escape the path component as
52
- # required by RFC1738; instead it is treated as per RFC2396.
53
- #
54
- # Arguments are user, password, host, port, path, typecode,
55
- # and arg_check, in that order.
56
- def self.new2(user, password, host, port, path,
57
- typecode = nil, arg_check = true)
58
- typecode = nil if typecode.size == 0
59
- if typecode && !TYPECODE.include?(typecode)
60
- raise ArgumentError,
61
- "bad typecode is specified: #{typecode}"
62
- end
63
-
64
- # do escape
65
-
66
- self.new('ftp',
67
- [user, password],
68
- host, port, nil,
69
- typecode ? path + TYPECODE_PREFIX + typecode : path,
70
- nil, nil, nil, arg_check)
71
- end
72
-
73
- #
74
- # == Description
75
- #
76
- # Creates a new URI::FTP object from components, with syntax checking.
77
- #
78
- # The components accepted are +userinfo+, +host+, +port+, +path+ and
79
- # +typecode+.
80
- #
81
- # The components should be provided either as an Array, or as a Hash
82
- # with keys formed by preceding the component names with a colon.
83
- #
84
- # If an Array is used, the components must be passed in the order
85
- # [userinfo, host, port, path, typecode]
86
- #
87
- # If the path supplied is absolute, it will be escaped in order to
88
- # make it absolute in the URI. Examples:
89
- #
90
- # require 'uri'
91
- #
92
- # uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
93
- # '/path/file.> zip', 'i'])
94
- # puts uri.to_s -> ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a
95
- #
96
- # uri2 = URI::FTP.build({:host => 'ftp.example.com',
97
- # :path => 'ruby/src'})
98
- # puts uri2.to_s -> ftp://ftp.example.com/ruby/src
99
- #
100
- def self.build(args)
101
-
102
- # Fix the incoming path to be generic URL syntax
103
- # FTP path -> URL path
104
- # foo/bar /foo/bar
105
- # /foo/bar /%2Ffoo/bar
106
- #
107
- if args.kind_of?(Array)
108
- args[3] = '/' + args[3].sub(/^\//, '%2F')
109
- else
110
- args[:path] = '/' + args[:path].sub(/^\//, '%2F')
111
- end
112
-
113
- tmp = Util::make_components_hash(self, args)
114
-
115
- if tmp[:typecode]
116
- if tmp[:typecode].size == 1
117
- tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode]
118
- end
119
- tmp[:path] << tmp[:typecode]
120
- end
121
-
122
- return super(tmp)
123
- end
124
-
125
- #
126
- # == Description
127
- #
128
- # Creates a new URI::FTP object from generic URL components with no
129
- # syntax checking.
130
- #
131
- # Unlike build(), this method does not escape the path component as
132
- # required by RFC1738; instead it is treated as per RFC2396.
133
- #
134
- # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
135
- # +opaque+, +query+ and +fragment+, in that order.
136
- #
137
- def initialize(*arg)
138
- arg[5] = arg[5].sub(/^\//,'').sub(/^%2F/,'/')
139
- super(*arg)
140
- @typecode = nil
141
- tmp = @path.index(TYPECODE_PREFIX)
142
- if tmp
143
- typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
144
- @path = @path[0..tmp - 1]
145
-
146
- if arg[-1]
147
- self.typecode = typecode
148
- else
149
- self.set_typecode(typecode)
150
- end
151
- end
152
- end
153
-
154
- # typecode accessor
155
- #
156
- # see URI::FTP::COMPONENT
157
- attr_reader :typecode
158
-
159
- # validates typecode +v+,
160
- # returns a +true+ or +false+ boolean
161
- #
162
- def check_typecode(v)
163
- if TYPECODE.include?(v)
164
- return true
165
- else
166
- raise InvalidComponentError,
167
- "bad typecode(expected #{TYPECODE.join(', ')}): #{v}"
168
- end
169
- end
170
- private :check_typecode
171
-
172
- # private setter for the typecode +v+
173
- #
174
- # see also URI::FTP.typecode=
175
- #
176
- def set_typecode(v)
177
- @typecode = v
178
- end
179
- protected :set_typecode
180
-
181
- #
182
- # == Args
183
- #
184
- # +v+::
185
- # String
186
- #
187
- # == Description
188
- #
189
- # public setter for the typecode +v+.
190
- # (with validation)
191
- #
192
- # see also URI::FTP.check_typecode
193
- #
194
- # == Usage
195
- #
196
- # require 'uri'
197
- #
198
- # uri = URI.parse("ftp://john@ftp.example.com/my_file.img")
199
- # #=> #<URI::FTP:0x00000000923650 URL:ftp://john@ftp.example.com/my_file.img>
200
- # uri.typecode = "i"
201
- # # => "i"
202
- # uri
203
- # #=> #<URI::FTP:0x00000000923650 URL:ftp://john@ftp.example.com/my_file.img;type=i>
204
- #
205
- def typecode=(typecode)
206
- check_typecode(typecode)
207
- set_typecode(typecode)
208
- typecode
209
- end
210
-
211
- def merge(oth) # :nodoc:
212
- tmp = super(oth)
213
- if self != tmp
214
- tmp.set_typecode(oth.typecode)
215
- end
216
-
217
- return tmp
218
- end
219
-
220
- # Returns the path from an FTP URI.
221
- #
222
- # RFC 1738 specifically states that the path for an FTP URI does not
223
- # include the / which separates the URI path from the URI host. Example:
224
- #
225
- # ftp://ftp.example.com/pub/ruby
226
- #
227
- # The above URI indicates that the client should connect to
228
- # ftp.example.com then cd pub/ruby from the initial login directory.
229
- #
230
- # If you want to cd to an absolute directory, you must include an
231
- # escaped / (%2F) in the path. Example:
232
- #
233
- # ftp://ftp.example.com/%2Fpub/ruby
234
- #
235
- # This method will then return "/pub/ruby"
236
- #
237
- def path
238
- return @path.sub(/^\//,'').sub(/^%2F/,'/')
239
- end
240
-
241
- def set_path(v)
242
- super("/" + v.sub(/^\//, "%2F"))
243
- end
244
- protected :set_path
245
-
246
- def to_s
247
- save_path = nil
248
- if @typecode
249
- save_path = @path
250
- @path = @path + TYPECODE_PREFIX + @typecode
251
- end
252
- str = super
253
- if @typecode
254
- @path = save_path
255
- end
256
-
257
- return str
258
- end
259
- end
260
- @@schemes['FTP'] = FTP
261
- end
@@ -1,1599 +0,0 @@
1
- # = uri/generic.rb
2
- #
3
- # Author:: Akira Yamada <akira@ruby-lang.org>
4
- # License:: You can redistribute it and/or modify it under the same term as Ruby.
5
- # Revision:: $Id$
6
- #
7
- # See URI for general documentation
8
- #
9
-
10
- require 'uri/common'
11
-
12
- module URI
13
-
14
- #
15
- # Base class for all URI classes.
16
- # Implements generic URI syntax as per RFC 2396.
17
- #
18
- class Generic
19
- include URI
20
-
21
- #
22
- # A Default port of nil for URI::Generic
23
- #
24
- DEFAULT_PORT = nil
25
-
26
- #
27
- # Returns default port
28
- #
29
- def self.default_port
30
- self::DEFAULT_PORT
31
- end
32
-
33
- #
34
- # Returns default port
35
- #
36
- def default_port
37
- self.class.default_port
38
- end
39
-
40
- #
41
- # An Array of the available components for URI::Generic
42
- #
43
- COMPONENT = [
44
- :scheme,
45
- :userinfo, :host, :port, :registry,
46
- :path, :opaque,
47
- :query,
48
- :fragment
49
- ].freeze
50
-
51
- #
52
- # Components of the URI in the order.
53
- #
54
- def self.component
55
- self::COMPONENT
56
- end
57
-
58
- #
59
- # Default to not use the registry for a URI::Generic
60
- #
61
- USE_REGISTRY = false
62
-
63
- #
64
- # Returns whether a registry of naming
65
- # authorities are being used.
66
- #
67
- def self.use_registry
68
- self::USE_REGISTRY
69
- end
70
-
71
- #
72
- # == Synopsis
73
- #
74
- # See #new
75
- #
76
- # == Description
77
- #
78
- # At first, tries to create a new URI::Generic instance using
79
- # URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
80
- # then it URI::Escape.escape all URI components and tries again.
81
- #
82
- #
83
- def self.build2(args)
84
- begin
85
- return self.build(args)
86
- rescue InvalidComponentError
87
- if args.kind_of?(Array)
88
- return self.build(args.collect{|x|
89
- if x
90
- parser.escape(x)
91
- else
92
- x
93
- end
94
- })
95
- elsif args.kind_of?(Hash)
96
- tmp = {}
97
- args.each do |key, value|
98
- tmp[key] = if value
99
- parser.escape(value)
100
- else
101
- value
102
- end
103
- end
104
- return self.build(tmp)
105
- end
106
- end
107
- end
108
-
109
- #
110
- # == Synopsis
111
- #
112
- # See #new
113
- #
114
- # == Description
115
- #
116
- # Creates a new URI::Generic instance from components of URI::Generic
117
- # with check. Components are: scheme, userinfo, host, port, registry, path,
118
- # opaque, query and fragment. You can provide arguments either by an Array or a Hash.
119
- # See #new for hash keys to use or for order of array items.
120
- #
121
- def self.build(args)
122
- if args.kind_of?(Array) &&
123
- args.size == ::URI::Generic::COMPONENT.size
124
- tmp = args
125
- elsif args.kind_of?(Hash)
126
- tmp = ::URI::Generic::COMPONENT.collect do |c|
127
- if args.include?(c)
128
- args[c]
129
- else
130
- nil
131
- end
132
- end
133
- else
134
- raise ArgumentError,
135
- "expected Array of or Hash of components of #{self.class} (#{self.class.component.join(', ')})"
136
- end
137
-
138
- tmp << nil
139
- tmp << true
140
- return self.new(*tmp)
141
- end
142
- #
143
- # == Args
144
- #
145
- # +scheme+::
146
- # Protocol scheme, i.e. 'http','ftp','mailto' and so on.
147
- # +userinfo+::
148
- # User name and password, i.e. 'sdmitry:bla'
149
- # +host+::
150
- # Server host name
151
- # +port+::
152
- # Server port
153
- # +registry+::
154
- # Registry of naming authorities.
155
- # +path+::
156
- # Path on server
157
- # +opaque+::
158
- # Opaque part
159
- # +query+::
160
- # Query data
161
- # +fragment+::
162
- # A part of URI after '#' sign
163
- # +parser+::
164
- # Parser for internal use [URI::DEFAULT_PARSER by default]
165
- # +arg_check+::
166
- # Check arguments [false by default]
167
- #
168
- # == Description
169
- #
170
- # Creates a new URI::Generic instance from ``generic'' components without check.
171
- #
172
- def initialize(scheme,
173
- userinfo, host, port, registry,
174
- path, opaque,
175
- query,
176
- fragment,
177
- parser = DEFAULT_PARSER,
178
- arg_check = false)
179
- @scheme = nil
180
- @user = nil
181
- @password = nil
182
- @host = nil
183
- @port = nil
184
- @path = nil
185
- @query = nil
186
- @opaque = nil
187
- @registry = nil
188
- @fragment = nil
189
- @parser = parser == DEFAULT_PARSER ? nil : parser
190
-
191
- if arg_check
192
- self.scheme = scheme
193
- self.userinfo = userinfo
194
- self.host = host
195
- self.port = port
196
- self.path = path
197
- self.query = query
198
- self.opaque = opaque
199
- self.registry = registry
200
- self.fragment = fragment
201
- else
202
- self.set_scheme(scheme)
203
- self.set_userinfo(userinfo)
204
- self.set_host(host)
205
- self.set_port(port)
206
- self.set_path(path)
207
- self.set_query(query)
208
- self.set_opaque(opaque)
209
- self.set_registry(registry)
210
- self.set_fragment(fragment)
211
- end
212
- if @registry && !self.class.use_registry
213
- raise InvalidURIError,
214
- "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
215
- end
216
-
217
- @scheme.freeze if @scheme
218
- self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
219
- self.set_port(self.default_port) if self.default_port && !@port
220
- end
221
-
222
- #
223
- # returns the scheme component of the URI.
224
- #
225
- # URI("http://foo/bar/baz").scheme #=> "http"
226
- #
227
- attr_reader :scheme
228
-
229
- # returns the host component of the URI.
230
- #
231
- # URI("http://foo/bar/baz").host #=> "foo"
232
- #
233
- # It returns nil if no host component.
234
- #
235
- # URI("mailto:foo@example.org").host #=> nil
236
- #
237
- # The component doesn't contains the port number.
238
- #
239
- # URI("http://foo:8080/bar/baz").host #=> "foo"
240
- #
241
- # Since IPv6 addresses are wrapped by brackets in URIs,
242
- # this method returns IPv6 addresses wrapped by brackets.
243
- # This form is not appropriate to pass socket methods such as TCPSocket.open.
244
- # If unwrapped host names are required, use "hostname" method.
245
- #
246
- # URI("http://[::1]/bar/baz").host #=> "[::1]"
247
- # URI("http://[::1]/bar/baz").hostname #=> "::1"
248
- #
249
- attr_reader :host
250
-
251
- # returns the port component of the URI.
252
- #
253
- # URI("http://foo/bar/baz").port #=> "80"
254
- #
255
- # URI("http://foo:8080/bar/baz").port #=> "8080"
256
- #
257
- attr_reader :port
258
-
259
- # returns the registry component of the URI.
260
- #
261
- # (see RFC2396 Section 3.2)
262
- #
263
- attr_reader :registry
264
-
265
- # returns the path component of the URI.
266
- #
267
- # URI("http://foo/bar/baz").path #=> "/bar/baz"
268
- #
269
- attr_reader :path
270
-
271
- # returns the query component of the URI.
272
- #
273
- # URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar"
274
- #
275
- attr_reader :query
276
-
277
- # returns the opaque part of the URI.
278
- #
279
- # URI("mailto:foo@example.org").opaque #=> "foo@example.org"
280
- #
281
- # Portion of the path that does make use of the slash '/'.
282
- # The path typically refers to the absolute path and the opaque part.
283
- # (see RFC2396 Section 3 and 5.2)
284
- #
285
- attr_reader :opaque
286
-
287
- # returns the fragment component of the URI.
288
- #
289
- # URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies"
290
- #
291
- attr_reader :fragment
292
-
293
- # returns the parser to be used.
294
- #
295
- # Unless a URI::Parser is defined, then DEFAULT_PARSER is used.
296
- #
297
- def parser
298
- if !defined?(@parser) || !@parser
299
- DEFAULT_PARSER
300
- else
301
- @parser || DEFAULT_PARSER
302
- end
303
- end
304
-
305
- # replace self by other URI object
306
- def replace!(oth)
307
- if self.class != oth.class
308
- raise ArgumentError, "expected #{self.class} object"
309
- end
310
-
311
- component.each do |c|
312
- self.__send__("#{c}=", oth.__send__(c))
313
- end
314
- end
315
- private :replace!
316
-
317
- #
318
- # Components of the URI in the order.
319
- #
320
- def component
321
- self.class.component
322
- end
323
-
324
- #
325
- # check the scheme +v+ component against the URI::Parser Regexp for :SCHEME
326
- #
327
- def check_scheme(v)
328
- if v && parser.regexp[:SCHEME] !~ v
329
- raise InvalidComponentError,
330
- "bad component(expected scheme component): #{v}"
331
- end
332
-
333
- return true
334
- end
335
- private :check_scheme
336
-
337
- # protected setter for the scheme component +v+
338
- #
339
- # see also URI::Generic.scheme=
340
- #
341
- def set_scheme(v)
342
- @scheme = v
343
- end
344
- protected :set_scheme
345
-
346
- #
347
- # == Args
348
- #
349
- # +v+::
350
- # String
351
- #
352
- # == Description
353
- #
354
- # public setter for the scheme component +v+.
355
- # (with validation)
356
- #
357
- # see also URI::Generic.check_scheme
358
- #
359
- # == Usage
360
- #
361
- # require 'uri'
362
- #
363
- # uri = URI.parse("http://my.example.com")
364
- # uri.scheme = "https"
365
- # # => "https"
366
- # uri
367
- # #=> #<URI::HTTP:0x000000008e89e8 URL:https://my.example.com>
368
- #
369
- def scheme=(v)
370
- check_scheme(v)
371
- set_scheme(v)
372
- v
373
- end
374
-
375
- #
376
- # check the +user+ and +password+.
377
- #
378
- # If +password+ is not provided, then +user+ is
379
- # split, using URI::Generic.split_userinfo, to
380
- # pull +user+ and +password.
381
- #
382
- # see also URI::Generic.check_user, URI::Generic.check_password
383
- #
384
- def check_userinfo(user, password = nil)
385
- if !password
386
- user, password = split_userinfo(user)
387
- end
388
- check_user(user)
389
- check_password(password, user)
390
-
391
- return true
392
- end
393
- private :check_userinfo
394
-
395
- #
396
- # check the user +v+ component for RFC2396 compliance
397
- # and against the URI::Parser Regexp for :USERINFO
398
- #
399
- # Can not have a registry or opaque component defined,
400
- # with a user component defined.
401
- #
402
- def check_user(v)
403
- if @registry || @opaque
404
- raise InvalidURIError,
405
- "can not set user with registry or opaque"
406
- end
407
-
408
- return v unless v
409
-
410
- if parser.regexp[:USERINFO] !~ v
411
- raise InvalidComponentError,
412
- "bad component(expected userinfo component or user component): #{v}"
413
- end
414
-
415
- return true
416
- end
417
- private :check_user
418
-
419
- #
420
- # check the password +v+ component for RFC2396 compliance
421
- # and against the URI::Parser Regexp for :USERINFO
422
- #
423
- # Can not have a registry or opaque component defined,
424
- # with a user component defined.
425
- #
426
- def check_password(v, user = @user)
427
- if @registry || @opaque
428
- raise InvalidURIError,
429
- "can not set password with registry or opaque"
430
- end
431
- return v unless v
432
-
433
- if !user
434
- raise InvalidURIError,
435
- "password component depends user component"
436
- end
437
-
438
- if parser.regexp[:USERINFO] !~ v
439
- raise InvalidComponentError,
440
- "bad component(expected user component): #{v}"
441
- end
442
-
443
- return true
444
- end
445
- private :check_password
446
-
447
- #
448
- # Sets userinfo, argument is string like 'name:pass'
449
- #
450
- def userinfo=(userinfo)
451
- if userinfo.nil?
452
- return nil
453
- end
454
- check_userinfo(*userinfo)
455
- set_userinfo(*userinfo)
456
- # returns userinfo
457
- end
458
-
459
- #
460
- # == Args
461
- #
462
- # +v+::
463
- # String
464
- #
465
- # == Description
466
- #
467
- # public setter for the +user+ component.
468
- # (with validation)
469
- #
470
- # see also URI::Generic.check_user
471
- #
472
- # == Usage
473
- #
474
- # require 'uri'
475
- #
476
- # uri = URI.parse("http://john:S3nsit1ve@my.example.com")
477
- # uri.user = "sam"
478
- # # => "sam"
479
- # uri
480
- # #=> #<URI::HTTP:0x00000000881d90 URL:http://sam:V3ry_S3nsit1ve@my.example.com>
481
- #
482
- def user=(user)
483
- check_user(user)
484
- set_user(user)
485
- # returns user
486
- end
487
-
488
- #
489
- # == Args
490
- #
491
- # +v+::
492
- # String
493
- #
494
- # == Description
495
- #
496
- # public setter for the +password+ component.
497
- # (with validation)
498
- #
499
- # see also URI::Generic.check_password
500
- #
501
- # == Usage
502
- #
503
- # require 'uri'
504
- #
505
- # uri = URI.parse("http://john:S3nsit1ve@my.example.com")
506
- # uri.password = "V3ry_S3nsit1ve"
507
- # # => "V3ry_S3nsit1ve"
508
- # uri
509
- # #=> #<URI::HTTP:0x00000000881d90 URL:http://john:V3ry_S3nsit1ve@my.example.com>
510
- #
511
- def password=(password)
512
- check_password(password)
513
- set_password(password)
514
- # returns password
515
- end
516
-
517
- # protect setter for the +user+ component, and +password+ if available.
518
- # (with validation)
519
- #
520
- # see also URI::Generic.userinfo=
521
- #
522
- def set_userinfo(user, password = nil)
523
- unless password
524
- user, password = split_userinfo(user)
525
- end
526
- @user = user
527
- @password = password if password
528
-
529
- [@user, @password]
530
- end
531
- protected :set_userinfo
532
-
533
- # protected setter for the user component +v+
534
- #
535
- # see also URI::Generic.user=
536
- #
537
- def set_user(v)
538
- set_userinfo(v, @password)
539
- v
540
- end
541
- protected :set_user
542
-
543
- # protected setter for the password component +v+
544
- #
545
- # see also URI::Generic.password=
546
- #
547
- def set_password(v)
548
- @password = v
549
- # returns v
550
- end
551
- protected :set_password
552
-
553
- # returns the userinfo +ui+ as user, password
554
- # if properly formated as 'user:password'
555
- def split_userinfo(ui)
556
- return nil, nil unless ui
557
- user, password = ui.split(/:/, 2)
558
-
559
- return user, password
560
- end
561
- private :split_userinfo
562
-
563
- # escapes 'user:password' +v+ based on RFC 1738 section 3.1
564
- def escape_userpass(v)
565
- v = parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
566
- end
567
- private :escape_userpass
568
-
569
- # returns the userinfo, either as 'user' or 'user:password'
570
- def userinfo
571
- if @user.nil?
572
- nil
573
- elsif @password.nil?
574
- @user
575
- else
576
- @user + ':' + @password
577
- end
578
- end
579
-
580
- # returns the user component
581
- def user
582
- @user
583
- end
584
-
585
- # returns the password component
586
- def password
587
- @password
588
- end
589
-
590
- #
591
- # check the host +v+ component for RFC2396 compliance
592
- # and against the URI::Parser Regexp for :HOST
593
- #
594
- # Can not have a registry or opaque component defined,
595
- # with a host component defined.
596
- #
597
- def check_host(v)
598
- return v unless v
599
-
600
- if @registry || @opaque
601
- raise InvalidURIError,
602
- "can not set host with registry or opaque"
603
- elsif parser.regexp[:HOST] !~ v
604
- raise InvalidComponentError,
605
- "bad component(expected host component): #{v}"
606
- end
607
-
608
- return true
609
- end
610
- private :check_host
611
-
612
- # protected setter for the host component +v+
613
- #
614
- # see also URI::Generic.host=
615
- #
616
- def set_host(v)
617
- @host = v
618
- end
619
- protected :set_host
620
-
621
- #
622
- # == Args
623
- #
624
- # +v+::
625
- # String
626
- #
627
- # == Description
628
- #
629
- # public setter for the host component +v+.
630
- # (with validation)
631
- #
632
- # see also URI::Generic.check_host
633
- #
634
- # == Usage
635
- #
636
- # require 'uri'
637
- #
638
- # uri = URI.parse("http://my.example.com")
639
- # uri.host = "foo.com"
640
- # # => "foo.com"
641
- # uri
642
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://foo.com>
643
- #
644
- def host=(v)
645
- check_host(v)
646
- set_host(v)
647
- v
648
- end
649
-
650
- # extract the host part of the URI and unwrap brackets for IPv6 addresses.
651
- #
652
- # This method is same as URI::Generic#host except
653
- # brackets for IPv6 (andn future IP) addresses are removed.
654
- #
655
- # u = URI("http://[::1]/bar")
656
- # p u.hostname #=> "::1"
657
- # p u.host #=> "[::1]"
658
- #
659
- def hostname
660
- v = self.host
661
- /\A\[(.*)\]\z/ =~ v ? $1 : v
662
- end
663
-
664
- # set the host part of the URI as the argument with brackets for IPv6 addresses.
665
- #
666
- # This method is same as URI::Generic#host= except
667
- # the argument can be bare IPv6 address.
668
- #
669
- # u = URI("http://foo/bar")
670
- # p u.to_s #=> "http://foo/bar"
671
- # u.hostname = "::1"
672
- # p u.to_s #=> "http://[::1]/bar"
673
- #
674
- # If the arugument seems IPv6 address,
675
- # it is wrapped by brackets.
676
- #
677
- def hostname=(v)
678
- v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v
679
- self.host = v
680
- end
681
-
682
- #
683
- # check the port +v+ component for RFC2396 compliance
684
- # and against the URI::Parser Regexp for :PORT
685
- #
686
- # Can not have a registry or opaque component defined,
687
- # with a port component defined.
688
- #
689
- def check_port(v)
690
- return v unless v
691
-
692
- if @registry || @opaque
693
- raise InvalidURIError,
694
- "can not set port with registry or opaque"
695
- elsif !v.kind_of?(Fixnum) && parser.regexp[:PORT] !~ v
696
- raise InvalidComponentError,
697
- "bad component(expected port component): #{v}"
698
- end
699
-
700
- return true
701
- end
702
- private :check_port
703
-
704
- # protected setter for the port component +v+
705
- #
706
- # see also URI::Generic.port=
707
- #
708
- def set_port(v)
709
- unless !v || v.kind_of?(Fixnum)
710
- if v.empty?
711
- v = nil
712
- else
713
- v = v.to_i
714
- end
715
- end
716
- @port = v
717
- end
718
- protected :set_port
719
-
720
- #
721
- # == Args
722
- #
723
- # +v+::
724
- # String
725
- #
726
- # == Description
727
- #
728
- # public setter for the port component +v+.
729
- # (with validation)
730
- #
731
- # see also URI::Generic.check_port
732
- #
733
- # == Usage
734
- #
735
- # require 'uri'
736
- #
737
- # uri = URI.parse("http://my.example.com")
738
- # uri.port = 8080
739
- # # => 8080
740
- # uri
741
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com:8080>
742
- #
743
- def port=(v)
744
- check_port(v)
745
- set_port(v)
746
- port
747
- end
748
-
749
- #
750
- # check the registry +v+ component for RFC2396 compliance
751
- # and against the URI::Parser Regexp for :REGISTRY
752
- #
753
- # Can not have a host, port or user component defined,
754
- # with a registry component defined.
755
- #
756
- def check_registry(v)
757
- return v unless v
758
-
759
- # raise if both server and registry are not nil, because:
760
- # authority = server | reg_name
761
- # server = [ [ userinfo "@" ] hostport ]
762
- if @host || @port || @user # userinfo = @user + ':' + @password
763
- raise InvalidURIError,
764
- "can not set registry with host, port, or userinfo"
765
- elsif v && parser.regexp[:REGISTRY] !~ v
766
- raise InvalidComponentError,
767
- "bad component(expected registry component): #{v}"
768
- end
769
-
770
- return true
771
- end
772
- private :check_registry
773
-
774
- # protected setter for the registry component +v+
775
- #
776
- # see also URI::Generic.registry=
777
- #
778
- def set_registry(v)
779
- @registry = v
780
- end
781
- protected :set_registry
782
-
783
- #
784
- # == Args
785
- #
786
- # +v+::
787
- # String
788
- #
789
- # == Description
790
- #
791
- # public setter for the registry component +v+.
792
- # (with validation)
793
- #
794
- # see also URI::Generic.check_registry
795
- #
796
- def registry=(v)
797
- check_registry(v)
798
- set_registry(v)
799
- v
800
- end
801
-
802
- #
803
- # check the path +v+ component for RFC2396 compliance
804
- # and against the URI::Parser Regexp
805
- # for :ABS_PATH and :REL_PATH
806
- #
807
- # Can not have a opaque component defined,
808
- # with a path component defined.
809
- #
810
- def check_path(v)
811
- # raise if both hier and opaque are not nil, because:
812
- # absoluteURI = scheme ":" ( hier_part | opaque_part )
813
- # hier_part = ( net_path | abs_path ) [ "?" query ]
814
- if v && @opaque
815
- raise InvalidURIError,
816
- "path conflicts with opaque"
817
- end
818
-
819
- # If scheme is ftp, path may be relative.
820
- # See RFC 1738 section 3.2.2, and RFC 2396.
821
- if @scheme && @scheme != "ftp"
822
- if v && v != '' && parser.regexp[:ABS_PATH] !~ v
823
- raise InvalidComponentError,
824
- "bad component(expected absolute path component): #{v}"
825
- end
826
- else
827
- if v && v != '' && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v
828
- raise InvalidComponentError,
829
- "bad component(expected relative path component): #{v}"
830
- end
831
- end
832
-
833
- return true
834
- end
835
- private :check_path
836
-
837
- # protected setter for the path component +v+
838
- #
839
- # see also URI::Generic.path=
840
- #
841
- def set_path(v)
842
- @path = v
843
- end
844
- protected :set_path
845
-
846
- #
847
- # == Args
848
- #
849
- # +v+::
850
- # String
851
- #
852
- # == Description
853
- #
854
- # public setter for the path component +v+.
855
- # (with validation)
856
- #
857
- # see also URI::Generic.check_path
858
- #
859
- # == Usage
860
- #
861
- # require 'uri'
862
- #
863
- # uri = URI.parse("http://my.example.com/pub/files")
864
- # uri.path = "/faq/"
865
- # # => "/faq/"
866
- # uri
867
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/faq/>
868
- #
869
- def path=(v)
870
- check_path(v)
871
- set_path(v)
872
- v
873
- end
874
-
875
- #
876
- # check the query +v+ component for RFC2396 compliance
877
- # and against the URI::Parser Regexp for :QUERY
878
- #
879
- # Can not have a opaque component defined,
880
- # with a query component defined.
881
- #
882
- def check_query(v)
883
- return v unless v
884
-
885
- # raise if both hier and opaque are not nil, because:
886
- # absoluteURI = scheme ":" ( hier_part | opaque_part )
887
- # hier_part = ( net_path | abs_path ) [ "?" query ]
888
- if @opaque
889
- raise InvalidURIError,
890
- "query conflicts with opaque"
891
- end
892
-
893
- if v && v != '' && parser.regexp[:QUERY] !~ v
894
- raise InvalidComponentError,
895
- "bad component(expected query component): #{v}"
896
- end
897
-
898
- return true
899
- end
900
- private :check_query
901
-
902
- # protected setter for the query component +v+
903
- #
904
- # see also URI::Generic.query=
905
- #
906
- def set_query(v)
907
- @query = v
908
- end
909
- protected :set_query
910
-
911
- #
912
- # == Args
913
- #
914
- # +v+::
915
- # String
916
- #
917
- # == Description
918
- #
919
- # public setter for the query component +v+.
920
- # (with validation)
921
- #
922
- # see also URI::Generic.check_query
923
- #
924
- # == Usage
925
- #
926
- # require 'uri'
927
- #
928
- # uri = URI.parse("http://my.example.com/?id=25")
929
- # uri.query = "id=1"
930
- # # => "id=1"
931
- # uri
932
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/?id=1>
933
- #
934
- def query=(v)
935
- check_query(v)
936
- set_query(v)
937
- v
938
- end
939
-
940
- #
941
- # check the opaque +v+ component for RFC2396 compliance and
942
- # against the URI::Parser Regexp for :OPAQUE
943
- #
944
- # Can not have a host, port, user or path component defined,
945
- # with an opaque component defined.
946
- #
947
- def check_opaque(v)
948
- return v unless v
949
-
950
- # raise if both hier and opaque are not nil, because:
951
- # absoluteURI = scheme ":" ( hier_part | opaque_part )
952
- # hier_part = ( net_path | abs_path ) [ "?" query ]
953
- if @host || @port || @user || @path # userinfo = @user + ':' + @password
954
- raise InvalidURIError,
955
- "can not set opaque with host, port, userinfo or path"
956
- elsif v && parser.regexp[:OPAQUE] !~ v
957
- raise InvalidComponentError,
958
- "bad component(expected opaque component): #{v}"
959
- end
960
-
961
- return true
962
- end
963
- private :check_opaque
964
-
965
- # protected setter for the opaque component +v+
966
- #
967
- # see also URI::Generic.opaque=
968
- #
969
- def set_opaque(v)
970
- @opaque = v
971
- end
972
- protected :set_opaque
973
-
974
- #
975
- # == Args
976
- #
977
- # +v+::
978
- # String
979
- #
980
- # == Description
981
- #
982
- # public setter for the opaque component +v+.
983
- # (with validation)
984
- #
985
- # see also URI::Generic.check_opaque
986
- #
987
- def opaque=(v)
988
- check_opaque(v)
989
- set_opaque(v)
990
- v
991
- end
992
-
993
- #
994
- # check the fragment +v+ component against the URI::Parser Regexp for :FRAGMENT
995
- #
996
- def check_fragment(v)
997
- return v unless v
998
-
999
- if v && v != '' && parser.regexp[:FRAGMENT] !~ v
1000
- raise InvalidComponentError,
1001
- "bad component(expected fragment component): #{v}"
1002
- end
1003
-
1004
- return true
1005
- end
1006
- private :check_fragment
1007
-
1008
- # protected setter for the fragment component +v+
1009
- #
1010
- # see also URI::Generic.fragment=
1011
- #
1012
- def set_fragment(v)
1013
- @fragment = v
1014
- end
1015
- protected :set_fragment
1016
-
1017
- #
1018
- # == Args
1019
- #
1020
- # +v+::
1021
- # String
1022
- #
1023
- # == Description
1024
- #
1025
- # public setter for the fragment component +v+.
1026
- # (with validation)
1027
- #
1028
- # see also URI::Generic.check_fragment
1029
- #
1030
- # == Usage
1031
- #
1032
- # require 'uri'
1033
- #
1034
- # uri = URI.parse("http://my.example.com/?id=25#time=1305212049")
1035
- # uri.fragment = "time=1305212086"
1036
- # # => "time=1305212086"
1037
- # uri
1038
- # #=> #<URI::HTTP:0x000000007a81f8 URL:http://my.example.com/?id=25#time=1305212086>
1039
- #
1040
- def fragment=(v)
1041
- check_fragment(v)
1042
- set_fragment(v)
1043
- v
1044
- end
1045
-
1046
- #
1047
- # Checks if URI has a path
1048
- #
1049
- def hierarchical?
1050
- if @path
1051
- true
1052
- else
1053
- false
1054
- end
1055
- end
1056
-
1057
- #
1058
- # Checks if URI is an absolute one
1059
- #
1060
- def absolute?
1061
- if @scheme
1062
- true
1063
- else
1064
- false
1065
- end
1066
- end
1067
- alias absolute absolute?
1068
-
1069
- #
1070
- # Checks if URI is relative
1071
- #
1072
- def relative?
1073
- !absolute?
1074
- end
1075
-
1076
- #
1077
- # returns an Array of the path split on '/'
1078
- #
1079
- def split_path(path)
1080
- path.split(%r{/+}, -1)
1081
- end
1082
- private :split_path
1083
-
1084
- #
1085
- # Merges a base path +base+, with relative path +rel+,
1086
- # returns a modified base path.
1087
- #
1088
- def merge_path(base, rel)
1089
-
1090
- # RFC2396, Section 5.2, 5)
1091
- # RFC2396, Section 5.2, 6)
1092
- base_path = split_path(base)
1093
- rel_path = split_path(rel)
1094
-
1095
- # RFC2396, Section 5.2, 6), a)
1096
- base_path << '' if base_path.last == '..'
1097
- while i = base_path.index('..')
1098
- base_path.slice!(i - 1, 2)
1099
- end
1100
-
1101
- if (first = rel_path.first) and first.empty?
1102
- base_path.clear
1103
- rel_path.shift
1104
- end
1105
-
1106
- # RFC2396, Section 5.2, 6), c)
1107
- # RFC2396, Section 5.2, 6), d)
1108
- rel_path.push('') if rel_path.last == '.' || rel_path.last == '..'
1109
- rel_path.delete('.')
1110
-
1111
- # RFC2396, Section 5.2, 6), e)
1112
- tmp = []
1113
- rel_path.each do |x|
1114
- if x == '..' &&
1115
- !(tmp.empty? || tmp.last == '..')
1116
- tmp.pop
1117
- else
1118
- tmp << x
1119
- end
1120
- end
1121
-
1122
- add_trailer_slash = !tmp.empty?
1123
- if base_path.empty?
1124
- base_path = [''] # keep '/' for root directory
1125
- elsif add_trailer_slash
1126
- base_path.pop
1127
- end
1128
- while x = tmp.shift
1129
- if x == '..'
1130
- # RFC2396, Section 4
1131
- # a .. or . in an absolute path has no special meaning
1132
- base_path.pop if base_path.size > 1
1133
- else
1134
- # if x == '..'
1135
- # valid absolute (but abnormal) path "/../..."
1136
- # else
1137
- # valid absolute path
1138
- # end
1139
- base_path << x
1140
- tmp.each {|t| base_path << t}
1141
- add_trailer_slash = false
1142
- break
1143
- end
1144
- end
1145
- base_path.push('') if add_trailer_slash
1146
-
1147
- return base_path.join('/')
1148
- end
1149
- private :merge_path
1150
-
1151
- #
1152
- # == Args
1153
- #
1154
- # +oth+::
1155
- # URI or String
1156
- #
1157
- # == Description
1158
- #
1159
- # Destructive form of #merge
1160
- #
1161
- # == Usage
1162
- #
1163
- # require 'uri'
1164
- #
1165
- # uri = URI.parse("http://my.example.com")
1166
- # uri.merge!("/main.rbx?page=1")
1167
- # p uri
1168
- # # => #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
1169
- #
1170
- def merge!(oth)
1171
- t = merge(oth)
1172
- if self == t
1173
- nil
1174
- else
1175
- replace!(t)
1176
- self
1177
- end
1178
- end
1179
-
1180
- #
1181
- # == Args
1182
- #
1183
- # +oth+::
1184
- # URI or String
1185
- #
1186
- # == Description
1187
- #
1188
- # Merges two URI's.
1189
- #
1190
- # == Usage
1191
- #
1192
- # require 'uri'
1193
- #
1194
- # uri = URI.parse("http://my.example.com")
1195
- # p uri.merge("/main.rbx?page=1")
1196
- # # => #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
1197
- #
1198
- def merge(oth)
1199
- begin
1200
- base, rel = merge0(oth)
1201
- rescue
1202
- raise $!.class, $!.message
1203
- end
1204
-
1205
- if base == rel
1206
- return base
1207
- end
1208
-
1209
- authority = rel.userinfo || rel.host || rel.port
1210
-
1211
- # RFC2396, Section 5.2, 2)
1212
- if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
1213
- base.set_fragment(rel.fragment) if rel.fragment
1214
- return base
1215
- end
1216
-
1217
- base.set_query(nil)
1218
- base.set_fragment(nil)
1219
-
1220
- # RFC2396, Section 5.2, 4)
1221
- if !authority
1222
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
1223
- else
1224
- # RFC2396, Section 5.2, 4)
1225
- base.set_path(rel.path) if rel.path
1226
- end
1227
-
1228
- # RFC2396, Section 5.2, 7)
1229
- base.set_userinfo(rel.userinfo) if rel.userinfo
1230
- base.set_host(rel.host) if rel.host
1231
- base.set_port(rel.port) if rel.port
1232
- base.set_query(rel.query) if rel.query
1233
- base.set_fragment(rel.fragment) if rel.fragment
1234
-
1235
- return base
1236
- end # merge
1237
- alias + merge
1238
-
1239
- # return base and rel.
1240
- # you can modify `base', but can not `rel'.
1241
- def merge0(oth)
1242
- oth = parser.send(:convert_to_uri, oth)
1243
-
1244
- if self.relative? && oth.relative?
1245
- raise BadURIError,
1246
- "both URI are relative"
1247
- end
1248
-
1249
- if self.absolute? && oth.absolute?
1250
- #raise BadURIError,
1251
- # "both URI are absolute"
1252
- # hmm... should return oth for usability?
1253
- return oth, oth
1254
- end
1255
-
1256
- if self.absolute?
1257
- return self.dup, oth
1258
- else
1259
- return oth, oth
1260
- end
1261
- end
1262
- private :merge0
1263
-
1264
- # :stopdoc:
1265
- def route_from_path(src, dst)
1266
- case dst
1267
- when src
1268
- # RFC2396, Section 4.2
1269
- return ''
1270
- when %r{(?:\A|/)\.\.?(?:/|\z)}
1271
- # dst has abnormal absolute path,
1272
- # like "/./", "/../", "/x/../", ...
1273
- return dst.dup
1274
- end
1275
-
1276
- src_path = src.scan(%r{(?:\A|[^/]+)/})
1277
- dst_path = dst.scan(%r{(?:\A|[^/]+)/?})
1278
-
1279
- # discard same parts
1280
- while !dst_path.empty? && dst_path.first == src_path.first
1281
- src_path.shift
1282
- dst_path.shift
1283
- end
1284
-
1285
- tmp = dst_path.join
1286
-
1287
- # calculate
1288
- if src_path.empty?
1289
- if tmp.empty?
1290
- return './'
1291
- elsif dst_path.first.include?(':') # (see RFC2396 Section 5)
1292
- return './' + tmp
1293
- else
1294
- return tmp
1295
- end
1296
- end
1297
-
1298
- return '../' * src_path.size + tmp
1299
- end
1300
- private :route_from_path
1301
- # :startdoc:
1302
-
1303
- # :stopdoc:
1304
- def route_from0(oth)
1305
- oth = parser.send(:convert_to_uri, oth)
1306
- if self.relative?
1307
- raise BadURIError,
1308
- "relative URI: #{self}"
1309
- end
1310
- if oth.relative?
1311
- raise BadURIError,
1312
- "relative URI: #{oth}"
1313
- end
1314
-
1315
- if self.scheme != oth.scheme
1316
- return self, self.dup
1317
- end
1318
- rel = URI::Generic.new(nil, # it is relative URI
1319
- self.userinfo, self.host, self.port,
1320
- self.registry, self.path, self.opaque,
1321
- self.query, self.fragment, parser)
1322
-
1323
- if rel.userinfo != oth.userinfo ||
1324
- rel.host.to_s.downcase != oth.host.to_s.downcase ||
1325
- rel.port != oth.port
1326
-
1327
- if self.userinfo.nil? && self.host.nil?
1328
- return self, self.dup
1329
- end
1330
-
1331
- rel.set_port(nil) if rel.port == oth.default_port
1332
- return rel, rel
1333
- end
1334
- rel.set_userinfo(nil)
1335
- rel.set_host(nil)
1336
- rel.set_port(nil)
1337
-
1338
- if rel.path && rel.path == oth.path
1339
- rel.set_path('')
1340
- rel.set_query(nil) if rel.query == oth.query
1341
- return rel, rel
1342
- elsif rel.opaque && rel.opaque == oth.opaque
1343
- rel.set_opaque('')
1344
- rel.set_query(nil) if rel.query == oth.query
1345
- return rel, rel
1346
- end
1347
-
1348
- # you can modify `rel', but can not `oth'.
1349
- return oth, rel
1350
- end
1351
- private :route_from0
1352
- # :startdoc:
1353
-
1354
- #
1355
- # == Args
1356
- #
1357
- # +oth+::
1358
- # URI or String
1359
- #
1360
- # == Description
1361
- #
1362
- # Calculates relative path from oth to self
1363
- #
1364
- # == Usage
1365
- #
1366
- # require 'uri'
1367
- #
1368
- # uri = URI.parse('http://my.example.com/main.rbx?page=1')
1369
- # p uri.route_from('http://my.example.com')
1370
- # #=> #<URI::Generic:0x20218858 URL:/main.rbx?page=1>
1371
- #
1372
- def route_from(oth)
1373
- # you can modify `rel', but can not `oth'.
1374
- begin
1375
- oth, rel = route_from0(oth)
1376
- rescue
1377
- raise $!.class, $!.message
1378
- end
1379
- if oth == rel
1380
- return rel
1381
- end
1382
-
1383
- rel.set_path(route_from_path(oth.path, self.path))
1384
- if rel.path == './' && self.query
1385
- # "./?foo" -> "?foo"
1386
- rel.set_path('')
1387
- end
1388
-
1389
- return rel
1390
- end
1391
-
1392
- alias - route_from
1393
-
1394
- #
1395
- # == Args
1396
- #
1397
- # +oth+::
1398
- # URI or String
1399
- #
1400
- # == Description
1401
- #
1402
- # Calculates relative path to oth from self
1403
- #
1404
- # == Usage
1405
- #
1406
- # require 'uri'
1407
- #
1408
- # uri = URI.parse('http://my.example.com')
1409
- # p uri.route_to('http://my.example.com/main.rbx?page=1')
1410
- # #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1>
1411
- #
1412
- def route_to(oth)
1413
- parser.send(:convert_to_uri, oth).route_from(self)
1414
- end
1415
-
1416
- #
1417
- # Returns normalized URI
1418
- #
1419
- def normalize
1420
- uri = dup
1421
- uri.normalize!
1422
- uri
1423
- end
1424
-
1425
- #
1426
- # Destructive version of #normalize
1427
- #
1428
- def normalize!
1429
- if path && path == ''
1430
- set_path('/')
1431
- end
1432
- if scheme && scheme != scheme.downcase
1433
- set_scheme(self.scheme.downcase)
1434
- end
1435
- if host && host != host.downcase
1436
- set_host(self.host.downcase)
1437
- end
1438
- end
1439
-
1440
- # returns the assemble String with path and query components
1441
- def path_query
1442
- str = @path
1443
- if @query
1444
- str += '?' + @query
1445
- end
1446
- str
1447
- end
1448
- private :path_query
1449
-
1450
- #
1451
- # Constructs String from URI
1452
- #
1453
- def to_s
1454
- str = ''
1455
- if @scheme
1456
- str << @scheme
1457
- str << ':'
1458
- end
1459
-
1460
- if @opaque
1461
- str << @opaque
1462
-
1463
- else
1464
- if @registry
1465
- str << @registry
1466
- else
1467
- if @host
1468
- str << '//'
1469
- end
1470
- if self.userinfo
1471
- str << self.userinfo
1472
- str << '@'
1473
- end
1474
- if @host
1475
- str << @host
1476
- end
1477
- if @port && @port != self.default_port
1478
- str << ':'
1479
- str << @port.to_s
1480
- end
1481
- end
1482
-
1483
- str << path_query
1484
- end
1485
-
1486
- if @fragment
1487
- str << '#'
1488
- str << @fragment
1489
- end
1490
-
1491
- str
1492
- end
1493
-
1494
- #
1495
- # Compares to URI's
1496
- #
1497
- def ==(oth)
1498
- if self.class == oth.class
1499
- self.normalize.component_ary == oth.normalize.component_ary
1500
- else
1501
- false
1502
- end
1503
- end
1504
-
1505
- def hash
1506
- self.component_ary.hash
1507
- end
1508
-
1509
- def eql?(oth)
1510
- self.class == oth.class &&
1511
- parser == oth.parser &&
1512
- self.component_ary.eql?(oth.component_ary)
1513
- end
1514
-
1515
- =begin
1516
-
1517
- --- URI::Generic#===(oth)
1518
-
1519
- =end
1520
- # def ===(oth)
1521
- # raise NotImplementedError
1522
- # end
1523
-
1524
- =begin
1525
- =end
1526
-
1527
-
1528
- # returns an Array of the components defined from the COMPONENT Array
1529
- def component_ary
1530
- component.collect do |x|
1531
- self.send(x)
1532
- end
1533
- end
1534
- protected :component_ary
1535
-
1536
- # == Args
1537
- #
1538
- # +components+::
1539
- # Multiple Symbol arguments defined in URI::HTTP
1540
- #
1541
- # == Description
1542
- #
1543
- # Selects specified components from URI
1544
- #
1545
- # == Usage
1546
- #
1547
- # require 'uri'
1548
- #
1549
- # uri = URI.parse('http://myuser:mypass@my.example.com/test.rbx')
1550
- # p uri.select(:userinfo, :host, :path)
1551
- # # => ["myuser:mypass", "my.example.com", "/test.rbx"]
1552
- #
1553
- def select(*components)
1554
- components.collect do |c|
1555
- if component.include?(c)
1556
- self.send(c)
1557
- else
1558
- raise ArgumentError,
1559
- "expected of components of #{self.class} (#{self.class.component.join(', ')})"
1560
- end
1561
- end
1562
- end
1563
-
1564
- @@to_s = Kernel.instance_method(:to_s)
1565
- def inspect
1566
- @@to_s.bind(self).call.sub!(/>\z/) {" URL:#{self}>"}
1567
- end
1568
-
1569
- #
1570
- # == Args
1571
- #
1572
- # +v+::
1573
- # URI or String
1574
- #
1575
- # == Description
1576
- #
1577
- # attempt to parse other URI +oth+
1578
- # return [parsed_oth, self]
1579
- #
1580
- # == Usage
1581
- #
1582
- # require 'uri'
1583
- #
1584
- # uri = URI.parse("http://my.example.com")
1585
- # uri.coerce("http://foo.com")
1586
- # #=> [#<URI::HTTP:0x00000000bcb028 URL:http://foo.com/>, #<URI::HTTP:0x00000000d92178 URL:http://my.example.com>]
1587
- #
1588
- def coerce(oth)
1589
- case oth
1590
- when String
1591
- oth = parser.parse(oth)
1592
- else
1593
- super
1594
- end
1595
-
1596
- return oth, self
1597
- end
1598
- end
1599
- end