solutious-stella 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +39 -2
- data/LICENSE.txt +19 -0
- data/README.rdoc +85 -0
- data/Rakefile +54 -59
- data/bin/example_test.rb +82 -0
- data/bin/example_webapp.rb +63 -0
- data/lib/{stella/logger.rb → logger.rb} +6 -11
- data/lib/stella.rb +76 -58
- data/lib/stella/clients.rb +161 -0
- data/lib/stella/command/base.rb +4 -24
- data/lib/stella/command/form.rb +36 -0
- data/lib/stella/command/get.rb +44 -0
- data/lib/stella/common.rb +53 -0
- data/lib/stella/crypto.rb +88 -0
- data/lib/stella/data/domain.rb +2 -2
- data/lib/stella/data/http.rb +164 -36
- data/lib/stella/environment.rb +66 -0
- data/lib/stella/functest.rb +105 -0
- data/lib/stella/loadtest.rb +186 -0
- data/lib/{utils → stella}/stats.rb +16 -20
- data/lib/stella/testplan.rb +237 -0
- data/lib/stella/testrunner.rb +64 -0
- data/lib/storable.rb +280 -0
- data/lib/threadify.rb +171 -0
- data/lib/timeunits.rb +65 -0
- data/lib/util/httputil.rb +266 -0
- data/stella.gemspec +69 -0
- data/tryouts/drb/drb_test.rb +65 -0
- data/tryouts/drb/open4.rb +19 -0
- data/tryouts/drb/slave.rb +27 -0
- data/tryouts/oo_tryout.rb +30 -0
- metadata +39 -107
- data/README.textile +0 -162
- data/bin/stella +0 -12
- data/bin/stella.bat +0 -12
- data/lib/daemonize.rb +0 -56
- data/lib/pcaplet.rb +0 -180
- data/lib/stella/adapter/ab.rb +0 -337
- data/lib/stella/adapter/base.rb +0 -106
- data/lib/stella/adapter/httperf.rb +0 -305
- data/lib/stella/adapter/pcap_watcher.rb +0 -221
- data/lib/stella/adapter/proxy_watcher.rb +0 -76
- data/lib/stella/adapter/siege.rb +0 -341
- data/lib/stella/cli.rb +0 -258
- data/lib/stella/cli/agents.rb +0 -73
- data/lib/stella/cli/base.rb +0 -55
- data/lib/stella/cli/language.rb +0 -18
- data/lib/stella/cli/localtest.rb +0 -78
- data/lib/stella/cli/sysinfo.rb +0 -16
- data/lib/stella/cli/watch.rb +0 -278
- data/lib/stella/command/localtest.rb +0 -358
- data/lib/stella/response.rb +0 -85
- data/lib/stella/storable.rb +0 -201
- data/lib/stella/support.rb +0 -276
- data/lib/stella/sysinfo.rb +0 -257
- data/lib/stella/test/definition.rb +0 -79
- data/lib/stella/test/run/summary.rb +0 -70
- data/lib/stella/test/stats.rb +0 -114
- data/lib/stella/text.rb +0 -64
- data/lib/stella/text/resource.rb +0 -38
- data/lib/utils/crypto-key.rb +0 -84
- data/lib/utils/domainutil.rb +0 -47
- data/lib/utils/escape.rb +0 -302
- data/lib/utils/fileutil.rb +0 -78
- data/lib/utils/httputil.rb +0 -266
- data/lib/utils/mathutil.rb +0 -15
- data/lib/utils/textgraph.rb +0 -267
- data/lib/utils/timerutil.rb +0 -58
- data/lib/win32/Console.rb +0 -970
- data/lib/win32/Console/ANSI.rb +0 -305
- data/support/kvm.h +0 -91
- data/support/ruby-pcap-takuma-notes.txt +0 -19
- data/support/ruby-pcap-takuma-patch.txt +0 -30
- data/support/text/en.yaml +0 -80
- data/support/text/nl.yaml +0 -7
- data/support/useragents.txt +0 -75
- data/tests/01-util_test.rb +0 -0
- data/tests/02-stella-util_test.rb +0 -42
- data/tests/10-stella_test.rb +0 -104
- data/tests/11-stella-storable_test.rb +0 -68
- data/tests/60-stella-command_test.rb +0 -248
- data/tests/80-stella-cli_test.rb +0 -45
- data/tests/spec-helper.rb +0 -31
data/lib/utils/domainutil.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'net/dns/packet'
|
3
|
-
|
4
|
-
module DomainUtil
|
5
|
-
|
6
|
-
def DomainUtil.parse_domain_request(data=[])
|
7
|
-
return unless data && !data.empty?
|
8
|
-
data = data.split(/\r?\n/) unless data.kind_of? Array
|
9
|
-
data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
|
10
|
-
|
11
|
-
dns_data = Net::DNS::Packet.parse( data.join($/) )
|
12
|
-
return unless dns_data.header.query?
|
13
|
-
domain_name = dns_data.question[0].qName
|
14
|
-
return dns_data, domain_name, dns_data.header
|
15
|
-
end
|
16
|
-
|
17
|
-
def DomainUtil.parse_domain_response(data=[])
|
18
|
-
return unless data && !data.empty?
|
19
|
-
data = data.split(/\r?\n/) unless data.kind_of? Array
|
20
|
-
data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
|
21
|
-
|
22
|
-
# This is the heavy lifting.
|
23
|
-
dns_data = Net::DNS::Packet.parse( data.join($/) )
|
24
|
-
|
25
|
-
# We don't want queries or empty answers
|
26
|
-
return if dns_data.header.query? || dns_data.answer.nil? || dns_data.answer.empty?
|
27
|
-
|
28
|
-
domain_name = dns_data.answer[0].name
|
29
|
-
|
30
|
-
# Empty the lists if they are already populated
|
31
|
-
addresses = []
|
32
|
-
cnames = []
|
33
|
-
|
34
|
-
# Store the CNAMEs associated to this domain. Can be empty.
|
35
|
-
dns_data.each_cname do |cname|
|
36
|
-
cnames << cname.to_s
|
37
|
-
end
|
38
|
-
|
39
|
-
# Store the IP address for this domain. If empty, the lookup was unsuccessful.
|
40
|
-
dns_data.each_address do |ip|
|
41
|
-
addresses << ip.to_s
|
42
|
-
end
|
43
|
-
|
44
|
-
return dns_data, domain_name, dns_data.header, addresses, cnames
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
data/lib/utils/escape.rb
DELETED
@@ -1,302 +0,0 @@
|
|
1
|
-
# escape.rb - escape/unescape library for several formats
|
2
|
-
#
|
3
|
-
# Copyright (C) 2006,2007 Tanaka Akira <akr@fsij.org>
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions are met:
|
7
|
-
#
|
8
|
-
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
-
# list of conditions and the following disclaimer.
|
10
|
-
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
# 3. The name of the author may not be used to endorse or promote products
|
14
|
-
# derived from this software without specific prior written permission.
|
15
|
-
#
|
16
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
17
|
-
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
18
|
-
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
19
|
-
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
20
|
-
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
21
|
-
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
22
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
23
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
24
|
-
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
25
|
-
# OF SUCH DAMAGE.
|
26
|
-
|
27
|
-
# Escape module provides several escape functions.
|
28
|
-
# * URI
|
29
|
-
# * HTML
|
30
|
-
# * shell command
|
31
|
-
module EscapeUtil
|
32
|
-
module_function
|
33
|
-
|
34
|
-
class StringWrapper
|
35
|
-
class << self
|
36
|
-
alias new_no_dup new
|
37
|
-
def new(str)
|
38
|
-
new_no_dup(str.dup)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def initialize(str)
|
43
|
-
@str = str
|
44
|
-
end
|
45
|
-
|
46
|
-
def to_s
|
47
|
-
@str.dup
|
48
|
-
end
|
49
|
-
|
50
|
-
def inspect
|
51
|
-
"\#<#{self.class}: #{@str}>"
|
52
|
-
end
|
53
|
-
|
54
|
-
def ==(other)
|
55
|
-
other.class == self.class && @str == other.instance_variable_get(:@str)
|
56
|
-
end
|
57
|
-
alias eql? ==
|
58
|
-
|
59
|
-
def hash
|
60
|
-
@str.hash
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class ShellEscaped < StringWrapper
|
65
|
-
end
|
66
|
-
|
67
|
-
# Escape.shell_command composes
|
68
|
-
# a sequence of words to
|
69
|
-
# a single shell command line.
|
70
|
-
# All shell meta characters are quoted and
|
71
|
-
# the words are concatenated with interleaving space.
|
72
|
-
# It returns an instance of ShellEscaped.
|
73
|
-
#
|
74
|
-
# Escape.shell_command(["ls", "/"]) #=> #<Escape::ShellEscaped: ls />
|
75
|
-
# Escape.shell_command(["echo", "*"]) #=> #<Escape::ShellEscaped: echo '*'>
|
76
|
-
#
|
77
|
-
# Note that system(*command) and
|
78
|
-
# system(Escape.shell_command(command)) is roughly same.
|
79
|
-
# There are two exception as follows.
|
80
|
-
# * The first is that the later may invokes /bin/sh.
|
81
|
-
# * The second is an interpretation of an array with only one element:
|
82
|
-
# the element is parsed by the shell with the former but
|
83
|
-
# it is recognized as single word with the later.
|
84
|
-
# For example, system(*["echo foo"]) invokes echo command with an argument "foo".
|
85
|
-
# But system(Escape.shell_command(["echo foo"])) invokes "echo foo" command without arguments (and it probably fails).
|
86
|
-
def shell_command(command)
|
87
|
-
s = command.map {|word| shell_single_word(word) }.join(' ')
|
88
|
-
ShellEscaped.new_no_dup(s)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Escape.shell_single_word quotes shell meta characters.
|
92
|
-
# It returns an instance of ShellEscaped.
|
93
|
-
#
|
94
|
-
# The result string is always single shell word, even if
|
95
|
-
# the argument is "".
|
96
|
-
# Escape.shell_single_word("") returns #<Escape::ShellEscaped: ''>.
|
97
|
-
#
|
98
|
-
# Escape.shell_single_word("") #=> #<Escape::ShellEscaped: ''>
|
99
|
-
# Escape.shell_single_word("foo") #=> #<Escape::ShellEscaped: foo>
|
100
|
-
# Escape.shell_single_word("*") #=> #<Escape::ShellEscaped: '*'>
|
101
|
-
def shell_single_word(str)
|
102
|
-
if str && str.empty?
|
103
|
-
ShellEscaped.new_no_dup("''")
|
104
|
-
elsif %r{\A[0-9A-Za-z+,./:=@_-]+\z} =~ str
|
105
|
-
ShellEscaped.new(str)
|
106
|
-
else
|
107
|
-
result = ''
|
108
|
-
str.scan(/('+)|[^']+/) {
|
109
|
-
if $1
|
110
|
-
result << %q{\'} * $1.length
|
111
|
-
else
|
112
|
-
result << "'#{$&}'"
|
113
|
-
end
|
114
|
-
}
|
115
|
-
ShellEscaped.new_no_dup(result)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
class PercentEncoded < StringWrapper
|
120
|
-
end
|
121
|
-
|
122
|
-
# Escape.uri_segment escapes URI segment using percent-encoding.
|
123
|
-
# It returns an instance of PercentEncoded.
|
124
|
-
#
|
125
|
-
# Escape.uri_segment("a/b") #=> #<Escape::PercentEncoded: a%2Fb>
|
126
|
-
#
|
127
|
-
# The segment is "/"-splitted element after authority before query in URI, as follows.
|
128
|
-
#
|
129
|
-
# scheme://authority/segment1/segment2/.../segmentN?query#fragment
|
130
|
-
#
|
131
|
-
# See RFC 3986 for details of URI.
|
132
|
-
def uri_segment(str)
|
133
|
-
# pchar - pct-encoded = unreserved / sub-delims / ":" / "@"
|
134
|
-
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
135
|
-
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
136
|
-
s = str.gsub(%r{[^A-Za-z0-9\-._~!$&'()*+,;=:@]}n) {
|
137
|
-
'%' + $&.unpack("H2")[0].upcase
|
138
|
-
}
|
139
|
-
PercentEncoded.new_no_dup(s)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Escape.uri_path escapes URI path using percent-encoding.
|
143
|
-
# The given path should be a sequence of (non-escaped) segments separated by "/".
|
144
|
-
# The segments cannot contains "/".
|
145
|
-
# It returns an instance of PercentEncoded.
|
146
|
-
#
|
147
|
-
# Escape.uri_path("a/b/c") #=> #<Escape::PercentEncoded: a/b/c>
|
148
|
-
# Escape.uri_path("a?b/c?d/e?f") #=> #<Escape::PercentEncoded: a%3Fb/c%3Fd/e%3Ff>
|
149
|
-
#
|
150
|
-
# The path is the part after authority before query in URI, as follows.
|
151
|
-
#
|
152
|
-
# scheme://authority/path#fragment
|
153
|
-
#
|
154
|
-
# See RFC 3986 for details of URI.
|
155
|
-
#
|
156
|
-
# Note that this function is not appropriate to convert OS path to URI.
|
157
|
-
def uri_path(str)
|
158
|
-
s = str.gsub(%r{[^/]+}n) { uri_segment($&) }
|
159
|
-
PercentEncoded.new_no_dup(s)
|
160
|
-
end
|
161
|
-
|
162
|
-
# :stopdoc:
|
163
|
-
def html_form_fast(pairs, sep='&')
|
164
|
-
s = pairs.map {|k, v|
|
165
|
-
# query-chars - pct-encoded - x-www-form-urlencoded-delimiters =
|
166
|
-
# unreserved / "!" / "$" / "'" / "(" / ")" / "*" / "," / ":" / "@" / "/" / "?"
|
167
|
-
# query-char - pct-encoded = unreserved / sub-delims / ":" / "@" / "/" / "?"
|
168
|
-
# query-char = pchar / "/" / "?" = unreserved / pct-encoded / sub-delims / ":" / "@" / "/" / "?"
|
169
|
-
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
170
|
-
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
171
|
-
# x-www-form-urlencoded-delimiters = "&" / "+" / ";" / "="
|
172
|
-
k = k.gsub(%r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n) {
|
173
|
-
'%' + $&.unpack("H2")[0].upcase
|
174
|
-
}
|
175
|
-
v = v.gsub(%r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n) {
|
176
|
-
'%' + $&.unpack("H2")[0].upcase
|
177
|
-
}
|
178
|
-
"#{k}=#{v}"
|
179
|
-
}.join(sep)
|
180
|
-
PercentEncoded.new_no_dup(s)
|
181
|
-
end
|
182
|
-
# :startdoc:
|
183
|
-
|
184
|
-
# Escape.html_form composes HTML form key-value pairs as a x-www-form-urlencoded encoded string.
|
185
|
-
# It returns an instance of PercentEncoded.
|
186
|
-
#
|
187
|
-
# Escape.html_form takes an array of pair of strings or
|
188
|
-
# an hash from string to string.
|
189
|
-
#
|
190
|
-
# Escape.html_form([["a","b"], ["c","d"]]) #=> #<Escape::PercentEncoded: a=b&c=d>
|
191
|
-
# Escape.html_form({"a"=>"b", "c"=>"d"}) #=> #<Escape::PercentEncoded: a=b&c=d>
|
192
|
-
#
|
193
|
-
# In the array form, it is possible to use same key more than once.
|
194
|
-
# (It is required for a HTML form which contains
|
195
|
-
# checkboxes and select element with multiple attribute.)
|
196
|
-
#
|
197
|
-
# Escape.html_form([["k","1"], ["k","2"]]) #=> #<Escape::PercentEncoded: k=1&k=2>
|
198
|
-
#
|
199
|
-
# If the strings contains characters which must be escaped in x-www-form-urlencoded,
|
200
|
-
# they are escaped using %-encoding.
|
201
|
-
#
|
202
|
-
# Escape.html_form([["k=","&;="]]) #=> #<Escape::PercentEncoded: k%3D=%26%3B%3D>
|
203
|
-
#
|
204
|
-
# The separator can be specified by the optional second argument.
|
205
|
-
#
|
206
|
-
# Escape.html_form([["a","b"], ["c","d"]], ";") #=> #<Escape::PercentEncoded: a=b;c=d>
|
207
|
-
#
|
208
|
-
# See HTML 4.01 for details.
|
209
|
-
def html_form(pairs, sep='&')
|
210
|
-
r = ''
|
211
|
-
first = true
|
212
|
-
pairs.each {|k, v|
|
213
|
-
# query-chars - pct-encoded - x-www-form-urlencoded-delimiters =
|
214
|
-
# unreserved / "!" / "$" / "'" / "(" / ")" / "*" / "," / ":" / "@" / "/" / "?"
|
215
|
-
# query-char - pct-encoded = unreserved / sub-delims / ":" / "@" / "/" / "?"
|
216
|
-
# query-char = pchar / "/" / "?" = unreserved / pct-encoded / sub-delims / ":" / "@" / "/" / "?"
|
217
|
-
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
218
|
-
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
219
|
-
# x-www-form-urlencoded-delimiters = "&" / "+" / ";" / "="
|
220
|
-
r << sep if !first
|
221
|
-
first = false
|
222
|
-
k.each_byte {|byte|
|
223
|
-
ch = byte.chr
|
224
|
-
if %r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n =~ ch
|
225
|
-
r << "%" << ch.unpack("H2")[0].upcase
|
226
|
-
else
|
227
|
-
r << ch
|
228
|
-
end
|
229
|
-
}
|
230
|
-
r << '='
|
231
|
-
v.each_byte {|byte|
|
232
|
-
ch = byte.chr
|
233
|
-
if %r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n =~ ch
|
234
|
-
r << "%" << ch.unpack("H2")[0].upcase
|
235
|
-
else
|
236
|
-
r << ch
|
237
|
-
end
|
238
|
-
}
|
239
|
-
}
|
240
|
-
PercentEncoded.new_no_dup(r)
|
241
|
-
end
|
242
|
-
|
243
|
-
class HTMLEscaped < StringWrapper
|
244
|
-
end
|
245
|
-
|
246
|
-
# :stopdoc:
|
247
|
-
HTML_TEXT_ESCAPE_HASH = {
|
248
|
-
'&' => '&',
|
249
|
-
'<' => '<',
|
250
|
-
'>' => '>',
|
251
|
-
}
|
252
|
-
# :startdoc:
|
253
|
-
|
254
|
-
# Escape.html_text escapes a string appropriate for HTML text using character references.
|
255
|
-
# It returns an instance of HTMLEscaped.
|
256
|
-
#
|
257
|
-
# It escapes 3 characters:
|
258
|
-
# * '&' to '&'
|
259
|
-
# * '<' to '<'
|
260
|
-
# * '>' to '>'
|
261
|
-
#
|
262
|
-
# Escape.html_text("abc") #=> #<Escape::HTMLEscaped: abc>
|
263
|
-
# Escape.html_text("a & b < c > d") #=> #<Escape::HTMLEscaped: a & b < c > d>
|
264
|
-
#
|
265
|
-
# This function is not appropriate for escaping HTML element attribute
|
266
|
-
# because quotes are not escaped.
|
267
|
-
def html_text(str)
|
268
|
-
s = str.gsub(/[&<>]/) {|ch| HTML_TEXT_ESCAPE_HASH[ch] }
|
269
|
-
HTMLEscaped.new_no_dup(s)
|
270
|
-
end
|
271
|
-
|
272
|
-
# :stopdoc:
|
273
|
-
HTML_ATTR_ESCAPE_HASH = {
|
274
|
-
'&' => '&',
|
275
|
-
'<' => '<',
|
276
|
-
'>' => '>',
|
277
|
-
'"' => '"',
|
278
|
-
}
|
279
|
-
# :startdoc:
|
280
|
-
|
281
|
-
class HTMLAttrValue < StringWrapper
|
282
|
-
end
|
283
|
-
|
284
|
-
# Escape.html_attr_value encodes a string as a double-quoted HTML attribute using character references.
|
285
|
-
# It returns an instance of HTMLAttrValue.
|
286
|
-
#
|
287
|
-
# Escape.html_attr_value("abc") #=> #<Escape::HTMLAttrValue: "abc">
|
288
|
-
# Escape.html_attr_value("a&b") #=> #<Escape::HTMLAttrValue: "a&b">
|
289
|
-
# Escape.html_attr_value("ab&<>\"c") #=> #<Escape::HTMLAttrValue: "ab&<>"c">
|
290
|
-
# Escape.html_attr_value("a'c") #=> #<Escape::HTMLAttrValue: "a'c">
|
291
|
-
#
|
292
|
-
# It escapes 4 characters:
|
293
|
-
# * '&' to '&'
|
294
|
-
# * '<' to '<'
|
295
|
-
# * '>' to '>'
|
296
|
-
# * '"' to '"'
|
297
|
-
#
|
298
|
-
def html_attr_value(str)
|
299
|
-
s = '"' + str.gsub(/[&<>"]/) {|ch| HTML_ATTR_ESCAPE_HASH[ch] } + '"'
|
300
|
-
HTMLAttrValue.new_no_dup(s)
|
301
|
-
end
|
302
|
-
end
|
data/lib/utils/fileutil.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module FileUtil
|
4
|
-
|
5
|
-
def FileUtil.read_file(path)
|
6
|
-
FileUtil.read_file_to_array(path).join('')
|
7
|
-
end
|
8
|
-
|
9
|
-
def FileUtil.read_file_to_array(path)
|
10
|
-
contents = []
|
11
|
-
return contents unless File.exists?(path)
|
12
|
-
|
13
|
-
open(path, 'r') do |l|
|
14
|
-
contents = l.readlines
|
15
|
-
end
|
16
|
-
|
17
|
-
contents
|
18
|
-
end
|
19
|
-
def FileUtil.read_binary_file(path)
|
20
|
-
contents = ''
|
21
|
-
return contents unless File.exists?(path)
|
22
|
-
|
23
|
-
open(path, 'rb') do |l|
|
24
|
-
while (!l.eof?)
|
25
|
-
contents << l.read(4096)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
contents
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def FileUtil.write_file(path, content, flush=true)
|
35
|
-
FileUtil.write_or_append_file('w', path, content, flush)
|
36
|
-
end
|
37
|
-
|
38
|
-
def FileUtil.append_file(path, content, flush=true)
|
39
|
-
FileUtil.write_or_append_file('a', path, content, flush)
|
40
|
-
end
|
41
|
-
|
42
|
-
def FileUtil.write_or_append_file(write_or_append, path, content = '', flush = true)
|
43
|
-
#STDERR.puts "Writing to #{ path }..."
|
44
|
-
FileUtil.create_dir(File.dirname(path))
|
45
|
-
|
46
|
-
open(path, write_or_append) do |f|
|
47
|
-
f.puts content
|
48
|
-
f.flush if flush;
|
49
|
-
end
|
50
|
-
File.chmod(0600, path)
|
51
|
-
end
|
52
|
-
|
53
|
-
def FileUtil.create_file(filepath, perm='w', file_perms=nil, force=false)
|
54
|
-
raise Exception.new("File #{filepath} already exists!") if File.exists?(filepath) && !force
|
55
|
-
|
56
|
-
newfile = File.new(filepath, perm)
|
57
|
-
begin
|
58
|
-
if file_perms && File.exists?(file_perms)
|
59
|
-
File.chown(File.stat(file_perms).uid.to_i, File.stat(file_perms).gid.to_i, filepath)
|
60
|
-
end
|
61
|
-
rescue NotImplementedError => ex
|
62
|
-
end
|
63
|
-
|
64
|
-
newfile
|
65
|
-
end
|
66
|
-
|
67
|
-
def FileUtil.create_dir(dirpath, dir_perms=nil)
|
68
|
-
return if File.directory?(dirpath)
|
69
|
-
|
70
|
-
#STDERR.puts "Creating #{ dirpath }"
|
71
|
-
FileUtils.makedirs(dirpath)
|
72
|
-
|
73
|
-
if dir_perms && File.exists?(dir_perms)
|
74
|
-
File.chown(File.stat(dir_perms).uid.to_i, File.stat(dir_perms).gid.to_i, dirpath)
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
data/lib/utils/httputil.rb
DELETED
@@ -1,266 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'uri'
|
3
|
-
require 'timeout'
|
4
|
-
require 'net/http'
|
5
|
-
|
6
|
-
module HTTPUtil
|
7
|
-
VALID_METHODS = %w{GET HEAD POST PUT DELETE}
|
8
|
-
@@timeout = 20
|
9
|
-
|
10
|
-
# Takes a string. See WEBrick::parse_header(string).
|
11
|
-
def HTTPUtil.parse_header(raw)
|
12
|
-
header = Hash.new([].freeze)
|
13
|
-
raw.each_line do |line|
|
14
|
-
case line
|
15
|
-
when /\A(.+?):\s+(.+)\z/om
|
16
|
-
name, value = $1, $2
|
17
|
-
name = name.tr('-', '_').to_sym
|
18
|
-
value.strip!
|
19
|
-
|
20
|
-
header[name] = [] unless header.has_key?(name)
|
21
|
-
header[name] << value
|
22
|
-
end
|
23
|
-
end
|
24
|
-
header
|
25
|
-
end
|
26
|
-
|
27
|
-
# Takes a string or array. See parse_header_body for further info.
|
28
|
-
# Returns +method+, +http_version+, +uri+, +header+, +body+
|
29
|
-
def HTTPUtil.parse_http_request(data, host=:unknown, port=80)
|
30
|
-
return unless data && !data.empty?
|
31
|
-
data = data.split(/\r?\n/) unless data.kind_of? Array
|
32
|
-
data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
|
33
|
-
request_line = data.shift # i.e. GET /path HTTP/1.1
|
34
|
-
method, path, http_version = nil
|
35
|
-
|
36
|
-
# With WEBrick and other proxies, the entire URI is included in HTTP requests.
|
37
|
-
# i.e. GET http://stellaaahhhh.com/streetcar.png HTTP/1.1
|
38
|
-
# The parser is expecting just the absolute path.
|
39
|
-
if request_line =~ /^(\S+)\s+(http:\/\/.+)\s+(HTTP.+)?/mo
|
40
|
-
uri = URI.parse($2)
|
41
|
-
request_line = "#{$1} #{uri.request_uri} #{$3}"
|
42
|
-
host = uri.host
|
43
|
-
end
|
44
|
-
|
45
|
-
if request_line =~ /^(\S+)\s+(\S+)(?:\s+HTTP\/(\d+\.\d+))?/mo
|
46
|
-
method = $1
|
47
|
-
http_version = $3 # Comes before $2 b/c the split resets the numbered vars
|
48
|
-
path, query_string = $2.split('?')
|
49
|
-
|
50
|
-
# We only process the header and body data when we know we're
|
51
|
-
# starting from the beginning of a request string. We don't
|
52
|
-
# want no partials.
|
53
|
-
header, body = HTTPUtil.parse_header_body(data)
|
54
|
-
query = HTTPUtil.parse_query(method, query_string)
|
55
|
-
|
56
|
-
|
57
|
-
# TODO: Parse username/password
|
58
|
-
uri = URI::HTTP.build({
|
59
|
-
:scheme => 'http',
|
60
|
-
:host => header[:Host][0] || host.to_s,
|
61
|
-
:port => port,
|
62
|
-
:path => path,
|
63
|
-
:query => query_string
|
64
|
-
})
|
65
|
-
|
66
|
-
else
|
67
|
-
rl = request_line.sub(/\x0d?\x0a\z/o, '')
|
68
|
-
raise "Bad Request-Line `#{rl}'."
|
69
|
-
end
|
70
|
-
|
71
|
-
return method, http_version, uri, header, body
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
# Takes a string or array. See parse_header_body for further info.
|
76
|
-
# Returns +status+, +http_version+, +message+, +header+, +body+
|
77
|
-
def HTTPUtil.parse_http_response(data=[])
|
78
|
-
return unless data && !data.empty?
|
79
|
-
data = data.split(/\r?\n/) unless data.kind_of? Array
|
80
|
-
data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
|
81
|
-
status_line = data.shift # ie. HTTP/1.1 200 OK
|
82
|
-
http_version, status, message = nil
|
83
|
-
|
84
|
-
if status_line =~ /^HTTP\/(\d.+?)(\s+(\d\d\d)\s+(.+))?$/mo
|
85
|
-
http_version = $1
|
86
|
-
status = $2
|
87
|
-
message = $4
|
88
|
-
|
89
|
-
header, body, query = HTTPUtil.parse_header_body(data)
|
90
|
-
|
91
|
-
else
|
92
|
-
raise "Bad Response-Line `#{status_line}'."
|
93
|
-
end
|
94
|
-
|
95
|
-
return status, http_version, message, header, body
|
96
|
-
end
|
97
|
-
|
98
|
-
# Process everything after the first line of an HTTP request or response:
|
99
|
-
# GET / HTTP/1.1
|
100
|
-
# HTTP/1.1 200 OK
|
101
|
-
# etc...
|
102
|
-
# Used by parse_http_request and parse_http_response but can be used separately.
|
103
|
-
# Takes a string or array of strings. A string should be formatted like an HTTP
|
104
|
-
# request or response. If a body is present it should be separated by two newlines.
|
105
|
-
# An array of string should contain an empty or nil element between the header
|
106
|
-
# and body content. This will happen naturally if the raw lines were split by
|
107
|
-
# a single line terminator. (i.e. /\n/ rather than /\n\n/)
|
108
|
-
# Returns header (hash), body (string)
|
109
|
-
def HTTPUtil.parse_header_body(data=[])
|
110
|
-
header, body = {}, nil
|
111
|
-
data = data.split(/\r?\n/) unless data.kind_of? Array
|
112
|
-
data.shift while (data[0].nil? || data[0].empty?) # Remove leading empties
|
113
|
-
|
114
|
-
return header, body unless data && !data.empty?
|
115
|
-
|
116
|
-
#puts data.to_yaml
|
117
|
-
|
118
|
-
# Skip that first line if it exists
|
119
|
-
data.shift if data[0].match(/\AHTTP|GET|POST|DELETE|PUT|HEAD/mo)
|
120
|
-
|
121
|
-
header_lines = []
|
122
|
-
header_lines << data.shift while (!data[0].nil? && !data[0].empty?)
|
123
|
-
header = HTTPUtil::parse_header(header_lines.join($/))
|
124
|
-
|
125
|
-
# We omit the blank line that delimits the header from the body
|
126
|
-
body = data[1..-1].join($/) unless data.empty?
|
127
|
-
|
128
|
-
return header, body
|
129
|
-
end
|
130
|
-
|
131
|
-
def HTTPUtil.parse_query(request_method, query_string, content_type='', body='')
|
132
|
-
query = Hash.new([].freeze)
|
133
|
-
|
134
|
-
if request_method == "GET" || request_method == "HEAD"
|
135
|
-
query = HTTPUtil::parse_query_from_string(query_string)
|
136
|
-
elsif content_type =~ /^application\/x-www-form-urlencoded/
|
137
|
-
query = HTTPUtil::parse_query_from_string(body)
|
138
|
-
elsif content_type =~ /^multipart\/form-data; boundary=(.+)/
|
139
|
-
boundary = $1.tr('"', '')
|
140
|
-
query = HTTPUtil::parse_form_data(body, boundary)
|
141
|
-
else
|
142
|
-
query
|
143
|
-
end
|
144
|
-
|
145
|
-
query
|
146
|
-
end
|
147
|
-
|
148
|
-
def HTTPUtil.validate_method(meth='GET')
|
149
|
-
(VALID_METHODS.member? meth.upcase) ? meth : VALID_METHODS[0]
|
150
|
-
end
|
151
|
-
|
152
|
-
# Parses a query string by breaking it up at the '&'
|
153
|
-
# and ';' characters. You can also use this to parse
|
154
|
-
# cookies by changing the characters used in the second
|
155
|
-
# parameter (which defaults to '&;'.
|
156
|
-
# Stolen from Mongrel
|
157
|
-
def HTTPUtil.parse_query_from_string(qs, d = '&;')
|
158
|
-
params = {}
|
159
|
-
(qs||'').split(/[#{d}] */n).inject(params) { |h,p|
|
160
|
-
k, v=unescape(p).split('=',2)
|
161
|
-
next unless k
|
162
|
-
k = k.tr('-', '_').to_sym
|
163
|
-
if cur = params[k]
|
164
|
-
if cur.class == Array
|
165
|
-
params[k] << v
|
166
|
-
else
|
167
|
-
params[k] = [cur, v]
|
168
|
-
end
|
169
|
-
else
|
170
|
-
params[k] = v
|
171
|
-
end
|
172
|
-
}
|
173
|
-
|
174
|
-
return params
|
175
|
-
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
# Based on WEBrick::HTTPutils::parse_form_data
|
180
|
-
def HTTPUtil.parse_form_data(io, boundary)
|
181
|
-
boundary_regexp = /\A--#{boundary}(--)?#{$/}\z/
|
182
|
-
form_data = Hash.new
|
183
|
-
return form_data unless io
|
184
|
-
data = nil
|
185
|
-
io.each_line{|line|
|
186
|
-
if boundary_regexp =~ line
|
187
|
-
if data
|
188
|
-
data.chop!
|
189
|
-
key = data.name.tr('-', '_').to_sym
|
190
|
-
if form_data.has_key?(key)
|
191
|
-
form_data[key].append_data(data)
|
192
|
-
else
|
193
|
-
form_data[key] = data
|
194
|
-
end
|
195
|
-
end
|
196
|
-
data = FormData.new
|
197
|
-
next
|
198
|
-
else
|
199
|
-
if data
|
200
|
-
data << line
|
201
|
-
end
|
202
|
-
end
|
203
|
-
}
|
204
|
-
return form_data
|
205
|
-
end
|
206
|
-
|
207
|
-
|
208
|
-
# Extend the basic query string parser provided by the cgi module.
|
209
|
-
# converts single valued params (the most common case) to
|
210
|
-
# objects instead of arrays
|
211
|
-
#
|
212
|
-
# Input:
|
213
|
-
# the query string
|
214
|
-
#
|
215
|
-
# Output:
|
216
|
-
# hash of parameters, contains arrays for multivalued parameters
|
217
|
-
# (multiselect, checkboxes , etc)
|
218
|
-
# If no query string is provided (nil or "") returns an empty hash.
|
219
|
-
def HTTPUtil.query_to_hash(query_string)
|
220
|
-
return {} unless query_string
|
221
|
-
|
222
|
-
query_parameters = HTTPUtil.parse_query(query_string)
|
223
|
-
|
224
|
-
query_parameters.each { |key, val|
|
225
|
-
# replace the array with an object
|
226
|
-
query_parameters[key] = val[0] if 1 == val.length
|
227
|
-
}
|
228
|
-
|
229
|
-
# set default value to nil! cgi sets this to []
|
230
|
-
query_parameters.default = nil
|
231
|
-
|
232
|
-
return query_parameters
|
233
|
-
end
|
234
|
-
|
235
|
-
def HTTPUtil.hash_to_query(parameters)
|
236
|
-
return '' unless parameters
|
237
|
-
pairs = []
|
238
|
-
parameters.each do |param, value|
|
239
|
-
pairs << "#{param}=#{URI.escape(value.to_s)}"
|
240
|
-
end
|
241
|
-
return pairs.join('&')
|
242
|
-
#return pairs.join(";")
|
243
|
-
end
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
# Performs URI escaping so that you can construct proper
|
248
|
-
# query strings faster. Use this rather than the cgi.rb
|
249
|
-
# version since it's faster. (Stolen from Mongrel/Camping).
|
250
|
-
def HTTPUtil.escape(s)
|
251
|
-
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
|
252
|
-
'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
253
|
-
}.tr(' ', '+')
|
254
|
-
end
|
255
|
-
|
256
|
-
|
257
|
-
# Unescapes a URI escaped string. (Stolen from Mongrel/Camping).
|
258
|
-
def HTTPUtil.unescape(s)
|
259
|
-
s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
|
260
|
-
[$1.delete('%')].pack('H*')
|
261
|
-
}
|
262
|
-
end
|
263
|
-
|
264
|
-
|
265
|
-
end
|
266
|
-
|