addressable 0.1.0

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.
@@ -0,0 +1,5 @@
1
+ === Addressable 0.1.0
2
+ * initial release
3
+ * implementation based on RFC 3986, 3987
4
+ * support for IRIs via libidn
5
+ * support for the URI Template draft spec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Addressable, Copyright (c) 2006-2007 Bob Aman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ Addressable is a replacement for the URI implementation that is part of
2
+ Ruby's standard library. It more closely conforms to the relevant RFCs and
3
+ adds support for IRIs and URI templates.
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
3
+ <head>
4
+ <title>C0 code coverage information</title>
5
+ <style type='text/css'>body { background-color: rgb(240, 240, 245); }</style>
6
+ <style type='text/css'>span.cross-ref-title {
7
+ font-size: 140%;
8
+ }
9
+ span.cross-ref a {
10
+ text-decoration: none;
11
+ }
12
+ span.cross-ref {
13
+ background-color:#f3f7fa;
14
+ border: 1px dashed #333;
15
+ margin: 1em;
16
+ padding: 0.5em;
17
+ overflow: hidden;
18
+ }
19
+ a.crossref-toggle {
20
+ text-decoration: none;
21
+ }
22
+ span.marked0 {
23
+ background-color: rgb(185, 210, 200);
24
+ display: block;
25
+ }
26
+ span.marked1 {
27
+ background-color: rgb(190, 215, 205);
28
+ display: block;
29
+ }
30
+ span.inferred0 {
31
+ background-color: rgb(175, 200, 200);
32
+ display: block;
33
+ }
34
+ span.inferred1 {
35
+ background-color: rgb(180, 205, 205);
36
+ display: block;
37
+ }
38
+ span.uncovered0 {
39
+ background-color: rgb(225, 110, 110);
40
+ display: block;
41
+ }
42
+ span.uncovered1 {
43
+ background-color: rgb(235, 120, 120);
44
+ display: block;
45
+ }
46
+ span.overview {
47
+ border-bottom: 8px solid black;
48
+ }
49
+ div.overview {
50
+ border-bottom: 8px solid black;
51
+ }
52
+ body {
53
+ font-family: verdana, arial, helvetica;
54
+ }
55
+ div.footer {
56
+ font-size: 68%;
57
+ margin-top: 1.5em;
58
+ }
59
+ h1, h2, h3, h4, h5, h6 {
60
+ margin-bottom: 0.5em;
61
+ }
62
+ h5 {
63
+ margin-top: 0.5em;
64
+ }
65
+ .hidden {
66
+ display: none;
67
+ }
68
+ div.separator {
69
+ height: 10px;
70
+ }
71
+ /* Commented out for better readability, esp. on IE */
72
+ /*
73
+ table tr td, table tr th {
74
+ font-size: 68%;
75
+ }
76
+ td.value table tr td {
77
+ font-size: 11px;
78
+ }
79
+ */
80
+ table.percent_graph {
81
+ height: 12px;
82
+ border: #808080 1px solid;
83
+ empty-cells: show;
84
+ }
85
+ table.percent_graph td.covered {
86
+ height: 10px;
87
+ background: #00f000;
88
+ }
89
+ table.percent_graph td.uncovered {
90
+ height: 10px;
91
+ background: #e00000;
92
+ }
93
+ table.percent_graph td.NA {
94
+ height: 10px;
95
+ background: #eaeaea;
96
+ }
97
+ table.report {
98
+ border-collapse: collapse;
99
+ width: 100%;
100
+ }
101
+ table.report td.heading {
102
+ background: #dcecff;
103
+ border: #d0d0d0 1px solid;
104
+ font-weight: bold;
105
+ text-align: center;
106
+ }
107
+ table.report td.heading:hover {
108
+ background: #c0ffc0;
109
+ }
110
+ table.report td.text {
111
+ border: #d0d0d0 1px solid;
112
+ }
113
+ table.report td.value,
114
+ table.report td.lines_total,
115
+ table.report td.lines_code {
116
+ text-align: right;
117
+ border: #d0d0d0 1px solid;
118
+ }
119
+ table.report tr.light {
120
+ background-color: rgb(240, 240, 245);
121
+ }
122
+ table.report tr.dark {
123
+ background-color: rgb(230, 230, 235);
124
+ }
125
+ </style>
126
+ <script type='text/javascript'>
127
+ // <![CDATA[
128
+ function toggleCode( id ) {
129
+ if ( document.getElementById )
130
+ elem = document.getElementById( id );
131
+ else if ( document.all )
132
+ elem = eval( "document.all." + id );
133
+ else
134
+ return false;
135
+
136
+ elemStyle = elem.style;
137
+
138
+ if ( elemStyle.display != "block" ) {
139
+ elemStyle.display = "block"
140
+ } else {
141
+ elemStyle.display = "none"
142
+ }
143
+
144
+ return true;
145
+ }
146
+
147
+ // Make cross-references hidden by default
148
+ document.writeln( "<style type=\"text/css\">span.cross-ref { display: none }</style>" )
149
+ // ]]>
150
+ </script>
151
+ </head>
152
+ <body>
153
+ <h3>C0 code coverage information</h3>
154
+ <p>Generated on Wed Sep 05 00:27:38 -0400 2007 with <a href='http://eigenclass.org/hiki.rb?rcov'>rcov 0.8.0</a>
155
+ </p>
156
+ <hr /> <table class='report'>
157
+ <thead>
158
+ <tr>
159
+ <td class='heading'>Name</td>
160
+ <td class='heading'>Total lines</td>
161
+ <td class='heading'>Lines of code</td>
162
+ <td class='heading'>Total coverage</td>
163
+ <td class='heading'>Code coverage</td>
164
+ </tr>
165
+ </thead>
166
+ <tbody>
167
+ <tr class='light'>
168
+ <td>TOTAL</td>
169
+ <td class='lines_total'>
170
+ <tt>1092</tt>
171
+ </td>
172
+ <td class='lines_code'>
173
+ <tt>805</tt>
174
+ </td>
175
+ <td>
176
+ <table cellspacing='0' cellpadding='0' align='right'>
177
+ <tr>
178
+ <td>
179
+ <tt class='coverage_total'>100.0%</tt>&nbsp;</td>
180
+ <td>
181
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
182
+ <tr>
183
+ <td class='covered' width='100' />
184
+ <td class='uncovered' width='0' />
185
+ </tr>
186
+ </table>
187
+ </td>
188
+ </tr>
189
+ </table>
190
+ </td>
191
+ <td>
192
+ <table cellspacing='0' cellpadding='0' align='right'>
193
+ <tr>
194
+ <td>
195
+ <tt class='coverage_code'>100.0%</tt>&nbsp;</td>
196
+ <td>
197
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
198
+ <tr>
199
+ <td class='covered' width='100' />
200
+ <td class='uncovered' width='0' />
201
+ </tr>
202
+ </table>
203
+ </td>
204
+ </tr>
205
+ </table>
206
+ </td>
207
+ </tr>
208
+ <tr class='dark'>
209
+ <td>
210
+ <a href='lib-addressable-uri_rb.html'>lib/addressable/uri.rb</a>
211
+ </td>
212
+ <td class='lines_total'>
213
+ <tt>1092</tt>
214
+ </td>
215
+ <td class='lines_code'>
216
+ <tt>805</tt>
217
+ </td>
218
+ <td>
219
+ <table cellspacing='0' cellpadding='0' align='right'>
220
+ <tr>
221
+ <td>
222
+ <tt class='coverage_total'>100.0%</tt>&nbsp;</td>
223
+ <td>
224
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
225
+ <tr>
226
+ <td class='covered' width='100' />
227
+ <td class='uncovered' width='0' />
228
+ </tr>
229
+ </table>
230
+ </td>
231
+ </tr>
232
+ </table>
233
+ </td>
234
+ <td>
235
+ <table cellspacing='0' cellpadding='0' align='right'>
236
+ <tr>
237
+ <td>
238
+ <tt class='coverage_code'>100.0%</tt>&nbsp;</td>
239
+ <td>
240
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
241
+ <tr>
242
+ <td class='covered' width='100' />
243
+ <td class='uncovered' width='0' />
244
+ </tr>
245
+ </table>
246
+ </td>
247
+ </tr>
248
+ </table>
249
+ </td>
250
+ </tr>
251
+ </tbody>
252
+ </table><hr /> <p>Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'>rcov code coverage analysis tool for Ruby</a> version 0.8.0.</p><p>
253
+ <a href='http://validator.w3.org/check/referer'>
254
+ <img src='http://www.w3.org/Icons/valid-xhtml11' height='31' alt='Valid XHTML 1.1!' width='88' />
255
+ </a>
256
+ <a href='http://jigsaw.w3.org/css-validator/check/referer'>
257
+ <img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px' />
258
+ </a>
259
+ </p>
260
+ </body>
261
+ </html>
@@ -0,0 +1,1723 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
3
+ <head>
4
+ <title>lib/addressable/uri.rb - C0 code coverage information</title>
5
+ <style type='text/css'>body { background-color: rgb(240, 240, 245); }</style>
6
+ <style type='text/css'>span.cross-ref-title {
7
+ font-size: 140%;
8
+ }
9
+ span.cross-ref a {
10
+ text-decoration: none;
11
+ }
12
+ span.cross-ref {
13
+ background-color:#f3f7fa;
14
+ border: 1px dashed #333;
15
+ margin: 1em;
16
+ padding: 0.5em;
17
+ overflow: hidden;
18
+ }
19
+ a.crossref-toggle {
20
+ text-decoration: none;
21
+ }
22
+ span.marked0 {
23
+ background-color: rgb(185, 210, 200);
24
+ display: block;
25
+ }
26
+ span.marked1 {
27
+ background-color: rgb(190, 215, 205);
28
+ display: block;
29
+ }
30
+ span.inferred0 {
31
+ background-color: rgb(175, 200, 200);
32
+ display: block;
33
+ }
34
+ span.inferred1 {
35
+ background-color: rgb(180, 205, 205);
36
+ display: block;
37
+ }
38
+ span.uncovered0 {
39
+ background-color: rgb(225, 110, 110);
40
+ display: block;
41
+ }
42
+ span.uncovered1 {
43
+ background-color: rgb(235, 120, 120);
44
+ display: block;
45
+ }
46
+ span.overview {
47
+ border-bottom: 8px solid black;
48
+ }
49
+ div.overview {
50
+ border-bottom: 8px solid black;
51
+ }
52
+ body {
53
+ font-family: verdana, arial, helvetica;
54
+ }
55
+ div.footer {
56
+ font-size: 68%;
57
+ margin-top: 1.5em;
58
+ }
59
+ h1, h2, h3, h4, h5, h6 {
60
+ margin-bottom: 0.5em;
61
+ }
62
+ h5 {
63
+ margin-top: 0.5em;
64
+ }
65
+ .hidden {
66
+ display: none;
67
+ }
68
+ div.separator {
69
+ height: 10px;
70
+ }
71
+ /* Commented out for better readability, esp. on IE */
72
+ /*
73
+ table tr td, table tr th {
74
+ font-size: 68%;
75
+ }
76
+ td.value table tr td {
77
+ font-size: 11px;
78
+ }
79
+ */
80
+ table.percent_graph {
81
+ height: 12px;
82
+ border: #808080 1px solid;
83
+ empty-cells: show;
84
+ }
85
+ table.percent_graph td.covered {
86
+ height: 10px;
87
+ background: #00f000;
88
+ }
89
+ table.percent_graph td.uncovered {
90
+ height: 10px;
91
+ background: #e00000;
92
+ }
93
+ table.percent_graph td.NA {
94
+ height: 10px;
95
+ background: #eaeaea;
96
+ }
97
+ table.report {
98
+ border-collapse: collapse;
99
+ width: 100%;
100
+ }
101
+ table.report td.heading {
102
+ background: #dcecff;
103
+ border: #d0d0d0 1px solid;
104
+ font-weight: bold;
105
+ text-align: center;
106
+ }
107
+ table.report td.heading:hover {
108
+ background: #c0ffc0;
109
+ }
110
+ table.report td.text {
111
+ border: #d0d0d0 1px solid;
112
+ }
113
+ table.report td.value,
114
+ table.report td.lines_total,
115
+ table.report td.lines_code {
116
+ text-align: right;
117
+ border: #d0d0d0 1px solid;
118
+ }
119
+ table.report tr.light {
120
+ background-color: rgb(240, 240, 245);
121
+ }
122
+ table.report tr.dark {
123
+ background-color: rgb(230, 230, 235);
124
+ }
125
+ </style>
126
+ <script type='text/javascript'>
127
+ // <![CDATA[
128
+ function toggleCode( id ) {
129
+ if ( document.getElementById )
130
+ elem = document.getElementById( id );
131
+ else if ( document.all )
132
+ elem = eval( "document.all." + id );
133
+ else
134
+ return false;
135
+
136
+ elemStyle = elem.style;
137
+
138
+ if ( elemStyle.display != "block" ) {
139
+ elemStyle.display = "block"
140
+ } else {
141
+ elemStyle.display = "none"
142
+ }
143
+
144
+ return true;
145
+ }
146
+
147
+ // Make cross-references hidden by default
148
+ document.writeln( "<style type=\"text/css\">span.cross-ref { display: none }</style>" )
149
+ // ]]>
150
+ </script>
151
+ <style type='text/css'>span.run0 {
152
+ background-color: rgb(178, 204, 255);
153
+ display: block;
154
+ }
155
+ span.run1 {
156
+ background-color: rgb(178, 206, 255);
157
+ display: block;
158
+ }
159
+ span.run2 {
160
+ background-color: rgb(178, 209, 255);
161
+ display: block;
162
+ }
163
+ span.run3 {
164
+ background-color: rgb(178, 211, 255);
165
+ display: block;
166
+ }
167
+ span.run4 {
168
+ background-color: rgb(178, 214, 255);
169
+ display: block;
170
+ }
171
+ span.run5 {
172
+ background-color: rgb(178, 218, 255);
173
+ display: block;
174
+ }
175
+ span.run6 {
176
+ background-color: rgb(178, 220, 255);
177
+ display: block;
178
+ }
179
+ span.run7 {
180
+ background-color: rgb(178, 223, 255);
181
+ display: block;
182
+ }
183
+ span.run8 {
184
+ background-color: rgb(178, 225, 255);
185
+ display: block;
186
+ }
187
+ span.run9 {
188
+ background-color: rgb(178, 228, 255);
189
+ display: block;
190
+ }
191
+ span.run10 {
192
+ background-color: rgb(178, 232, 255);
193
+ display: block;
194
+ }
195
+ span.run11 {
196
+ background-color: rgb(178, 234, 255);
197
+ display: block;
198
+ }
199
+ span.run12 {
200
+ background-color: rgb(178, 237, 255);
201
+ display: block;
202
+ }
203
+ span.run13 {
204
+ background-color: rgb(178, 239, 255);
205
+ display: block;
206
+ }
207
+ span.run14 {
208
+ background-color: rgb(178, 242, 255);
209
+ display: block;
210
+ }
211
+ span.run15 {
212
+ background-color: rgb(178, 246, 255);
213
+ display: block;
214
+ }
215
+ span.run16 {
216
+ background-color: rgb(178, 248, 255);
217
+ display: block;
218
+ }
219
+ span.run17 {
220
+ background-color: rgb(178, 251, 255);
221
+ display: block;
222
+ }
223
+ span.run18 {
224
+ background-color: rgb(178, 253, 255);
225
+ display: block;
226
+ }
227
+ span.run19 {
228
+ background-color: rgb(178, 255, 253);
229
+ display: block;
230
+ }
231
+ span.run20 {
232
+ background-color: rgb(178, 255, 249);
233
+ display: block;
234
+ }
235
+ span.run21 {
236
+ background-color: rgb(178, 255, 247);
237
+ display: block;
238
+ }
239
+ span.run22 {
240
+ background-color: rgb(178, 255, 244);
241
+ display: block;
242
+ }
243
+ span.run23 {
244
+ background-color: rgb(178, 255, 242);
245
+ display: block;
246
+ }
247
+ span.run24 {
248
+ background-color: rgb(178, 255, 239);
249
+ display: block;
250
+ }
251
+ span.run25 {
252
+ background-color: rgb(178, 255, 235);
253
+ display: block;
254
+ }
255
+ span.run26 {
256
+ background-color: rgb(178, 255, 233);
257
+ display: block;
258
+ }
259
+ span.run27 {
260
+ background-color: rgb(178, 255, 230);
261
+ display: block;
262
+ }
263
+ span.run28 {
264
+ background-color: rgb(178, 255, 228);
265
+ display: block;
266
+ }
267
+ span.run29 {
268
+ background-color: rgb(178, 255, 225);
269
+ display: block;
270
+ }
271
+ span.run30 {
272
+ background-color: rgb(178, 255, 221);
273
+ display: block;
274
+ }
275
+ span.run31 {
276
+ background-color: rgb(178, 255, 219);
277
+ display: block;
278
+ }
279
+ span.run32 {
280
+ background-color: rgb(178, 255, 216);
281
+ display: block;
282
+ }
283
+ span.run33 {
284
+ background-color: rgb(178, 255, 214);
285
+ display: block;
286
+ }
287
+ span.run34 {
288
+ background-color: rgb(178, 255, 211);
289
+ display: block;
290
+ }
291
+ span.run35 {
292
+ background-color: rgb(178, 255, 207);
293
+ display: block;
294
+ }
295
+ span.run36 {
296
+ background-color: rgb(178, 255, 205);
297
+ display: block;
298
+ }
299
+ span.run37 {
300
+ background-color: rgb(178, 255, 202);
301
+ display: block;
302
+ }
303
+ span.run38 {
304
+ background-color: rgb(178, 255, 200);
305
+ display: block;
306
+ }
307
+ span.run39 {
308
+ background-color: rgb(178, 255, 197);
309
+ display: block;
310
+ }
311
+ span.run40 {
312
+ background-color: rgb(178, 255, 193);
313
+ display: block;
314
+ }
315
+ span.run41 {
316
+ background-color: rgb(178, 255, 191);
317
+ display: block;
318
+ }
319
+ span.run42 {
320
+ background-color: rgb(178, 255, 188);
321
+ display: block;
322
+ }
323
+ span.run43 {
324
+ background-color: rgb(178, 255, 186);
325
+ display: block;
326
+ }
327
+ span.run44 {
328
+ background-color: rgb(178, 255, 183);
329
+ display: block;
330
+ }
331
+ span.run45 {
332
+ background-color: rgb(178, 255, 179);
333
+ display: block;
334
+ }
335
+ span.run46 {
336
+ background-color: rgb(179, 255, 178);
337
+ display: block;
338
+ }
339
+ span.run47 {
340
+ background-color: rgb(182, 255, 178);
341
+ display: block;
342
+ }
343
+ span.run48 {
344
+ background-color: rgb(184, 255, 178);
345
+ display: block;
346
+ }
347
+ span.run49 {
348
+ background-color: rgb(187, 255, 178);
349
+ display: block;
350
+ }
351
+ span.run50 {
352
+ background-color: rgb(191, 255, 178);
353
+ display: block;
354
+ }
355
+ span.run51 {
356
+ background-color: rgb(193, 255, 178);
357
+ display: block;
358
+ }
359
+ span.run52 {
360
+ background-color: rgb(196, 255, 178);
361
+ display: block;
362
+ }
363
+ span.run53 {
364
+ background-color: rgb(198, 255, 178);
365
+ display: block;
366
+ }
367
+ span.run54 {
368
+ background-color: rgb(201, 255, 178);
369
+ display: block;
370
+ }
371
+ span.run55 {
372
+ background-color: rgb(205, 255, 178);
373
+ display: block;
374
+ }
375
+ span.run56 {
376
+ background-color: rgb(207, 255, 178);
377
+ display: block;
378
+ }
379
+ span.run57 {
380
+ background-color: rgb(210, 255, 178);
381
+ display: block;
382
+ }
383
+ span.run58 {
384
+ background-color: rgb(212, 255, 178);
385
+ display: block;
386
+ }
387
+ span.run59 {
388
+ background-color: rgb(215, 255, 178);
389
+ display: block;
390
+ }
391
+ span.run60 {
392
+ background-color: rgb(219, 255, 178);
393
+ display: block;
394
+ }
395
+ span.run61 {
396
+ background-color: rgb(221, 255, 178);
397
+ display: block;
398
+ }
399
+ span.run62 {
400
+ background-color: rgb(224, 255, 178);
401
+ display: block;
402
+ }
403
+ span.run63 {
404
+ background-color: rgb(226, 255, 178);
405
+ display: block;
406
+ }
407
+ span.run64 {
408
+ background-color: rgb(229, 255, 178);
409
+ display: block;
410
+ }
411
+ span.run65 {
412
+ background-color: rgb(233, 255, 178);
413
+ display: block;
414
+ }
415
+ span.run66 {
416
+ background-color: rgb(235, 255, 178);
417
+ display: block;
418
+ }
419
+ span.run67 {
420
+ background-color: rgb(238, 255, 178);
421
+ display: block;
422
+ }
423
+ span.run68 {
424
+ background-color: rgb(240, 255, 178);
425
+ display: block;
426
+ }
427
+ span.run69 {
428
+ background-color: rgb(243, 255, 178);
429
+ display: block;
430
+ }
431
+ span.run70 {
432
+ background-color: rgb(247, 255, 178);
433
+ display: block;
434
+ }
435
+ span.run71 {
436
+ background-color: rgb(249, 255, 178);
437
+ display: block;
438
+ }
439
+ span.run72 {
440
+ background-color: rgb(252, 255, 178);
441
+ display: block;
442
+ }
443
+ span.run73 {
444
+ background-color: rgb(255, 255, 178);
445
+ display: block;
446
+ }
447
+ span.run74 {
448
+ background-color: rgb(255, 252, 178);
449
+ display: block;
450
+ }
451
+ span.run75 {
452
+ background-color: rgb(255, 248, 178);
453
+ display: block;
454
+ }
455
+ span.run76 {
456
+ background-color: rgb(255, 246, 178);
457
+ display: block;
458
+ }
459
+ span.run77 {
460
+ background-color: rgb(255, 243, 178);
461
+ display: block;
462
+ }
463
+ span.run78 {
464
+ background-color: rgb(255, 240, 178);
465
+ display: block;
466
+ }
467
+ span.run79 {
468
+ background-color: rgb(255, 238, 178);
469
+ display: block;
470
+ }
471
+ span.run80 {
472
+ background-color: rgb(255, 234, 178);
473
+ display: block;
474
+ }
475
+ span.run81 {
476
+ background-color: rgb(255, 232, 178);
477
+ display: block;
478
+ }
479
+ span.run82 {
480
+ background-color: rgb(255, 229, 178);
481
+ display: block;
482
+ }
483
+ span.run83 {
484
+ background-color: rgb(255, 226, 178);
485
+ display: block;
486
+ }
487
+ span.run84 {
488
+ background-color: rgb(255, 224, 178);
489
+ display: block;
490
+ }
491
+ span.run85 {
492
+ background-color: rgb(255, 220, 178);
493
+ display: block;
494
+ }
495
+ span.run86 {
496
+ background-color: rgb(255, 218, 178);
497
+ display: block;
498
+ }
499
+ span.run87 {
500
+ background-color: rgb(255, 215, 178);
501
+ display: block;
502
+ }
503
+ span.run88 {
504
+ background-color: rgb(255, 212, 178);
505
+ display: block;
506
+ }
507
+ span.run89 {
508
+ background-color: rgb(255, 210, 178);
509
+ display: block;
510
+ }
511
+ span.run90 {
512
+ background-color: rgb(255, 206, 178);
513
+ display: block;
514
+ }
515
+ span.run91 {
516
+ background-color: rgb(255, 204, 178);
517
+ display: block;
518
+ }
519
+ span.run92 {
520
+ background-color: rgb(255, 201, 178);
521
+ display: block;
522
+ }
523
+ span.run93 {
524
+ background-color: rgb(255, 198, 178);
525
+ display: block;
526
+ }
527
+ span.run94 {
528
+ background-color: rgb(255, 196, 178);
529
+ display: block;
530
+ }
531
+ span.run95 {
532
+ background-color: rgb(255, 192, 178);
533
+ display: block;
534
+ }
535
+ span.run96 {
536
+ background-color: rgb(255, 189, 178);
537
+ display: block;
538
+ }
539
+ span.run97 {
540
+ background-color: rgb(255, 187, 178);
541
+ display: block;
542
+ }
543
+ span.run98 {
544
+ background-color: rgb(255, 184, 178);
545
+ display: block;
546
+ }
547
+ span.run99 {
548
+ background-color: rgb(255, 182, 178);
549
+ display: block;
550
+ }
551
+ span.run100 {
552
+ background-color: rgb(255, 178, 178);
553
+ display: block;
554
+ }
555
+ </style>
556
+ </head>
557
+ <body>
558
+ <h3>C0 code coverage information</h3>
559
+ <p>Generated on Wed Sep 05 00:27:42 -0400 2007 with <a href='http://eigenclass.org/hiki.rb?rcov'>rcov 0.8.0</a>
560
+ </p>
561
+ <hr /><pre><span class='marked0'>Code reported as executed by Ruby looks like this...
562
+ </span><span class='marked1'>and this: this line is also marked as covered.
563
+ </span><span class='inferred0'>Lines considered as run by rcov, but not reported by Ruby, look like this,
564
+ </span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).
565
+ </span><span class='uncovered0'>Finally, here&apos;s a line marked as not executed.
566
+ </span></pre>
567
+ <table class='report'>
568
+ <thead>
569
+ <tr>
570
+ <td class='heading'>Name</td>
571
+ <td class='heading'>Total lines</td>
572
+ <td class='heading'>Lines of code</td>
573
+ <td class='heading'>Total coverage</td>
574
+ <td class='heading'>Code coverage</td>
575
+ </tr>
576
+ </thead>
577
+ <tbody>
578
+ <tr class='light'>
579
+ <td>
580
+ <a href='lib-addressable-uri_rb.html'>lib/addressable/uri.rb</a>
581
+ </td>
582
+ <td class='lines_total'>
583
+ <tt>1092</tt>
584
+ </td>
585
+ <td class='lines_code'>
586
+ <tt>805</tt>
587
+ </td>
588
+ <td>
589
+ <table cellspacing='0' cellpadding='0' align='right'>
590
+ <tr>
591
+ <td>
592
+ <tt class='coverage_total'>100.0%</tt>&nbsp;</td>
593
+ <td>
594
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
595
+ <tr>
596
+ <td class='covered' width='100' />
597
+ <td class='uncovered' width='0' />
598
+ </tr>
599
+ </table>
600
+ </td>
601
+ </tr>
602
+ </table>
603
+ </td>
604
+ <td>
605
+ <table cellspacing='0' cellpadding='0' align='right'>
606
+ <tr>
607
+ <td>
608
+ <tt class='coverage_code'>100.0%</tt>&nbsp;</td>
609
+ <td>
610
+ <table cellspacing='0' class='percent_graph' cellpadding='0' width='100'>
611
+ <tr>
612
+ <td class='covered' width='100' />
613
+ <td class='uncovered' width='0' />
614
+ </tr>
615
+ </table>
616
+ </td>
617
+ </tr>
618
+ </table>
619
+ </td>
620
+ </tr>
621
+ </tbody>
622
+ </table><pre><span class="inferred1"><a name="line1" /> 1 #--
623
+ </span><span class="inferred0"><a name="line2" /> 2 # Addressable, Copyright (c) 2006-2007 Bob Aman
624
+ </span><span class="inferred1"><a name="line3" /> 3 #
625
+ </span><span class="inferred0"><a name="line4" /> 4 # Permission is hereby granted, free of charge, to any person obtaining
626
+ </span><span class="inferred1"><a name="line5" /> 5 # a copy of this software and associated documentation files (the
627
+ </span><span class="inferred0"><a name="line6" /> 6 # &quot;Software&quot;), to deal in the Software without restriction, including
628
+ </span><span class="inferred1"><a name="line7" /> 7 # without limitation the rights to use, copy, modify, merge, publish,
629
+ </span><span class="inferred0"><a name="line8" /> 8 # distribute, sublicense, and/or sell copies of the Software, and to
630
+ </span><span class="inferred1"><a name="line9" /> 9 # permit persons to whom the Software is furnished to do so, subject to
631
+ </span><span class="inferred0"><a name="line10" /> 10 # the following conditions:
632
+ </span><span class="inferred1"><a name="line11" /> 11 #
633
+ </span><span class="inferred0"><a name="line12" /> 12 # The above copyright notice and this permission notice shall be
634
+ </span><span class="inferred1"><a name="line13" /> 13 # included in all copies or substantial portions of the Software.
635
+ </span><span class="inferred0"><a name="line14" /> 14 #
636
+ </span><span class="inferred1"><a name="line15" /> 15 # THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
637
+ </span><span class="inferred0"><a name="line16" /> 16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
638
+ </span><span class="inferred1"><a name="line17" /> 17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
639
+ </span><span class="inferred0"><a name="line18" /> 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
640
+ </span><span class="inferred1"><a name="line19" /> 19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
641
+ </span><span class="inferred0"><a name="line20" /> 20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
642
+ </span><span class="inferred1"><a name="line21" /> 21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
643
+ </span><span class="inferred0"><a name="line22" /> 22 #++
644
+ </span><span class="inferred1"><a name="line23" /> 23
645
+ </span><span class="marked0"><a name="line24" /> 24 module Addressable
646
+ </span><span class="inferred1"><a name="line25" /> 25 # This is an implementation of a URI parser based on RFC 3986.
647
+ </span><span class="marked0"><a name="line26" /> 26 class URI
648
+ </span><span class="inferred1"><a name="line27" /> 27 # Raised if something other than a uri is supplied.
649
+ </span><span class="marked0"><a name="line28" /> 28 class InvalidURIError &lt; StandardError
650
+ </span><span class="inferred1"><a name="line29" /> 29 end
651
+ </span><span class="inferred0"><a name="line30" /> 30
652
+ </span><span class="inferred1"><a name="line31" /> 31 # Raised if an invalid method option is supplied.
653
+ </span><span class="marked0"><a name="line32" /> 32 class InvalidOptionError &lt; StandardError
654
+ </span><span class="inferred1"><a name="line33" /> 33 end
655
+ </span><span class="inferred0"><a name="line34" /> 34
656
+ </span><span class="inferred1"><a name="line35" /> 35 # Raised if an invalid method option is supplied.
657
+ </span><span class="marked0"><a name="line36" /> 36 class InvalidTemplateValue &lt; StandardError
658
+ </span><span class="inferred1"><a name="line37" /> 37 end
659
+ </span><span class="inferred0"><a name="line38" /> 38
660
+ </span><span class="marked1"><a name="line39" /> 39 module CharacterClasses
661
+ </span><span class="marked0"><a name="line40" /> 40 ALPHA = &quot;a-zA-Z&quot;
662
+ </span><span class="marked1"><a name="line41" /> 41 DIGIT = &quot;0-9&quot;
663
+ </span><span class="marked0"><a name="line42" /> 42 GEN_DELIMS = &quot;\\:\\/\\?\\#\\[\\]\\@&quot;
664
+ </span><span class="marked1"><a name="line43" /> 43 SUB_DELIMS = &quot;\\!\\$\\&amp;\\'\\(\\)\\*\\+\\,\\;\\=&quot;
665
+ </span><span class="marked0"><a name="line44" /> 44 RESERVED = GEN_DELIMS + SUB_DELIMS
666
+ </span><span class="marked1"><a name="line45" /> 45 UNRESERVED = ALPHA + DIGIT + &quot;\\-\\.\\_\\~&quot;
667
+ </span><span class="marked0"><a name="line46" /> 46 PCHAR = UNRESERVED + SUB_DELIMS + &quot;\\:\\@&quot;
668
+ </span><span class="marked1"><a name="line47" /> 47 SCHEME = ALPHA + DIGIT + &quot;\\-\\+\\.&quot;
669
+ </span><span class="marked0"><a name="line48" /> 48 AUTHORITY = PCHAR
670
+ </span><span class="marked1"><a name="line49" /> 49 PATH = PCHAR + &quot;\\/&quot;
671
+ </span><span class="marked0"><a name="line50" /> 50 QUERY = PCHAR + &quot;\\/\\?&quot;
672
+ </span><span class="marked1"><a name="line51" /> 51 FRAGMENT = PCHAR + &quot;\\/\\?&quot;
673
+ </span><span class="inferred0"><a name="line52" /> 52 end
674
+ </span><span class="inferred1"><a name="line53" /> 53
675
+ </span><span class="inferred0"><a name="line54" /> 54 # Returns a URI object based on the parsed string.
676
+ </span><span class="marked1"><a name="line55" /> 55 def self.parse(uri_string)
677
+ </span><span class="marked0"><a name="line56" /> 56 return nil if uri_string.nil?
678
+ </span><span class="inferred1"><a name="line57" /> 57
679
+ </span><span class="inferred0"><a name="line58" /> 58 # If a URI object is passed, just return itself.
680
+ </span><span class="marked1"><a name="line59" /> 59 return uri_string if uri_string.kind_of?(self)
681
+ </span><span class="inferred0"><a name="line60" /> 60
682
+ </span><span class="inferred1"><a name="line61" /> 61 # If a URI object of the Ruby standard library variety is passed,
683
+ </span><span class="inferred0"><a name="line62" /> 62 # convert it to a string, then parse the string.
684
+ </span><span class="marked1"><a name="line63" /> 63 if uri_string.class.name =~ /^URI::/
685
+ </span><span class="inferred0"><a name="line64" /> 64 uri_string = uri_string.to_s
686
+ </span><span class="inferred1"><a name="line65" /> 65 end
687
+ </span><span class="inferred0"><a name="line66" /> 66
688
+ </span><span class="marked1"><a name="line67" /> 67 uri_regex =
689
+ </span><span class="inferred0"><a name="line68" /> 68 /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/
690
+ </span><span class="marked1"><a name="line69" /> 69 scan = uri_string.scan(uri_regex)
691
+ </span><span class="marked0"><a name="line70" /> 70 fragments = scan[0]
692
+ </span><span class="marked1"><a name="line71" /> 71 return nil if fragments.nil?
693
+ </span><span class="marked0"><a name="line72" /> 72 scheme = fragments[1]
694
+ </span><span class="marked1"><a name="line73" /> 73 authority = fragments[3]
695
+ </span><span class="marked0"><a name="line74" /> 74 path = fragments[4]
696
+ </span><span class="marked1"><a name="line75" /> 75 query = fragments[6]
697
+ </span><span class="marked0"><a name="line76" /> 76 fragment = fragments[8]
698
+ </span><span class="marked1"><a name="line77" /> 77 userinfo = nil
699
+ </span><span class="marked0"><a name="line78" /> 78 user = nil
700
+ </span><span class="marked1"><a name="line79" /> 79 password = nil
701
+ </span><span class="marked0"><a name="line80" /> 80 host = nil
702
+ </span><span class="marked1"><a name="line81" /> 81 port = nil
703
+ </span><span class="marked0"><a name="line82" /> 82 if authority != nil
704
+ </span><span class="marked1"><a name="line83" /> 83 userinfo = authority.scan(/^([^\[\]]*)@/).flatten[0]
705
+ </span><span class="marked0"><a name="line84" /> 84 if userinfo != nil
706
+ </span><span class="marked1"><a name="line85" /> 85 user = userinfo.strip.scan(/^([^:]*):?/).flatten[0]
707
+ </span><span class="marked0"><a name="line86" /> 86 password = userinfo.strip.scan(/:(.*)$/).flatten[0]
708
+ </span><span class="inferred1"><a name="line87" /> 87 end
709
+ </span><span class="marked0"><a name="line88" /> 88 host = authority.gsub(/^([^\[\]]*)@/, &quot;&quot;).gsub(/:([^:@\[\]]*?)$/, &quot;&quot;)
710
+ </span><span class="marked1"><a name="line89" /> 89 port = authority.scan(/:([^:@\[\]]*?)$/).flatten[0]
711
+ </span><span class="inferred0"><a name="line90" /> 90 end
712
+ </span><span class="marked1"><a name="line91" /> 91 if port.nil? || port == &quot;&quot;
713
+ </span><span class="marked0"><a name="line92" /> 92 port = nil
714
+ </span><span class="inferred1"><a name="line93" /> 93 end
715
+ </span><span class="inferred0"><a name="line94" /> 94
716
+ </span><span class="inferred1"><a name="line95" /> 95 # WARNING: Not standards-compliant, but follows the theme
717
+ </span><span class="inferred0"><a name="line96" /> 96 # of Postel's law:
718
+ </span><span class="inferred1"><a name="line97" /> 97 #
719
+ </span><span class="inferred0"><a name="line98" /> 98 # Special exception for dealing with the retarded idea of the
720
+ </span><span class="inferred1"><a name="line99" /> 99 # feed pseudo-protocol. Without this exception, the parser will read
721
+ </span><span class="inferred0"><a name="line100" /> 100 # the URI as having a blank port number, instead of as having a second
722
+ </span><span class="inferred1"><a name="line101" /> 101 # URI embedded within. This exception translates these broken URIs
723
+ </span><span class="inferred0"><a name="line102" /> 102 # and instead treats the inner URI as opaque.
724
+ </span><span class="marked1"><a name="line103" /> 103 if scheme == &quot;feed&quot; &amp;&amp; host == &quot;http&quot;
725
+ </span><span class="marked0"><a name="line104" /> 104 userinfo = nil
726
+ </span><span class="marked1"><a name="line105" /> 105 user = nil
727
+ </span><span class="marked0"><a name="line106" /> 106 password = nil
728
+ </span><span class="marked1"><a name="line107" /> 107 host = nil
729
+ </span><span class="marked0"><a name="line108" /> 108 port = nil
730
+ </span><span class="marked1"><a name="line109" /> 109 path = authority + path
731
+ </span><span class="inferred0"><a name="line110" /> 110 end
732
+ </span><span class="inferred1"><a name="line111" /> 111
733
+ </span><span class="marked0"><a name="line112" /> 112 return Addressable::URI.new(
734
+ </span><span class="marked1"><a name="line113" /> 113 scheme, user, password, host, port, path, query, fragment)
735
+ </span><span class="inferred0"><a name="line114" /> 114 end
736
+ </span><span class="inferred1"><a name="line115" /> 115
737
+ </span><span class="inferred0"><a name="line116" /> 116 # Converts a path to a file protocol URI. If the path supplied is
738
+ </span><span class="inferred1"><a name="line117" /> 117 # relative, it will be returned as a relative URI. If the path supplied
739
+ </span><span class="inferred0"><a name="line118" /> 118 # is actually a URI, it will return the parsed URI.
740
+ </span><span class="marked1"><a name="line119" /> 119 def self.convert_path(path)
741
+ </span><span class="marked0"><a name="line120" /> 120 return nil if path.nil?
742
+ </span><span class="inferred1"><a name="line121" /> 121
743
+ </span><span class="marked0"><a name="line122" /> 122 converted_uri = path.strip
744
+ </span><span class="marked1"><a name="line123" /> 123 if converted_uri.length &gt; 0 &amp;&amp; converted_uri[0..0] == &quot;/&quot;
745
+ </span><span class="marked0"><a name="line124" /> 124 converted_uri = &quot;file://&quot; + converted_uri
746
+ </span><span class="inferred1"><a name="line125" /> 125 end
747
+ </span><span class="inferred0"><a name="line126" /> 126 if converted_uri.length &gt; 0 &amp;&amp;
748
+ </span><span class="marked1"><a name="line127" /> 127 converted_uri.scan(/^[a-zA-Z]:[\\\/]/).size &gt; 0
749
+ </span><span class="marked0"><a name="line128" /> 128 converted_uri = &quot;file:///&quot; + converted_uri
750
+ </span><span class="inferred1"><a name="line129" /> 129 end
751
+ </span><span class="marked0"><a name="line130" /> 130 converted_uri.gsub!(/^file:\/*/i, &quot;file:///&quot;)
752
+ </span><span class="marked1"><a name="line131" /> 131 if converted_uri =~ /^file:/i
753
+ </span><span class="inferred0"><a name="line132" /> 132 # Adjust windows-style uris
754
+ </span><span class="marked1"><a name="line133" /> 133 converted_uri.gsub!(/^file:\/\/\/([a-zA-Z])\|/i, 'file:///\1:')
755
+ </span><span class="marked0"><a name="line134" /> 134 converted_uri.gsub!(/\\/, '/')
756
+ </span><span class="marked1"><a name="line135" /> 135 converted_uri = self.parse(converted_uri).normalize
757
+ </span><span class="marked0"><a name="line136" /> 136 if File.exists?(converted_uri.path) &amp;&amp;
758
+ </span><span class="marked1"><a name="line137" /> 137 File.stat(converted_uri.path).directory?
759
+ </span><span class="marked0"><a name="line138" /> 138 converted_uri.path.gsub!(/\/$/, &quot;&quot;)
760
+ </span><span class="marked1"><a name="line139" /> 139 converted_uri.path = converted_uri.path + '/'
761
+ </span><span class="inferred0"><a name="line140" /> 140 end
762
+ </span><span class="inferred1"><a name="line141" /> 141 else
763
+ </span><span class="marked0"><a name="line142" /> 142 converted_uri = self.parse(converted_uri)
764
+ </span><span class="inferred1"><a name="line143" /> 143 end
765
+ </span><span class="inferred0"><a name="line144" /> 144
766
+ </span><span class="marked1"><a name="line145" /> 145 return converted_uri
767
+ </span><span class="inferred0"><a name="line146" /> 146 end
768
+ </span><span class="inferred1"><a name="line147" /> 147
769
+ </span><span class="inferred0"><a name="line148" /> 148 # Expands a URI template into a full URI.
770
+ </span><span class="inferred1"><a name="line149" /> 149 #
771
+ </span><span class="inferred0"><a name="line150" /> 150 # An optional processor object may be supplied. The object should
772
+ </span><span class="inferred1"><a name="line151" /> 151 # respond to either the :validate or :transform messages or both.
773
+ </span><span class="inferred0"><a name="line152" /> 152 # Both the :validate and :transform methods should take two parameters:
774
+ </span><span class="inferred1"><a name="line153" /> 153 # :name and :value. The :validate method should return true or false;
775
+ </span><span class="inferred0"><a name="line154" /> 154 # true if the value of the variable is valid, false otherwise. The
776
+ </span><span class="inferred1"><a name="line155" /> 155 # :transform method should return the transformed variable value as a
777
+ </span><span class="inferred0"><a name="line156" /> 156 # string.
778
+ </span><span class="inferred1"><a name="line157" /> 157 #
779
+ </span><span class="inferred0"><a name="line158" /> 158 # An example:
780
+ </span><span class="inferred1"><a name="line159" /> 159 #
781
+ </span><span class="inferred0"><a name="line160" /> 160 # class ExampleProcessor
782
+ </span><span class="inferred1"><a name="line161" /> 161 # def self.validate(name, value)
783
+ </span><span class="inferred0"><a name="line162" /> 162 # return !!(value =~ /^[\w ]+$/) if name == &quot;query&quot;
784
+ </span><span class="inferred1"><a name="line163" /> 163 # return true
785
+ </span><span class="inferred0"><a name="line164" /> 164 # end
786
+ </span><span class="inferred1"><a name="line165" /> 165 #
787
+ </span><span class="inferred0"><a name="line166" /> 166 # def self.transform(name, value)
788
+ </span><span class="inferred1"><a name="line167" /> 167 # return value.gsub(/ /, &quot;+&quot;) if name == &quot;query&quot;
789
+ </span><span class="inferred0"><a name="line168" /> 168 # return value
790
+ </span><span class="inferred1"><a name="line169" /> 169 # end
791
+ </span><span class="inferred0"><a name="line170" /> 170 # end
792
+ </span><span class="inferred1"><a name="line171" /> 171 #
793
+ </span><span class="inferred0"><a name="line172" /> 172 # Addressable::URI.expand_template(
794
+ </span><span class="inferred1"><a name="line173" /> 173 # &quot;http://example.com/search/{query}/&quot;,
795
+ </span><span class="inferred0"><a name="line174" /> 174 # {&quot;query&quot; =&gt; &quot;an example search query&quot;},
796
+ </span><span class="inferred1"><a name="line175" /> 175 # ExampleProcessor).to_s
797
+ </span><span class="inferred0"><a name="line176" /> 176 # =&gt; &quot;http://example.com/search/an+example+search+query/&quot;
798
+ </span><span class="marked1"><a name="line177" /> 177 def self.expand_template(pattern, mapping, processor=nil)
799
+ </span><span class="marked0"><a name="line178" /> 178 result = pattern.dup
800
+ </span><span class="marked1"><a name="line179" /> 179 for name, value in mapping
801
+ </span><span class="marked0"><a name="line180" /> 180 transformed_value = value
802
+ </span><span class="marked1"><a name="line181" /> 181 if processor != nil
803
+ </span><span class="marked0"><a name="line182" /> 182 if processor.respond_to?(:validate)
804
+ </span><span class="marked1"><a name="line183" /> 183 if !processor.validate(name, value)
805
+ </span><span class="marked0"><a name="line184" /> 184 raise InvalidTemplateValue,
806
+ </span><span class="inferred1"><a name="line185" /> 185 &quot;(#{name}, #{value}) is an invalid template value.&quot;
807
+ </span><span class="inferred0"><a name="line186" /> 186 end
808
+ </span><span class="inferred1"><a name="line187" /> 187 end
809
+ </span><span class="marked0"><a name="line188" /> 188 if processor.respond_to?(:transform)
810
+ </span><span class="marked1"><a name="line189" /> 189 transformed_value = processor.transform(name, value)
811
+ </span><span class="inferred0"><a name="line190" /> 190 end
812
+ </span><span class="inferred1"><a name="line191" /> 191 end
813
+ </span><span class="inferred0"><a name="line192" /> 192
814
+ </span><span class="inferred1"><a name="line193" /> 193 # Handle percent escaping
815
+ </span><span class="marked0"><a name="line194" /> 194 transformed_value = self.encode_segment(transformed_value,
816
+ </span><span class="inferred1"><a name="line195" /> 195 Addressable::URI::CharacterClasses::RESERVED +
817
+ </span><span class="inferred0"><a name="line196" /> 196 Addressable::URI::CharacterClasses::UNRESERVED)
818
+ </span><span class="inferred1"><a name="line197" /> 197
819
+ </span><span class="marked0"><a name="line198" /> 198 result.gsub!(/\{#{Regexp.escape(name)}\}/, transformed_value)
820
+ </span><span class="inferred1"><a name="line199" /> 199 end
821
+ </span><span class="marked0"><a name="line200" /> 200 result.gsub!(/\{[#{CharacterClasses::UNRESERVED}]+\}/, &quot;&quot;)
822
+ </span><span class="marked1"><a name="line201" /> 201 return Addressable::URI.parse(result)
823
+ </span><span class="inferred0"><a name="line202" /> 202 end
824
+ </span><span class="inferred1"><a name="line203" /> 203
825
+ </span><span class="inferred0"><a name="line204" /> 204 # Joins several uris together.
826
+ </span><span class="marked1"><a name="line205" /> 205 def self.join(*uris)
827
+ </span><span class="marked0"><a name="line206" /> 206 uri_objects = uris.collect do |uri|
828
+ </span><span class="marked1"><a name="line207" /> 207 uri.kind_of?(self) ? uri : self.parse(uri.to_s)
829
+ </span><span class="inferred0"><a name="line208" /> 208 end
830
+ </span><span class="marked1"><a name="line209" /> 209 result = uri_objects.shift.dup
831
+ </span><span class="marked0"><a name="line210" /> 210 for uri in uri_objects
832
+ </span><span class="marked1"><a name="line211" /> 211 result.merge!(uri)
833
+ </span><span class="inferred0"><a name="line212" /> 212 end
834
+ </span><span class="marked1"><a name="line213" /> 213 return result
835
+ </span><span class="inferred0"><a name="line214" /> 214 end
836
+ </span><span class="inferred1"><a name="line215" /> 215
837
+ </span><span class="inferred0"><a name="line216" /> 216 # Percent encodes a URI segment. Returns a string. Takes an optional
838
+ </span><span class="inferred1"><a name="line217" /> 217 # character class parameter, which should be specified as a string
839
+ </span><span class="inferred0"><a name="line218" /> 218 # containing a regular expression character class (not including the
840
+ </span><span class="inferred1"><a name="line219" /> 219 # surrounding square brackets). The character class parameter defaults
841
+ </span><span class="inferred0"><a name="line220" /> 220 # to the reserved plus unreserved character classes specified in
842
+ </span><span class="inferred1"><a name="line221" /> 221 # RFC 3986. Usage of the constants within the CharacterClasses module is
843
+ </span><span class="inferred0"><a name="line222" /> 222 # highly recommended when using this method.
844
+ </span><span class="inferred1"><a name="line223" /> 223 #
845
+ </span><span class="inferred0"><a name="line224" /> 224 # An example:
846
+ </span><span class="inferred1"><a name="line225" /> 225 #
847
+ </span><span class="inferred0"><a name="line226" /> 226 # Addressable::URI.escape_segment(&quot;simple-example&quot;, &quot;b-zB-Z0-9&quot;)
848
+ </span><span class="inferred1"><a name="line227" /> 227 # =&gt; &quot;simple%2Dex%61mple&quot;
849
+ </span><span class="marked0"><a name="line228" /> 228 def self.encode_segment(segment, character_class=
850
+ </span><span class="inferred1"><a name="line229" /> 229 Addressable::URI::CharacterClasses::RESERVED +
851
+ </span><span class="marked0"><a name="line230" /> 230 Addressable::URI::CharacterClasses::UNRESERVED)
852
+ </span><span class="marked1"><a name="line231" /> 231 return nil if segment.nil?
853
+ </span><span class="inferred0"><a name="line232" /> 232 return segment.gsub(
854
+ </span><span class="inferred1"><a name="line233" /> 233 /[^#{character_class}]/
855
+ </span><span class="inferred0"><a name="line234" /> 234 ) do |sequence|
856
+ </span><span class="marked1"><a name="line235" /> 235 (&quot;%&quot; + sequence.unpack('C')[0].to_s(16).upcase)
857
+ </span><span class="marked0"><a name="line236" /> 236 end
858
+ </span><span class="inferred1"><a name="line237" /> 237 end
859
+ </span><span class="inferred0"><a name="line238" /> 238
860
+ </span><span class="inferred1"><a name="line239" /> 239 # Unencodes any percent encoded characters within a URI segment.
861
+ </span><span class="inferred0"><a name="line240" /> 240 # Returns a string.
862
+ </span><span class="marked1"><a name="line241" /> 241 def self.unencode_segment(segment)
863
+ </span><span class="marked0"><a name="line242" /> 242 return nil if segment.nil?
864
+ </span><span class="inferred1"><a name="line243" /> 243 return segment.to_s.gsub(/%[0-9a-f]{2}/i) do |sequence|
865
+ </span><span class="marked0"><a name="line244" /> 244 sequence[1..3].to_i(16).chr
866
+ </span><span class="marked1"><a name="line245" /> 245 end
867
+ </span><span class="inferred0"><a name="line246" /> 246 end
868
+ </span><span class="inferred1"><a name="line247" /> 247
869
+ </span><span class="inferred0"><a name="line248" /> 248 # Percent encodes any special characters in the URI. This method does
870
+ </span><span class="inferred1"><a name="line249" /> 249 # not take IRIs or IDNs into account.
871
+ </span><span class="marked0"><a name="line250" /> 250 def self.encode(uri)
872
+ </span><span class="marked1"><a name="line251" /> 251 uri_object = uri.kind_of?(self) ? uri : self.parse(uri.to_s)
873
+ </span><span class="marked0"><a name="line252" /> 252 return Addressable::URI.new(
874
+ </span><span class="marked1"><a name="line253" /> 253 self.encode_segment(uri_object.scheme,
875
+ </span><span class="inferred0"><a name="line254" /> 254 Addressable::URI::CharacterClasses::SCHEME),
876
+ </span><span class="marked1"><a name="line255" /> 255 self.encode_segment(uri_object.user,
877
+ </span><span class="inferred0"><a name="line256" /> 256 Addressable::URI::CharacterClasses::AUTHORITY),
878
+ </span><span class="marked1"><a name="line257" /> 257 self.encode_segment(uri_object.password,
879
+ </span><span class="inferred0"><a name="line258" /> 258 Addressable::URI::CharacterClasses::AUTHORITY),
880
+ </span><span class="marked1"><a name="line259" /> 259 self.encode_segment(uri_object.host,
881
+ </span><span class="inferred0"><a name="line260" /> 260 Addressable::URI::CharacterClasses::AUTHORITY),
882
+ </span><span class="marked1"><a name="line261" /> 261 self.encode_segment(uri_object.specified_port,
883
+ </span><span class="inferred0"><a name="line262" /> 262 Addressable::URI::CharacterClasses::AUTHORITY),
884
+ </span><span class="marked1"><a name="line263" /> 263 self.encode_segment(uri_object.path,
885
+ </span><span class="inferred0"><a name="line264" /> 264 Addressable::URI::CharacterClasses::PATH),
886
+ </span><span class="marked1"><a name="line265" /> 265 self.encode_segment(uri_object.query,
887
+ </span><span class="inferred0"><a name="line266" /> 266 Addressable::URI::CharacterClasses::QUERY),
888
+ </span><span class="marked1"><a name="line267" /> 267 self.encode_segment(uri_object.fragment,
889
+ </span><span class="inferred0"><a name="line268" /> 268 Addressable::URI::CharacterClasses::FRAGMENT)
890
+ </span><span class="marked1"><a name="line269" /> 269 ).to_s
891
+ </span><span class="inferred0"><a name="line270" /> 270 end
892
+ </span><span class="inferred1"><a name="line271" /> 271
893
+ </span><span class="marked0"><a name="line272" /> 272 class &lt;&lt; self
894
+ </span><span class="marked1"><a name="line273" /> 273 alias_method :escape, :encode
895
+ </span><span class="inferred0"><a name="line274" /> 274 end
896
+ </span><span class="inferred1"><a name="line275" /> 275
897
+ </span><span class="inferred0"><a name="line276" /> 276 # Normalizes the encoding of a URI. Characters within a hostname are
898
+ </span><span class="inferred1"><a name="line277" /> 277 # not percent encoded to allow for internationalized domain names.
899
+ </span><span class="marked0"><a name="line278" /> 278 def self.normalized_encode(uri)
900
+ </span><span class="marked1"><a name="line279" /> 279 uri_object = uri.kind_of?(self) ? uri : self.parse(uri.to_s)
901
+ </span><span class="marked0"><a name="line280" /> 280 segments = {
902
+ </span><span class="marked1"><a name="line281" /> 281 :scheme =&gt; self.unencode_segment(uri_object.scheme),
903
+ </span><span class="marked0"><a name="line282" /> 282 :user =&gt; self.unencode_segment(uri_object.user),
904
+ </span><span class="marked1"><a name="line283" /> 283 :password =&gt; self.unencode_segment(uri_object.password),
905
+ </span><span class="marked0"><a name="line284" /> 284 :host =&gt; self.unencode_segment(uri_object.host),
906
+ </span><span class="marked1"><a name="line285" /> 285 :port =&gt; self.unencode_segment(uri_object.specified_port),
907
+ </span><span class="marked0"><a name="line286" /> 286 :path =&gt; self.unencode_segment(uri_object.path),
908
+ </span><span class="marked1"><a name="line287" /> 287 :query =&gt; self.unencode_segment(uri_object.query),
909
+ </span><span class="marked0"><a name="line288" /> 288 :fragment =&gt; self.unencode_segment(uri_object.fragment)
910
+ </span><span class="inferred1"><a name="line289" /> 289 }
911
+ </span><span class="marked0"><a name="line290" /> 290 if URI::IDNA.send(:use_libidn?)
912
+ </span><span class="marked1"><a name="line291" /> 291 segments.each do |key, value|
913
+ </span><span class="marked0"><a name="line292" /> 292 if value != nil
914
+ </span><span class="marked1"><a name="line293" /> 293 segments[key] = IDN::Stringprep.nfkc_normalize(value.to_s)
915
+ </span><span class="inferred0"><a name="line294" /> 294 end
916
+ </span><span class="inferred1"><a name="line295" /> 295 end
917
+ </span><span class="inferred0"><a name="line296" /> 296 end
918
+ </span><span class="marked1"><a name="line297" /> 297 return Addressable::URI.new(
919
+ </span><span class="marked0"><a name="line298" /> 298 self.encode_segment(segments[:scheme],
920
+ </span><span class="inferred1"><a name="line299" /> 299 Addressable::URI::CharacterClasses::SCHEME),
921
+ </span><span class="marked0"><a name="line300" /> 300 self.encode_segment(segments[:user],
922
+ </span><span class="inferred1"><a name="line301" /> 301 Addressable::URI::CharacterClasses::AUTHORITY),
923
+ </span><span class="marked0"><a name="line302" /> 302 self.encode_segment(segments[:password],
924
+ </span><span class="inferred1"><a name="line303" /> 303 Addressable::URI::CharacterClasses::AUTHORITY),
925
+ </span><span class="inferred0"><a name="line304" /> 304 segments[:host],
926
+ </span><span class="inferred1"><a name="line305" /> 305 segments[:port],
927
+ </span><span class="marked0"><a name="line306" /> 306 self.encode_segment(segments[:path],
928
+ </span><span class="inferred1"><a name="line307" /> 307 Addressable::URI::CharacterClasses::PATH),
929
+ </span><span class="marked0"><a name="line308" /> 308 self.encode_segment(segments[:query],
930
+ </span><span class="inferred1"><a name="line309" /> 309 Addressable::URI::CharacterClasses::QUERY),
931
+ </span><span class="marked0"><a name="line310" /> 310 self.encode_segment(segments[:fragment],
932
+ </span><span class="inferred1"><a name="line311" /> 311 Addressable::URI::CharacterClasses::FRAGMENT)
933
+ </span><span class="marked0"><a name="line312" /> 312 ).to_s
934
+ </span><span class="inferred1"><a name="line313" /> 313 end
935
+ </span><span class="inferred0"><a name="line314" /> 314
936
+ </span><span class="inferred1"><a name="line315" /> 315 # Extracts uris from an arbitrary body of text.
937
+ </span><span class="marked0"><a name="line316" /> 316 def self.extract(text, options={})
938
+ </span><span class="marked1"><a name="line317" /> 317 defaults = {:base =&gt; nil, :parse =&gt; false}
939
+ </span><span class="marked0"><a name="line318" /> 318 options = defaults.merge(options)
940
+ </span><span class="marked1"><a name="line319" /> 319 raise InvalidOptionError unless (options.keys - defaults.keys).empty?
941
+ </span><span class="inferred0"><a name="line320" /> 320 # This regular expression needs to be less forgiving or else it would
942
+ </span><span class="inferred1"><a name="line321" /> 321 # match virtually all text. Which isn't exactly what we're going for.
943
+ </span><span class="marked0"><a name="line322" /> 322 extract_regex = /((([a-z\+]+):)[^ \n\&lt;\&gt;\&quot;\\]+[\w\/])/
944
+ </span><span class="marked1"><a name="line323" /> 323 extracted_uris =
945
+ </span><span class="marked0"><a name="line324" /> 324 text.scan(extract_regex).collect { |match| match[0] }
946
+ </span><span class="marked1"><a name="line325" /> 325 sgml_extract_regex = /&lt;[^&gt;]+href=\&quot;([^\&quot;]+?)\&quot;[^&gt;]*&gt;/
947
+ </span><span class="marked0"><a name="line326" /> 326 sgml_extracted_uris =
948
+ </span><span class="inferred1"><a name="line327" /> 327 text.scan(sgml_extract_regex).collect { |match| match[0] }
949
+ </span><span class="marked0"><a name="line328" /> 328 extracted_uris.concat(sgml_extracted_uris - extracted_uris)
950
+ </span><span class="marked1"><a name="line329" /> 329 textile_extract_regex = /\&quot;.+?\&quot;:([^ ]+\/[^ ]+)[ \,\.\;\:\?\!\&lt;\&gt;\&quot;]/i
951
+ </span><span class="marked0"><a name="line330" /> 330 textile_extracted_uris =
952
+ </span><span class="inferred1"><a name="line331" /> 331 text.scan(textile_extract_regex).collect { |match| match[0] }
953
+ </span><span class="marked0"><a name="line332" /> 332 extracted_uris.concat(textile_extracted_uris - extracted_uris)
954
+ </span><span class="marked1"><a name="line333" /> 333 parsed_uris = []
955
+ </span><span class="marked0"><a name="line334" /> 334 base_uri = nil
956
+ </span><span class="marked1"><a name="line335" /> 335 if options[:base] != nil
957
+ </span><span class="marked0"><a name="line336" /> 336 base_uri = options[:base] if options[:base].kind_of?(self)
958
+ </span><span class="marked1"><a name="line337" /> 337 base_uri = self.parse(options[:base].to_s) if base_uri == nil
959
+ </span><span class="inferred0"><a name="line338" /> 338 end
960
+ </span><span class="marked1"><a name="line339" /> 339 for uri_string in extracted_uris
961
+ </span><span class="marked0"><a name="line340" /> 340 begin
962
+ </span><span class="marked1"><a name="line341" /> 341 if base_uri == nil
963
+ </span><span class="marked0"><a name="line342" /> 342 parsed_uris &lt;&lt; self.parse(uri_string)
964
+ </span><span class="inferred1"><a name="line343" /> 343 else
965
+ </span><span class="marked0"><a name="line344" /> 344 parsed_uris &lt;&lt; (base_uri + self.parse(uri_string))
966
+ </span><span class="inferred1"><a name="line345" /> 345 end
967
+ </span><span class="inferred0"><a name="line346" /> 346 rescue Exception
968
+ </span><span class="marked1"><a name="line347" /> 347 nil
969
+ </span><span class="inferred0"><a name="line348" /> 348 end
970
+ </span><span class="inferred1"><a name="line349" /> 349 end
971
+ </span><span class="marked0"><a name="line350" /> 350 parsed_uris.reject! do |uri|
972
+ </span><span class="marked1"><a name="line351" /> 351 (uri.scheme =~ /T\d+/ ||
973
+ </span><span class="marked0"><a name="line352" /> 352 uri.scheme == &quot;xmlns&quot; ||
974
+ </span><span class="marked1"><a name="line353" /> 353 uri.scheme == &quot;xml&quot; ||
975
+ </span><span class="marked0"><a name="line354" /> 354 uri.scheme == &quot;thr&quot; ||
976
+ </span><span class="marked1"><a name="line355" /> 355 uri.scheme == &quot;this&quot; ||
977
+ </span><span class="marked0"><a name="line356" /> 356 uri.scheme == &quot;float&quot; ||
978
+ </span><span class="marked1"><a name="line357" /> 357 uri.scheme == &quot;user&quot; ||
979
+ </span><span class="marked0"><a name="line358" /> 358 uri.scheme == &quot;username&quot; ||
980
+ </span><span class="marked1"><a name="line359" /> 359 uri.scheme == &quot;out&quot;)
981
+ </span><span class="inferred0"><a name="line360" /> 360 end
982
+ </span><span class="marked1"><a name="line361" /> 361 if options[:parse]
983
+ </span><span class="marked0"><a name="line362" /> 362 return parsed_uris
984
+ </span><span class="inferred1"><a name="line363" /> 363 else
985
+ </span><span class="marked0"><a name="line364" /> 364 return parsed_uris.collect { |uri| uri.to_s }
986
+ </span><span class="inferred1"><a name="line365" /> 365 end
987
+ </span><span class="inferred0"><a name="line366" /> 366 end
988
+ </span><span class="inferred1"><a name="line367" /> 367
989
+ </span><span class="inferred0"><a name="line368" /> 368 # Creates a new uri object from component parts. Passing nil for
990
+ </span><span class="inferred1"><a name="line369" /> 369 # any of these parameters is acceptable.
991
+ </span><span class="marked0"><a name="line370" /> 370 def initialize(scheme, user, password, host, port, path, query, fragment)
992
+ </span><span class="marked1"><a name="line371" /> 371 @scheme = scheme
993
+ </span><span class="marked0"><a name="line372" /> 372 @scheme = nil if @scheme.to_s.strip == &quot;&quot;
994
+ </span><span class="marked1"><a name="line373" /> 373 @user = user
995
+ </span><span class="marked0"><a name="line374" /> 374 @password = password
996
+ </span><span class="marked1"><a name="line375" /> 375 @host = host
997
+ </span><span class="marked0"><a name="line376" /> 376 @specified_port = port.to_s
998
+ </span><span class="marked1"><a name="line377" /> 377 @port = port
999
+ </span><span class="marked0"><a name="line378" /> 378 @port = @port.to_s if @port.kind_of?(Fixnum)
1000
+ </span><span class="marked1"><a name="line379" /> 379 if @port != nil &amp;&amp; !(@port =~ /^\d+$/)
1001
+ </span><span class="marked0"><a name="line380" /> 380 raise InvalidURIError,
1002
+ </span><span class="inferred1"><a name="line381" /> 381 &quot;Invalid port number: #{@port.inspect}&quot;
1003
+ </span><span class="inferred0"><a name="line382" /> 382 end
1004
+ </span><span class="marked1"><a name="line383" /> 383 @port = @port.to_i
1005
+ </span><span class="marked0"><a name="line384" /> 384 @port = nil if @port == 0
1006
+ </span><span class="marked1"><a name="line385" /> 385 @path = path
1007
+ </span><span class="marked0"><a name="line386" /> 386 @query = query
1008
+ </span><span class="marked1"><a name="line387" /> 387 @fragment = fragment
1009
+ </span><span class="inferred0"><a name="line388" /> 388
1010
+ </span><span class="marked1"><a name="line389" /> 389 validate()
1011
+ </span><span class="inferred0"><a name="line390" /> 390 end
1012
+ </span><span class="inferred1"><a name="line391" /> 391
1013
+ </span><span class="inferred0"><a name="line392" /> 392 # Returns the scheme (protocol) for this URI.
1014
+ </span><span class="marked1"><a name="line393" /> 393 def scheme
1015
+ </span><span class="marked0"><a name="line394" /> 394 return @scheme
1016
+ </span><span class="marked1"><a name="line395" /> 395 end
1017
+ </span><span class="inferred0"><a name="line396" /> 396
1018
+ </span><span class="inferred1"><a name="line397" /> 397 # Sets the scheme (protocol for this URI.)
1019
+ </span><span class="marked0"><a name="line398" /> 398 def scheme=(new_scheme)
1020
+ </span><span class="marked1"><a name="line399" /> 399 @scheme = new_scheme
1021
+ </span><span class="marked0"><a name="line400" /> 400 end
1022
+ </span><span class="inferred1"><a name="line401" /> 401
1023
+ </span><span class="inferred0"><a name="line402" /> 402 # Returns the user for this URI.
1024
+ </span><span class="marked1"><a name="line403" /> 403 def user
1025
+ </span><span class="marked0"><a name="line404" /> 404 return @user
1026
+ </span><span class="marked1"><a name="line405" /> 405 end
1027
+ </span><span class="inferred0"><a name="line406" /> 406
1028
+ </span><span class="inferred1"><a name="line407" /> 407 # Sets the user for this URI.
1029
+ </span><span class="marked0"><a name="line408" /> 408 def user=(new_user)
1030
+ </span><span class="marked1"><a name="line409" /> 409 @user = new_user
1031
+ </span><span class="inferred0"><a name="line410" /> 410
1032
+ </span><span class="inferred1"><a name="line411" /> 411 # You can't have a nil user with a non-nil password
1033
+ </span><span class="marked0"><a name="line412" /> 412 if @password != nil
1034
+ </span><span class="marked1"><a name="line413" /> 413 @user = &quot;&quot; if @user.nil?
1035
+ </span><span class="inferred0"><a name="line414" /> 414 end
1036
+ </span><span class="inferred1"><a name="line415" /> 415
1037
+ </span><span class="inferred0"><a name="line416" /> 416 # Reset dependant values
1038
+ </span><span class="marked1"><a name="line417" /> 417 @userinfo = nil
1039
+ </span><span class="marked0"><a name="line418" /> 418 @authority = nil
1040
+ </span><span class="inferred1"><a name="line419" /> 419
1041
+ </span><span class="inferred0"><a name="line420" /> 420 # Ensure we haven't created an invalid URI
1042
+ </span><span class="marked1"><a name="line421" /> 421 validate()
1043
+ </span><span class="inferred0"><a name="line422" /> 422 end
1044
+ </span><span class="inferred1"><a name="line423" /> 423
1045
+ </span><span class="inferred0"><a name="line424" /> 424 # Returns the password for this URI.
1046
+ </span><span class="marked1"><a name="line425" /> 425 def password
1047
+ </span><span class="marked0"><a name="line426" /> 426 return @password
1048
+ </span><span class="marked1"><a name="line427" /> 427 end
1049
+ </span><span class="inferred0"><a name="line428" /> 428
1050
+ </span><span class="inferred1"><a name="line429" /> 429 # Sets the password for this URI.
1051
+ </span><span class="marked0"><a name="line430" /> 430 def password=(new_password)
1052
+ </span><span class="marked1"><a name="line431" /> 431 @password = new_password
1053
+ </span><span class="inferred0"><a name="line432" /> 432
1054
+ </span><span class="inferred1"><a name="line433" /> 433 # You can't have a nil user with a non-nil password
1055
+ </span><span class="marked0"><a name="line434" /> 434 if @password != nil
1056
+ </span><span class="marked1"><a name="line435" /> 435 @user = &quot;&quot; if @user.nil?
1057
+ </span><span class="inferred0"><a name="line436" /> 436 end
1058
+ </span><span class="inferred1"><a name="line437" /> 437
1059
+ </span><span class="inferred0"><a name="line438" /> 438 # Reset dependant values
1060
+ </span><span class="marked1"><a name="line439" /> 439 @userinfo = nil
1061
+ </span><span class="marked0"><a name="line440" /> 440 @authority = nil
1062
+ </span><span class="inferred1"><a name="line441" /> 441
1063
+ </span><span class="inferred0"><a name="line442" /> 442 # Ensure we haven't created an invalid URI
1064
+ </span><span class="marked1"><a name="line443" /> 443 validate()
1065
+ </span><span class="inferred0"><a name="line444" /> 444 end
1066
+ </span><span class="inferred1"><a name="line445" /> 445
1067
+ </span><span class="inferred0"><a name="line446" /> 446 # Returns the username and password segment of this URI.
1068
+ </span><span class="marked1"><a name="line447" /> 447 def userinfo
1069
+ </span><span class="marked0"><a name="line448" /> 448 if !defined?(@userinfo) || @userinfo.nil?
1070
+ </span><span class="marked1"><a name="line449" /> 449 current_user = self.user
1071
+ </span><span class="marked0"><a name="line450" /> 450 current_password = self.password
1072
+ </span><span class="marked1"><a name="line451" /> 451 if current_user == nil &amp;&amp; current_password == nil
1073
+ </span><span class="marked0"><a name="line452" /> 452 @userinfo = nil
1074
+ </span><span class="marked1"><a name="line453" /> 453 elsif current_user != nil &amp;&amp; current_password == nil
1075
+ </span><span class="marked0"><a name="line454" /> 454 @userinfo = &quot;#{current_user}&quot;
1076
+ </span><span class="marked1"><a name="line455" /> 455 elsif current_user != nil &amp;&amp; current_password != nil
1077
+ </span><span class="marked0"><a name="line456" /> 456 @userinfo = &quot;#{current_user}:#{current_password}&quot;
1078
+ </span><span class="inferred1"><a name="line457" /> 457 end
1079
+ </span><span class="inferred0"><a name="line458" /> 458 end
1080
+ </span><span class="marked1"><a name="line459" /> 459 return @userinfo
1081
+ </span><span class="inferred0"><a name="line460" /> 460 end
1082
+ </span><span class="inferred1"><a name="line461" /> 461
1083
+ </span><span class="inferred0"><a name="line462" /> 462 # Sets the username and password segment of this URI.
1084
+ </span><span class="marked1"><a name="line463" /> 463 def userinfo=(new_userinfo)
1085
+ </span><span class="marked0"><a name="line464" /> 464 new_user = new_userinfo.to_s.strip.scan(/^(.*):/).flatten[0]
1086
+ </span><span class="marked1"><a name="line465" /> 465 new_password = new_userinfo.to_s.strip.scan(/:(.*)$/).flatten[0]
1087
+ </span><span class="inferred0"><a name="line466" /> 466
1088
+ </span><span class="inferred1"><a name="line467" /> 467 # Password assigned first to ensure validity in case of nil
1089
+ </span><span class="marked0"><a name="line468" /> 468 self.password = new_password
1090
+ </span><span class="marked1"><a name="line469" /> 469 self.user = new_user
1091
+ </span><span class="inferred0"><a name="line470" /> 470
1092
+ </span><span class="inferred1"><a name="line471" /> 471 # Reset dependant values
1093
+ </span><span class="marked0"><a name="line472" /> 472 @authority = nil
1094
+ </span><span class="inferred1"><a name="line473" /> 473
1095
+ </span><span class="inferred0"><a name="line474" /> 474 # Ensure we haven't created an invalid URI
1096
+ </span><span class="marked1"><a name="line475" /> 475 validate()
1097
+ </span><span class="inferred0"><a name="line476" /> 476 end
1098
+ </span><span class="inferred1"><a name="line477" /> 477
1099
+ </span><span class="inferred0"><a name="line478" /> 478 # Returns the host for this URI.
1100
+ </span><span class="marked1"><a name="line479" /> 479 def host
1101
+ </span><span class="marked0"><a name="line480" /> 480 return @host
1102
+ </span><span class="marked1"><a name="line481" /> 481 end
1103
+ </span><span class="inferred0"><a name="line482" /> 482
1104
+ </span><span class="inferred1"><a name="line483" /> 483 # Sets the host for this URI.
1105
+ </span><span class="marked0"><a name="line484" /> 484 def host=(new_host)
1106
+ </span><span class="marked1"><a name="line485" /> 485 @host = new_host
1107
+ </span><span class="inferred0"><a name="line486" /> 486
1108
+ </span><span class="inferred1"><a name="line487" /> 487 # Reset dependant values
1109
+ </span><span class="marked0"><a name="line488" /> 488 @authority = nil
1110
+ </span><span class="inferred1"><a name="line489" /> 489
1111
+ </span><span class="inferred0"><a name="line490" /> 490 # Ensure we haven't created an invalid URI
1112
+ </span><span class="marked1"><a name="line491" /> 491 validate()
1113
+ </span><span class="inferred0"><a name="line492" /> 492 end
1114
+ </span><span class="inferred1"><a name="line493" /> 493
1115
+ </span><span class="inferred0"><a name="line494" /> 494 # Returns the authority segment of this URI.
1116
+ </span><span class="marked1"><a name="line495" /> 495 def authority
1117
+ </span><span class="marked0"><a name="line496" /> 496 if !defined?(@authority) || @authority.nil?
1118
+ </span><span class="marked1"><a name="line497" /> 497 return nil if self.host.nil?
1119
+ </span><span class="marked0"><a name="line498" /> 498 @authority = &quot;&quot;
1120
+ </span><span class="marked1"><a name="line499" /> 499 if self.userinfo != nil
1121
+ </span><span class="marked0"><a name="line500" /> 500 @authority &lt;&lt; &quot;#{self.userinfo}@&quot;
1122
+ </span><span class="inferred1"><a name="line501" /> 501 end
1123
+ </span><span class="marked0"><a name="line502" /> 502 @authority &lt;&lt; self.host
1124
+ </span><span class="marked1"><a name="line503" /> 503 if self.specified_port != nil
1125
+ </span><span class="marked0"><a name="line504" /> 504 @authority &lt;&lt; &quot;:#{self.specified_port}&quot;
1126
+ </span><span class="inferred1"><a name="line505" /> 505 end
1127
+ </span><span class="inferred0"><a name="line506" /> 506 end
1128
+ </span><span class="marked1"><a name="line507" /> 507 return @authority
1129
+ </span><span class="inferred0"><a name="line508" /> 508 end
1130
+ </span><span class="inferred1"><a name="line509" /> 509
1131
+ </span><span class="inferred0"><a name="line510" /> 510 # Sets the authority segment of this URI.
1132
+ </span><span class="marked1"><a name="line511" /> 511 def authority=(new_authority)
1133
+ </span><span class="marked0"><a name="line512" /> 512 if new_authority != nil
1134
+ </span><span class="marked1"><a name="line513" /> 513 new_userinfo = new_authority.scan(/^([^\[\]]*)@/).flatten[0]
1135
+ </span><span class="marked0"><a name="line514" /> 514 if new_userinfo != nil
1136
+ </span><span class="marked1"><a name="line515" /> 515 new_user = new_userinfo.strip.scan(/^([^:]*):?/).flatten[0]
1137
+ </span><span class="marked0"><a name="line516" /> 516 new_password = new_userinfo.strip.scan(/:(.*)$/).flatten[0]
1138
+ </span><span class="inferred1"><a name="line517" /> 517 end
1139
+ </span><span class="marked0"><a name="line518" /> 518 new_host =
1140
+ </span><span class="inferred1"><a name="line519" /> 519 new_authority.gsub(/^([^\[\]]*)@/, &quot;&quot;).gsub(/:([^:@\[\]]*?)$/, &quot;&quot;)
1141
+ </span><span class="marked0"><a name="line520" /> 520 new_port =
1142
+ </span><span class="inferred1"><a name="line521" /> 521 new_authority.scan(/:([^:@\[\]]*?)$/).flatten[0]
1143
+ </span><span class="inferred0"><a name="line522" /> 522 end
1144
+ </span><span class="marked1"><a name="line523" /> 523 new_port = nil if new_port == &quot;&quot;
1145
+ </span><span class="inferred0"><a name="line524" /> 524
1146
+ </span><span class="inferred1"><a name="line525" /> 525 # Password assigned first to ensure validity in case of nil
1147
+ </span><span class="marked0"><a name="line526" /> 526 self.password = new_password
1148
+ </span><span class="marked1"><a name="line527" /> 527 self.user = new_user
1149
+ </span><span class="marked0"><a name="line528" /> 528 self.host = new_host
1150
+ </span><span class="inferred1"><a name="line529" /> 529
1151
+ </span><span class="inferred0"><a name="line530" /> 530 # Port reset to allow port normalization
1152
+ </span><span class="marked1"><a name="line531" /> 531 @port = nil
1153
+ </span><span class="marked0"><a name="line532" /> 532 @specified_port = new_port
1154
+ </span><span class="inferred1"><a name="line533" /> 533
1155
+ </span><span class="inferred0"><a name="line534" /> 534 # Ensure we haven't created an invalid URI
1156
+ </span><span class="marked1"><a name="line535" /> 535 validate()
1157
+ </span><span class="inferred0"><a name="line536" /> 536 end
1158
+ </span><span class="inferred1"><a name="line537" /> 537
1159
+ </span><span class="inferred0"><a name="line538" /> 538 # Returns an array of known ip-based schemes. These schemes typically
1160
+ </span><span class="inferred1"><a name="line539" /> 539 # use a similar URI form:
1161
+ </span><span class="inferred0"><a name="line540" /> 540 # //&lt;user&gt;:&lt;password&gt;@&lt;host&gt;:&lt;port&gt;/&lt;url-path&gt;
1162
+ </span><span class="marked1"><a name="line541" /> 541 def self.ip_based_schemes
1163
+ </span><span class="marked0"><a name="line542" /> 542 return self.scheme_mapping.keys
1164
+ </span><span class="marked1"><a name="line543" /> 543 end
1165
+ </span><span class="inferred0"><a name="line544" /> 544
1166
+ </span><span class="inferred1"><a name="line545" /> 545 # Returns a hash of common IP-based schemes and their default port
1167
+ </span><span class="inferred0"><a name="line546" /> 546 # numbers. Adding new schemes to this hash, as necessary, will allow
1168
+ </span><span class="inferred1"><a name="line547" /> 547 # for better URI normalization.
1169
+ </span><span class="marked0"><a name="line548" /> 548 def self.scheme_mapping
1170
+ </span><span class="marked1"><a name="line549" /> 549 if !defined?(@protocol_mapping) || @protocol_mapping.nil?
1171
+ </span><span class="marked0"><a name="line550" /> 550 @protocol_mapping = {
1172
+ </span><span class="inferred1"><a name="line551" /> 551 &quot;http&quot; =&gt; 80,
1173
+ </span><span class="inferred0"><a name="line552" /> 552 &quot;https&quot; =&gt; 443,
1174
+ </span><span class="inferred1"><a name="line553" /> 553 &quot;ftp&quot; =&gt; 21,
1175
+ </span><span class="inferred0"><a name="line554" /> 554 &quot;tftp&quot; =&gt; 69,
1176
+ </span><span class="inferred1"><a name="line555" /> 555 &quot;ssh&quot; =&gt; 22,
1177
+ </span><span class="inferred0"><a name="line556" /> 556 &quot;svn+ssh&quot; =&gt; 22,
1178
+ </span><span class="inferred1"><a name="line557" /> 557 &quot;telnet&quot; =&gt; 23,
1179
+ </span><span class="inferred0"><a name="line558" /> 558 &quot;nntp&quot; =&gt; 119,
1180
+ </span><span class="inferred1"><a name="line559" /> 559 &quot;gopher&quot; =&gt; 70,
1181
+ </span><span class="inferred0"><a name="line560" /> 560 &quot;wais&quot; =&gt; 210,
1182
+ </span><span class="inferred1"><a name="line561" /> 561 &quot;ldap&quot; =&gt; 389,
1183
+ </span><span class="inferred0"><a name="line562" /> 562 &quot;prospero&quot; =&gt; 1525
1184
+ </span><span class="inferred1"><a name="line563" /> 563 }
1185
+ </span><span class="inferred0"><a name="line564" /> 564 end
1186
+ </span><span class="marked1"><a name="line565" /> 565 return @protocol_mapping
1187
+ </span><span class="inferred0"><a name="line566" /> 566 end
1188
+ </span><span class="inferred1"><a name="line567" /> 567
1189
+ </span><span class="inferred0"><a name="line568" /> 568 # Returns the port number for this URI. This method will normalize to the
1190
+ </span><span class="inferred1"><a name="line569" /> 569 # default port for the URI's scheme if the port isn't explicitly specified
1191
+ </span><span class="inferred0"><a name="line570" /> 570 # in the URI.
1192
+ </span><span class="marked1"><a name="line571" /> 571 def port
1193
+ </span><span class="marked0"><a name="line572" /> 572 if @port.to_i == 0
1194
+ </span><span class="marked1"><a name="line573" /> 573 if self.scheme.nil?
1195
+ </span><span class="marked0"><a name="line574" /> 574 @port = nil
1196
+ </span><span class="inferred1"><a name="line575" /> 575 else
1197
+ </span><span class="marked0"><a name="line576" /> 576 @port = self.class.scheme_mapping[self.scheme.strip.downcase]
1198
+ </span><span class="inferred1"><a name="line577" /> 577 end
1199
+ </span><span class="marked0"><a name="line578" /> 578 return @port
1200
+ </span><span class="inferred1"><a name="line579" /> 579 else
1201
+ </span><span class="marked0"><a name="line580" /> 580 @port = @port.to_i
1202
+ </span><span class="marked1"><a name="line581" /> 581 return @port
1203
+ </span><span class="inferred0"><a name="line582" /> 582 end
1204
+ </span><span class="marked1"><a name="line583" /> 583 end
1205
+ </span><span class="inferred0"><a name="line584" /> 584
1206
+ </span><span class="inferred1"><a name="line585" /> 585 # Sets the port for this URI.
1207
+ </span><span class="marked0"><a name="line586" /> 586 def port=(new_port)
1208
+ </span><span class="marked1"><a name="line587" /> 587 @port = new_port.to_s.to_i
1209
+ </span><span class="marked0"><a name="line588" /> 588 @specified_port = @port
1210
+ </span><span class="marked1"><a name="line589" /> 589 @authority = nil
1211
+ </span><span class="inferred0"><a name="line590" /> 590 end
1212
+ </span><span class="inferred1"><a name="line591" /> 591
1213
+ </span><span class="inferred0"><a name="line592" /> 592 # Returns the port number that was actually specified in the URI string.
1214
+ </span><span class="marked1"><a name="line593" /> 593 def specified_port
1215
+ </span><span class="marked0"><a name="line594" /> 594 port = @specified_port.to_s.to_i
1216
+ </span><span class="marked1"><a name="line595" /> 595 if port == 0
1217
+ </span><span class="marked0"><a name="line596" /> 596 return nil
1218
+ </span><span class="inferred1"><a name="line597" /> 597 else
1219
+ </span><span class="marked0"><a name="line598" /> 598 return port
1220
+ </span><span class="inferred1"><a name="line599" /> 599 end
1221
+ </span><span class="inferred0"><a name="line600" /> 600 end
1222
+ </span><span class="inferred1"><a name="line601" /> 601
1223
+ </span><span class="inferred0"><a name="line602" /> 602 # Returns the path for this URI.
1224
+ </span><span class="marked1"><a name="line603" /> 603 def path
1225
+ </span><span class="marked0"><a name="line604" /> 604 return @path
1226
+ </span><span class="marked1"><a name="line605" /> 605 end
1227
+ </span><span class="inferred0"><a name="line606" /> 606
1228
+ </span><span class="inferred1"><a name="line607" /> 607 # Sets the path for this URI.
1229
+ </span><span class="marked0"><a name="line608" /> 608 def path=(new_path)
1230
+ </span><span class="marked1"><a name="line609" /> 609 @path = new_path
1231
+ </span><span class="marked0"><a name="line610" /> 610 end
1232
+ </span><span class="inferred1"><a name="line611" /> 611
1233
+ </span><span class="inferred0"><a name="line612" /> 612 # Returns the basename, if any, of the file at the path being referenced.
1234
+ </span><span class="inferred1"><a name="line613" /> 613 # Returns nil if there is no path component.
1235
+ </span><span class="marked0"><a name="line614" /> 614 def basename
1236
+ </span><span class="marked1"><a name="line615" /> 615 return nil if self.path == nil
1237
+ </span><span class="marked0"><a name="line616" /> 616 return File.basename(self.path).gsub(/;[^\/]*$/, &quot;&quot;)
1238
+ </span><span class="inferred1"><a name="line617" /> 617 end
1239
+ </span><span class="inferred0"><a name="line618" /> 618
1240
+ </span><span class="inferred1"><a name="line619" /> 619 # Returns the extension, if any, of the file at the path being referenced.
1241
+ </span><span class="inferred0"><a name="line620" /> 620 # Returns &quot;&quot; if there is no extension or nil if there is no path
1242
+ </span><span class="inferred1"><a name="line621" /> 621 # component.
1243
+ </span><span class="marked0"><a name="line622" /> 622 def extname
1244
+ </span><span class="marked1"><a name="line623" /> 623 return nil if self.path == nil
1245
+ </span><span class="marked0"><a name="line624" /> 624 return File.extname(self.basename.gsub(/;[^\/]*$/, &quot;&quot;))
1246
+ </span><span class="inferred1"><a name="line625" /> 625 end
1247
+ </span><span class="inferred0"><a name="line626" /> 626
1248
+ </span><span class="inferred1"><a name="line627" /> 627 # Returns the query string for this URI.
1249
+ </span><span class="marked0"><a name="line628" /> 628 def query
1250
+ </span><span class="marked1"><a name="line629" /> 629 return @query
1251
+ </span><span class="marked0"><a name="line630" /> 630 end
1252
+ </span><span class="inferred1"><a name="line631" /> 631
1253
+ </span><span class="inferred0"><a name="line632" /> 632 # Sets the query string for this URI.
1254
+ </span><span class="marked1"><a name="line633" /> 633 def query=(new_query)
1255
+ </span><span class="marked0"><a name="line634" /> 634 @query = new_query
1256
+ </span><span class="marked1"><a name="line635" /> 635 end
1257
+ </span><span class="inferred0"><a name="line636" /> 636
1258
+ </span><span class="inferred1"><a name="line637" /> 637 # Returns the fragment for this URI.
1259
+ </span><span class="marked0"><a name="line638" /> 638 def fragment
1260
+ </span><span class="marked1"><a name="line639" /> 639 return @fragment
1261
+ </span><span class="marked0"><a name="line640" /> 640 end
1262
+ </span><span class="inferred1"><a name="line641" /> 641
1263
+ </span><span class="inferred0"><a name="line642" /> 642 # Sets the fragment for this URI.
1264
+ </span><span class="marked1"><a name="line643" /> 643 def fragment=(new_fragment)
1265
+ </span><span class="marked0"><a name="line644" /> 644 @fragment = new_fragment
1266
+ </span><span class="marked1"><a name="line645" /> 645 end
1267
+ </span><span class="inferred0"><a name="line646" /> 646
1268
+ </span><span class="inferred1"><a name="line647" /> 647 # Returns true if the URI uses an IP-based protocol.
1269
+ </span><span class="marked0"><a name="line648" /> 648 def ip_based?
1270
+ </span><span class="marked1"><a name="line649" /> 649 return false if self.scheme.nil?
1271
+ </span><span class="marked0"><a name="line650" /> 650 return self.class.ip_based_schemes.include?(self.scheme.strip.downcase)
1272
+ </span><span class="inferred1"><a name="line651" /> 651 end
1273
+ </span><span class="inferred0"><a name="line652" /> 652
1274
+ </span><span class="inferred1"><a name="line653" /> 653 # Returns true if this URI is known to be relative.
1275
+ </span><span class="marked0"><a name="line654" /> 654 def relative?
1276
+ </span><span class="marked1"><a name="line655" /> 655 return self.scheme.nil?
1277
+ </span><span class="marked0"><a name="line656" /> 656 end
1278
+ </span><span class="inferred1"><a name="line657" /> 657
1279
+ </span><span class="inferred0"><a name="line658" /> 658 # Returns true if this URI is known to be absolute.
1280
+ </span><span class="marked1"><a name="line659" /> 659 def absolute?
1281
+ </span><span class="marked0"><a name="line660" /> 660 return !relative?
1282
+ </span><span class="marked1"><a name="line661" /> 661 end
1283
+ </span><span class="inferred0"><a name="line662" /> 662
1284
+ </span><span class="inferred1"><a name="line663" /> 663 # Joins two URIs together.
1285
+ </span><span class="marked0"><a name="line664" /> 664 def +(uri)
1286
+ </span><span class="marked1"><a name="line665" /> 665 if !uri.kind_of?(self.class)
1287
+ </span><span class="marked0"><a name="line666" /> 666 uri = URI.parse(uri.to_s)
1288
+ </span><span class="inferred1"><a name="line667" /> 667 end
1289
+ </span><span class="marked0"><a name="line668" /> 668 if uri.to_s == &quot;&quot;
1290
+ </span><span class="marked1"><a name="line669" /> 669 return self.dup
1291
+ </span><span class="inferred0"><a name="line670" /> 670 end
1292
+ </span><span class="inferred1"><a name="line671" /> 671
1293
+ </span><span class="marked0"><a name="line672" /> 672 joined_scheme = nil
1294
+ </span><span class="marked1"><a name="line673" /> 673 joined_user = nil
1295
+ </span><span class="marked0"><a name="line674" /> 674 joined_password = nil
1296
+ </span><span class="marked1"><a name="line675" /> 675 joined_host = nil
1297
+ </span><span class="marked0"><a name="line676" /> 676 joined_port = nil
1298
+ </span><span class="marked1"><a name="line677" /> 677 joined_path = nil
1299
+ </span><span class="marked0"><a name="line678" /> 678 joined_query = nil
1300
+ </span><span class="marked1"><a name="line679" /> 679 joined_fragment = nil
1301
+ </span><span class="inferred0"><a name="line680" /> 680
1302
+ </span><span class="inferred1"><a name="line681" /> 681 # Section 5.2.2 of RFC 3986
1303
+ </span><span class="marked0"><a name="line682" /> 682 if uri.scheme != nil
1304
+ </span><span class="marked1"><a name="line683" /> 683 joined_scheme = uri.scheme
1305
+ </span><span class="marked0"><a name="line684" /> 684 joined_user = uri.user
1306
+ </span><span class="marked1"><a name="line685" /> 685 joined_password = uri.password
1307
+ </span><span class="marked0"><a name="line686" /> 686 joined_host = uri.host
1308
+ </span><span class="marked1"><a name="line687" /> 687 joined_port = uri.specified_port
1309
+ </span><span class="marked0"><a name="line688" /> 688 joined_path = self.class.normalize_path(uri.path)
1310
+ </span><span class="marked1"><a name="line689" /> 689 joined_query = uri.query
1311
+ </span><span class="inferred0"><a name="line690" /> 690 else
1312
+ </span><span class="marked1"><a name="line691" /> 691 if uri.authority != nil
1313
+ </span><span class="marked0"><a name="line692" /> 692 joined_user = uri.user
1314
+ </span><span class="marked1"><a name="line693" /> 693 joined_password = uri.password
1315
+ </span><span class="marked0"><a name="line694" /> 694 joined_host = uri.host
1316
+ </span><span class="marked1"><a name="line695" /> 695 joined_port = uri.specified_port
1317
+ </span><span class="marked0"><a name="line696" /> 696 joined_path = self.class.normalize_path(uri.path)
1318
+ </span><span class="marked1"><a name="line697" /> 697 joined_query = uri.query
1319
+ </span><span class="inferred0"><a name="line698" /> 698 else
1320
+ </span><span class="marked1"><a name="line699" /> 699 if uri.path == nil || uri.path == &quot;&quot;
1321
+ </span><span class="marked0"><a name="line700" /> 700 joined_path = self.path
1322
+ </span><span class="marked1"><a name="line701" /> 701 if uri.query != nil
1323
+ </span><span class="marked0"><a name="line702" /> 702 joined_query = uri.query
1324
+ </span><span class="inferred1"><a name="line703" /> 703 else
1325
+ </span><span class="marked0"><a name="line704" /> 704 joined_query = self.query
1326
+ </span><span class="inferred1"><a name="line705" /> 705 end
1327
+ </span><span class="inferred0"><a name="line706" /> 706 else
1328
+ </span><span class="marked1"><a name="line707" /> 707 if uri.path[0..0] == &quot;/&quot;
1329
+ </span><span class="marked0"><a name="line708" /> 708 joined_path = self.class.normalize_path(uri.path)
1330
+ </span><span class="inferred1"><a name="line709" /> 709 else
1331
+ </span><span class="marked0"><a name="line710" /> 710 base_path = self.path.nil? ? &quot;&quot; : self.path.dup
1332
+ </span><span class="marked1"><a name="line711" /> 711 base_path = self.class.normalize_path(base_path)
1333
+ </span><span class="marked0"><a name="line712" /> 712 base_path.gsub!(/\/[^\/]+$/, &quot;/&quot;)
1334
+ </span><span class="marked1"><a name="line713" /> 713 joined_path = self.class.normalize_path(base_path + uri.path)
1335
+ </span><span class="inferred0"><a name="line714" /> 714 end
1336
+ </span><span class="marked1"><a name="line715" /> 715 joined_query = uri.query
1337
+ </span><span class="inferred0"><a name="line716" /> 716 end
1338
+ </span><span class="marked1"><a name="line717" /> 717 joined_user = self.user
1339
+ </span><span class="marked0"><a name="line718" /> 718 joined_password = self.password
1340
+ </span><span class="marked1"><a name="line719" /> 719 joined_host = self.host
1341
+ </span><span class="marked0"><a name="line720" /> 720 joined_port = self.specified_port
1342
+ </span><span class="inferred1"><a name="line721" /> 721 end
1343
+ </span><span class="marked0"><a name="line722" /> 722 joined_scheme = self.scheme
1344
+ </span><span class="inferred1"><a name="line723" /> 723 end
1345
+ </span><span class="marked0"><a name="line724" /> 724 joined_fragment = uri.fragment
1346
+ </span><span class="inferred1"><a name="line725" /> 725
1347
+ </span><span class="marked0"><a name="line726" /> 726 return Addressable::URI.new(
1348
+ </span><span class="inferred1"><a name="line727" /> 727 joined_scheme,
1349
+ </span><span class="inferred0"><a name="line728" /> 728 joined_user,
1350
+ </span><span class="inferred1"><a name="line729" /> 729 joined_password,
1351
+ </span><span class="inferred0"><a name="line730" /> 730 joined_host,
1352
+ </span><span class="inferred1"><a name="line731" /> 731 joined_port,
1353
+ </span><span class="inferred0"><a name="line732" /> 732 joined_path,
1354
+ </span><span class="inferred1"><a name="line733" /> 733 joined_query,
1355
+ </span><span class="inferred0"><a name="line734" /> 734 joined_fragment
1356
+ </span><span class="marked1"><a name="line735" /> 735 )
1357
+ </span><span class="inferred0"><a name="line736" /> 736 end
1358
+ </span><span class="inferred1"><a name="line737" /> 737
1359
+ </span><span class="inferred0"><a name="line738" /> 738 # Merges two URIs together.
1360
+ </span><span class="marked1"><a name="line739" /> 739 def merge(uri)
1361
+ </span><span class="marked0"><a name="line740" /> 740 return self + uri
1362
+ </span><span class="marked1"><a name="line741" /> 741 end
1363
+ </span><span class="inferred0"><a name="line742" /> 742
1364
+ </span><span class="inferred1"><a name="line743" /> 743 # Destructive form of merge.
1365
+ </span><span class="marked0"><a name="line744" /> 744 def merge!(uri)
1366
+ </span><span class="marked1"><a name="line745" /> 745 replace_self(self.merge(uri))
1367
+ </span><span class="marked0"><a name="line746" /> 746 end
1368
+ </span><span class="inferred1"><a name="line747" /> 747
1369
+ </span><span class="inferred0"><a name="line748" /> 748 # Returns the shortest normalized relative form of this URI that uses the
1370
+ </span><span class="inferred1"><a name="line749" /> 749 # supplied URI as a base for resolution. Returns an absolute URI if
1371
+ </span><span class="inferred0"><a name="line750" /> 750 # necessary.
1372
+ </span><span class="marked1"><a name="line751" /> 751 def route_from(uri)
1373
+ </span><span class="marked0"><a name="line752" /> 752 uri = uri.kind_of?(self.class) ? uri : self.class.parse(uri.to_s)
1374
+ </span><span class="marked1"><a name="line753" /> 753 uri = uri.normalize
1375
+ </span><span class="marked0"><a name="line754" /> 754 normalized_self = self.normalize
1376
+ </span><span class="marked1"><a name="line755" /> 755 if normalized_self.relative?
1377
+ </span><span class="marked0"><a name="line756" /> 756 raise ArgumentError, &quot;Expected absolute URI, got: #{self.to_s}&quot;
1378
+ </span><span class="inferred1"><a name="line757" /> 757 end
1379
+ </span><span class="marked0"><a name="line758" /> 758 if uri.relative?
1380
+ </span><span class="marked1"><a name="line759" /> 759 raise ArgumentError, &quot;Expected absolute URI, got: #{self.to_s}&quot;
1381
+ </span><span class="inferred0"><a name="line760" /> 760 end
1382
+ </span><span class="marked1"><a name="line761" /> 761 if normalized_self == uri
1383
+ </span><span class="marked0"><a name="line762" /> 762 return Addressable::URI.parse(&quot;##{normalized_self.fragment}&quot;)
1384
+ </span><span class="inferred1"><a name="line763" /> 763 end
1385
+ </span><span class="marked0"><a name="line764" /> 764 segments = normalized_self.to_h
1386
+ </span><span class="marked1"><a name="line765" /> 765 if normalized_self.scheme == uri.scheme
1387
+ </span><span class="marked0"><a name="line766" /> 766 segments[:scheme] = nil
1388
+ </span><span class="marked1"><a name="line767" /> 767 if normalized_self.authority == uri.authority
1389
+ </span><span class="marked0"><a name="line768" /> 768 segments[:user] = nil
1390
+ </span><span class="marked1"><a name="line769" /> 769 segments[:password] = nil
1391
+ </span><span class="marked0"><a name="line770" /> 770 segments[:host] = nil
1392
+ </span><span class="marked1"><a name="line771" /> 771 segments[:port] = nil
1393
+ </span><span class="marked0"><a name="line772" /> 772 if normalized_self.path == uri.path
1394
+ </span><span class="marked1"><a name="line773" /> 773 segments[:path] = nil
1395
+ </span><span class="marked0"><a name="line774" /> 774 if normalized_self.query == uri.query
1396
+ </span><span class="marked1"><a name="line775" /> 775 segments[:query] = nil
1397
+ </span><span class="inferred0"><a name="line776" /> 776 end
1398
+ </span><span class="inferred1"><a name="line777" /> 777 end
1399
+ </span><span class="inferred0"><a name="line778" /> 778 end
1400
+ </span><span class="inferred1"><a name="line779" /> 779 end
1401
+ </span><span class="inferred0"><a name="line780" /> 780 # Avoid network-path references.
1402
+ </span><span class="marked1"><a name="line781" /> 781 if segments[:scheme] == nil &amp;&amp; segments[:host] != nil
1403
+ </span><span class="marked0"><a name="line782" /> 782 segments[:scheme] = normalized_self.scheme
1404
+ </span><span class="inferred1"><a name="line783" /> 783 end
1405
+ </span><span class="marked0"><a name="line784" /> 784 return Addressable::URI.new(
1406
+ </span><span class="inferred1"><a name="line785" /> 785 segments[:scheme],
1407
+ </span><span class="inferred0"><a name="line786" /> 786 segments[:user],
1408
+ </span><span class="inferred1"><a name="line787" /> 787 segments[:password],
1409
+ </span><span class="inferred0"><a name="line788" /> 788 segments[:host],
1410
+ </span><span class="inferred1"><a name="line789" /> 789 segments[:port],
1411
+ </span><span class="inferred0"><a name="line790" /> 790 segments[:path],
1412
+ </span><span class="inferred1"><a name="line791" /> 791 segments[:query],
1413
+ </span><span class="inferred0"><a name="line792" /> 792 segments[:fragment]
1414
+ </span><span class="marked1"><a name="line793" /> 793 )
1415
+ </span><span class="inferred0"><a name="line794" /> 794 end
1416
+ </span><span class="inferred1"><a name="line795" /> 795
1417
+ </span><span class="inferred0"><a name="line796" /> 796 # Returns the shortest normalized relative form of the supplied URI that
1418
+ </span><span class="inferred1"><a name="line797" /> 797 # uses this URI as a base for resolution. Returns an absolute URI if
1419
+ </span><span class="inferred0"><a name="line798" /> 798 # necessary.
1420
+ </span><span class="marked1"><a name="line799" /> 799 def route_to(uri)
1421
+ </span><span class="marked0"><a name="line800" /> 800 uri = uri.kind_of?(self.class) ? uri : self.class.parse(uri.to_s)
1422
+ </span><span class="marked1"><a name="line801" /> 801 return uri.route_from(self)
1423
+ </span><span class="inferred0"><a name="line802" /> 802 end
1424
+ </span><span class="inferred1"><a name="line803" /> 803
1425
+ </span><span class="inferred0"><a name="line804" /> 804 # Returns a normalized URI object.
1426
+ </span><span class="inferred1"><a name="line805" /> 805 #
1427
+ </span><span class="inferred0"><a name="line806" /> 806 # NOTE: This method does not attempt to fully conform to specifications.
1428
+ </span><span class="inferred1"><a name="line807" /> 807 # It exists largely to correct other people's failures to read the
1429
+ </span><span class="inferred0"><a name="line808" /> 808 # specifications, and also to deal with caching issues since several
1430
+ </span><span class="inferred1"><a name="line809" /> 809 # different URIs may represent the same resource and should not be
1431
+ </span><span class="inferred0"><a name="line810" /> 810 # cached multiple times.
1432
+ </span><span class="marked1"><a name="line811" /> 811 def normalize
1433
+ </span><span class="marked0"><a name="line812" /> 812 normalized_scheme = nil
1434
+ </span><span class="marked1"><a name="line813" /> 813 normalized_scheme = self.scheme.strip.downcase if self.scheme != nil
1435
+ </span><span class="marked0"><a name="line814" /> 814 normalized_scheme = &quot;svn+ssh&quot; if normalized_scheme == &quot;ssh+svn&quot;
1436
+ </span><span class="marked1"><a name="line815" /> 815 if normalized_scheme == &quot;feed&quot;
1437
+ </span><span class="marked0"><a name="line816" /> 816 if self.to_s =~ /^feed:\/*http:\/*/
1438
+ </span><span class="marked1"><a name="line817" /> 817 return self.class.parse(
1439
+ </span><span class="marked0"><a name="line818" /> 818 self.to_s.scan(/^feed:\/*(http:\/*.*)/).flatten[0]).normalize
1440
+ </span><span class="inferred1"><a name="line819" /> 819 end
1441
+ </span><span class="inferred0"><a name="line820" /> 820 end
1442
+ </span><span class="marked1"><a name="line821" /> 821 normalized_user = nil
1443
+ </span><span class="marked0"><a name="line822" /> 822 normalized_user = self.user.strip if self.user != nil
1444
+ </span><span class="marked1"><a name="line823" /> 823 normalized_password = nil
1445
+ </span><span class="marked0"><a name="line824" /> 824 normalized_password = self.password.strip if self.password != nil
1446
+ </span><span class="marked1"><a name="line825" /> 825 normalized_host = nil
1447
+ </span><span class="marked0"><a name="line826" /> 826 normalized_host = self.host.strip.downcase if self.host != nil
1448
+ </span><span class="marked1"><a name="line827" /> 827 if normalized_host != nil
1449
+ </span><span class="marked0"><a name="line828" /> 828 begin
1450
+ </span><span class="marked1"><a name="line829" /> 829 normalized_host = URI::IDNA.to_ascii(normalized_host)
1451
+ </span><span class="inferred0"><a name="line830" /> 830 rescue Exception
1452
+ </span><span class="marked1"><a name="line831" /> 831 nil
1453
+ </span><span class="inferred0"><a name="line832" /> 832 end
1454
+ </span><span class="inferred1"><a name="line833" /> 833 end
1455
+ </span><span class="inferred0"><a name="line834" /> 834
1456
+ </span><span class="marked1"><a name="line835" /> 835 normalized_port = self.port
1457
+ </span><span class="marked0"><a name="line836" /> 836 if self.class.scheme_mapping[normalized_scheme] == normalized_port
1458
+ </span><span class="marked1"><a name="line837" /> 837 normalized_port = nil
1459
+ </span><span class="inferred0"><a name="line838" /> 838 end
1460
+ </span><span class="marked1"><a name="line839" /> 839 normalized_path = nil
1461
+ </span><span class="marked0"><a name="line840" /> 840 normalized_path = self.path.strip if self.path != nil
1462
+ </span><span class="inferred1"><a name="line841" /> 841 if normalized_path == nil &amp;&amp;
1463
+ </span><span class="marked0"><a name="line842" /> 842 normalized_scheme != nil &amp;&amp;
1464
+ </span><span class="inferred1"><a name="line843" /> 843 normalized_host != nil
1465
+ </span><span class="marked0"><a name="line844" /> 844 normalized_path = &quot;/&quot;
1466
+ </span><span class="inferred1"><a name="line845" /> 845 end
1467
+ </span><span class="marked0"><a name="line846" /> 846 if normalized_path != nil
1468
+ </span><span class="marked1"><a name="line847" /> 847 normalized_path = self.class.normalize_path(normalized_path)
1469
+ </span><span class="inferred0"><a name="line848" /> 848 end
1470
+ </span><span class="marked1"><a name="line849" /> 849 if normalized_path == &quot;&quot;
1471
+ </span><span class="marked0"><a name="line850" /> 850 if [&quot;http&quot;, &quot;https&quot;, &quot;ftp&quot;, &quot;tftp&quot;].include?(normalized_scheme)
1472
+ </span><span class="marked1"><a name="line851" /> 851 normalized_path = &quot;/&quot;
1473
+ </span><span class="inferred0"><a name="line852" /> 852 end
1474
+ </span><span class="inferred1"><a name="line853" /> 853 end
1475
+ </span><span class="inferred0"><a name="line854" /> 854
1476
+ </span><span class="marked1"><a name="line855" /> 855 normalized_query = nil
1477
+ </span><span class="marked0"><a name="line856" /> 856 normalized_query = self.query.strip if self.query != nil
1478
+ </span><span class="inferred1"><a name="line857" /> 857
1479
+ </span><span class="marked0"><a name="line858" /> 858 normalized_fragment = nil
1480
+ </span><span class="marked1"><a name="line859" /> 859 normalized_fragment = self.fragment.strip if self.fragment != nil
1481
+ </span><span class="marked0"><a name="line860" /> 860 return Addressable::URI.parse(
1482
+ </span><span class="marked1"><a name="line861" /> 861 Addressable::URI.normalized_encode(Addressable::URI.new(
1483
+ </span><span class="inferred0"><a name="line862" /> 862 normalized_scheme,
1484
+ </span><span class="inferred1"><a name="line863" /> 863 normalized_user,
1485
+ </span><span class="inferred0"><a name="line864" /> 864 normalized_password,
1486
+ </span><span class="inferred1"><a name="line865" /> 865 normalized_host,
1487
+ </span><span class="inferred0"><a name="line866" /> 866 normalized_port,
1488
+ </span><span class="inferred1"><a name="line867" /> 867 normalized_path,
1489
+ </span><span class="inferred0"><a name="line868" /> 868 normalized_query,
1490
+ </span><span class="inferred1"><a name="line869" /> 869 normalized_fragment
1491
+ </span><span class="marked0"><a name="line870" /> 870 )))
1492
+ </span><span class="inferred1"><a name="line871" /> 871 end
1493
+ </span><span class="inferred0"><a name="line872" /> 872
1494
+ </span><span class="inferred1"><a name="line873" /> 873 # Destructively normalizes this URI object.
1495
+ </span><span class="marked0"><a name="line874" /> 874 def normalize!
1496
+ </span><span class="marked1"><a name="line875" /> 875 replace_self(self.normalize)
1497
+ </span><span class="marked0"><a name="line876" /> 876 end
1498
+ </span><span class="inferred1"><a name="line877" /> 877
1499
+ </span><span class="inferred0"><a name="line878" /> 878 # Creates a URI suitable for display to users. If semantic attacks are
1500
+ </span><span class="inferred1"><a name="line879" /> 879 # likely, the application should try to detect these and warn the user.
1501
+ </span><span class="inferred0"><a name="line880" /> 880 # See RFC 3986 section 7.6 for more information.
1502
+ </span><span class="marked1"><a name="line881" /> 881 def display_uri
1503
+ </span><span class="marked0"><a name="line882" /> 882 display_uri = self.normalize
1504
+ </span><span class="marked1"><a name="line883" /> 883 begin
1505
+ </span><span class="marked0"><a name="line884" /> 884 display_uri.instance_variable_set(&quot;@host&quot;,
1506
+ </span><span class="marked1"><a name="line885" /> 885 URI::IDNA.to_unicode(display_uri.host))
1507
+ </span><span class="inferred0"><a name="line886" /> 886 rescue Exception
1508
+ </span><span class="marked1"><a name="line887" /> 887 nil
1509
+ </span><span class="inferred0"><a name="line888" /> 888 end
1510
+ </span><span class="marked1"><a name="line889" /> 889 return display_uri
1511
+ </span><span class="inferred0"><a name="line890" /> 890 end
1512
+ </span><span class="inferred1"><a name="line891" /> 891
1513
+ </span><span class="inferred0"><a name="line892" /> 892 # Returns true if the URI objects are equal. This method normalizes
1514
+ </span><span class="inferred1"><a name="line893" /> 893 # both URIs before doing the comparison, and allows comparison against
1515
+ </span><span class="inferred0"><a name="line894" /> 894 # strings.
1516
+ </span><span class="marked1"><a name="line895" /> 895 def ===(uri)
1517
+ </span><span class="marked0"><a name="line896" /> 896 uri_string = nil
1518
+ </span><span class="marked1"><a name="line897" /> 897 if uri.respond_to?(:normalize)
1519
+ </span><span class="marked0"><a name="line898" /> 898 uri_string = uri.normalize.to_s
1520
+ </span><span class="inferred1"><a name="line899" /> 899 else
1521
+ </span><span class="marked0"><a name="line900" /> 900 begin
1522
+ </span><span class="marked1"><a name="line901" /> 901 uri_string = URI.parse(uri.to_s).normalize.to_s
1523
+ </span><span class="inferred0"><a name="line902" /> 902 rescue Exception
1524
+ </span><span class="marked1"><a name="line903" /> 903 return false
1525
+ </span><span class="inferred0"><a name="line904" /> 904 end
1526
+ </span><span class="inferred1"><a name="line905" /> 905 end
1527
+ </span><span class="marked0"><a name="line906" /> 906 return self.normalize.to_s == uri_string
1528
+ </span><span class="inferred1"><a name="line907" /> 907 end
1529
+ </span><span class="inferred0"><a name="line908" /> 908
1530
+ </span><span class="inferred1"><a name="line909" /> 909 # Returns true if the URI objects are equal. This method normalizes
1531
+ </span><span class="inferred0"><a name="line910" /> 910 # both URIs before doing the comparison.
1532
+ </span><span class="marked1"><a name="line911" /> 911 def ==(uri)
1533
+ </span><span class="marked0"><a name="line912" /> 912 return false unless uri.kind_of?(self.class)
1534
+ </span><span class="marked1"><a name="line913" /> 913 return self.normalize.to_s == uri.normalize.to_s
1535
+ </span><span class="inferred0"><a name="line914" /> 914 end
1536
+ </span><span class="inferred1"><a name="line915" /> 915
1537
+ </span><span class="inferred0"><a name="line916" /> 916 # Returns true if the URI objects are equal. This method does NOT
1538
+ </span><span class="inferred1"><a name="line917" /> 917 # normalize either URI before doing the comparison.
1539
+ </span><span class="marked0"><a name="line918" /> 918 def eql?(uri)
1540
+ </span><span class="marked1"><a name="line919" /> 919 return false unless uri.kind_of?(self.class)
1541
+ </span><span class="marked0"><a name="line920" /> 920 return self.to_s == uri.to_s
1542
+ </span><span class="inferred1"><a name="line921" /> 921 end
1543
+ </span><span class="inferred0"><a name="line922" /> 922
1544
+ </span><span class="inferred1"><a name="line923" /> 923 # Clones the URI object.
1545
+ </span><span class="marked0"><a name="line924" /> 924 def dup
1546
+ </span><span class="marked1"><a name="line925" /> 925 duplicated_scheme = nil
1547
+ </span><span class="marked0"><a name="line926" /> 926 duplicated_scheme = self.scheme.dup if self.scheme != nil
1548
+ </span><span class="marked1"><a name="line927" /> 927 duplicated_user = nil
1549
+ </span><span class="marked0"><a name="line928" /> 928 duplicated_user = self.user.dup if self.user != nil
1550
+ </span><span class="marked1"><a name="line929" /> 929 duplicated_password = nil
1551
+ </span><span class="marked0"><a name="line930" /> 930 duplicated_password = self.password.dup if self.password != nil
1552
+ </span><span class="marked1"><a name="line931" /> 931 duplicated_host = nil
1553
+ </span><span class="marked0"><a name="line932" /> 932 duplicated_host = self.host.dup if self.host != nil
1554
+ </span><span class="marked1"><a name="line933" /> 933 duplicated_port = self.port
1555
+ </span><span class="marked0"><a name="line934" /> 934 duplicated_path = nil
1556
+ </span><span class="marked1"><a name="line935" /> 935 duplicated_path = self.path.dup if self.path != nil
1557
+ </span><span class="marked0"><a name="line936" /> 936 duplicated_query = nil
1558
+ </span><span class="marked1"><a name="line937" /> 937 duplicated_query = self.query.dup if self.query != nil
1559
+ </span><span class="marked0"><a name="line938" /> 938 duplicated_fragment = nil
1560
+ </span><span class="marked1"><a name="line939" /> 939 duplicated_fragment = self.fragment.dup if self.fragment != nil
1561
+ </span><span class="marked0"><a name="line940" /> 940 duplicated_uri = Addressable::URI.new(
1562
+ </span><span class="inferred1"><a name="line941" /> 941 duplicated_scheme,
1563
+ </span><span class="inferred0"><a name="line942" /> 942 duplicated_user,
1564
+ </span><span class="inferred1"><a name="line943" /> 943 duplicated_password,
1565
+ </span><span class="inferred0"><a name="line944" /> 944 duplicated_host,
1566
+ </span><span class="inferred1"><a name="line945" /> 945 duplicated_port,
1567
+ </span><span class="inferred0"><a name="line946" /> 946 duplicated_path,
1568
+ </span><span class="inferred1"><a name="line947" /> 947 duplicated_query,
1569
+ </span><span class="inferred0"><a name="line948" /> 948 duplicated_fragment
1570
+ </span><span class="inferred1"><a name="line949" /> 949 )
1571
+ </span><span class="marked0"><a name="line950" /> 950 @specified_port = nil if !defined?(@specified_port)
1572
+ </span><span class="marked1"><a name="line951" /> 951 duplicated_uri.instance_variable_set(&quot;@specified_port&quot;, @specified_port)
1573
+ </span><span class="marked0"><a name="line952" /> 952 return duplicated_uri
1574
+ </span><span class="inferred1"><a name="line953" /> 953 end
1575
+ </span><span class="inferred0"><a name="line954" /> 954
1576
+ </span><span class="inferred1"><a name="line955" /> 955 # Returns the assembled URI as a string.
1577
+ </span><span class="marked0"><a name="line956" /> 956 def to_s
1578
+ </span><span class="marked1"><a name="line957" /> 957 uri_string = &quot;&quot;
1579
+ </span><span class="marked0"><a name="line958" /> 958 uri_string &lt;&lt; &quot;#{self.scheme}:&quot; if self.scheme != nil
1580
+ </span><span class="marked1"><a name="line959" /> 959 uri_string &lt;&lt; &quot;//#{self.authority}&quot; if self.authority != nil
1581
+ </span><span class="marked0"><a name="line960" /> 960 uri_string &lt;&lt; self.path.to_s
1582
+ </span><span class="marked1"><a name="line961" /> 961 uri_string &lt;&lt; &quot;?#{self.query}&quot; if self.query != nil
1583
+ </span><span class="marked0"><a name="line962" /> 962 uri_string &lt;&lt; &quot;##{self.fragment}&quot; if self.fragment != nil
1584
+ </span><span class="marked1"><a name="line963" /> 963 return uri_string
1585
+ </span><span class="inferred0"><a name="line964" /> 964 end
1586
+ </span><span class="inferred1"><a name="line965" /> 965
1587
+ </span><span class="inferred0"><a name="line966" /> 966 # Returns a Hash of the URI segments.
1588
+ </span><span class="marked1"><a name="line967" /> 967 def to_h
1589
+ </span><span class="inferred0"><a name="line968" /> 968 return {
1590
+ </span><span class="marked1"><a name="line969" /> 969 :scheme =&gt; self.scheme,
1591
+ </span><span class="marked0"><a name="line970" /> 970 :user =&gt; self.user,
1592
+ </span><span class="marked1"><a name="line971" /> 971 :password =&gt; self.password,
1593
+ </span><span class="marked0"><a name="line972" /> 972 :host =&gt; self.host,
1594
+ </span><span class="marked1"><a name="line973" /> 973 :port =&gt; self.specified_port,
1595
+ </span><span class="marked0"><a name="line974" /> 974 :path =&gt; self.path,
1596
+ </span><span class="marked1"><a name="line975" /> 975 :query =&gt; self.query,
1597
+ </span><span class="marked0"><a name="line976" /> 976 :fragment =&gt; self.fragment
1598
+ </span><span class="marked1"><a name="line977" /> 977 }
1599
+ </span><span class="marked0"><a name="line978" /> 978 end
1600
+ </span><span class="inferred1"><a name="line979" /> 979
1601
+ </span><span class="inferred0"><a name="line980" /> 980 # Returns a string representation of the URI object's state.
1602
+ </span><span class="marked1"><a name="line981" /> 981 def inspect
1603
+ </span><span class="marked0"><a name="line982" /> 982 sprintf(&quot;#&lt;%s:%#0x URI:%s&gt;&quot;, self.class.to_s, self.object_id, self.to_s)
1604
+ </span><span class="marked1"><a name="line983" /> 983 end
1605
+ </span><span class="inferred0"><a name="line984" /> 984
1606
+ </span><span class="inferred1"><a name="line985" /> 985 # This module handles internationalized domain names. When Ruby has an
1607
+ </span><span class="inferred0"><a name="line986" /> 986 # implementation of nameprep, stringprep, punycode, etc, this
1608
+ </span><span class="inferred1"><a name="line987" /> 987 # module should contain an actual implementation of IDNA instead of
1609
+ </span><span class="inferred0"><a name="line988" /> 988 # returning nil if libidn can't be used.
1610
+ </span><span class="marked1"><a name="line989" /> 989 module IDNA
1611
+ </span><span class="inferred0"><a name="line990" /> 990 # Returns the ascii representation of the label.
1612
+ </span><span class="marked1"><a name="line991" /> 991 def self.to_ascii(label)
1613
+ </span><span class="marked0"><a name="line992" /> 992 return nil if label.nil?
1614
+ </span><span class="marked1"><a name="line993" /> 993 if self.use_libidn?
1615
+ </span><span class="marked0"><a name="line994" /> 994 return IDN::Idna.toASCII(label)
1616
+ </span><span class="inferred1"><a name="line995" /> 995 else
1617
+ </span><span class="marked0"><a name="line996" /> 996 raise NotImplementedError,
1618
+ </span><span class="inferred1"><a name="line997" /> 997 &quot;There is no available pure-ruby implementation. &quot; +
1619
+ </span><span class="inferred0"><a name="line998" /> 998 &quot;Install libidn bindings.&quot;
1620
+ </span><span class="inferred1"><a name="line999" /> 999 end
1621
+ </span><span class="inferred0"><a name="line1000" />1000 end
1622
+ </span><span class="inferred1"><a name="line1001" />1001
1623
+ </span><span class="inferred0"><a name="line1002" />1002 # Returns the unicode representation of the label.
1624
+ </span><span class="marked1"><a name="line1003" />1003 def self.to_unicode(label)
1625
+ </span><span class="marked0"><a name="line1004" />1004 return nil if label.nil?
1626
+ </span><span class="marked1"><a name="line1005" />1005 if self.use_libidn?
1627
+ </span><span class="marked0"><a name="line1006" />1006 return IDN::Idna.toUnicode(label)
1628
+ </span><span class="inferred1"><a name="line1007" />1007 else
1629
+ </span><span class="marked0"><a name="line1008" />1008 raise NotImplementedError,
1630
+ </span><span class="inferred1"><a name="line1009" />1009 &quot;There is no available pure-ruby implementation. &quot; +
1631
+ </span><span class="inferred0"><a name="line1010" />1010 &quot;Install libidn bindings.&quot;
1632
+ </span><span class="inferred1"><a name="line1011" />1011 end
1633
+ </span><span class="inferred0"><a name="line1012" />1012 end
1634
+ </span><span class="inferred1"><a name="line1013" />1013
1635
+ </span><span class="marked0"><a name="line1014" />1014 private
1636
+ </span><span class="inferred1"><a name="line1015" />1015 # Determines if the libidn bindings are available and able to be used.
1637
+ </span><span class="marked0"><a name="line1016" />1016 def self.use_libidn?
1638
+ </span><span class="marked1"><a name="line1017" />1017 if !defined?(@use_libidn) || @use_libidn.nil?
1639
+ </span><span class="marked0"><a name="line1018" />1018 begin
1640
+ </span><span class="marked1"><a name="line1019" />1019 require 'rubygems'
1641
+ </span><span class="inferred0"><a name="line1020" />1020 rescue LoadError
1642
+ </span><span class="marked1"><a name="line1021" />1021 nil
1643
+ </span><span class="inferred0"><a name="line1022" />1022 end
1644
+ </span><span class="marked1"><a name="line1023" />1023 begin
1645
+ </span><span class="marked0"><a name="line1024" />1024 require 'idn'
1646
+ </span><span class="inferred1"><a name="line1025" />1025 rescue LoadError
1647
+ </span><span class="marked0"><a name="line1026" />1026 nil
1648
+ </span><span class="inferred1"><a name="line1027" />1027 end
1649
+ </span><span class="marked0"><a name="line1028" />1028 @use_libidn = !!(defined?(IDN::Idna))
1650
+ </span><span class="inferred1"><a name="line1029" />1029 end
1651
+ </span><span class="marked0"><a name="line1030" />1030 return @use_libidn
1652
+ </span><span class="inferred1"><a name="line1031" />1031 end
1653
+ </span><span class="inferred0"><a name="line1032" />1032 end
1654
+ </span><span class="inferred1"><a name="line1033" />1033
1655
+ </span><span class="marked0"><a name="line1034" />1034 private
1656
+ </span><span class="inferred1"><a name="line1035" />1035 # Resolves paths to their simplest form.
1657
+ </span><span class="marked0"><a name="line1036" />1036 def self.normalize_path(path)
1658
+ </span><span class="marked1"><a name="line1037" />1037 return nil if path.nil?
1659
+ </span><span class="marked0"><a name="line1038" />1038 normalized_path = path.dup
1660
+ </span><span class="marked1"><a name="line1039" />1039 previous_state = normalized_path.dup
1661
+ </span><span class="inferred0"><a name="line1040" />1040 begin
1662
+ </span><span class="marked1"><a name="line1041" />1041 previous_state = normalized_path.dup
1663
+ </span><span class="marked0"><a name="line1042" />1042 normalized_path.gsub!(/\/\.\//, &quot;/&quot;)
1664
+ </span><span class="marked1"><a name="line1043" />1043 normalized_path.gsub!(/\/\.$/, &quot;/&quot;)
1665
+ </span><span class="marked0"><a name="line1044" />1044 parent = normalized_path.scan(/\/([^\/]+)\/\.\.\//).flatten[0]
1666
+ </span><span class="marked1"><a name="line1045" />1045 if parent != &quot;.&quot; &amp;&amp; parent != &quot;..&quot;
1667
+ </span><span class="marked0"><a name="line1046" />1046 normalized_path.gsub!(/\/#{parent}\/\.\.\//, &quot;/&quot;)
1668
+ </span><span class="inferred1"><a name="line1047" />1047 end
1669
+ </span><span class="marked0"><a name="line1048" />1048 parent = normalized_path.scan(/\/([^\/]+)\/\.\.$/).flatten[0]
1670
+ </span><span class="marked1"><a name="line1049" />1049 if parent != &quot;.&quot; &amp;&amp; parent != &quot;..&quot;
1671
+ </span><span class="marked0"><a name="line1050" />1050 normalized_path.gsub!(/\/#{parent}\/\.\.$/, &quot;/&quot;)
1672
+ </span><span class="inferred1"><a name="line1051" />1051 end
1673
+ </span><span class="marked0"><a name="line1052" />1052 normalized_path.gsub!(/^\.\.?\/?/, &quot;&quot;)
1674
+ </span><span class="marked1"><a name="line1053" />1053 normalized_path.gsub!(/^\/\.\.?\//, &quot;/&quot;)
1675
+ </span><span class="marked0"><a name="line1054" />1054 end until previous_state == normalized_path
1676
+ </span><span class="marked1"><a name="line1055" />1055 return normalized_path
1677
+ </span><span class="inferred0"><a name="line1056" />1056 end
1678
+ </span><span class="inferred1"><a name="line1057" />1057
1679
+ </span><span class="inferred0"><a name="line1058" />1058 # Ensures that the URI is valid.
1680
+ </span><span class="marked1"><a name="line1059" />1059 def validate
1681
+ </span><span class="marked0"><a name="line1060" />1060 if self.scheme == nil &amp;&amp; self.user == nil &amp;&amp; self.password == nil &amp;&amp;
1682
+ </span><span class="marked1"><a name="line1061" />1061 self.host == nil &amp;&amp; self.port == nil &amp;&amp; self.path == nil &amp;&amp;
1683
+ </span><span class="marked0"><a name="line1062" />1062 self.query == nil &amp;&amp; self.fragment == nil
1684
+ </span><span class="marked1"><a name="line1063" />1063 raise InvalidURIError, &quot;All segments were nil.&quot;
1685
+ </span><span class="inferred0"><a name="line1064" />1064 end
1686
+ </span><span class="marked1"><a name="line1065" />1065 if self.scheme != nil &amp;&amp;
1687
+ </span><span class="marked0"><a name="line1066" />1066 (self.host == nil || self.host == &quot;&quot;) &amp;&amp;
1688
+ </span><span class="marked1"><a name="line1067" />1067 (self.path == nil || self.path == &quot;&quot;)
1689
+ </span><span class="marked0"><a name="line1068" />1068 raise InvalidURIError,
1690
+ </span><span class="inferred1"><a name="line1069" />1069 &quot;Absolute URI missing hierarchical segment.&quot;
1691
+ </span><span class="inferred0"><a name="line1070" />1070 end
1692
+ </span><span class="inferred1"><a name="line1071" />1071 end
1693
+ </span><span class="inferred0"><a name="line1072" />1072
1694
+ </span><span class="inferred1"><a name="line1073" />1073 # Replaces the internal state of self with the specified URI's state.
1695
+ </span><span class="inferred0"><a name="line1074" />1074 # Used in destructive operations to avoid massive code repetition.
1696
+ </span><span class="marked1"><a name="line1075" />1075 def replace_self(uri)
1697
+ </span><span class="inferred0"><a name="line1076" />1076 # Reset dependant values
1698
+ </span><span class="marked1"><a name="line1077" />1077 @userinfo = nil
1699
+ </span><span class="marked0"><a name="line1078" />1078 @authority = nil
1700
+ </span><span class="inferred1"><a name="line1079" />1079
1701
+ </span><span class="marked0"><a name="line1080" />1080 @scheme = uri.scheme
1702
+ </span><span class="marked1"><a name="line1081" />1081 @user = uri.user
1703
+ </span><span class="marked0"><a name="line1082" />1082 @password = uri.password
1704
+ </span><span class="marked1"><a name="line1083" />1083 @host = uri.host
1705
+ </span><span class="marked0"><a name="line1084" />1084 @specified_port = uri.instance_variable_get(&quot;@specified_port&quot;)
1706
+ </span><span class="marked1"><a name="line1085" />1085 @port = @specified_port.to_s.to_i
1707
+ </span><span class="marked0"><a name="line1086" />1086 @path = uri.path
1708
+ </span><span class="marked1"><a name="line1087" />1087 @query = uri.query
1709
+ </span><span class="marked0"><a name="line1088" />1088 @fragment = uri.fragment
1710
+ </span><span class="marked1"><a name="line1089" />1089 return self
1711
+ </span><span class="inferred0"><a name="line1090" />1090 end
1712
+ </span><span class="inferred1"><a name="line1091" />1091 end
1713
+ </span><span class="inferred0"><a name="line1092" />1092 end
1714
+ </span></pre><hr /> <p>Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'>rcov code coverage analysis tool for Ruby</a> version 0.8.0.</p><p>
1715
+ <a href='http://validator.w3.org/check/referer'>
1716
+ <img src='http://www.w3.org/Icons/valid-xhtml10' height='31' alt='Valid XHTML 1.0!' width='88' />
1717
+ </a>
1718
+ <a href='http://jigsaw.w3.org/css-validator/check/referer'>
1719
+ <img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px' />
1720
+ </a>
1721
+ </p>
1722
+ </body>
1723
+ </html>