rfuzz 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/README +18 -17
  2. data/Rakefile +8 -3
  3. data/doc/rdoc/classes/RFuzz/Browser.html +229 -0
  4. data/doc/rdoc/classes/RFuzz/Browser.src/M000068.html +25 -0
  5. data/doc/rdoc/classes/RFuzz/Browser.src/M000069.html +23 -0
  6. data/doc/rdoc/classes/RFuzz/Browser.src/M000070.html +24 -0
  7. data/doc/rdoc/classes/RFuzz/HttpClient.html +10 -0
  8. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000010.html +10 -10
  9. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000011.html +18 -18
  10. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000012.html +36 -35
  11. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000013.html +35 -35
  12. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000014.html +43 -43
  13. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000015.html +22 -22
  14. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000016.html +12 -12
  15. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000017.html +18 -18
  16. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000018.html +4 -4
  17. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000019.html +12 -12
  18. data/doc/rdoc/classes/RFuzz/HttpEncoding.html +13 -0
  19. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000001.html +12 -12
  20. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000002.html +4 -4
  21. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000003.html +12 -12
  22. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000004.html +4 -4
  23. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000005.html +18 -18
  24. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000006.html +4 -4
  25. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000007.html +6 -6
  26. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000008.html +6 -6
  27. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000009.html +18 -18
  28. data/doc/rdoc/classes/RFuzz/Notifier.src/M000044.html +3 -3
  29. data/doc/rdoc/classes/RFuzz/Notifier.src/M000045.html +3 -3
  30. data/doc/rdoc/classes/RFuzz/Notifier.src/M000046.html +3 -3
  31. data/doc/rdoc/classes/RFuzz/Notifier.src/M000047.html +3 -3
  32. data/doc/rdoc/classes/RFuzz/Notifier.src/M000048.html +3 -3
  33. data/doc/rdoc/classes/RFuzz/Notifier.src/M000049.html +3 -3
  34. data/doc/rdoc/classes/RFuzz/Session.html +11 -1
  35. data/doc/rdoc/classes/RFuzz/Session.src/M000020.html +16 -16
  36. data/doc/rdoc/classes/RFuzz/Session.src/M000021.html +4 -4
  37. data/doc/rdoc/classes/RFuzz/Session.src/M000022.html +4 -4
  38. data/doc/rdoc/classes/RFuzz/Session.src/M000023.html +20 -20
  39. data/doc/rdoc/classes/RFuzz/Session.src/M000024.html +5 -5
  40. data/doc/rdoc/classes/RFuzz/Session.src/M000025.html +5 -5
  41. data/doc/rdoc/classes/RFuzz/Session.src/M000026.html +12 -12
  42. data/doc/rdoc/classes/RFuzz/Session.src/M000027.html +15 -15
  43. data/doc/rdoc/classes/RFuzz/Session.src/M000028.html +5 -5
  44. data/doc/rdoc/classes/RFuzz/Session.src/M000029.html +4 -4
  45. data/doc/rdoc/classes/RFuzz/Session.src/M000030.html +4 -4
  46. data/doc/rdoc/classes/RFuzz/Session.src/M000031.html +9 -9
  47. data/doc/rdoc/classes/RFuzz.html +5 -0
  48. data/doc/rdoc/created.rid +1 -1
  49. data/doc/rdoc/files/COPYING.html +1 -1
  50. data/doc/rdoc/files/LICENSE.html +1 -1
  51. data/doc/rdoc/files/README.html +23 -24
  52. data/doc/rdoc/files/lib/rfuzz/browser_rb.html +109 -0
  53. data/doc/rdoc/files/lib/rfuzz/client_rb.html +2 -1
  54. data/doc/rdoc/files/lib/rfuzz/random_rb.html +1 -1
  55. data/doc/rdoc/files/lib/rfuzz/rfuzz_rb.html +1 -1
  56. data/doc/rdoc/files/lib/rfuzz/session_rb.html +1 -1
  57. data/doc/rdoc/files/lib/rfuzz/stats_rb.html +1 -1
  58. data/doc/rdoc/fr_class_index.html +1 -0
  59. data/doc/rdoc/fr_file_index.html +1 -0
  60. data/doc/rdoc/fr_method_index.html +9 -6
  61. data/examples/cl_watcher.rb +36 -0
  62. data/examples/mongrel_test_suite/test/http/access_authentication.rb +8 -0
  63. data/examples/mongrel_test_suite/test/http/appendix.rb +76 -0
  64. data/examples/mongrel_test_suite/test/http/base_protocol.rb +4 -7
  65. data/examples/mongrel_test_suite/test/http/caching_in_http.rb +140 -0
  66. data/examples/mongrel_test_suite/test/http/connections.rb +48 -0
  67. data/examples/mongrel_test_suite/test/http/content_negotiation.rb +20 -0
  68. data/examples/mongrel_test_suite/test/http/entity.rb +24 -0
  69. data/examples/mongrel_test_suite/test/http/header_field_definitions.rb +231 -0
  70. data/examples/mongrel_test_suite/test/http/http_message.rb +122 -0
  71. data/examples/mongrel_test_suite/test/http/method_definitions.rb +52 -0
  72. data/examples/mongrel_test_suite/test/http/protocol_parameters.rb +286 -0
  73. data/examples/mongrel_test_suite/test/http/request.rb +28 -0
  74. data/examples/mongrel_test_suite/test/http/response.rb +20 -0
  75. data/examples/mongrel_test_suite/test/http/security_considerations.rb +54 -0
  76. data/examples/mongrel_test_suite/test/http/status_code_definitions.rb +192 -0
  77. data/ext/fuzzrnd/fuzzrnd.c +1 -2
  78. data/lib/rfuzz/browser.rb +53 -0
  79. data/lib/rfuzz/client.rb +11 -6
  80. data/lib/rfuzz/session.rb +3 -1
  81. data/tools/rakehelp.rb +4 -2
  82. metadata +24 -15
  83. data/test/coverage/index.html +0 -388
  84. data/test/coverage/lib-rfuzz-client_rb.html +0 -1127
  85. data/test/coverage/lib-rfuzz-random_rb.html +0 -739
  86. data/test/coverage/lib-rfuzz-session_rb.html +0 -783
  87. data/test/coverage/lib-rfuzz-stats_rb.html +0 -788
  88. data/test/server.rb +0 -101
  89. data/test/test_client.rb +0 -164
  90. data/test/test_fuzzrnd.rb +0 -31
  91. data/test/test_httpparser.rb +0 -48
  92. data/test/test_random.rb +0 -75
  93. data/test/test_session.rb +0 -33
  94. data/test/test_stats.rb +0 -45
data/README CHANGED
@@ -7,9 +7,13 @@ being very mean to a web server.
7
7
  At the moment is has a working and fairly extensive HTTP 1.1 client and some
8
8
  basic statistics math borrowed from the Mongrel project.
9
9
 
10
- In order for the test cases to run you need to start any Rails project on
11
- port 3000. Future releases will have tests starting built-in Mongrel servers to
12
- validate client functionality.
10
+ == RubyForge Project
11
+
12
+ The project is hosted at:
13
+
14
+ http://rubyforge.org/projects/rfuzz/
15
+
16
+ Where you can file bugs and other things, as well as download gems manually.
13
17
 
14
18
 
15
19
  == Motivation
@@ -25,14 +29,15 @@ It may also perform analysis of performance data and work as a simply load or
25
29
  pen testing tool. This is only a secondary goal though since there's plenty of
26
30
  good tools for that.
27
31
 
28
- == Downloading
32
+ == Installing
29
33
 
30
- Right now RFuzz just sits on my server, so you can download
31
- http://www.zedshaw.com/projects/rfuzz/rfuzz-0.4.gem or
32
- http://www.zedshaw.com/projects/rfuzz/rfuzz-0.4.tgz
33
- for the 0.4 version.
34
+ You can install RFuzz by simply using RubyGems:
35
+
36
+ sudo gem install rfuzz
37
+
38
+ It doesn't support windows unless you have build tools that can compile
39
+ modules against Ruby. No, you don't get this with Ruby One Click.
34
40
 
35
- Once it can actually be used to fuzz a system I'll make a RubyForge project.
36
41
 
37
42
  == RFuzz HTTP Client
38
43
 
@@ -83,10 +88,10 @@ parameters, cookies, and headers in blocks of requests to reduce repetition.
83
88
 
84
89
  === Client Limitations
85
90
 
86
- You can use the HTTP client right now to do HTTP requests and it is probably a
87
- lot easier than net/http for most requests that don't require complex POST bodies
88
- encoding. It also contains full documentation and has a full suite of encoding
89
- and decoding libraries. It can't handle large HTTP bodies yet.
91
+ The client handles chunked encoding inside the parser but the code for it is
92
+ still quite nasty. I'll be attacking that and cleaning it up very soon.
93
+ Even with this it's able to efficiently parse chunked encodings without
94
+ many problems (but could be better).
90
95
 
91
96
  It can't also parse cookies properly yet, so the above example kind of works, but the
92
97
  cookie isn't returned right.
@@ -244,9 +249,5 @@ some confounding element which made the test invalid.
244
249
 
245
250
  == Source Code
246
251
 
247
- The .tgz file (mentioned Downloading) has the source if you're interested. Remember
248
- that *you must have a rails app on 3000* for the tests to run. Just a limitation
249
- right now until I hook Mongrel into the test framework as the feedback loop.
250
-
251
252
  You can also view http://www.zedshaw.com/projects/rfuzz/coverage/ for the rcov
252
253
  generated coverage report which is also a decent source browser.
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ require 'fileutils'
8
8
  include FileUtils
9
9
 
10
10
  setup_tests
11
- setup_clean ["pkg", "lib/*.bundle", "*.gem", ".config"]
11
+ setup_clean ["pkg", "lib/*.bundle", "*.gem", ".config", "ext/**/Makefile"]
12
12
 
13
13
  setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
14
14
 
@@ -18,7 +18,7 @@ setup_extension('fuzzrnd','fuzzrnd')
18
18
  desc "Does a full compile, test run"
19
19
  task :default => [:http11_client, :fuzzrnd, :test]
20
20
 
21
- version="0.6"
21
+ version="0.7"
22
22
  name="rfuzz"
23
23
 
24
24
  setup_gem(name, version) do |spec|
@@ -43,6 +43,11 @@ task :uninstall => [:clean] do
43
43
  sh %{sudo gem uninstall #{name}}
44
44
  end
45
45
 
46
- task :project => [:clean, :ragel, :default, :test, :rdoc, :rcov, :package] do
46
+ task :site do
47
+ sh %{pushd doc/site; webgen; popd}
48
+ sh %{scp -r doc/site/output/* @rubyforge.org:/var/www/gforge-projects/rfuzz/}
49
+ end
50
+
51
+ task :project => [:clean, :ragel, :default, :test, :rdoc, :rcov, :package, :site] do
47
52
  sh %{scp -r doc/rdoc test/coverage @rubyforge.org:/var/www/gforge-projects/rfuzz/}
48
53
  end
@@ -0,0 +1,229 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Class: RFuzz::Browser</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="classHeader">
50
+ <table class="header-table">
51
+ <tr class="top-aligned-row">
52
+ <td><strong>Class</strong></td>
53
+ <td class="class-name-in-header">RFuzz::Browser</td>
54
+ </tr>
55
+ <tr class="top-aligned-row">
56
+ <td><strong>In:</strong></td>
57
+ <td>
58
+ <a href="../../files/lib/rfuzz/browser_rb.html">
59
+ lib/rfuzz/browser.rb
60
+ </a>
61
+ <br />
62
+ </td>
63
+ </tr>
64
+
65
+ <tr class="top-aligned-row">
66
+ <td><strong>Parent:</strong></td>
67
+ <td>
68
+ Object
69
+ </td>
70
+ </tr>
71
+ </table>
72
+ </div>
73
+ <!-- banner header -->
74
+
75
+ <div id="bodyContent">
76
+
77
+
78
+
79
+ <div id="contextContent">
80
+
81
+ <div id="description">
82
+ <p>
83
+ A simple class that emulates a browser using hpricot.
84
+ </p>
85
+
86
+ </div>
87
+
88
+
89
+ </div>
90
+
91
+ <div id="method-list">
92
+ <h3 class="section-bar">Methods</h3>
93
+
94
+ <div class="name-list">
95
+ <a href="#M000070">links</a>&nbsp;&nbsp;
96
+ <a href="#M000068">new</a>&nbsp;&nbsp;
97
+ <a href="#M000069">start</a>&nbsp;&nbsp;
98
+ </div>
99
+ </div>
100
+
101
+ </div>
102
+
103
+
104
+ <!-- if includes -->
105
+
106
+ <div id="section">
107
+
108
+
109
+ <div id="constants-list">
110
+ <h3 class="section-bar">Constants</h3>
111
+
112
+ <div class="name-list">
113
+ <table summary="Constants">
114
+ <tr class="top-aligned-row context-row">
115
+ <td class="context-item-name">DEFAULT_AGENT</td>
116
+ <td>=</td>
117
+ <td class="context-item-value">&quot;Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060608 Ubuntu/dapper-security Firefox/1.5.0.4&quot;</td>
118
+ </tr>
119
+ </table>
120
+ </div>
121
+ </div>
122
+
123
+
124
+
125
+ <div id="attribute-list">
126
+ <h3 class="section-bar">Attributes</h3>
127
+
128
+ <div class="name-list">
129
+ <table>
130
+ <tr class="top-aligned-row context-row">
131
+ <td class="context-item-name">agent</td>
132
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
133
+ <td class="context-item-desc"></td>
134
+ </tr>
135
+ <tr class="top-aligned-row context-row">
136
+ <td class="context-item-name">client</td>
137
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
138
+ <td class="context-item-desc"></td>
139
+ </tr>
140
+ <tr class="top-aligned-row context-row">
141
+ <td class="context-item-name">doc</td>
142
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
143
+ <td class="context-item-desc"></td>
144
+ </tr>
145
+ <tr class="top-aligned-row context-row">
146
+ <td class="context-item-name">response</td>
147
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
148
+ <td class="context-item-desc"></td>
149
+ </tr>
150
+ </table>
151
+ </div>
152
+ </div>
153
+
154
+
155
+
156
+ <!-- if method_list -->
157
+ <div id="methods">
158
+ <h3 class="section-bar">Public Class methods</h3>
159
+
160
+ <div id="method-M000068" class="method-detail">
161
+ <a name="M000068"></a>
162
+
163
+ <div class="method-heading">
164
+ <a href="Browser.src/M000068.html" target="Code" class="method-signature"
165
+ onclick="popupCode('Browser.src/M000068.html');return false;">
166
+ <span class="method-name">new</span><span class="method-args">(host, port=80, ops={}, agent=DEFAULT_AGENT)</span>
167
+ </a>
168
+ </div>
169
+
170
+ <div class="method-description">
171
+ <p>
172
+ The default agent used is Mozilla (from linux Dapper Drake), but you can
173
+ change it to something else.
174
+ </p>
175
+ </div>
176
+ </div>
177
+
178
+ <h3 class="section-bar">Public Instance methods</h3>
179
+
180
+ <div id="method-M000070" class="method-detail">
181
+ <a name="M000070"></a>
182
+
183
+ <div class="method-heading">
184
+ <a href="Browser.src/M000070.html" target="Code" class="method-signature"
185
+ onclick="popupCode('Browser.src/M000070.html');return false;">
186
+ <span class="method-name">links</span><span class="method-args">(matching=nil)</span>
187
+ </a>
188
+ </div>
189
+
190
+ <div class="method-description">
191
+ <p>
192
+ Returns an Array of Hpricot objects that are the links on the current page.
193
+ If you pass in matching as a regex (or any === compatible with String) then
194
+ it&#8217;ll only return those links.
195
+ </p>
196
+ </div>
197
+ </div>
198
+
199
+ <div id="method-M000069" class="method-detail">
200
+ <a name="M000069"></a>
201
+
202
+ <div class="method-heading">
203
+ <a href="Browser.src/M000069.html" target="Code" class="method-signature"
204
+ onclick="popupCode('Browser.src/M000069.html');return false;">
205
+ <span class="method-name">start</span><span class="method-args">(uri, ops={})</span>
206
+ </a>
207
+ </div>
208
+
209
+ <div class="method-description">
210
+ <p>
211
+ Makes the browser do a GET to this location. It takes the same params as <a
212
+ href="HttpClient.html">HttpClient</a> does for any method.
213
+ </p>
214
+ </div>
215
+ </div>
216
+
217
+
218
+ </div>
219
+
220
+
221
+ </div>
222
+
223
+
224
+ <div id="validator-badges">
225
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
226
+ </div>
227
+
228
+ </body>
229
+ </html>
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html>
7
+ <head>
8
+ <title>new (RFuzz::Browser)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
+ </head>
12
+ <body class="standalone-code">
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/browser.rb, line 17</span>
14
+ 17: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>=<span class="ruby-value">80</span>, <span class="ruby-identifier">ops</span>={}, <span class="ruby-identifier">agent</span>=<span class="ruby-constant">DEFAULT_AGENT</span>)
15
+ 18: <span class="ruby-ivar">@agent</span> = <span class="ruby-identifier">agent</span>
16
+ 19: <span class="ruby-ivar">@client</span> = <span class="ruby-constant">HttpClient</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>, <span class="ruby-identifier">ops</span>)
17
+ 20:
18
+ 21: <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>] <span class="ruby-operator">||=</span> {}
19
+ 22: <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>][<span class="ruby-value str">&quot;User-Agent&quot;</span>] <span class="ruby-operator">||=</span> <span class="ruby-ivar">@agent</span>
20
+ 23:
21
+ 24: <span class="ruby-ivar">@doc</span> = <span class="ruby-keyword kw">nil</span>
22
+ 25: <span class="ruby-ivar">@response</span> = <span class="ruby-keyword kw">nil</span>
23
+ 26: <span class="ruby-keyword kw">end</span></pre>
24
+ </body>
25
+ </html>
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html>
7
+ <head>
8
+ <title>start (RFuzz::Browser)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
+ </head>
12
+ <body class="standalone-code">
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/browser.rb, line 30</span>
14
+ 30: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">start</span>(<span class="ruby-identifier">uri</span>, <span class="ruby-identifier">ops</span>={})
15
+ 31: <span class="ruby-ivar">@response</span> = <span class="ruby-ivar">@client</span>.<span class="ruby-identifier">get</span>(<span class="ruby-identifier">uri</span>,<span class="ruby-identifier">ops</span>)
16
+ 32: <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@response</span>.<span class="ruby-identifier">http_status</span> <span class="ruby-operator">!=</span> <span class="ruby-value str">&quot;200&quot;</span>
17
+ 33: <span class="ruby-identifier">raise</span> <span class="ruby-node">&quot;Invalid status: #{@response.http_status}&quot;</span>
18
+ 34: <span class="ruby-keyword kw">end</span>
19
+ 35:
20
+ 36: <span class="ruby-ivar">@doc</span> = <span class="ruby-constant">Hpricot</span>(<span class="ruby-ivar">@response</span>.<span class="ruby-identifier">http_body</span>)
21
+ 37: <span class="ruby-keyword kw">end</span></pre>
22
+ </body>
23
+ </html>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html>
7
+ <head>
8
+ <title>links (RFuzz::Browser)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
+ </head>
12
+ <body class="standalone-code">
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/browser.rb, line 42</span>
14
+ 42: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">links</span>(<span class="ruby-identifier">matching</span>=<span class="ruby-keyword kw">nil</span>)
15
+ 43: <span class="ruby-identifier">links</span> = <span class="ruby-ivar">@doc</span><span class="ruby-operator">/</span><span class="ruby-identifier">:a</span>
16
+ 44: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">matching</span>
17
+ 45: <span class="ruby-comment cmt"># return only the ones that match</span>
18
+ 46: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">links</span>.<span class="ruby-identifier">select</span> {<span class="ruby-operator">|</span><span class="ruby-identifier">l</span><span class="ruby-operator">|</span> <span class="ruby-identifier">matching</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">l</span>.<span class="ruby-identifier">attributes</span>[<span class="ruby-value str">&quot;href&quot;</span>]}
19
+ 47: <span class="ruby-keyword kw">else</span>
20
+ 48: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">links</span>
21
+ 49: <span class="ruby-keyword kw">end</span>
22
+ 50: <span class="ruby-keyword kw">end</span></pre>
23
+ </body>
24
+ </html>
@@ -208,6 +208,16 @@ information.
208
208
  <td>=</td>
209
209
  <td class="context-item-value">&quot;%s %s HTTP/1.1\r\n&quot;</td>
210
210
  </tr>
211
+ <tr class="top-aligned-row context-row">
212
+ <td class="context-item-name">REQ_CONTENT_LENGTH</td>
213
+ <td>=</td>
214
+ <td class="context-item-value">&quot;Content-Length&quot;</td>
215
+ </tr>
216
+ <tr class="top-aligned-row context-row">
217
+ <td class="context-item-name">REQ_HOST</td>
218
+ <td>=</td>
219
+ <td class="context-item-value">&quot;Host&quot;</td>
220
+ </tr>
211
221
  </table>
212
222
  </div>
213
223
  </div>
@@ -10,15 +10,15 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 210</span>
14
- 210: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>, <span class="ruby-identifier">options</span> = {})
15
- 211: <span class="ruby-ivar">@options</span> = <span class="ruby-identifier">options</span>
16
- 212: <span class="ruby-ivar">@host</span> = <span class="ruby-identifier">host</span>
17
- 213: <span class="ruby-ivar">@port</span> = <span class="ruby-identifier">port</span>
18
- 214: <span class="ruby-ivar">@cookies</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:cookies</span>] <span class="ruby-operator">||</span> {}
19
- 215: <span class="ruby-ivar">@allowed_methods</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:allowed_methods</span>] <span class="ruby-operator">||</span> [<span class="ruby-identifier">:put</span>, <span class="ruby-identifier">:get</span>, <span class="ruby-identifier">:post</span>, <span class="ruby-identifier">:delete</span>, <span class="ruby-identifier">:head</span>]
20
- 216: <span class="ruby-ivar">@notifier</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:notifier</span>]
21
- 217: <span class="ruby-ivar">@redirect</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:redirect</span>] <span class="ruby-operator">||</span> <span class="ruby-keyword kw">false</span>
22
- 218: <span class="ruby-keyword kw">end</span></pre>
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 214</span>
14
+ 214: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>, <span class="ruby-identifier">options</span> = {})
15
+ 215: <span class="ruby-ivar">@options</span> = <span class="ruby-identifier">options</span>
16
+ 216: <span class="ruby-ivar">@host</span> = <span class="ruby-identifier">host</span>
17
+ 217: <span class="ruby-ivar">@port</span> = <span class="ruby-identifier">port</span>
18
+ 218: <span class="ruby-ivar">@cookies</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:cookies</span>] <span class="ruby-operator">||</span> {}
19
+ 219: <span class="ruby-ivar">@allowed_methods</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:allowed_methods</span>] <span class="ruby-operator">||</span> [<span class="ruby-identifier">:put</span>, <span class="ruby-identifier">:get</span>, <span class="ruby-identifier">:post</span>, <span class="ruby-identifier">:delete</span>, <span class="ruby-identifier">:head</span>]
20
+ 220: <span class="ruby-ivar">@notifier</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:notifier</span>]
21
+ 221: <span class="ruby-ivar">@redirect</span> = <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:redirect</span>] <span class="ruby-operator">||</span> <span class="ruby-keyword kw">false</span>
22
+ 222: <span class="ruby-keyword kw">end</span></pre>
23
23
  </body>
24
24
  </html>
@@ -10,25 +10,25 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 226</span>
14
- 226: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">build_request</span>(<span class="ruby-identifier">out</span>, <span class="ruby-identifier">method</span>, <span class="ruby-identifier">uri</span>, <span class="ruby-identifier">req</span>)
15
- 227: <span class="ruby-identifier">ops</span> = <span class="ruby-ivar">@options</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">req</span>)
16
- 228: <span class="ruby-identifier">query</span> = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:query</span>]
17
- 229:
18
- 230: <span class="ruby-comment cmt"># merge head differently since that's typically what they mean</span>
19
- 231: <span class="ruby-identifier">head</span> = <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:head</span>] <span class="ruby-operator">||</span> {}
20
- 232: <span class="ruby-identifier">head</span> = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>].<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">head</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>]
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 230</span>
14
+ 230: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">build_request</span>(<span class="ruby-identifier">out</span>, <span class="ruby-identifier">method</span>, <span class="ruby-identifier">uri</span>, <span class="ruby-identifier">req</span>)
15
+ 231: <span class="ruby-identifier">ops</span> = <span class="ruby-ivar">@options</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">req</span>)
16
+ 232: <span class="ruby-identifier">query</span> = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:query</span>]
21
17
  233:
22
- 234: <span class="ruby-comment cmt"># setup basic headers we always need</span>
23
- 235: <span class="ruby-identifier">head</span>[<span class="ruby-constant">HOST</span>] = <span class="ruby-identifier">encode_host</span>(<span class="ruby-ivar">@host</span>,<span class="ruby-ivar">@port</span>)
24
- 236: <span class="ruby-identifier">head</span>[<span class="ruby-constant">CONTENT_LENGTH</span>] = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>] <span class="ruby-operator">?</span> <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>].<span class="ruby-identifier">length</span> <span class="ruby-operator">:</span> <span class="ruby-value">0</span>
18
+ 234: <span class="ruby-comment cmt"># merge head differently since that's typically what they mean</span>
19
+ 235: <span class="ruby-identifier">head</span> = <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:head</span>] <span class="ruby-operator">||</span> {}
20
+ 236: <span class="ruby-identifier">head</span> = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>].<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">head</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:head</span>]
25
21
  237:
26
- 238: <span class="ruby-comment cmt"># blast it out</span>
27
- 239: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-constant">HTTP_REQUEST_HEADER</span> <span class="ruby-operator">%</span> [<span class="ruby-identifier">method</span>, <span class="ruby-identifier">encode_query</span>(<span class="ruby-identifier">uri</span>,<span class="ruby-identifier">query</span>)])
28
- 240: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">encode_headers</span>(<span class="ruby-identifier">head</span>))
29
- 241: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">encode_cookies</span>(<span class="ruby-ivar">@cookies</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">req</span>[<span class="ruby-identifier">:cookies</span>] <span class="ruby-operator">||</span> {})))
30
- 242: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-value str">&quot;\r\n&quot;</span>)
31
- 243: <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>] <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;&quot;</span>
32
- 244: <span class="ruby-keyword kw">end</span></pre>
22
+ 238: <span class="ruby-comment cmt"># setup basic headers we always need</span>
23
+ 239: <span class="ruby-identifier">head</span>[<span class="ruby-constant">REQ_HOST</span>] = <span class="ruby-identifier">encode_host</span>(<span class="ruby-ivar">@host</span>,<span class="ruby-ivar">@port</span>)
24
+ 240: <span class="ruby-identifier">head</span>[<span class="ruby-constant">REQ_CONTENT_LENGTH</span>] = <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>] <span class="ruby-operator">?</span> <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>].<span class="ruby-identifier">length</span> <span class="ruby-operator">:</span> <span class="ruby-value">0</span>
25
+ 241:
26
+ 242: <span class="ruby-comment cmt"># blast it out</span>
27
+ 243: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-constant">HTTP_REQUEST_HEADER</span> <span class="ruby-operator">%</span> [<span class="ruby-identifier">method</span>, <span class="ruby-identifier">encode_query</span>(<span class="ruby-identifier">uri</span>,<span class="ruby-identifier">query</span>)])
28
+ 244: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">encode_headers</span>(<span class="ruby-identifier">head</span>))
29
+ 245: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">encode_cookies</span>(<span class="ruby-ivar">@cookies</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">req</span>[<span class="ruby-identifier">:cookies</span>] <span class="ruby-operator">||</span> {})))
30
+ 246: <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-value str">&quot;\r\n&quot;</span>)
31
+ 247: <span class="ruby-identifier">ops</span>[<span class="ruby-identifier">:body</span>] <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;&quot;</span>
32
+ 248: <span class="ruby-keyword kw">end</span></pre>
33
33
  </body>
34
34
  </html>
@@ -10,40 +10,41 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 246</span>
14
- 246: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">read_chunks</span>(<span class="ruby-identifier">input</span>, <span class="ruby-identifier">out</span>, <span class="ruby-identifier">parser</span>)
15
- 247: <span class="ruby-keyword kw">begin</span>
16
- 248: <span class="ruby-keyword kw">until</span> <span class="ruby-identifier">input</span>.<span class="ruby-identifier">closed?</span>
17
- 249: <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">reset</span>
18
- 250: <span class="ruby-identifier">chunk</span> = <span class="ruby-constant">HttpResponse</span>.<span class="ruby-identifier">new</span>
19
- 251: <span class="ruby-identifier">line</span> = <span class="ruby-identifier">input</span>.<span class="ruby-identifier">readline</span>(<span class="ruby-value str">&quot;\r\n&quot;</span>)
20
- 252: <span class="ruby-identifier">nread</span> = <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">execute</span>(<span class="ruby-identifier">chunk</span>, <span class="ruby-identifier">line</span>, <span class="ruby-value">0</span>)
21
- 253:
22
- 254: <span class="ruby-keyword kw">if</span> <span class="ruby-operator">!</span><span class="ruby-identifier">parser</span>.<span class="ruby-identifier">finished?</span>
23
- 255: <span class="ruby-comment cmt"># tried to read this header but couldn't</span>
24
- 256: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_header</span>, <span class="ruby-identifier">line</span>
25
- 257: <span class="ruby-keyword kw">end</span>
26
- 258:
27
- 259: <span class="ruby-identifier">size</span> = <span class="ruby-identifier">chunk</span>.<span class="ruby-identifier">http_chunk_size</span> <span class="ruby-value">? </span><span class="ruby-identifier">chunk</span>.<span class="ruby-identifier">http_chunk_size</span>.<span class="ruby-identifier">to_i</span>(<span class="ruby-identifier">base</span>=<span class="ruby-value">16</span>) <span class="ruby-operator">:</span> <span class="ruby-value">0</span>
28
- 260:
29
- 261: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">size</span> <span class="ruby-operator">==</span> <span class="ruby-value">0</span>
30
- 262: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:finished</span>, <span class="ruby-keyword kw">nil</span>
31
- 263: <span class="ruby-keyword kw">end</span>
32
- 264: <span class="ruby-identifier">remain</span> = <span class="ruby-identifier">size</span> <span class="ruby-operator">-</span><span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">input</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">size</span>))
33
- 265: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_body</span>, <span class="ruby-identifier">remain</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">remain</span> <span class="ruby-operator">&gt;</span> <span class="ruby-value">0</span>
34
- 266:
35
- 267: <span class="ruby-identifier">line</span> = <span class="ruby-identifier">input</span>.<span class="ruby-identifier">read</span>(<span class="ruby-value">2</span>)
36
- 268: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">line</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-keyword kw">or</span> <span class="ruby-identifier">line</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">&lt;</span> <span class="ruby-value">2</span>
37
- 269: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_trailer</span>, <span class="ruby-identifier">line</span>
38
- 270: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">line</span> <span class="ruby-operator">!=</span> <span class="ruby-value str">&quot;\r\n&quot;</span>
39
- 271: <span class="ruby-identifier">raise</span> <span class="ruby-constant">HttpClientParserError</span>.<span class="ruby-identifier">new</span>(<span class="ruby-value str">&quot;invalid chunked encoding trailer&quot;</span>)
40
- 272: <span class="ruby-keyword kw">end</span>
41
- 273: <span class="ruby-keyword kw">end</span>
42
- 274: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">EOFError</span>
43
- 275: <span class="ruby-comment cmt"># this is thrown when the header read is attempted and </span>
44
- 276: <span class="ruby-comment cmt"># there's nothing in the buffer</span>
45
- 277: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:eof_error</span>, <span class="ruby-keyword kw">nil</span>
46
- 278: <span class="ruby-keyword kw">end</span>
47
- 279: <span class="ruby-keyword kw">end</span></pre>
13
+ <pre> <span class="ruby-comment cmt"># File lib/rfuzz/client.rb, line 250</span>
14
+ 250: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">read_chunks</span>(<span class="ruby-identifier">input</span>, <span class="ruby-identifier">out</span>, <span class="ruby-identifier">parser</span>)
15
+ 251: <span class="ruby-keyword kw">begin</span>
16
+ 252: <span class="ruby-keyword kw">until</span> <span class="ruby-identifier">input</span>.<span class="ruby-identifier">closed?</span>
17
+ 253: <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">reset</span>
18
+ 254: <span class="ruby-identifier">chunk</span> = <span class="ruby-constant">HttpResponse</span>.<span class="ruby-identifier">new</span>
19
+ 255: <span class="ruby-identifier">line</span> = <span class="ruby-identifier">input</span>.<span class="ruby-identifier">readline</span>(<span class="ruby-value str">&quot;\r\n&quot;</span>)
20
+ 256: <span class="ruby-identifier">nread</span> = <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">execute</span>(<span class="ruby-identifier">chunk</span>, <span class="ruby-identifier">line</span>, <span class="ruby-value">0</span>)
21
+ 257:
22
+ 258: <span class="ruby-keyword kw">if</span> <span class="ruby-operator">!</span><span class="ruby-identifier">parser</span>.<span class="ruby-identifier">finished?</span>
23
+ 259: <span class="ruby-comment cmt"># tried to read this header but couldn't</span>
24
+ 260: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_header</span>, <span class="ruby-identifier">line</span>
25
+ 261: <span class="ruby-keyword kw">end</span>
26
+ 262:
27
+ 263: <span class="ruby-identifier">size</span> = <span class="ruby-identifier">chunk</span>.<span class="ruby-identifier">http_chunk_size</span> <span class="ruby-value">? </span><span class="ruby-identifier">chunk</span>.<span class="ruby-identifier">http_chunk_size</span>.<span class="ruby-identifier">to_i</span>(<span class="ruby-identifier">base</span>=<span class="ruby-value">16</span>) <span class="ruby-operator">:</span> <span class="ruby-value">0</span>
28
+ 264:
29
+ 265: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">size</span> <span class="ruby-operator">==</span> <span class="ruby-value">0</span>
30
+ 266: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:finished</span>, <span class="ruby-keyword kw">nil</span>
31
+ 267: <span class="ruby-keyword kw">end</span>
32
+ 268:
33
+ 269: <span class="ruby-identifier">remain</span> = <span class="ruby-identifier">size</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">out</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">input</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">size</span>))
34
+ 270: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_body</span>, <span class="ruby-identifier">remain</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">remain</span> <span class="ruby-operator">&gt;</span> <span class="ruby-value">0</span>
35
+ 271:
36
+ 272: <span class="ruby-identifier">line</span> = <span class="ruby-identifier">input</span>.<span class="ruby-identifier">read</span>(<span class="ruby-value">2</span>)
37
+ 273: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">line</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-keyword kw">or</span> <span class="ruby-identifier">line</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">&lt;</span> <span class="ruby-value">2</span>
38
+ 274: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:incomplete_trailer</span>, <span class="ruby-identifier">line</span>
39
+ 275: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">line</span> <span class="ruby-operator">!=</span> <span class="ruby-value str">&quot;\r\n&quot;</span>
40
+ 276: <span class="ruby-identifier">raise</span> <span class="ruby-constant">HttpClientParserError</span>.<span class="ruby-identifier">new</span>(<span class="ruby-value str">&quot;invalid chunked encoding trailer&quot;</span>)
41
+ 277: <span class="ruby-keyword kw">end</span>
42
+ 278: <span class="ruby-keyword kw">end</span>
43
+ 279: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">EOFError</span>
44
+ 280: <span class="ruby-comment cmt"># this is thrown when the header read is attempted and </span>
45
+ 281: <span class="ruby-comment cmt"># there's nothing in the buffer</span>
46
+ 282: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">:eof_error</span>, <span class="ruby-keyword kw">nil</span>
47
+ 283: <span class="ruby-keyword kw">end</span>
48
+ 284: <span class="ruby-keyword kw">end</span></pre>
48
49
  </body>
49
50
  </html>