source: trunk/www.guidonia.net/wp/wp-content/plugins/feedwordpress/relative_uri.class.php@ 44

Last change on this file since 44 was 44, checked in by luciano, 14 years ago
File size: 6.1 KB
Line 
1<?php
2# Relative URI static class: PHP class for resolving relative URLs
3#
4# This class is derived (under the terms of the GPL) from URL Class 0.3 by
5# Keyvan Minoukadeh <keyvan@k1m.com>, which is great but more than we need
6# for FeedWordPress's purposes. The class has been stripped down to a single
7# public method: Relative_URI::resolve($url, $base), which resolves the URI in
8# $url relative to the URI in $base
9
10class Relative_URI
11{
12 // Resolve relative URI in $url against the base URI in $base. If $base
13 // is not supplied, then we use the REQUEST_URI of this script.
14 //
15 // I'm hoping this method reflects RFC 2396 Section 5.2
16 function resolve ($url, $base = NULL)
17 {
18 if (is_null($base)):
19 $base = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
20 endif;
21
22 $base = Relative_URI::_encode(trim($base));
23 $uri_parts = Relative_URI::_parse_url($base);
24
25 $url = Relative_URI::_encode(trim($url));
26 $parts = Relative_URI::_parse_url($url);
27
28 $uri_parts['fragment'] = (isset($parts['fragment']) ? $parts['fragment'] : null);
29 $uri_parts['query'] = (isset($parts['query']) ? $parts['query'] : null);
30
31 // if path is empty, and scheme, host, and query are undefined,
32 // the URL is referring the base URL
33
34 if (($parts['path'] == '') && !isset($parts['scheme']) && !isset($parts['host']) && !isset($parts['query'])) {
35 // If the URI is empty or only a fragment, return the base URI
36 return $base . (isset($parts['fragment']) ? '#'.$parts['fragment'] : '');
37 } elseif (isset($parts['scheme'])) {
38 // If the scheme is set, then the URI is absolute.
39 return $url;
40 } elseif (isset($parts['host'])) {
41 $uri_parts['host'] = $parts['host'];
42 $uri_parts['path'] = $parts['path'];
43 } else {
44 // We have a relative path but not a host.
45
46 // start ugly fix:
47 // prepend slash to path if base host is set, base path is not set, and url path is not absolute
48 if ($uri_parts['host'] && ($uri_parts['path'] == '')
49 && (strlen($parts['path']) > 0)
50 && (substr($parts['path'], 0, 1) != '/')) {
51 $parts['path'] = '/'.$parts['path'];
52 } // end ugly fix
53
54 if (substr($parts['path'], 0, 1) == '/') {
55 $uri_parts['path'] = $parts['path'];
56 } else {
57 // copy base path excluding any characters after the last (right-most) slash character
58 $buffer = substr($uri_parts['path'], 0, (int)strrpos($uri_parts['path'], '/')+1);
59 // append relative path
60 $buffer .= $parts['path'];
61 // remove "./" where "." is a complete path segment.
62 $buffer = str_replace('/./', '/', $buffer);
63 if (substr($buffer, 0, 2) == './') {
64 $buffer = substr($buffer, 2);
65 }
66 // if buffer ends with "." as a complete path segment, remove it
67 if (substr($buffer, -2) == '/.') {
68 $buffer = substr($buffer, 0, -1);
69 }
70 // remove "<segment>/../" where <segment> is a complete path segment not equal to ".."
71 $search_finished = false;
72 $segment = explode('/', $buffer);
73 while (!$search_finished) {
74 for ($x=0; $x+1 < count($segment);) {
75 if (($segment[$x] != '') && ($segment[$x] != '..') && ($segment[$x+1] == '..')) {
76 if ($x+2 == count($segment)) $segment[] = '';
77 unset($segment[$x], $segment[$x+1]);
78 $segment = array_values($segment);
79 continue 2;
80 } else {
81 $x++;
82 }
83 }
84 $search_finished = true;
85 }
86 $buffer = (count($segment) == 1) ? '/' : implode('/', $segment);
87 $uri_parts['path'] = $buffer;
88
89 }
90 }
91
92 // If we've gotten to this point, we can try to put the pieces
93 // back together.
94 $ret = '';
95 if (isset($uri_parts['scheme'])) $ret .= $uri_parts['scheme'].':';
96 if (isset($uri_parts['user'])) {
97 $ret .= $uri_parts['user'];
98 if (isset($uri_parts['pass'])) $ret .= ':'.$uri_parts['parts'];
99 $ret .= '@';
100 }
101 if (isset($uri_parts['host'])) {
102 $ret .= '//'.$uri_parts['host'];
103 if (isset($uri_parts['port'])) $ret .= ':'.$uri_parts['port'];
104 }
105 $ret .= $uri_parts['path'];
106 if (isset($uri_parts['query'])) $ret .= '?'.$uri_parts['query'];
107 if (isset($uri_parts['fragment'])) $ret .= '#'.$uri_parts['fragment'];
108
109 return $ret;
110 }
111
112 /**
113 * Parse URL
114 *
115 * Regular expression grabbed from RFC 2396 Appendix B.
116 * This is a replacement for PHPs builtin parse_url().
117 * @param string $url
118 * @access private
119 * @return array
120 */
121 function _parse_url($url)
122 {
123 // I'm using this pattern instead of parse_url() as there's a few strings where parse_url()
124 // generates a warning.
125 if (preg_match('!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!', $url, $match)) {
126 $parts = array();
127 if ($match[1] != '') $parts['scheme'] = $match[2];
128 if ($match[3] != '') $parts['auth'] = $match[4];
129 // parse auth
130 if (isset($parts['auth'])) {
131 // store user info
132 if (($at_pos = strpos($parts['auth'], '@')) !== false) {
133 $userinfo = explode(':', substr($parts['auth'], 0, $at_pos), 2);
134 $parts['user'] = $userinfo[0];
135 if (isset($userinfo[1])) $parts['pass'] = $userinfo[1];
136 $parts['auth'] = substr($parts['auth'], $at_pos+1);
137 }
138 // get port number
139 if ($port_pos = strrpos($parts['auth'], ':')) {
140 $parts['host'] = substr($parts['auth'], 0, $port_pos);
141 $parts['port'] = (int)substr($parts['auth'], $port_pos+1);
142 if ($parts['port'] < 1) $parts['port'] = null;
143 } else {
144 $parts['host'] = $parts['auth'];
145 }
146 }
147 unset($parts['auth']);
148 $parts['path'] = $match[5];
149 if (isset($match[6]) && ($match[6] != '')) $parts['query'] = $match[7];
150 if (isset($match[8]) && ($match[8] != '')) $parts['fragment'] = $match[9];
151 return $parts;
152 }
153 // shouldn't reach here
154 return array('path'=>'');
155 }
156
157 function _encode($string)
158 {
159 static $replace = array();
160 if (!count($replace)) {
161 $find = array(32, 34, 60, 62, 123, 124, 125, 91, 92, 93, 94, 96, 127);
162 $find = array_merge(range(0, 31), $find);
163 $find = array_map('chr', $find);
164 foreach ($find as $char) {
165 $replace[$char] = '%'.bin2hex($char);
166 }
167 }
168 // escape control characters and a few other characters
169 $encoded = strtr($string, $replace);
170 // remove any character outside the hex range: 21 - 7E (see www.asciitable.com)
171 return preg_replace('/[^\x21-\x7e]/', '', $encoded);
172 }
173} // class Relative_URI
174
Note: See TracBrowser for help on using the repository browser.