opal 0.3.11 → 0.3.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (282) hide show
  1. data/.gitignore +13 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +20 -0
  4. data/README.md +11 -116
  5. data/Rakefile +126 -0
  6. data/bin/opal +1 -2
  7. data/docs/spec_runner.html +16 -0
  8. data/index.html +434 -0
  9. data/lib/opal.rb +14 -15
  10. data/lib/opal/builder.rb +46 -148
  11. data/lib/opal/command.rb +45 -115
  12. data/lib/opal/context.rb +139 -78
  13. data/lib/opal/dependency_builder.rb +34 -0
  14. data/lib/opal/environment.rb +92 -0
  15. data/lib/opal/parser/grammar.rb +4915 -0
  16. data/lib/opal/{parser.y → parser/grammar.y} +430 -284
  17. data/lib/opal/parser/lexer.rb +1329 -0
  18. data/lib/opal/parser/parser.rb +1460 -0
  19. data/lib/opal/parser/scope.rb +140 -0
  20. data/lib/opal/parser/sexp.rb +17 -0
  21. data/lib/opal/version.rb +2 -1
  22. data/opal.gemspec +23 -0
  23. data/opal.js +3149 -4162
  24. data/runtime/README.md +25 -0
  25. data/runtime/corelib/alpha.rb +10 -0
  26. data/runtime/corelib/array.rb +962 -0
  27. data/runtime/corelib/basic_object.rb +66 -0
  28. data/runtime/corelib/boolean.rb +44 -0
  29. data/runtime/corelib/class.rb +43 -0
  30. data/runtime/corelib/comparable.rb +25 -0
  31. data/runtime/corelib/complex.rb +2 -0
  32. data/runtime/corelib/dir.rb +29 -0
  33. data/runtime/corelib/enumerable.rb +316 -0
  34. data/runtime/corelib/enumerator.rb +80 -0
  35. data/runtime/corelib/error.rb +25 -0
  36. data/runtime/corelib/file.rb +80 -0
  37. data/runtime/corelib/hash.rb +503 -0
  38. data/runtime/corelib/io.rb +44 -0
  39. data/runtime/corelib/kernel.rb +237 -0
  40. data/runtime/corelib/load_order +29 -0
  41. data/runtime/corelib/match_data.rb +37 -0
  42. data/runtime/corelib/module.rb +171 -0
  43. data/runtime/corelib/native.rb +50 -0
  44. data/runtime/corelib/nil_class.rb +47 -0
  45. data/runtime/corelib/numeric.rb +219 -0
  46. data/runtime/corelib/object.rb +21 -0
  47. data/runtime/corelib/proc.rb +42 -0
  48. data/runtime/corelib/range.rb +38 -0
  49. data/runtime/corelib/rational.rb +16 -0
  50. data/runtime/corelib/regexp.rb +63 -0
  51. data/runtime/corelib/string.rb +185 -0
  52. data/runtime/corelib/struct.rb +97 -0
  53. data/runtime/corelib/time.rb +196 -0
  54. data/runtime/corelib/top_self.rb +7 -0
  55. data/runtime/gemlib/alpha.rb +5 -0
  56. data/runtime/gemlib/kernel.rb +17 -0
  57. data/runtime/gemlib/load_order +2 -0
  58. data/runtime/kernel/class.js +256 -0
  59. data/runtime/kernel/debug.js +42 -0
  60. data/runtime/kernel/init.js +114 -0
  61. data/runtime/kernel/load_order +5 -0
  62. data/runtime/kernel/loader.js +151 -0
  63. data/runtime/kernel/runtime.js +414 -0
  64. data/runtime/spec/README.md +34 -0
  65. data/runtime/spec/core/array/allocate_spec.rb +15 -0
  66. data/runtime/spec/core/array/append_spec.rb +31 -0
  67. data/runtime/spec/core/array/assoc_spec.rb +29 -0
  68. data/runtime/spec/core/array/at_spec.rb +38 -0
  69. data/runtime/spec/core/array/clear_spec.rb +22 -0
  70. data/runtime/spec/core/array/collect_spec.rb +3 -0
  71. data/runtime/spec/core/array/compact_spec.rb +42 -0
  72. data/runtime/spec/core/array/concat_spec.rb +21 -0
  73. data/runtime/spec/core/array/constructor_spec.rb +24 -0
  74. data/runtime/spec/core/array/count_spec.rb +11 -0
  75. data/runtime/spec/core/array/delete_at_spec.rb +31 -0
  76. data/runtime/spec/core/array/delete_if_spec.rb +24 -0
  77. data/runtime/spec/core/array/delete_spec.rb +26 -0
  78. data/runtime/spec/core/array/each_index_spec.rb +33 -0
  79. data/runtime/spec/core/array/each_spec.rb +11 -0
  80. data/runtime/spec/core/array/element_reference_spec.rb +136 -0
  81. data/runtime/spec/core/array/element_set_spec.rb +7 -0
  82. data/runtime/spec/core/array/empty_spec.rb +10 -0
  83. data/runtime/spec/core/array/eql_spec.rb +3 -0
  84. data/runtime/spec/core/array/equal_value_spec.rb +3 -0
  85. data/runtime/spec/core/array/fetch_spec.rb +26 -0
  86. data/runtime/spec/core/array/first_spec.rb +54 -0
  87. data/runtime/spec/core/array/fixtures/classes.rb +8 -0
  88. data/runtime/spec/core/array/flatten_spec.rb +41 -0
  89. data/runtime/spec/core/array/include_spec.rb +20 -0
  90. data/runtime/spec/core/array/insert_spec.rb +59 -0
  91. data/runtime/spec/core/array/last_spec.rb +57 -0
  92. data/runtime/spec/core/array/length_spec.rb +3 -0
  93. data/runtime/spec/core/array/map_spec.rb +3 -0
  94. data/runtime/spec/core/array/plus_spec.rb +16 -0
  95. data/runtime/spec/core/array/pop_spec.rb +79 -0
  96. data/runtime/spec/core/array/push_spec.rb +19 -0
  97. data/runtime/spec/core/array/rassoc_spec.rb +12 -0
  98. data/runtime/spec/core/array/reject_spec.rb +54 -0
  99. data/runtime/spec/core/array/replace_spec.rb +3 -0
  100. data/runtime/spec/core/array/reverse_each_spec.rb +18 -0
  101. data/runtime/spec/core/array/reverse_spec.rb +9 -0
  102. data/runtime/spec/core/array/shared/collect.rb +53 -0
  103. data/runtime/spec/core/array/shared/eql.rb +19 -0
  104. data/runtime/spec/core/array/shared/length.rb +6 -0
  105. data/runtime/spec/core/array/shared/replace.rb +31 -0
  106. data/runtime/spec/core/class/new_spec.rb +19 -0
  107. data/runtime/spec/core/enumerable/all_spec.rb +102 -0
  108. data/runtime/spec/core/enumerable/any_spec.rb +115 -0
  109. data/runtime/spec/core/enumerable/collect_spec.rb +3 -0
  110. data/runtime/spec/core/enumerable/count_spec.rb +29 -0
  111. data/runtime/spec/core/enumerable/detect_spec.rb +3 -0
  112. data/runtime/spec/core/enumerable/find_spec.rb +3 -0
  113. data/runtime/spec/core/enumerable/fixtures/classes.rb +26 -0
  114. data/runtime/spec/core/enumerable/shared/collect.rb +12 -0
  115. data/runtime/spec/core/enumerable/shared/entries.rb +7 -0
  116. data/runtime/spec/core/enumerable/shared/find.rb +49 -0
  117. data/runtime/spec/core/enumerable/to_a_spec.rb +7 -0
  118. data/runtime/spec/core/false/and_spec.rb +11 -0
  119. data/runtime/spec/core/false/inspect_spec.rb +7 -0
  120. data/runtime/spec/core/false/or_spec.rb +11 -0
  121. data/runtime/spec/core/false/to_s_spec.rb +7 -0
  122. data/runtime/spec/core/false/xor_spec.rb +11 -0
  123. data/runtime/spec/core/hash/allocate_spec.rb +15 -0
  124. data/runtime/spec/core/hash/assoc_spec.rb +29 -0
  125. data/runtime/spec/core/hash/clear_spec.rb +21 -0
  126. data/runtime/spec/core/hash/clone_spec.rb +12 -0
  127. data/runtime/spec/core/hash/default_spec.rb +6 -0
  128. data/runtime/spec/core/hash/delete_if_spec.rb +15 -0
  129. data/runtime/spec/core/hash/element_reference_spec.rb +16 -0
  130. data/runtime/spec/core/hash/element_set_spec.rb +8 -0
  131. data/runtime/spec/core/hash/new_spec.rb +13 -0
  132. data/runtime/spec/core/matchdata/to_a_spec.rb +7 -0
  133. data/runtime/spec/core/nil/and_spec.rb +12 -0
  134. data/runtime/spec/core/nil/inspect_spec.rb +8 -0
  135. data/runtime/spec/core/nil/nil_spec.rb +8 -0
  136. data/runtime/spec/core/nil/or_spec.rb +12 -0
  137. data/runtime/spec/core/nil/to_a_spec.rb +8 -0
  138. data/runtime/spec/core/nil/to_f_spec.rb +12 -0
  139. data/runtime/spec/core/nil/to_i_spec.rb +12 -0
  140. data/runtime/spec/core/nil/to_s_spec.rb +8 -0
  141. data/runtime/spec/core/nil/xor_spec.rb +12 -0
  142. data/runtime/spec/core/numeric/equal_value_spec.rb +11 -0
  143. data/runtime/spec/core/object/is_a_spec.rb +2 -0
  144. data/runtime/spec/core/object/shared/kind_of.rb +0 -0
  145. data/runtime/spec/core/regexp/match_spec.rb +23 -0
  146. data/runtime/spec/core/regexp/shared/match.rb +11 -0
  147. data/runtime/spec/core/symbol/to_proc_spec.rb +8 -0
  148. data/runtime/spec/core/true/and_spec.rb +11 -0
  149. data/runtime/spec/core/true/inspect_spec.rb +7 -0
  150. data/runtime/spec/core/true/or_spec.rb +11 -0
  151. data/runtime/spec/core/true/to_s_spec.rb +7 -0
  152. data/runtime/spec/core/true/xor_spec.rb +11 -0
  153. data/runtime/spec/language/alias_spec.rb +25 -0
  154. data/runtime/spec/language/and_spec.rb +62 -0
  155. data/runtime/spec/language/array_spec.rb +68 -0
  156. data/runtime/spec/language/block_spec.rb +105 -0
  157. data/runtime/spec/language/break_spec.rb +49 -0
  158. data/runtime/spec/language/case_spec.rb +165 -0
  159. data/runtime/spec/language/defined_spec.rb +80 -0
  160. data/runtime/spec/language/ensure_spec.rb +82 -0
  161. data/runtime/spec/language/fixtures/block.rb +19 -0
  162. data/runtime/spec/language/fixtures/break.rb +39 -0
  163. data/runtime/spec/language/fixtures/defined.rb +9 -0
  164. data/runtime/spec/language/fixtures/ensure.rb +37 -0
  165. data/runtime/spec/language/fixtures/next.rb +46 -0
  166. data/runtime/spec/language/fixtures/send.rb +36 -0
  167. data/runtime/spec/language/fixtures/super.rb +43 -0
  168. data/runtime/spec/language/hash_spec.rb +43 -0
  169. data/runtime/spec/language/if_spec.rb +278 -0
  170. data/runtime/spec/language/loop_spec.rb +32 -0
  171. data/runtime/spec/language/next_spec.rb +128 -0
  172. data/runtime/spec/language/or_spec.rb +65 -0
  173. data/runtime/spec/language/predefined_spec.rb +21 -0
  174. data/runtime/spec/language/regexp/interpolation_spec.rb +9 -0
  175. data/runtime/spec/language/regexp_spec.rb +7 -0
  176. data/runtime/spec/language/send_spec.rb +105 -0
  177. data/runtime/spec/language/string_spec.rb +4 -0
  178. data/runtime/spec/language/super_spec.rb +18 -0
  179. data/runtime/spec/language/symbol_spec.rb +41 -0
  180. data/runtime/spec/language/undef_spec.rb +16 -0
  181. data/runtime/spec/language/unless_spec.rb +44 -0
  182. data/runtime/spec/language/until_spec.rb +137 -0
  183. data/runtime/spec/language/variables_spec.rb +28 -0
  184. data/runtime/spec/language/versions/hash_1.9.rb +20 -0
  185. data/runtime/spec/language/while_spec.rb +175 -0
  186. data/runtime/spec/library/stringscanner/scan_spec.rb +36 -0
  187. data/runtime/spec/opal/forwardable/def_instance_delegator_spec.rb +49 -0
  188. data/runtime/spec/opal/opal/defined_spec.rb +15 -0
  189. data/runtime/spec/opal/opal/function_spec.rb +11 -0
  190. data/runtime/spec/opal/opal/native_spec.rb +16 -0
  191. data/runtime/spec/opal/opal/null_spec.rb +10 -0
  192. data/runtime/spec/opal/opal/number_spec.rb +11 -0
  193. data/runtime/spec/opal/opal/object_spec.rb +16 -0
  194. data/runtime/spec/opal/opal/string_spec.rb +11 -0
  195. data/runtime/spec/opal/opal/typeof_spec.rb +9 -0
  196. data/runtime/spec/opal/opal/undefined_spec.rb +10 -0
  197. data/runtime/spec/opal/true/case_compare_spec.rb +12 -0
  198. data/runtime/spec/opal/true/class_spec.rb +10 -0
  199. data/runtime/spec/spec_helper.rb +25 -0
  200. data/runtime/stdlib/base64.rb +91 -0
  201. data/runtime/stdlib/date.rb +4 -0
  202. data/{stdlib → runtime/stdlib}/dev.rb +0 -0
  203. data/runtime/stdlib/forwardable.rb +33 -0
  204. data/runtime/stdlib/optparse.rb +0 -0
  205. data/runtime/stdlib/pp.rb +6 -0
  206. data/{stdlib → runtime/stdlib}/racc/parser.rb +0 -0
  207. data/runtime/stdlib/rbconfig.rb +0 -0
  208. data/runtime/stdlib/si.rb +17 -0
  209. data/runtime/stdlib/strscan.rb +53 -0
  210. data/runtime/stdlib/uri.rb +111 -0
  211. data/runtime/stdlib/uri/common.rb +1014 -0
  212. data/runtime/stdlib/uri/ftp.rb +261 -0
  213. data/runtime/stdlib/uri/generic.rb +1599 -0
  214. data/runtime/stdlib/uri/http.rb +106 -0
  215. data/runtime/stdlib/uri/https.rb +22 -0
  216. data/runtime/stdlib/uri/ldap.rb +260 -0
  217. data/runtime/stdlib/uri/ldaps.rb +20 -0
  218. data/runtime/stdlib/uri/mailto.rb +280 -0
  219. data/spec/builder/build_source_spec.rb +52 -0
  220. data/spec/builder/fixtures/build_source/adam.rb +0 -0
  221. data/spec/builder/fixtures/build_source/bar/a.rb +0 -0
  222. data/spec/builder/fixtures/build_source/bar/wow/b.rb +0 -0
  223. data/spec/builder/fixtures/build_source/bar/wow/cow/c.rb +0 -0
  224. data/spec/builder/fixtures/build_source/beynon.rb +0 -0
  225. data/spec/builder/fixtures/build_source/charles.js +0 -0
  226. data/spec/builder/fixtures/build_source/foo/a.rb +0 -0
  227. data/spec/builder/fixtures/build_source/foo/b.rb +0 -0
  228. data/spec/builder/fixtures/build_source/foo/x.js +0 -0
  229. data/spec/builder/fixtures/build_source/foo/y.js +0 -0
  230. data/spec/builder/output_path_spec.rb +50 -0
  231. data/spec/grammar/alias_spec.rb +26 -0
  232. data/spec/grammar/and_spec.rb +13 -0
  233. data/spec/grammar/array_spec.rb +22 -0
  234. data/spec/grammar/attrasgn_spec.rb +28 -0
  235. data/spec/grammar/begin_spec.rb +38 -0
  236. data/spec/grammar/block_spec.rb +12 -0
  237. data/spec/grammar/break_spec.rb +17 -0
  238. data/spec/grammar/call_spec.rb +58 -0
  239. data/spec/grammar/class_spec.rb +35 -0
  240. data/spec/grammar/const_spec.rb +13 -0
  241. data/spec/grammar/cvar_spec.rb +11 -0
  242. data/spec/grammar/def_spec.rb +60 -0
  243. data/spec/grammar/false_spec.rb +17 -0
  244. data/spec/grammar/file_spec.rb +7 -0
  245. data/spec/grammar/gvar_spec.rb +13 -0
  246. data/spec/grammar/hash_spec.rb +17 -0
  247. data/spec/grammar/iasgn_spec.rb +9 -0
  248. data/spec/grammar/if_spec.rb +26 -0
  249. data/spec/grammar/iter_spec.rb +59 -0
  250. data/spec/grammar/ivar_spec.rb +9 -0
  251. data/spec/grammar/lasgn_spec.rb +8 -0
  252. data/spec/grammar/line_spec.rb +8 -0
  253. data/spec/grammar/lvar_spec.rb +38 -0
  254. data/spec/grammar/module_spec.rb +27 -0
  255. data/spec/grammar/nil_spec.rb +17 -0
  256. data/spec/grammar/not_spec.rb +27 -0
  257. data/spec/grammar/op_asgn1_spec.rb +23 -0
  258. data/spec/grammar/op_asgn2_spec.rb +23 -0
  259. data/spec/grammar/or_spec.rb +13 -0
  260. data/spec/grammar/return_spec.rb +17 -0
  261. data/spec/grammar/sclass_spec.rb +20 -0
  262. data/spec/grammar/self_spec.rb +17 -0
  263. data/spec/grammar/str_spec.rb +96 -0
  264. data/spec/grammar/super_spec.rb +20 -0
  265. data/spec/grammar/true_spec.rb +17 -0
  266. data/spec/grammar/undef_spec.rb +15 -0
  267. data/spec/grammar/unless_spec.rb +13 -0
  268. data/spec/grammar/while_spec.rb +15 -0
  269. data/spec/grammar/xstr_spec.rb +116 -0
  270. data/spec/grammar/yield_spec.rb +20 -0
  271. data/spec/spec_helper.rb +9 -0
  272. metadata +346 -21
  273. data/lib/opal/bundle.rb +0 -34
  274. data/lib/opal/lexer.rb +0 -902
  275. data/lib/opal/nodes.rb +0 -2150
  276. data/lib/opal/parser.rb +0 -4894
  277. data/lib/opal/rake/bundle_task.rb +0 -63
  278. data/opal-parser.js +0 -8343
  279. data/stdlib/strscan.rb +0 -52
  280. data/templates/init/Rakefile +0 -7
  281. data/templates/init/index.html +0 -17
  282. data/templates/init/lib/__NAME__.rb +0 -2
@@ -0,0 +1,261 @@
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
@@ -0,0 +1,1599 @@
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