ruby-web 1.1.1

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 (190) hide show
  1. data/ChangeLog +474 -0
  2. data/INSTALL.txt +9 -0
  3. data/InstalledFiles +180 -0
  4. data/LICENSE.txt +74 -0
  5. data/Rakefile +529 -0
  6. data/TODO +65 -0
  7. data/doc/additional.xml +149 -0
  8. data/doc/core.xml +652 -0
  9. data/doc/credits/index.xml +52 -0
  10. data/doc/credits/php.contributors.xml +118 -0
  11. data/doc/credits/php.language-snippets.ent +622 -0
  12. data/doc/install/index.xml +136 -0
  13. data/doc/install/mac/index.xml +21 -0
  14. data/doc/install/ruby-web.install.rb.instructions.xml +7 -0
  15. data/doc/install/unix/index.xml +46 -0
  16. data/doc/install/win/apache1.xml +166 -0
  17. data/doc/install/win/apache2.xml +141 -0
  18. data/doc/install/win/iis.xml +162 -0
  19. data/doc/install/win/index.xml +24 -0
  20. data/doc/install/win/installer.xml +31 -0
  21. data/doc/install/win/manual.xml +43 -0
  22. data/doc/manual.xml +69 -0
  23. data/doc/old/apache_cgi.txt +23 -0
  24. data/doc/old/fastcgi.txt +23 -0
  25. data/doc/old/mod_ruby.txt +21 -0
  26. data/doc/old/snippets.rdoc +183 -0
  27. data/doc/old/webrick.txt +23 -0
  28. data/doc/old/windows_cgi.txt +9 -0
  29. data/doc/tutorial.xml +14 -0
  30. data/doc/xsl/manual-multi.xsl +10 -0
  31. data/doc/xsl/manual-pdf.xsl +6 -0
  32. data/doc/xsl/manual-single.xsl +6 -0
  33. data/doc/xsl/manual.css +22 -0
  34. data/install.rb +1022 -0
  35. data/lib/formatter.rb +314 -0
  36. data/lib/html-parser.rb +429 -0
  37. data/lib/htmlrepair.rb +113 -0
  38. data/lib/htmlsplit.rb +842 -0
  39. data/lib/sgml-parser.rb +332 -0
  40. data/lib/web.rb +68 -0
  41. data/lib/web/assertinclude.rb +129 -0
  42. data/lib/web/config.rb +50 -0
  43. data/lib/web/connection.rb +1070 -0
  44. data/lib/web/convenience.rb +154 -0
  45. data/lib/web/formreader.rb +318 -0
  46. data/lib/web/htmlparser/html-parser.rb +429 -0
  47. data/lib/web/htmlparser/sgml-parser.rb +332 -0
  48. data/lib/web/htmltools/element.rb +296 -0
  49. data/lib/web/htmltools/stparser.rb +276 -0
  50. data/lib/web/htmltools/tags.rb +286 -0
  51. data/lib/web/htmltools/tree.rb +139 -0
  52. data/lib/web/htmltools/xmltree.rb +160 -0
  53. data/lib/web/htmltools/xpath.rb +71 -0
  54. data/lib/web/info.rb +63 -0
  55. data/lib/web/load.rb +210 -0
  56. data/lib/web/mime.rb +87 -0
  57. data/lib/web/phprb.rb +340 -0
  58. data/lib/web/resources/test/cookie.rb +33 -0
  59. data/lib/web/resources/test/counter.rb +20 -0
  60. data/lib/web/resources/test/multipart.rb +14 -0
  61. data/lib/web/resources/test/redirect.rb +8 -0
  62. data/lib/web/resources/test/stock.rb +33 -0
  63. data/lib/web/sapi/apache.rb +129 -0
  64. data/lib/web/sapi/fastcgi.rb +22 -0
  65. data/lib/web/sapi/install/apache.rb +180 -0
  66. data/lib/web/sapi/install/iis.rb +93 -0
  67. data/lib/web/sapi/install/macosx.rb +90 -0
  68. data/lib/web/sapi/webrick.rb +86 -0
  69. data/lib/web/session.rb +83 -0
  70. data/lib/web/shim/cgi.rb +129 -0
  71. data/lib/web/shim/rails.rb +175 -0
  72. data/lib/web/stringio.rb +78 -0
  73. data/lib/web/strscanparser.rb +24 -0
  74. data/lib/web/tagparser.rb +96 -0
  75. data/lib/web/testing.rb +666 -0
  76. data/lib/web/traceoutput.rb +75 -0
  77. data/lib/web/unit.rb +56 -0
  78. data/lib/web/upload.rb +59 -0
  79. data/lib/web/validate.rb +52 -0
  80. data/lib/web/wiki.rb +557 -0
  81. data/lib/web/wiki/linker.rb +72 -0
  82. data/lib/web/wiki/page.rb +201 -0
  83. data/lib/webunit.rb +27 -0
  84. data/lib/webunit/assert.rb +152 -0
  85. data/lib/webunit/converter.rb +154 -0
  86. data/lib/webunit/cookie.rb +118 -0
  87. data/lib/webunit/domwalker.rb +185 -0
  88. data/lib/webunit/exception.rb +14 -0
  89. data/lib/webunit/form.rb +116 -0
  90. data/lib/webunit/frame.rb +37 -0
  91. data/lib/webunit/htmlelem.rb +122 -0
  92. data/lib/webunit/image.rb +26 -0
  93. data/lib/webunit/jscript.rb +31 -0
  94. data/lib/webunit/link.rb +33 -0
  95. data/lib/webunit/params.rb +321 -0
  96. data/lib/webunit/parser.rb +229 -0
  97. data/lib/webunit/response.rb +464 -0
  98. data/lib/webunit/runtest.rb +41 -0
  99. data/lib/webunit/table.rb +148 -0
  100. data/lib/webunit/testcase.rb +45 -0
  101. data/lib/webunit/ui/cui/testrunner.rb +50 -0
  102. data/lib/webunit/utils.rb +68 -0
  103. data/lib/webunit/webunit.rb +28 -0
  104. data/test/dev/action.rb +83 -0
  105. data/test/dev/forms.rb +104 -0
  106. data/test/dev/forms2.rb +104 -0
  107. data/test/dev/parser.rb +17 -0
  108. data/test/dev/scripts/dump.rb +24 -0
  109. data/test/dev/scripts/makedist.rb +62 -0
  110. data/test/dev/scripts/uri.rb +41 -0
  111. data/test/dev/scripts/uri/common.rb +432 -0
  112. data/test/dev/scripts/uri/ftp.rb +149 -0
  113. data/test/dev/scripts/uri/generic.rb +1106 -0
  114. data/test/dev/scripts/uri/http.rb +76 -0
  115. data/test/dev/scripts/uri/https.rb +26 -0
  116. data/test/dev/scripts/uri/ldap.rb +238 -0
  117. data/test/dev/scripts/uri/mailto.rb +260 -0
  118. data/test/dev/scripts/urireg.rb +174 -0
  119. data/test/dev/simpledispatcher.rb +156 -0
  120. data/test/dev/test.action.rb +146 -0
  121. data/test/dev/test.formreader.rb +463 -0
  122. data/test/dev/test.simpledispatcher.rb +186 -0
  123. data/test/dev/webunit/conv/digit-0.rb +21 -0
  124. data/test/dev/webunit/conv/digit-1.rb +17 -0
  125. data/test/dev/webunit/conv/digit.rb +23 -0
  126. data/test/dev/webunit/conv/test_digit-0.rb +16 -0
  127. data/test/dev/webunit/conv/test_digit-1.rb +19 -0
  128. data/test/dev/webunit/conv/test_digit.rb +26 -0
  129. data/test/dev/webunit/conv/test_digit_view-0.rb +76 -0
  130. data/test/dev/webunit/conv/test_digit_view-1.rb +102 -0
  131. data/test/dev/webunit/conv/test_digit_view.rb +134 -0
  132. data/test/installation/htdocs/cgi_test.rb +296 -0
  133. data/test/installation/htdocs/test_install.rb +4 -0
  134. data/test/installation/runwebtest.rb +5 -0
  135. data/test/installation/test_cookie.rb +128 -0
  136. data/test/installation/test_form.rb +47 -0
  137. data/test/installation/test_multipart.rb +51 -0
  138. data/test/installation/test_request.rb +24 -0
  139. data/test/installation/test_response.rb +35 -0
  140. data/test/unit/htdocs/cookie.rb +32 -0
  141. data/test/unit/htdocs/multipart.rb +28 -0
  142. data/test/unit/htdocs/redirect.rb +12 -0
  143. data/test/unit/htdocs/simple.rb +13 -0
  144. data/test/unit/htdocs/stock.rb +33 -0
  145. data/test/unit/test_assert.rb +162 -0
  146. data/test/unit/test_cookie.rb +114 -0
  147. data/test/unit/test_domwalker.rb +77 -0
  148. data/test/unit/test_form.rb +42 -0
  149. data/test/unit/test_frame.rb +40 -0
  150. data/test/unit/test_htmlelem.rb +74 -0
  151. data/test/unit/test_image.rb +45 -0
  152. data/test/unit/test_jscript.rb +57 -0
  153. data/test/unit/test_link.rb +85 -0
  154. data/test/unit/test_multipart.rb +51 -0
  155. data/test/unit/test_params.rb +210 -0
  156. data/test/unit/test_parser.rb +53 -0
  157. data/test/unit/test_response.rb +150 -0
  158. data/test/unit/test_table.rb +70 -0
  159. data/test/unit/test_utils.rb +106 -0
  160. data/test/unit/test_webunit.rb +28 -0
  161. data/test/web/mod_ruby_stub.rb +39 -0
  162. data/test/web/test.assertinclude.rb +109 -0
  163. data/test/web/test.buffer.rb +182 -0
  164. data/test/web/test.code.loader.rb +78 -0
  165. data/test/web/test.config.rb +31 -0
  166. data/test/web/test.error.handling.rb +91 -0
  167. data/test/web/test.formreader-2.0.rb +352 -0
  168. data/test/web/test.load.rb +125 -0
  169. data/test/web/test.mime-type.rb +23 -0
  170. data/test/web/test.narf.cgi.rb +106 -0
  171. data/test/web/test.phprb.rb +239 -0
  172. data/test/web/test.request.rb +368 -0
  173. data/test/web/test.response.rb +637 -0
  174. data/test/web/test.ruby-web.rb +10 -0
  175. data/test/web/test.session.rb +50 -0
  176. data/test/web/test.shim.cgi.rb +96 -0
  177. data/test/web/test.tagparser.rb +65 -0
  178. data/test/web/test.template2.rb +297 -0
  179. data/test/web/test.testing2.rb +318 -0
  180. data/test/web/test.upload.rb +45 -0
  181. data/test/web/test.validate.rb +46 -0
  182. data/test/web/test.web.test.rb +495 -0
  183. data/test/wiki/test.history.rb +297 -0
  184. data/test/wiki/test.illustration_page.rb +287 -0
  185. data/test/wiki/test.linker.rb +197 -0
  186. data/test/wiki/test.tarpit.rb +56 -0
  187. data/test/wiki/test.wiki.rb +300 -0
  188. data/test/wikitestroot/admin.rb +7 -0
  189. data/test/wikitestroot/wiki.rb +6 -0
  190. metadata +234 -0
@@ -0,0 +1,104 @@
1
+
2
+ class Date # :nodoc:
3
+ def _dump(limit) Marshal.dump([@rjd, @sg], -1) end
4
+ def self._load(str) new0(*Marshal.load(str)) end
5
+ end
6
+
7
+ def encode64(bin) # :nodoc:
8
+ [bin].pack("m").gsub(/\n/,'').gsub(/=/,'.')
9
+ end
10
+
11
+ def decode64(str) # :nodoc:
12
+ str.gsub(/\./,'=').unpack("m")[0]
13
+ end
14
+
15
+
16
+ module Web
17
+ module Request # :nodoc
18
+ def Request.typed_params params
19
+ params2 = {}
20
+ params.collect do |k,v|
21
+ if ! (k =~ /type/)
22
+ if (atype = params["#{k}-type"][0])
23
+ begin
24
+ params2[k] = eval(Web.unescape(atype)).unencode(v[0])
25
+ rescue
26
+ params2[k] = eval(Web.unescape(atype)).unencode(Web.unescape(v[0]))
27
+ end
28
+ else
29
+ if v[0].kind_of? String
30
+ params2[k] = v[0]
31
+ else
32
+ params2[k] = v[0]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ params2
38
+ end
39
+
40
+ def Request.parse_typed_params query_string
41
+ Request.typed_params(Web::Request.parse_query_string(query_string))
42
+ end
43
+ end
44
+
45
+ class << self
46
+ def encode_objects hash
47
+ newhash = {}
48
+ hash.each do |k,v|
49
+ v = ([] << v).flatten
50
+ v.each { |v|
51
+ if v.kind_of?(String)
52
+ newhash[k] = v
53
+ elsif
54
+ newhash[k] = Web.escape(v.encode)
55
+ newhash["#{k}-type"] = v.class.name
56
+ end
57
+ }
58
+ end
59
+ newhash
60
+ end
61
+
62
+ def typed_params
63
+ $__web__cgi.typed_params
64
+ end
65
+ end
66
+
67
+ class CGI
68
+ def typed_params
69
+ Request.typed_params multiple_params
70
+ end
71
+
72
+ def make_query_string params
73
+ params.collect do |a,b|
74
+ "#{a}=#{Web.escape(b)}"
75
+ end.join("&")
76
+ end
77
+
78
+ def query
79
+ if Web["__submitted"] != ""
80
+ aquery = {}
81
+ typed_params.each do |k,v|
82
+ if k =~ /^__q\.(.+)/
83
+ aquery[$1] = v
84
+ end
85
+ end
86
+ aquery
87
+ else
88
+ typed_params
89
+ end
90
+ end
91
+
92
+ def reset_headers
93
+ @headers_sent = false
94
+ end
95
+
96
+ def script_path
97
+ if m = /(.*)\//.match(Web.get_cgi.script_name)
98
+ $1
99
+ else
100
+ ""
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,104 @@
1
+
2
+ class Date # :nodoc:
3
+ def _dump(limit) Marshal.dump([@rjd, @sg], -1) end
4
+ def self._load(str) new0(*Marshal.load(str)) end
5
+ end
6
+
7
+ def encode64(bin) # :nodoc:
8
+ [bin].pack("m").gsub(/\n/,'').gsub(/=/,'.')
9
+ end
10
+
11
+ def decode64(str) # :nodoc:
12
+ str.gsub(/\./,'=').unpack("m")[0]
13
+ end
14
+
15
+
16
+ module Web
17
+ module Request # :nodoc
18
+ def Request.typed_params params
19
+ params2 = {}
20
+ params.collect do |k,v|
21
+ if ! (k =~ /type/)
22
+ if (atype = params["#{k}-type"][0])
23
+ begin
24
+ params2[k] = eval(Web.unescape(atype)).unencode(v[0])
25
+ rescue
26
+ params2[k] = eval(Web.unescape(atype)).unencode(Web.unescape(v[0]))
27
+ end
28
+ else
29
+ if v[0].kind_of? String
30
+ params2[k] = v[0]
31
+ else
32
+ params2[k] = v[0]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ params2
38
+ end
39
+
40
+ def Request.parse_typed_params query_string
41
+ Request.typed_params(Web::Request.parse_query_string(query_string))
42
+ end
43
+ end
44
+
45
+ class << self
46
+ def encode_objects hash
47
+ newhash = {}
48
+ hash.each do |k,v|
49
+ v = ([] << v).flatten
50
+ v.each { |v|
51
+ if v.kind_of?(String)
52
+ newhash[k] = v
53
+ elsif
54
+ newhash[k] = Web.escape(v.encode)
55
+ newhash["#{k}-type"] = v.class.name
56
+ end
57
+ }
58
+ end
59
+ newhash
60
+ end
61
+
62
+ def typed_params
63
+ $__web__cgi.typed_params
64
+ end
65
+ end
66
+
67
+ class CGI
68
+ def typed_params
69
+ Request.typed_params multiple_params
70
+ end
71
+
72
+ def make_query_string params
73
+ params.collect do |a,b|
74
+ "#{a}=#{Web.escape(b)}"
75
+ end.join("&")
76
+ end
77
+
78
+ def query
79
+ if Web["__submitted"] != ""
80
+ aquery = {}
81
+ typed_params.each do |k,v|
82
+ if k =~ /^__q\.(.+)/
83
+ aquery[$1] = v
84
+ end
85
+ end
86
+ aquery
87
+ else
88
+ typed_params
89
+ end
90
+ end
91
+
92
+ def reset_headers
93
+ @headers_sent = false
94
+ end
95
+
96
+ def script_path
97
+ if m = /(.*)\//.match(Web.get_cgi.script_name)
98
+ $1
99
+ else
100
+ ""
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,17 @@
1
+ # note this returns the un-arrayified version of the array
2
+ def parse_query_string_typed(query) #:nodoc: :notest:
3
+ params = parse_query_string query
4
+ params2 = {}
5
+ params.collect do |k,v|
6
+ if ! (k =~ /type/)
7
+ if (atype = params["#{k}#type"][0])
8
+ params2[k] = Module.const_get(atype.intern).unencode(v[0])
9
+ else
10
+ params2[k] = v[0]
11
+ end
12
+ end
13
+ end
14
+ params2
15
+ end
16
+
17
+
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/ruby
2
+
3
+ filename="/Users/patsplat/Desktop/temp.bin"
4
+
5
+ if (ENV['REQUEST_METHOD'] == "POST")
6
+ length = Integer(ENV['CONTENT_LENGTH'])
7
+ $stdin.binmode
8
+ contents = $stdin.read(length) or ''
9
+ File.open( filename, "w" ) { |file|
10
+ file.binmode
11
+ file.write( contents )
12
+ }
13
+ end
14
+
15
+ #Web['file'].save( '/Users/patsplat/Desktop/test.png' )
16
+
17
+ #Web::puts contents
18
+
19
+ #Web::send_file( '/Users/patsplat/Desktop/test.png' )
20
+
21
+ print "Content-type: text/html\r\n\r\n"
22
+ print "hello!<br>content-length: #{ length }<br>"
23
+ print "boundary: #{ ENV['CONTENT_TYPE'] }<br>"
24
+ print ENV.inspect
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/ruby
2
+
3
+ NARF_SVN_SERVER = "http://svn.narf-lib.org/svn/narf"
4
+
5
+ cwd = Dir.pwd
6
+
7
+ require 'ftools'
8
+
9
+ if ARGV.size != 3
10
+ puts "Usage: ruby scripts/makedist.rb username password 1.2.3"
11
+ puts ""
12
+ puts " * username and password are your narf svn credentials"
13
+ puts " * 1.2.3 is the narf release number"
14
+ exit
15
+ end
16
+
17
+ username = ARGV[0]
18
+ password = ARGV[1]
19
+ version = ARGV[2]
20
+
21
+ versiontag = "VERSION_#{version.gsub(/\./,'_')}"
22
+
23
+ system( "rm narf*.gem" )
24
+ gemspec = File.open( "narf.gemspec", "r" ) { |f|
25
+ f.read
26
+ }
27
+ gemspec.sub(/s.version = "\d.\d.\d"/,
28
+ "s.version = \"#{version}\"" )
29
+ File.open("narf.gemspec", "w" ) { |f|
30
+ f.write gemspec
31
+ }
32
+
33
+ svn = "svn --username #{username} --password #{ password }"
34
+ system( "#{svn} log > ChangeLog")
35
+ system( "#{svn} commit -m \"Preparing for #{version} release\"" )
36
+ system( "#{svn} delete #{NARF_SVN_SERVER}/releases/#{versiontag} -m \"Deleted any existing release branch for #{version}\"" )
37
+ system( "#{svn} copy #{NARF_SVN_SERVER}/trunk/ #{NARF_SVN_SERVER}/releases/#{versiontag} -m \"Created release branch for #{version}\"" )
38
+
39
+ Dir.mkdir( "../dist" ) unless( File.exists? "../dist" )
40
+ system("rm -Rf ../dist/narf-#{version}")
41
+ Dir.chdir("../dist")
42
+
43
+ system("#{svn} export #{NARF_SVN_SERVER}/releases/#{versiontag} narf-#{version}" )
44
+
45
+ system("cd narf-#{version}; ruby build.rb rdoc");
46
+ system("tar cvzf narf-#{version}.tgz narf-#{version}")
47
+
48
+ # update sourcefoge
49
+ system("ncftpput upload.sourceforge.net incoming narf-#{version}.tgz")
50
+
51
+ # build gems
52
+ Dir.chdir(cwd)
53
+ system("gem build narf.gemspec")
54
+ system("ncftpput upload.sourceforge.net incoming narf-#{version}.gem")
55
+
56
+ # update raa
57
+
58
+ # update ruby-forge
59
+
60
+
61
+
62
+
@@ -0,0 +1,41 @@
1
+ #
2
+ # $Id: uri.rb,v 1.1.1.1 2002/11/29 04:34:24 patsplat Exp $
3
+ #
4
+ # Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
5
+ # You can redistribute it and/or modify it under the same term as Ruby.
6
+ #
7
+
8
+ =begin
9
+
10
+ Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
11
+ You can redistribute it and/or modify it under the same term as Ruby.
12
+
13
+ = URI - URI support for Ruby
14
+
15
+ =end
16
+
17
+ module URI
18
+ VERSION_CODE = '000907'.freeze
19
+ VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
20
+ end
21
+
22
+ =begin
23
+
24
+ == Components
25
+
26
+ * ((<URI>)) Module
27
+ * ((<URI::Generic>)) Class
28
+ * ((<URI::FTP>)) Class
29
+ * ((<URI::HTTP>)) Class
30
+ * ((<URI::HTTPS>)) Class
31
+ * ((<URI::LDAP>)) Class
32
+ * ((<URI::MailTo>)) Class
33
+
34
+ =end
35
+ require 'uri/common'
36
+ require 'uri/generic'
37
+ require 'uri/ftp'
38
+ require 'uri/http'
39
+ require 'uri/https'
40
+ require 'uri/ldap'
41
+ require 'uri/mailto'
@@ -0,0 +1,432 @@
1
+ #
2
+ # $Id: common.rb,v 1.1.1.1 2002/11/29 04:34:25 patsplat Exp $
3
+ #
4
+ # Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
5
+ # You can redistribute it and/or modify it under the same term as Ruby.
6
+ #
7
+
8
+ =begin
9
+
10
+ == URI
11
+
12
+ =end
13
+
14
+ module URI
15
+ module REGEXP
16
+ module PATTERN
17
+ # RFC 2396 (URI Generic Syntax)
18
+ # RFC 2732 (IPv6 Literal Addresses in URL's)
19
+ # RFC 2373 (IPv6 Addressing Architecture)
20
+
21
+ # alpha = lowalpha | upalpha
22
+ ALPHA = "a-zA-Z"
23
+ # alphanum = alpha | digit
24
+ ALNUM = "#{ALPHA}\\d"
25
+
26
+ # hex = digit | "A" | "B" | "C" | "D" | "E" | "F" |
27
+ # "a" | "b" | "c" | "d" | "e" | "f"
28
+ HEX = "a-fA-F\\d"
29
+ # escaped = "%" hex hex
30
+ ESCAPED = "%[#{HEX}]{2}"
31
+ # mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
32
+ # "(" | ")"
33
+ # unreserved = alphanum | mark
34
+ UNRESERVED = "-_.!~*'()#{ALNUM}"
35
+ # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
36
+ # "$" | ","
37
+ # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
38
+ # "$" | "," | "[" | "]" (RFC 2732)
39
+ RESERVED = ";/?:@&=+$,\\[\\]"
40
+
41
+ # uric = reserved | unreserved | escaped
42
+ URIC = "(?:[#{UNRESERVED}#{RESERVED}]|#{ESCAPED})"
43
+ # uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
44
+ # "&" | "=" | "+" | "$" | ","
45
+ URIC_NO_SLASH = "(?:[#{UNRESERVED};?:@&=+$,]|#{ESCAPED})"
46
+ # query = *uric
47
+ QUERY = "#{URIC}*"
48
+ # fragment = *uric
49
+ FRAGMENT = "#{URIC}*"
50
+
51
+ # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
52
+ DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
53
+ # toplabel = alpha | alpha *( alphanum | "-" ) alphanum
54
+ TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
55
+ # hostname = *( domainlabel "." ) toplabel [ "." ]
56
+ HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
57
+
58
+ # RFC 2373, APPENDIX B:
59
+ # IPv6address = hexpart [ ":" IPv4address ]
60
+ # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
61
+ # hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
62
+ # hexseq = hex4 *( ":" hex4)
63
+ # hex4 = 1*4HEXDIG
64
+ #
65
+ # XXX: This definition has a flaw. "::" + IPv4address must be
66
+ # allowed too. Here is a replacement.
67
+ #
68
+ # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
69
+ IPV4ADDR = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
70
+ # hex4 = 1*4HEXDIG
71
+ HEX4 = "[#{HEX}]{1,4}"
72
+ # lastpart = hex4 | IPv4address
73
+ LASTPART = "(?:#{HEX4}|#{IPV4ADDR})"
74
+ # hexseq1 = *( hex4 ":" ) hex4
75
+ HEXSEQ1 = "(?:#{HEX4}:)*#{HEX4}"
76
+ # hexseq2 = *( hex4 ":" ) lastpart
77
+ HEXSEQ2 = "(?:#{HEX4}:)*#{LASTPART}"
78
+ # IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ]
79
+ IPV6ADDR = "(?:#{HEXSEQ2}|(?:#{HEXSEQ1})?::(?:#{HEXSEQ2})?)"
80
+
81
+ # IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT
82
+ # unused
83
+
84
+ # ipv6reference = "[" IPv6address "]" (RFC 2732)
85
+ IPV6REF = "\\[#{IPV6ADDR}\\]"
86
+
87
+ # host = hostname | IPv4address
88
+ # host = hostname | IPv4address | IPv6reference (RFC 2732)
89
+ HOST = "(?:#{HOSTNAME}|#{IPV4ADDR}|#{IPV6REF})"
90
+ # port = *digit
91
+ PORT = "\d*"
92
+ # hostport = host [ ":" port ]
93
+ HOSTPORT = "#{HOST}(?:#{PORT})?"
94
+
95
+ # userinfo = *( unreserved | escaped |
96
+ # ";" | ":" | "&" | "=" | "+" | "$" | "," )
97
+ USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})*"
98
+
99
+ # pchar = unreserved | escaped |
100
+ # ":" | "@" | "&" | "=" | "+" | "$" | ","
101
+ PCHAR = "(?:[#{UNRESERVED}:@&=+$,]|#{ESCAPED})"
102
+ # param = *pchar
103
+ PARAM = "#{PCHAR}*"
104
+ # segment = *pchar *( ";" param )
105
+ SEGMENT = "#{PCHAR}*(?:;#{PARAM})*"
106
+ # path_segments = segment *( "/" segment )
107
+ PATH_SEGMENTS = "#{SEGMENT}(?:/#{SEGMENT})*"
108
+
109
+ # server = [ [ userinfo "@" ] hostport ]
110
+ SERVER = "(?:#{USERINFO}@)?#{HOSTPORT}"
111
+ # reg_name = 1*( unreserved | escaped | "$" | "," |
112
+ # ";" | ":" | "@" | "&" | "=" | "+" )
113
+ REG_NAME = "(?:[#{UNRESERVED}$,;+@&=+]|#{ESCAPED})+"
114
+ # authority = server | reg_name
115
+ AUTHORITY = "(?:#{SERVER}|#{REG_NAME})"
116
+
117
+ # rel_segment = 1*( unreserved | escaped |
118
+ # ";" | "@" | "&" | "=" | "+" | "$" | "," )
119
+ REL_SEGMENT = "(?:[#{UNRESERVED};@&=+$,]|#{ESCAPED})+"
120
+
121
+ # scheme = alpha *( alpha | digit | "+" | "-" | "." )
122
+ SCHEME = "[#{ALPHA}][-+.#{ALPHA}\\d]*"
123
+
124
+ # abs_path = "/" path_segments
125
+ ABS_PATH = "/#{PATH_SEGMENTS}"
126
+ # rel_path = rel_segment [ abs_path ]
127
+ REL_PATH = "#{REL_SEGMENT}(?:#{ABS_PATH})?"
128
+ # net_path = "//" authority [ abs_path ]
129
+ NET_PATH = "//#{AUTHORITY}(?:#{ABS_PATH})?"
130
+
131
+ # hier_part = ( net_path | abs_path ) [ "?" query ]
132
+ HIER_PART = "(?:#{NET_PATH}|#{ABS_PATH})(?:\\?(?:#{QUERY}))?"
133
+ # opaque_part = uric_no_slash *uric
134
+ OPAQUE_PART = "#{URIC_NO_SLASH}#{URIC}*"
135
+
136
+ # absoluteURI = scheme ":" ( hier_part | opaque_part )
137
+ ABS_URI = "#{SCHEME}:(?:#{HIER_PART}|#{OPAQUE_PART})"
138
+ # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
139
+ REL_URI = "(?:#{NET_PATH}|#{ABS_PATH}|#{REL_PATH})(?:\\?#{QUERY})?"
140
+
141
+ # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
142
+ URI_REF = "(?:#{ABS_URI}|#{REL_URI})?(?:##{FRAGMENT})?"
143
+
144
+ # XXX:
145
+ X_ABS_URI = "
146
+ (#{PATTERN::SCHEME}): (?# 1: scheme)
147
+ (?:
148
+ (?:(?:
149
+ //(?:
150
+ (?:(?:(#{PATTERN::USERINFO})@)? (?# 2: userinfo)
151
+ (?:(#{PATTERN::HOST})(?::(\\d*))?))?(?# 3: host, 4: port)
152
+ |
153
+ (#{PATTERN::REG_NAME}) (?# 5: registry)
154
+ ))?
155
+ ((?!//)#{PATTERN::ABS_PATH})? (?# 6: path)
156
+ )(?:\\?(#{PATTERN::QUERY}))? (?# 7: query)
157
+ |
158
+ (#{PATTERN::OPAQUE_PART}) (?# 8: opaque)
159
+ )
160
+ (?:\\#(#{PATTERN::FRAGMENT}))? (?# 9: fragment)
161
+ "
162
+ X_REL_URI = "
163
+ (?:
164
+ (?:
165
+ //
166
+ (?:
167
+ (?:(#{PATTERN::USERINFO})@)? (?# 1: userinfo)
168
+ (#{PATTERN::HOST})?(?::(\\d*))? (?# 2: host, 3: port)
169
+ |
170
+ (#{PATTERN::REG_NAME}) (?# 4: registry)
171
+ )
172
+ )
173
+ |
174
+ (#{PATTERN::REL_SEGMENT}) (?# 5: rel_segment)
175
+ )?
176
+ (#{PATTERN::ABS_PATH})? (?# 6: abs_path)
177
+ (?:\\?(#{PATTERN::QUERY}))? (?# 7: query)
178
+ (?:\\#(#{PATTERN::FRAGMENT}))? (?# 8: fragment)
179
+ "
180
+ end # PATTERN
181
+
182
+ # for URI::split
183
+ ABS_URI = Regexp.new('^' + PATTERN::X_ABS_URI + '$', #'
184
+ Regexp::EXTENDED, 'N').freeze
185
+ REL_URI = Regexp.new('^' + PATTERN::X_REL_URI + '$', #'
186
+ Regexp::EXTENDED, 'N').freeze
187
+
188
+ # for URI::extract
189
+ URI_REF = Regexp.new(PATTERN::URI_REF, false, 'N').freeze
190
+ ABS_URI_REF = Regexp.new(PATTERN::X_ABS_URI, Regexp::EXTENDED, 'N').freeze
191
+ REL_URI_REF = Regexp.new(PATTERN::X_REL_URI, Regexp::EXTENDED, 'N').freeze
192
+
193
+ # for URI::escape/unescape
194
+ ESCAPED = Regexp.new(PATTERN::ESCAPED, false, 'N').freeze
195
+ UNSAFE = Regexp.new("[^#{PATTERN::UNRESERVED}#{PATTERN::RESERVED}]",
196
+ false, 'N').freeze
197
+
198
+ # for Generic#initialize
199
+ SCHEME = Regexp.new("^#{PATTERN::SCHEME}$", false, 'N').freeze #"
200
+ USERINFO = Regexp.new("^#{PATTERN::USERINFO}$", false, 'N').freeze #"
201
+ HOST = Regexp.new("^#{PATTERN::HOST}$", false, 'N').freeze #"
202
+ PORT = Regexp.new("^#{PATTERN::PORT}$", false, 'N').freeze #"
203
+ OPAQUE = Regexp.new("^#{PATTERN::OPAQUE_PART}$", false, 'N').freeze #"
204
+ REGISTRY = Regexp.new("^#{PATTERN::REG_NAME}$", false, 'N').freeze #"
205
+ ABS_PATH = Regexp.new("^#{PATTERN::ABS_PATH}$", false, 'N').freeze #"
206
+ REL_PATH = Regexp.new("^#{PATTERN::REL_PATH}$", false, 'N').freeze #"
207
+ QUERY = Regexp.new("^#{PATTERN::QUERY}$", false, 'N').freeze #"
208
+ FRAGMENT = Regexp.new("^#{PATTERN::FRAGMENT}$", false, 'N').freeze #"
209
+ end # REGEXP
210
+
211
+ module Util
212
+ def make_components_hash(klass, array_hash)
213
+ tmp = {}
214
+ if array_hash.kind_of?(Array) &&
215
+ array_hash.size == klass.component.size - 1
216
+ klass.component[1..-1].each_index do |i|
217
+ begin
218
+ tmp[klass.component[i + 1]] = array_hash[i].clone
219
+ rescue TypeError
220
+ tmp[klass.component[i + 1]] = array_hash[i]
221
+ end
222
+ end
223
+
224
+ elsif array_hash.kind_of?(Hash)
225
+ array_hash.each do |key, value|
226
+ begin
227
+ tmp[key] = value.clone
228
+ rescue TypeError
229
+ tmp[key] = value
230
+ end
231
+ end
232
+ else
233
+ raise ArgumentError,
234
+ "expected Array of or Hash of components of #{klass.to_s} (#{klass.component[1..-1].join(', ')})"
235
+ end
236
+ tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase
237
+
238
+ return tmp
239
+ end
240
+ module_function :make_components_hash
241
+ end
242
+
243
+ module Escape
244
+ include REGEXP
245
+
246
+ def escape(str, unsafe = UNSAFE)
247
+ unless unsafe.kind_of?(Regexp)
248
+ # perhaps unsafe is String object
249
+ unsafe = Regexp.new(Regexp.quote(unsafe), false, 'N')
250
+ end
251
+ str.gsub(unsafe) do |us|
252
+ tmp = ''
253
+ us.each_byte do |uc|
254
+ tmp << sprintf('%%%02X', uc)
255
+ end
256
+ tmp
257
+ end
258
+ end
259
+ alias encode escape
260
+
261
+ def unescape(str)
262
+ str.gsub(ESCAPED) do
263
+ $&[1,2].hex.chr
264
+ end
265
+ end
266
+ alias decode unescape
267
+ end
268
+
269
+ include REGEXP
270
+ extend Escape
271
+
272
+ @@schemes = {}
273
+
274
+ class Error < StandardError; end
275
+ class InvalidURIError < Error; end # it is not URI.
276
+ class InvalidComponentError < Error; end # it is not component of URI.
277
+ class BadURIError < Error; end # the URI is valid but it is bad for the position.
278
+
279
+ =begin
280
+
281
+ === Methods
282
+
283
+ --- URI::split(uri)
284
+
285
+ =end
286
+
287
+ def self.split(uri)
288
+ case uri
289
+ when ''
290
+ # null uri
291
+
292
+ when ABS_URI
293
+ scheme, userinfo, host, port,
294
+ registry, path, query, opaque, fragment = $~[1..-1]
295
+
296
+ # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
297
+
298
+ # absoluteURI = scheme ":" ( hier_part | opaque_part )
299
+ # hier_part = ( net_path | abs_path ) [ "?" query ]
300
+ # opaque_part = uric_no_slash *uric
301
+
302
+ # abs_path = "/" path_segments
303
+ # net_path = "//" authority [ abs_path ]
304
+
305
+ # authority = server | reg_name
306
+ # server = [ [ userinfo "@" ] hostport ]
307
+
308
+ if !scheme
309
+ raise InvalidURIError,
310
+ "bad URI(absolute but no scheme): #{uri}"
311
+ end
312
+ if !opaque && (!path && (!host && !registry))
313
+ raise InvalidURIError,
314
+ "bad URI(absolute but no path): #{uri}"
315
+ end
316
+
317
+ when REL_URI
318
+ scheme = nil
319
+ opaque = nil
320
+
321
+ userinfo, host, port, registry,
322
+ rel_segment, abs_path, query, fragment = $~[1..-1]
323
+ if rel_segment && abs_path
324
+ path = rel_segment + abs_path
325
+ elsif rel_segment
326
+ path = rel_segment
327
+ elsif abs_path
328
+ path = abs_path
329
+ end
330
+
331
+ # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
332
+
333
+ # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
334
+
335
+ # net_path = "//" authority [ abs_path ]
336
+ # abs_path = "/" path_segments
337
+ # rel_path = rel_segment [ abs_path ]
338
+
339
+ # authority = server | reg_name
340
+ # server = [ [ userinfo "@" ] hostport ]
341
+
342
+ else
343
+ raise InvalidURIError, "bad URI(is not URI?): #{uri}"
344
+ end
345
+
346
+ path = '' if !path && !opaque # (see RFC2396 Section 5.2)
347
+ ret = [
348
+ scheme,
349
+ userinfo, host, port, # X
350
+ registry, # X
351
+ path, # Y
352
+ opaque, # Y
353
+ query,
354
+ fragment
355
+ ]
356
+ return ret
357
+ end
358
+
359
+ =begin
360
+
361
+ --- URI::parse(uri_str)
362
+
363
+ =end
364
+ def self.parse(uri)
365
+ scheme, userinfo, host, port,
366
+ registry, path, opaque, query, fragment = self.split(uri)
367
+
368
+ if scheme && @@schemes.include?(scheme.upcase)
369
+ @@schemes[scheme.upcase].new(scheme, userinfo, host, port,
370
+ registry, path, opaque, query,
371
+ fragment)
372
+ else
373
+ Generic.new(scheme, userinfo, host, port,
374
+ registry, path, opaque, query,
375
+ fragment)
376
+ end
377
+ end
378
+
379
+ =begin
380
+
381
+ --- URI::join(str[, str, ...])
382
+
383
+ =end
384
+ def self.join(*str)
385
+ u = self.parse(str[0])
386
+ str[1 .. -1].each do |x|
387
+ u = u.merge(x)
388
+ end
389
+ u
390
+ end
391
+
392
+ =begin
393
+
394
+ --- URI::extract(str[, schemes])
395
+
396
+ =end
397
+ def self.extract(str, schemes = [])
398
+ urls = []
399
+ if schemes.size > 0
400
+ tmp = Regexp.new('(?:' + schemes.collect{|s|
401
+ Regexp.quote(s + ':')
402
+ }.join('|') + ')',
403
+ Regexp::IGNORECASE, 'N')
404
+ str.scan(tmp) {
405
+ tmp_str = $& + $'
406
+ if ABS_URI_REF =~ tmp_str
407
+ if block_given?
408
+ yield($&)
409
+ else
410
+ urls << $&
411
+ end
412
+ end
413
+ }
414
+
415
+ else
416
+ str.scan(ABS_URI_REF) {
417
+ if block_given?
418
+ yield($&)
419
+ else
420
+ urls << $&
421
+ end
422
+ }
423
+ end
424
+
425
+ if block_given?
426
+ return nil
427
+ else
428
+ return urls
429
+ end
430
+ end
431
+
432
+ end # URI