addressable 1.0.0 → 1.0.1

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