rhodes 1.5.4 → 1.5.5
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.
- data/Manifest.txt +11 -1
- data/Rakefile +1 -1
- data/lib/extensions/digest/ext/Rakefile +11 -6
- data/lib/extensions/digest/ext/build.bat +2 -0
- data/lib/extensions/uri/uri.rb +29 -0
- data/lib/extensions/uri/uri/common.rb +727 -0
- data/lib/extensions/uri/uri/ftp.rb +198 -0
- data/lib/extensions/uri/uri/generic.rb +1128 -0
- data/lib/extensions/uri/uri/http.rb +100 -0
- data/lib/extensions/uri/uri/https.rb +20 -0
- data/lib/extensions/uri/uri/ldap.rb +190 -0
- data/lib/extensions/uri/uri/ldaps.rb +12 -0
- data/lib/extensions/uri/uri/mailto.rb +266 -0
- data/lib/framework/rhodes.rb +2 -2
- data/lib/framework/rhom/rhom_db_adapter.rb +12 -26
- data/lib/framework/rhom/rhom_object_factory.rb +8 -1
- data/lib/framework/version.rb +2 -2
- data/lib/rhodes.rb +2 -2
- data/platform/android/Rhodes/AndroidManifest.xml +2 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +87 -42
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +58 -7
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/MainView.java +2 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +35 -19
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +4 -0
- data/platform/android/build/android.rake +30 -25
- data/platform/bb/build/rhodes_build.files +1 -1
- data/platform/bb/rhodes/rhodes.jdp +1 -1
- data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +1 -1
- data/platform/bb/rhodes/src/com/rho/rubyext/Alert.java +300 -0
- data/platform/bb/rhodes/src/com/rho/rubyext/GeoLocation.java +42 -5
- data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +3 -4
- data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +33 -107
- data/platform/iphone/Classes/RhoRunnerAppDelegate.m +2 -0
- data/platform/iphone/Info.plist +1 -1
- data/platform/iphone/rbuild/iphone.rake +1 -1
- data/platform/iphone/rhoextlib/rhoextlib.xcodeproj/project.pbxproj +4 -0
- data/platform/shared/common/RhoMutexLock.h +8 -1
- data/platform/shared/common/RhodesApp.cpp +1 -1
- data/platform/shared/db/DBAdapter.cpp +77 -8
- data/platform/shared/db/DBAdapter.h +24 -9
- data/platform/shared/db/DBResult.cpp +19 -0
- data/platform/shared/db/DBResult.h +7 -5
- data/platform/shared/net/HttpServer.cpp +2 -0
- data/platform/shared/ruby/ext/rho/rhoruby.c +55 -0
- data/platform/shared/ruby/ext/rho/rhoruby.h +9 -0
- data/platform/shared/ruby/ext/rho/rhosupport.c +13 -4
- data/platform/shared/ruby/ext/sqlite3_api/sqlite3_api_wrap.c +21 -0
- data/platform/shared/ruby/thread_pthread.c +4 -4
- data/platform/shared/ruby/thread_win32.c +4 -4
- data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +19 -1
- data/platform/shared/rubyJVM/src/com/rho/db/DBAdapter.java +57 -24
- data/platform/shared/rubyJVM/src/com/rho/net/NetRequest.java +6 -1
- data/platform/shared/rubyJVM/src/com/rho/sync/SyncSource.java +2 -2
- data/platform/shared/rubyJVM/src/com/rho/sync/SyncThread.java +5 -5
- data/platform/shared/sync/SyncSource.cpp +1 -1
- data/platform/shared/sync/SyncThread.cpp +6 -9
- data/platform/wm/rhodes/Rhodes.cpp +4 -0
- data/rakefile.rb +1 -1
- metadata +13 -3
- data/platform/bb/rhodes/src/rhomobile/Alert.java +0 -65
data/Manifest.txt
CHANGED
@@ -37,6 +37,7 @@ lib/extensions/debugger/debugger.rb
|
|
37
37
|
lib/extensions/digest/digest/hmac.rb
|
38
38
|
lib/extensions/digest/digest.rb
|
39
39
|
lib/extensions/digest/ext/build
|
40
|
+
lib/extensions/digest/ext/build.bat
|
40
41
|
lib/extensions/digest/ext/defs.h
|
41
42
|
lib/extensions/digest/ext/depend
|
42
43
|
lib/extensions/digest/ext/digest.c
|
@@ -161,6 +162,15 @@ lib/extensions/rholang/lang_sr.rb
|
|
161
162
|
lib/extensions/rholang/rhoerror_ru.rb
|
162
163
|
lib/extensions/rholang/rhomsg_ru.rb
|
163
164
|
lib/extensions/set/set.rb
|
165
|
+
lib/extensions/uri/uri/common.rb
|
166
|
+
lib/extensions/uri/uri/ftp.rb
|
167
|
+
lib/extensions/uri/uri/generic.rb
|
168
|
+
lib/extensions/uri/uri/http.rb
|
169
|
+
lib/extensions/uri/uri/https.rb
|
170
|
+
lib/extensions/uri/uri/ldap.rb
|
171
|
+
lib/extensions/uri/uri/ldaps.rb
|
172
|
+
lib/extensions/uri/uri/mailto.rb
|
173
|
+
lib/extensions/uri/uri.rb
|
164
174
|
lib/framework/bsearch.rb
|
165
175
|
lib/framework/builtinME.rb
|
166
176
|
lib/framework/date/format.rb
|
@@ -514,11 +524,11 @@ platform/bb/rhodes/src/com/rho/net/SSLSocket.java
|
|
514
524
|
platform/bb/rhodes/src/com/rho/net/TCPSocket.java
|
515
525
|
platform/bb/rhodes/src/com/rho/RhoMainScreen.java
|
516
526
|
platform/bb/rhodes/src/com/rho/RhoRubyHelper.java
|
527
|
+
platform/bb/rhodes/src/com/rho/rubyext/Alert.java
|
517
528
|
platform/bb/rhodes/src/com/rho/rubyext/GeoLocation.java
|
518
529
|
platform/bb/rhodes/src/com/rho/rubyext/System.java
|
519
530
|
platform/bb/rhodes/src/com/rho/rubyext/XMLParser.java
|
520
531
|
platform/bb/rhodes/src/com/rho/Version.java
|
521
|
-
platform/bb/rhodes/src/rhomobile/Alert.java
|
522
532
|
platform/bb/rhodes/src/rhomobile/camera/Camera.java
|
523
533
|
platform/bb/rhodes/src/rhomobile/camera/CameraFilesListener.java
|
524
534
|
platform/bb/rhodes/src/rhomobile/camera/CameraScreen.java
|
data/Rakefile
CHANGED
@@ -127,7 +127,7 @@ def add_linker_library(libraryname)
|
|
127
127
|
tmpdir = $startdir + "/platform/iphone/build/rhorunner.build/#{$configuration}-" +
|
128
128
|
( simulator ? "iphonesimulator" : "iphoneos") + "/rhorunner.build"
|
129
129
|
end
|
130
|
-
$ldflags << "#{tmpdir}
|
130
|
+
$ldflags << "#{tmpdir}/lib#{libraryname}.a\n" unless $ldflags.nil?
|
131
131
|
end
|
132
132
|
|
133
133
|
def set_linker_flags
|
@@ -9,16 +9,16 @@ def build_extension(name, arch)
|
|
9
9
|
|
10
10
|
args = []
|
11
11
|
args << "-I."
|
12
|
-
args << "-I
|
13
|
-
args << "-I
|
12
|
+
args << "-I#{$rootdir}/platform/shared/ruby/include"
|
13
|
+
args << "-I#{$rootdir}/platform/shared"
|
14
14
|
|
15
15
|
if $android
|
16
|
-
args << "-I
|
17
|
-
args << "-I
|
16
|
+
args << "-I#{$rootdir}/platform/shared/ruby/linux"
|
17
|
+
args << "-I#{$rootdir}/platform/shared/ruby/generated"
|
18
18
|
cc_compile f, $tempdir, args or exit 1
|
19
19
|
|
20
20
|
else
|
21
|
-
args << "-I
|
21
|
+
args << "-I#{$rootdir}/platform/shared/ruby/iphone"
|
22
22
|
args << "-D_XOPEN_SOURCE"
|
23
23
|
args << "-D_DARWIN_C_SOURCE"
|
24
24
|
args << "-isysroot #{$sdkroot}"
|
@@ -74,8 +74,13 @@ namespace "build" do
|
|
74
74
|
task :config do
|
75
75
|
if ENV['ANDROID_API_LEVEL'] != nil
|
76
76
|
$targetdir = ENV['TARGET_TEMP_DIR']
|
77
|
+
raise "TARGET_TEMP_DIR is not set" if $targetdir.nil?
|
77
78
|
$tempdir = ENV['TEMP_FILES_DIR']
|
78
|
-
|
79
|
+
raise "TEMP_FILES_DIR is not set" if $tempdir.nil?
|
80
|
+
$rootdir = ENV['RHO_ROOT']
|
81
|
+
raise "RHO_ROOT is not set" if $rootdir.nil?
|
82
|
+
|
83
|
+
require File.join($rootdir, 'platform/android/build/androidcommon.rb')
|
79
84
|
|
80
85
|
setup_ndk(ENV['ANDROID_NDK'],ENV['ANDROID_API_LEVEL'])
|
81
86
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# URI support for Ruby
|
3
|
+
#
|
4
|
+
# Author:: Akira Yamada <akira@ruby-lang.org>
|
5
|
+
# Documentation:: Akira Yamada <akira@ruby-lang.org>, Dmitry V. Sabanin <sdmitry@lrn.ru>
|
6
|
+
# License::
|
7
|
+
# Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
|
8
|
+
# You can redistribute it and/or modify it under the same term as Ruby.
|
9
|
+
# Revision:: $Id: uri.rb 13772 2007-10-25 00:53:34Z akira $
|
10
|
+
#
|
11
|
+
# See URI for documentation
|
12
|
+
#
|
13
|
+
|
14
|
+
module URI
|
15
|
+
# :stopdoc:
|
16
|
+
VERSION_CODE = '000911'.freeze
|
17
|
+
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
|
18
|
+
# :startdoc:
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'uri/common'
|
23
|
+
require 'uri/generic'
|
24
|
+
require 'uri/ftp'
|
25
|
+
require 'uri/http'
|
26
|
+
require 'uri/https'
|
27
|
+
require 'uri/ldap'
|
28
|
+
require 'uri/ldaps'
|
29
|
+
require 'uri/mailto'
|
@@ -0,0 +1,727 @@
|
|
1
|
+
# = uri/common.rb
|
2
|
+
#
|
3
|
+
# Author:: Akira Yamada <akira@ruby-lang.org>
|
4
|
+
# Revision:: $Id: common.rb 22760 2009-03-04 09:21:12Z yugui $
|
5
|
+
# License::
|
6
|
+
# You can redistribute it and/or modify it under the same term as Ruby.
|
7
|
+
#
|
8
|
+
|
9
|
+
module URI
|
10
|
+
module REGEXP
|
11
|
+
#
|
12
|
+
# Patterns used to parse URI's
|
13
|
+
#
|
14
|
+
module PATTERN
|
15
|
+
# :stopdoc:
|
16
|
+
|
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
|
+
# domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
42
|
+
DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
|
43
|
+
# toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
44
|
+
TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
|
45
|
+
# hostname = *( domainlabel "." ) toplabel [ "." ]
|
46
|
+
HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
|
47
|
+
|
48
|
+
# :startdoc:
|
49
|
+
end # PATTERN
|
50
|
+
|
51
|
+
# :startdoc:
|
52
|
+
end # REGEXP
|
53
|
+
|
54
|
+
class Parser
|
55
|
+
include REGEXP
|
56
|
+
|
57
|
+
#
|
58
|
+
# == Synopsis
|
59
|
+
#
|
60
|
+
# URI::Parser.new([opts])
|
61
|
+
#
|
62
|
+
# == Args
|
63
|
+
#
|
64
|
+
# The constructor accepts a hash as options for parser.
|
65
|
+
# Keys of options are pattern names of URI components
|
66
|
+
# and values of options are pattern strings.
|
67
|
+
# The constructor generetes set of regexps for parsing URIs.
|
68
|
+
#
|
69
|
+
# You can use the following keys:
|
70
|
+
#
|
71
|
+
# * <tt>:ESCAPED</tt> (URI::PATTERN::ESCAPED in default)
|
72
|
+
# * <tt>:UNRESERVED</tt> (URI::PATTERN::UNRESERVED in default)
|
73
|
+
# * <tt>:DOMLABEL</tt> (URI::PATTERN::DOMLABEL in default)
|
74
|
+
# * <tt>:TOPLABEL</tt> (URI::PATTERN::TOPLABEL in default)
|
75
|
+
# * <tt>:HOSTNAME</tt> (URI::PATTERN::HOSTNAME in default)
|
76
|
+
#
|
77
|
+
# == Examples
|
78
|
+
#
|
79
|
+
# p = URI::Parser.new(:ESCPAED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})"
|
80
|
+
# u = p.parse("http://example.jp/%uABCD") #=> #<URI::HTTP:0xb78cf4f8 URL:http://example.jp/%uABCD>
|
81
|
+
# URI.parse(u.to_s) #=> raises URI::InvalidURIError
|
82
|
+
#
|
83
|
+
# s = "http://examle.com/ABCD"
|
84
|
+
# u1 = p.parse(s) #=> #<URI::HTTP:0xb78c3220 URL:http://example.com/ABCD>
|
85
|
+
# u2 = URI.parse(s) #=> #<URI::HTTP:0xb78b6d54 URL:http://example.com/ABCD>
|
86
|
+
# u1 == u2 #=> true
|
87
|
+
# u1.eql?(u2) #=> false
|
88
|
+
#
|
89
|
+
def initialize(opts = {})
|
90
|
+
@pattern = initialize_pattern(opts)
|
91
|
+
@pattern.each_value {|v| v.freeze}
|
92
|
+
@pattern.freeze
|
93
|
+
|
94
|
+
@regexp = initialize_regexp(@pattern)
|
95
|
+
@regexp.each_value {|v| v.freeze}
|
96
|
+
@regexp.freeze
|
97
|
+
end
|
98
|
+
attr_reader :pattern, :regexp
|
99
|
+
|
100
|
+
def split(uri)
|
101
|
+
case uri
|
102
|
+
when ''
|
103
|
+
# null uri
|
104
|
+
|
105
|
+
when @regexp[:ABS_URI]
|
106
|
+
scheme, opaque, userinfo, host, port,
|
107
|
+
registry, path, query, fragment = $~[1..-1]
|
108
|
+
|
109
|
+
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
|
110
|
+
|
111
|
+
# absoluteURI = scheme ":" ( hier_part | opaque_part )
|
112
|
+
# hier_part = ( net_path | abs_path ) [ "?" query ]
|
113
|
+
# opaque_part = uric_no_slash *uric
|
114
|
+
|
115
|
+
# abs_path = "/" path_segments
|
116
|
+
# net_path = "//" authority [ abs_path ]
|
117
|
+
|
118
|
+
# authority = server | reg_name
|
119
|
+
# server = [ [ userinfo "@" ] hostport ]
|
120
|
+
|
121
|
+
if !scheme
|
122
|
+
raise InvalidURIError,
|
123
|
+
"bad URI(absolute but no scheme): #{uri}"
|
124
|
+
end
|
125
|
+
if !opaque && (!path && (!host && !registry))
|
126
|
+
raise InvalidURIError,
|
127
|
+
"bad URI(absolute but no path): #{uri}"
|
128
|
+
end
|
129
|
+
|
130
|
+
when @regexp[:REL_URI]
|
131
|
+
scheme = nil
|
132
|
+
opaque = nil
|
133
|
+
|
134
|
+
userinfo, host, port, registry,
|
135
|
+
rel_segment, abs_path, query, fragment = $~[1..-1]
|
136
|
+
if rel_segment && abs_path
|
137
|
+
path = rel_segment + abs_path
|
138
|
+
elsif rel_segment
|
139
|
+
path = rel_segment
|
140
|
+
elsif abs_path
|
141
|
+
path = abs_path
|
142
|
+
end
|
143
|
+
|
144
|
+
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
|
145
|
+
|
146
|
+
# relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
|
147
|
+
|
148
|
+
# net_path = "//" authority [ abs_path ]
|
149
|
+
# abs_path = "/" path_segments
|
150
|
+
# rel_path = rel_segment [ abs_path ]
|
151
|
+
|
152
|
+
# authority = server | reg_name
|
153
|
+
# server = [ [ userinfo "@" ] hostport ]
|
154
|
+
|
155
|
+
else
|
156
|
+
raise InvalidURIError, "bad URI(is not URI?): #{uri}"
|
157
|
+
end
|
158
|
+
|
159
|
+
path = '' if !path && !opaque # (see RFC2396 Section 5.2)
|
160
|
+
ret = [
|
161
|
+
scheme,
|
162
|
+
userinfo, host, port, # X
|
163
|
+
registry, # X
|
164
|
+
path, # Y
|
165
|
+
opaque, # Y
|
166
|
+
query,
|
167
|
+
fragment
|
168
|
+
]
|
169
|
+
return ret
|
170
|
+
end
|
171
|
+
|
172
|
+
def parse(uri)
|
173
|
+
scheme, userinfo, host, port,
|
174
|
+
registry, path, opaque, query, fragment = self.split(uri)
|
175
|
+
|
176
|
+
if scheme && URI.scheme_list.include?(scheme.upcase)
|
177
|
+
URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
|
178
|
+
registry, path, opaque, query,
|
179
|
+
fragment, self)
|
180
|
+
else
|
181
|
+
Generic.new(scheme, userinfo, host, port,
|
182
|
+
registry, path, opaque, query,
|
183
|
+
fragment, self)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def join(*str)
|
188
|
+
u = self.parse(str[0])
|
189
|
+
str[1 .. -1].each do |x|
|
190
|
+
u = u.merge(x)
|
191
|
+
end
|
192
|
+
u
|
193
|
+
end
|
194
|
+
|
195
|
+
def extract(str, schemes = nil, &block)
|
196
|
+
if block_given?
|
197
|
+
str.scan(make_regexp(schemes)) { yield $& }
|
198
|
+
nil
|
199
|
+
else
|
200
|
+
result = []
|
201
|
+
str.scan(make_regexp(schemes)) { result.push $& }
|
202
|
+
result
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def make_regexp(schemes = nil)
|
207
|
+
unless schemes
|
208
|
+
@regexp[:ABS_URI_REF]
|
209
|
+
else
|
210
|
+
/(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def escape(str, unsafe = @regexp[:UNSAFE])
|
215
|
+
unless unsafe.kind_of?(Regexp)
|
216
|
+
# perhaps unsafe is String object
|
217
|
+
unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false)
|
218
|
+
end
|
219
|
+
str.gsub(unsafe) do
|
220
|
+
us = $&
|
221
|
+
tmp = ''
|
222
|
+
us.each_byte do |uc|
|
223
|
+
tmp << sprintf('%%%02X', uc)
|
224
|
+
end
|
225
|
+
tmp
|
226
|
+
end.force_encoding("US-ASCII")#Encoding::US_ASCII)
|
227
|
+
end
|
228
|
+
|
229
|
+
def unescape(str, escaped = @regexp[:ESCAPED])
|
230
|
+
str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(str.encoding)
|
231
|
+
end
|
232
|
+
|
233
|
+
@@to_s = Kernel.instance_method(:to_s)
|
234
|
+
def inspect
|
235
|
+
@@to_s.bind(self).call
|
236
|
+
end
|
237
|
+
|
238
|
+
private
|
239
|
+
|
240
|
+
def initialize_pattern(opts = {})
|
241
|
+
ret = {}
|
242
|
+
ret[:ESCAPED] = escaped = (opts.delete(:ESCAPED) || PATTERN::ESCAPED)
|
243
|
+
ret[:UNRESERVED] = unreserved = opts.delete(:UNRESERVED) || PATTERN::UNRESERVED
|
244
|
+
ret[:RESERVED] = reserved = opts.delete(:RESERVED) || PATTERN::RESERVED
|
245
|
+
ret[:DOMLABEL] = domlabel = opts.delete(:DOMLABEL) || PATTERN::DOMLABEL
|
246
|
+
ret[:TOPLABEL] = toplabel = opts.delete(:TOPLABEL) || PATTERN::TOPLABEL
|
247
|
+
ret[:HOSTNAME] = hostname = opts.delete(:HOSTNAME)
|
248
|
+
|
249
|
+
# RFC 2396 (URI Generic Syntax)
|
250
|
+
# RFC 2732 (IPv6 Literal Addresses in URL's)
|
251
|
+
# RFC 2373 (IPv6 Addressing Architecture)
|
252
|
+
|
253
|
+
# uric = reserved | unreserved | escaped
|
254
|
+
ret[:URIC] = uric = "(?:[#{unreserved}#{reserved}]|#{escaped})"
|
255
|
+
# uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
|
256
|
+
# "&" | "=" | "+" | "$" | ","
|
257
|
+
ret[:URIC_NO_SLASH] = uric_no_slash = "(?:[#{unreserved};?:@&=+$,]|#{escaped})"
|
258
|
+
# query = *uric
|
259
|
+
ret[:QUERY] = query = "#{uric}*"
|
260
|
+
# fragment = *uric
|
261
|
+
ret[:FRAGMENT] = fragment = "#{uric}*"
|
262
|
+
|
263
|
+
# hostname = *( domainlabel "." ) toplabel [ "." ]
|
264
|
+
unless hostname
|
265
|
+
ret[:HOSTNAME] = hostname = "(?:#{domlabel}\\.)*#{toplabel}\\.?"
|
266
|
+
end
|
267
|
+
|
268
|
+
# RFC 2373, APPENDIX B:
|
269
|
+
# IPv6address = hexpart [ ":" IPv4address ]
|
270
|
+
# IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
|
271
|
+
# hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
|
272
|
+
# hexseq = hex4 *( ":" hex4)
|
273
|
+
# hex4 = 1*4HEXDIG
|
274
|
+
#
|
275
|
+
# XXX: This definition has a flaw. "::" + IPv4address must be
|
276
|
+
# allowed too. Here is a replacement.
|
277
|
+
#
|
278
|
+
# IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
|
279
|
+
ret[:IPV4ADDR] = ipv4addr = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
|
280
|
+
# hex4 = 1*4HEXDIG
|
281
|
+
hex4 = "[#{PATTERN::HEX}]{1,4}"
|
282
|
+
# lastpart = hex4 | IPv4address
|
283
|
+
lastpart = "(?:#{hex4}|#{ipv4addr})"
|
284
|
+
# hexseq1 = *( hex4 ":" ) hex4
|
285
|
+
hexseq1 = "(?:#{hex4}:)*#{hex4}"
|
286
|
+
# hexseq2 = *( hex4 ":" ) lastpart
|
287
|
+
hexseq2 = "(?:#{hex4}:)*#{lastpart}"
|
288
|
+
# IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ]
|
289
|
+
ret[:IPV6ADDR] = ipv6addr = "(?:#{hexseq2}|(?:#{hexseq1})?::(?:#{hexseq2})?)"
|
290
|
+
|
291
|
+
# IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT
|
292
|
+
# unused
|
293
|
+
|
294
|
+
# ipv6reference = "[" IPv6address "]" (RFC 2732)
|
295
|
+
ret[:IPV6REF] = ipv6ref = "\\[#{ipv6addr}\\]"
|
296
|
+
|
297
|
+
# host = hostname | IPv4address
|
298
|
+
# host = hostname | IPv4address | IPv6reference (RFC 2732)
|
299
|
+
ret[:HOST] = host = "(?:#{hostname}|#{ipv4addr}|#{ipv6ref})"
|
300
|
+
# port = *digit
|
301
|
+
port = '\d*'
|
302
|
+
# hostport = host [ ":" port ]
|
303
|
+
ret[:HOSTPORT] = hostport = "#{host}(?::#{port})?"
|
304
|
+
|
305
|
+
# userinfo = *( unreserved | escaped |
|
306
|
+
# ";" | ":" | "&" | "=" | "+" | "$" | "," )
|
307
|
+
ret[:USERINFO] = userinfo = "(?:[#{unreserved};:&=+$,]|#{escaped})*"
|
308
|
+
|
309
|
+
# pchar = unreserved | escaped |
|
310
|
+
# ":" | "@" | "&" | "=" | "+" | "$" | ","
|
311
|
+
pchar = "(?:[#{unreserved}:@&=+$,]|#{escaped})"
|
312
|
+
# param = *pchar
|
313
|
+
param = "#{pchar}*"
|
314
|
+
# segment = *pchar *( ";" param )
|
315
|
+
segment = "#{pchar}*(?:;#{param})*"
|
316
|
+
# path_segments = segment *( "/" segment )
|
317
|
+
ret[:PATH_SEGMENTS] = path_segments = "#{segment}(?:/#{segment})*"
|
318
|
+
|
319
|
+
# server = [ [ userinfo "@" ] hostport ]
|
320
|
+
server = "(?:#{userinfo}@)?#{hostport}"
|
321
|
+
# reg_name = 1*( unreserved | escaped | "$" | "," |
|
322
|
+
# ";" | ":" | "@" | "&" | "=" | "+" )
|
323
|
+
ret[:REG_NAME] = reg_name = "(?:[#{unreserved}$,;:@&=+]|#{escaped})+"
|
324
|
+
# authority = server | reg_name
|
325
|
+
authority = "(?:#{server}|#{reg_name})"
|
326
|
+
|
327
|
+
# rel_segment = 1*( unreserved | escaped |
|
328
|
+
# ";" | "@" | "&" | "=" | "+" | "$" | "," )
|
329
|
+
ret[:REL_SEGMENT] = rel_segment = "(?:[#{unreserved};@&=+$,]|#{escaped})+"
|
330
|
+
|
331
|
+
# scheme = alpha *( alpha | digit | "+" | "-" | "." )
|
332
|
+
ret[:SCHEME] = scheme = "[#{PATTERN::ALPHA}][-+.#{PATTERN::ALPHA}\\d]*"
|
333
|
+
|
334
|
+
# abs_path = "/" path_segments
|
335
|
+
ret[:ABS_PATH] = abs_path = "/#{path_segments}"
|
336
|
+
# rel_path = rel_segment [ abs_path ]
|
337
|
+
ret[:REL_PATH] = rel_path = "#{rel_segment}(?:#{abs_path})?"
|
338
|
+
# net_path = "//" authority [ abs_path ]
|
339
|
+
ret[:NET_PATH] = net_path = "//#{authority}(?:#{abs_path})?"
|
340
|
+
|
341
|
+
# hier_part = ( net_path | abs_path ) [ "?" query ]
|
342
|
+
ret[:HIER_PART] = hier_part = "(?:#{net_path}|#{abs_path})(?:\\?(?:#{query}))?"
|
343
|
+
# opaque_part = uric_no_slash *uric
|
344
|
+
ret[:OPAQUE_PART] = opaque_part = "#{uric_no_slash}#{uric}*"
|
345
|
+
|
346
|
+
# absoluteURI = scheme ":" ( hier_part | opaque_part )
|
347
|
+
ret[:ABS_URI] = abs_uri = "#{scheme}:(?:#{hier_part}|#{opaque_part})"
|
348
|
+
# relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
|
349
|
+
ret[:REL_URI] = rel_uri = "(?:#{net_path}|#{abs_path}|#{rel_path})(?:\\?#{query})?"
|
350
|
+
|
351
|
+
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
|
352
|
+
ret[:URI_REF] = uri_ref = "(?:#{abs_uri}|#{rel_uri})?(?:##{fragment})?"
|
353
|
+
|
354
|
+
ret[:X_ABS_URI] = "
|
355
|
+
(#{scheme}): (?# 1: scheme)
|
356
|
+
(?:
|
357
|
+
(#{opaque_part}) (?# 2: opaque)
|
358
|
+
|
|
359
|
+
(?:(?:
|
360
|
+
//(?:
|
361
|
+
(?:(?:(#{userinfo})@)? (?# 3: userinfo)
|
362
|
+
(?:(#{host})(?::(\\d*))?))? (?# 4: host, 5: port)
|
363
|
+
|
|
364
|
+
(#{reg_name}) (?# 6: registry)
|
365
|
+
)
|
366
|
+
|
|
367
|
+
(?!//)) (?# XXX: '//' is the mark for hostport)
|
368
|
+
(#{abs_path})? (?# 7: path)
|
369
|
+
)(?:\\?(#{query}))? (?# 8: query)
|
370
|
+
)
|
371
|
+
(?:\\#(#{fragment}))? (?# 9: fragment)
|
372
|
+
"
|
373
|
+
|
374
|
+
ret[:X_REL_URI] = "
|
375
|
+
(?:
|
376
|
+
(?:
|
377
|
+
//
|
378
|
+
(?:
|
379
|
+
(?:(#{userinfo})@)? (?# 1: userinfo)
|
380
|
+
(#{host})?(?::(\\d*))? (?# 2: host, 3: port)
|
381
|
+
|
|
382
|
+
(#{reg_name}) (?# 4: registry)
|
383
|
+
)
|
384
|
+
)
|
385
|
+
|
|
386
|
+
(#{rel_segment}) (?# 5: rel_segment)
|
387
|
+
)?
|
388
|
+
(#{abs_path})? (?# 6: abs_path)
|
389
|
+
(?:\\?(#{query}))? (?# 7: query)
|
390
|
+
(?:\\#(#{fragment}))? (?# 8: fragment)
|
391
|
+
"
|
392
|
+
|
393
|
+
ret
|
394
|
+
end
|
395
|
+
|
396
|
+
def initialize_regexp(pattern)
|
397
|
+
ret = {}
|
398
|
+
|
399
|
+
# for URI::split
|
400
|
+
ret[:ABS_URI] = Regexp.new('^' + pattern[:X_ABS_URI] + '$', Regexp::EXTENDED)
|
401
|
+
ret[:REL_URI] = Regexp.new('^' + pattern[:X_REL_URI] + '$', Regexp::EXTENDED)
|
402
|
+
|
403
|
+
# for URI::extract
|
404
|
+
ret[:URI_REF] = Regexp.new(pattern[:URI_REF])
|
405
|
+
ret[:ABS_URI_REF] = Regexp.new(pattern[:X_ABS_URI], Regexp::EXTENDED)
|
406
|
+
ret[:REL_URI_REF] = Regexp.new(pattern[:X_REL_URI], Regexp::EXTENDED)
|
407
|
+
|
408
|
+
# for URI::escape/unescape
|
409
|
+
ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED])
|
410
|
+
ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]")
|
411
|
+
|
412
|
+
# for Generic#initialize
|
413
|
+
ret[:SCHEME] = Regexp.new("^#{pattern[:SCHEME]}$")
|
414
|
+
ret[:USERINFO] = Regexp.new("^#{pattern[:USERINFO]}$")
|
415
|
+
ret[:HOST] = Regexp.new("^#{pattern[:HOST]}$")
|
416
|
+
ret[:PORT] = Regexp.new("^#{pattern[:PORT]}$")
|
417
|
+
ret[:OPAQUE] = Regexp.new("^#{pattern[:OPAQUE_PART]}$")
|
418
|
+
ret[:REGISTRY] = Regexp.new("^#{pattern[:REG_NAME]}$")
|
419
|
+
ret[:ABS_PATH] = Regexp.new("^#{pattern[:ABS_PATH]}$")
|
420
|
+
ret[:REL_PATH] = Regexp.new("^#{pattern[:REL_PATH]}$")
|
421
|
+
ret[:QUERY] = Regexp.new("^#{pattern[:QUERY]}$")
|
422
|
+
ret[:FRAGMENT] = Regexp.new("^#{pattern[:FRAGMENT]}$")
|
423
|
+
|
424
|
+
ret
|
425
|
+
end
|
426
|
+
end # class Parser
|
427
|
+
|
428
|
+
DEFAULT_PARSER = Parser.new
|
429
|
+
DEFAULT_PARSER.pattern.each_pair do |sym, str|
|
430
|
+
unless REGEXP::PATTERN.const_defined?(sym)
|
431
|
+
REGEXP::PATTERN.const_set(sym, str)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
DEFAULT_PARSER.regexp.each_pair do |sym, str|
|
435
|
+
const_set(sym, str)
|
436
|
+
end
|
437
|
+
|
438
|
+
module Util # :nodoc:
|
439
|
+
def make_components_hash(klass, array_hash)
|
440
|
+
tmp = {}
|
441
|
+
if array_hash.kind_of?(Array) &&
|
442
|
+
array_hash.size == klass.component.size - 1
|
443
|
+
klass.component[1..-1].each_index do |i|
|
444
|
+
begin
|
445
|
+
tmp[klass.component[i + 1]] = array_hash[i].clone
|
446
|
+
rescue TypeError
|
447
|
+
tmp[klass.component[i + 1]] = array_hash[i]
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
elsif array_hash.kind_of?(Hash)
|
452
|
+
array_hash.each do |key, value|
|
453
|
+
begin
|
454
|
+
tmp[key] = value.clone
|
455
|
+
rescue TypeError
|
456
|
+
tmp[key] = value
|
457
|
+
end
|
458
|
+
end
|
459
|
+
else
|
460
|
+
raise ArgumentError,
|
461
|
+
"expected Array of or Hash of components of #{klass.to_s} (#{klass.component[1..-1].join(', ')})"
|
462
|
+
end
|
463
|
+
tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase
|
464
|
+
|
465
|
+
return tmp
|
466
|
+
end
|
467
|
+
module_function :make_components_hash
|
468
|
+
end
|
469
|
+
|
470
|
+
module Escape
|
471
|
+
#
|
472
|
+
# == Synopsis
|
473
|
+
#
|
474
|
+
# URI.escape(str [, unsafe])
|
475
|
+
#
|
476
|
+
# == Args
|
477
|
+
#
|
478
|
+
# +str+::
|
479
|
+
# String to replaces in.
|
480
|
+
# +unsafe+::
|
481
|
+
# Regexp that matches all symbols that must be replaced with codes.
|
482
|
+
# By default uses <tt>REGEXP::UNSAFE</tt>.
|
483
|
+
# When this argument is a String, it represents a character set.
|
484
|
+
#
|
485
|
+
# == Description
|
486
|
+
#
|
487
|
+
# Escapes the string, replacing all unsafe characters with codes.
|
488
|
+
#
|
489
|
+
# == Usage
|
490
|
+
#
|
491
|
+
# require 'uri'
|
492
|
+
#
|
493
|
+
# enc_uri = URI.escape("http://example.com/?a=\11\15")
|
494
|
+
# p enc_uri
|
495
|
+
# # => "http://example.com/?a=%09%0D"
|
496
|
+
#
|
497
|
+
# p URI.unescape(enc_uri)
|
498
|
+
# # => "http://example.com/?a=\t\r"
|
499
|
+
#
|
500
|
+
# p URI.escape("@?@!", "!?")
|
501
|
+
# # => "@%3F@%21"
|
502
|
+
#
|
503
|
+
def escape(*arg)
|
504
|
+
DEFAULT_PARSER.escape(*arg)
|
505
|
+
end
|
506
|
+
alias encode escape
|
507
|
+
#
|
508
|
+
# == Synopsis
|
509
|
+
#
|
510
|
+
# URI.unescape(str)
|
511
|
+
#
|
512
|
+
# == Args
|
513
|
+
#
|
514
|
+
# +str+::
|
515
|
+
# Unescapes the string.
|
516
|
+
#
|
517
|
+
# == Usage
|
518
|
+
#
|
519
|
+
# require 'uri'
|
520
|
+
#
|
521
|
+
# enc_uri = URI.escape("http://example.com/?a=\11\15")
|
522
|
+
# p enc_uri
|
523
|
+
# # => "http://example.com/?a=%09%0D"
|
524
|
+
#
|
525
|
+
# p URI.unescape(enc_uri)
|
526
|
+
# # => "http://example.com/?a=\t\r"
|
527
|
+
#
|
528
|
+
def unescape(*arg)
|
529
|
+
DEFAULT_PARSER.unescape(*arg)
|
530
|
+
end
|
531
|
+
alias decode unescape
|
532
|
+
end
|
533
|
+
|
534
|
+
extend Escape
|
535
|
+
include REGEXP
|
536
|
+
|
537
|
+
@@schemes = {}
|
538
|
+
def self.scheme_list
|
539
|
+
@@schemes
|
540
|
+
end
|
541
|
+
|
542
|
+
#
|
543
|
+
# Base class for all URI exceptions.
|
544
|
+
#
|
545
|
+
class Error < StandardError; end
|
546
|
+
#
|
547
|
+
# Not a URI.
|
548
|
+
#
|
549
|
+
class InvalidURIError < Error; end
|
550
|
+
#
|
551
|
+
# Not a URI component.
|
552
|
+
#
|
553
|
+
class InvalidComponentError < Error; end
|
554
|
+
#
|
555
|
+
# URI is valid, bad usage is not.
|
556
|
+
#
|
557
|
+
class BadURIError < Error; end
|
558
|
+
|
559
|
+
#
|
560
|
+
# == Synopsis
|
561
|
+
#
|
562
|
+
# URI::split(uri)
|
563
|
+
#
|
564
|
+
# == Args
|
565
|
+
#
|
566
|
+
# +uri+::
|
567
|
+
# String with URI.
|
568
|
+
#
|
569
|
+
# == Description
|
570
|
+
#
|
571
|
+
# Splits the string on following parts and returns array with result:
|
572
|
+
#
|
573
|
+
# * Scheme
|
574
|
+
# * Userinfo
|
575
|
+
# * Host
|
576
|
+
# * Port
|
577
|
+
# * Registry
|
578
|
+
# * Path
|
579
|
+
# * Opaque
|
580
|
+
# * Query
|
581
|
+
# * Fragment
|
582
|
+
#
|
583
|
+
# == Usage
|
584
|
+
#
|
585
|
+
# require 'uri'
|
586
|
+
#
|
587
|
+
# p URI.split("http://www.ruby-lang.org/")
|
588
|
+
# # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
|
589
|
+
#
|
590
|
+
def self.split(uri)
|
591
|
+
DEFAULT_PARSER.split(uri)
|
592
|
+
end
|
593
|
+
|
594
|
+
#
|
595
|
+
# == Synopsis
|
596
|
+
#
|
597
|
+
# URI::parse(uri_str)
|
598
|
+
#
|
599
|
+
# == Args
|
600
|
+
#
|
601
|
+
# +uri_str+::
|
602
|
+
# String with URI.
|
603
|
+
#
|
604
|
+
# == Description
|
605
|
+
#
|
606
|
+
# Creates one of the URI's subclasses instance from the string.
|
607
|
+
#
|
608
|
+
# == Raises
|
609
|
+
#
|
610
|
+
# URI::InvalidURIError
|
611
|
+
# Raised if URI given is not a correct one.
|
612
|
+
#
|
613
|
+
# == Usage
|
614
|
+
#
|
615
|
+
# require 'uri'
|
616
|
+
#
|
617
|
+
# uri = URI.parse("http://www.ruby-lang.org/")
|
618
|
+
# p uri
|
619
|
+
# # => #<URI::HTTP:0x202281be URL:http://www.ruby-lang.org/>
|
620
|
+
# p uri.scheme
|
621
|
+
# # => "http"
|
622
|
+
# p uri.host
|
623
|
+
# # => "www.ruby-lang.org"
|
624
|
+
#
|
625
|
+
def self.parse(uri)
|
626
|
+
DEFAULT_PARSER.parse(uri)
|
627
|
+
end
|
628
|
+
|
629
|
+
#
|
630
|
+
# == Synopsis
|
631
|
+
#
|
632
|
+
# URI::join(str[, str, ...])
|
633
|
+
#
|
634
|
+
# == Args
|
635
|
+
#
|
636
|
+
# +str+::
|
637
|
+
# String(s) to work with
|
638
|
+
#
|
639
|
+
# == Description
|
640
|
+
#
|
641
|
+
# Joins URIs.
|
642
|
+
#
|
643
|
+
# == Usage
|
644
|
+
#
|
645
|
+
# require 'uri'
|
646
|
+
#
|
647
|
+
# p URI.join("http://localhost/","main.rbx")
|
648
|
+
# # => #<URI::HTTP:0x2022ac02 URL:http://localhost/main.rbx>
|
649
|
+
#
|
650
|
+
def self.join(*str)
|
651
|
+
DEFAULT_PARSER.join(*str)
|
652
|
+
end
|
653
|
+
|
654
|
+
#
|
655
|
+
# == Synopsis
|
656
|
+
#
|
657
|
+
# URI::extract(str[, schemes][,&blk])
|
658
|
+
#
|
659
|
+
# == Args
|
660
|
+
#
|
661
|
+
# +str+::
|
662
|
+
# String to extract URIs from.
|
663
|
+
# +schemes+::
|
664
|
+
# Limit URI matching to a specific schemes.
|
665
|
+
#
|
666
|
+
# == Description
|
667
|
+
#
|
668
|
+
# Extracts URIs from a string. If block given, iterates through all matched URIs.
|
669
|
+
# Returns nil if block given or array with matches.
|
670
|
+
#
|
671
|
+
# == Usage
|
672
|
+
#
|
673
|
+
# require "uri"
|
674
|
+
#
|
675
|
+
# URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
|
676
|
+
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
|
677
|
+
#
|
678
|
+
def self.extract(str, schemes = nil, &block)
|
679
|
+
DEFAULT_PARSER.extract(str, schemes, &block)
|
680
|
+
end
|
681
|
+
|
682
|
+
#
|
683
|
+
# == Synopsis
|
684
|
+
#
|
685
|
+
# URI::regexp([match_schemes])
|
686
|
+
#
|
687
|
+
# == Args
|
688
|
+
#
|
689
|
+
# +match_schemes+::
|
690
|
+
# Array of schemes. If given, resulting regexp matches to URIs
|
691
|
+
# whose scheme is one of the match_schemes.
|
692
|
+
#
|
693
|
+
# == Description
|
694
|
+
# Returns a Regexp object which matches to URI-like strings.
|
695
|
+
# The Regexp object returned by this method includes arbitrary
|
696
|
+
# number of capture group (parentheses). Never rely on it's number.
|
697
|
+
#
|
698
|
+
# == Usage
|
699
|
+
#
|
700
|
+
# require 'uri'
|
701
|
+
#
|
702
|
+
# # extract first URI from html_string
|
703
|
+
# html_string.slice(URI.regexp)
|
704
|
+
#
|
705
|
+
# # remove ftp URIs
|
706
|
+
# html_string.sub(URI.regexp(['ftp'])
|
707
|
+
#
|
708
|
+
# # You should not rely on the number of parentheses
|
709
|
+
# html_string.scan(URI.regexp) do |*matches|
|
710
|
+
# p $&
|
711
|
+
# end
|
712
|
+
#
|
713
|
+
def self.regexp(schemes = nil)
|
714
|
+
DEFAULT_PARSER.make_regexp(schemes)
|
715
|
+
end
|
716
|
+
|
717
|
+
end
|
718
|
+
|
719
|
+
module Kernel
|
720
|
+
# alias for URI.parse.
|
721
|
+
#
|
722
|
+
# This method is introduced at 1.8.2.
|
723
|
+
def URI(uri_str) # :doc:
|
724
|
+
URI.parse(uri_str)
|
725
|
+
end
|
726
|
+
module_function :URI
|
727
|
+
end
|