OSDN Git Service

NP_Moblog v1.17
[nucleus-jp/nucleus-plugins.git] / trunk / NP_Moblog / sharedlibs / Net / URL.php
1 <?php\r
2 // +-----------------------------------------------------------------------+\r
3 // | Copyright (c) 2002-2004, Richard Heyes                                |\r
4 // | All rights reserved.                                                  |\r
5 // |                                                                       |\r
6 // | Redistribution and use in source and binary forms, with or without    |\r
7 // | modification, are permitted provided that the following conditions    |\r
8 // | are met:                                                              |\r
9 // |                                                                       |\r
10 // | o Redistributions of source code must retain the above copyright      |\r
11 // |   notice, this list of conditions and the following disclaimer.       |\r
12 // | o Redistributions in binary form must reproduce the above copyright   |\r
13 // |   notice, this list of conditions and the following disclaimer in the |\r
14 // |   documentation and/or other materials provided with the distribution.|\r
15 // | o The names of the authors may not be used to endorse or promote      |\r
16 // |   products derived from this software without specific prior written  |\r
17 // |   permission.                                                         |\r
18 // |                                                                       |\r
19 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |\r
20 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |\r
21 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |\r
22 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |\r
23 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |\r
24 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |\r
25 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |\r
26 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |\r
27 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |\r
28 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |\r
29 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |\r
30 // |                                                                       |\r
31 // +-----------------------------------------------------------------------+\r
32 // | Author: Richard Heyes <richard at php net>                            |\r
33 // +-----------------------------------------------------------------------+\r
34 //\r
35 // $Id: URL.php,v 1.1 2006/11/27 17:14:39 hsur Exp $\r
36 //\r
37 // Net_URL Class\r
38 \r
39 class Net_URL\r
40 {\r
41     /**\r
42     * Full url\r
43     * @var string\r
44     */\r
45     var $url;\r
46 \r
47     /**\r
48     * Protocol\r
49     * @var string\r
50     */\r
51     var $protocol;\r
52 \r
53     /**\r
54     * Username\r
55     * @var string\r
56     */\r
57     var $username;\r
58 \r
59     /**\r
60     * Password\r
61     * @var string\r
62     */\r
63     var $password;\r
64 \r
65     /**\r
66     * Host\r
67     * @var string\r
68     */\r
69     var $host;\r
70 \r
71     /**\r
72     * Port\r
73     * @var integer\r
74     */\r
75     var $port;\r
76 \r
77     /**\r
78     * Path\r
79     * @var string\r
80     */\r
81     var $path;\r
82 \r
83     /**\r
84     * Query string\r
85     * @var array\r
86     */\r
87     var $querystring;\r
88 \r
89     /**\r
90     * Anchor\r
91     * @var string\r
92     */\r
93     var $anchor;\r
94 \r
95     /**\r
96     * Whether to use []\r
97     * @var bool\r
98     */\r
99     var $useBrackets;\r
100 \r
101     /**\r
102     * PHP4 Constructor\r
103     *\r
104     * @see __construct()\r
105     */\r
106     function Net_URL($url = null, $useBrackets = true)\r
107     {\r
108         $this->__construct($url, $useBrackets);\r
109     }\r
110 \r
111     /**\r
112     * PHP5 Constructor\r
113     *\r
114     * Parses the given url and stores the various parts\r
115     * Defaults are used in certain cases\r
116     *\r
117     * @param string $url         Optional URL\r
118     * @param bool   $useBrackets Whether to use square brackets when\r
119     *                            multiple querystrings with the same name\r
120     *                            exist\r
121     */\r
122     function __construct($url = null, $useBrackets = true)\r
123     {\r
124         $HTTP_SERVER_VARS  = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];\r
125 \r
126         $this->useBrackets = $useBrackets;\r
127         $this->url         = $url;\r
128         $this->user        = '';\r
129         $this->pass        = '';\r
130         $this->host        = '';\r
131         $this->port        = 80;\r
132         $this->path        = '';\r
133         $this->querystring = array();\r
134         $this->anchor      = '';\r
135 \r
136         // Only use defaults if not an absolute URL given\r
137         if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) {\r
138 \r
139             $this->protocol    = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http');\r
140 \r
141             /**\r
142             * Figure out host/port\r
143             */\r
144             if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {\r
145                 $host = $matches[1];\r
146                 if (!empty($matches[3])) {\r
147                     $port = $matches[3];\r
148                 } else {\r
149                     $port = $this->getStandardPort($this->protocol);\r
150                 }\r
151             }\r
152 \r
153             $this->user        = '';\r
154             $this->pass        = '';\r
155             $this->host        = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');\r
156             $this->port        = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));\r
157             $this->path        = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';\r
158             $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;\r
159             $this->anchor      = '';\r
160         }\r
161 \r
162         // Parse the url and store the various parts\r
163         if (!empty($url)) {\r
164             $urlinfo = parse_url($url);\r
165 \r
166             // Default querystring\r
167             $this->querystring = array();\r
168 \r
169             foreach ($urlinfo as $key => $value) {\r
170                 switch ($key) {\r
171                     case 'scheme':\r
172                         $this->protocol = $value;\r
173                         $this->port     = $this->getStandardPort($value);\r
174                         break;\r
175 \r
176                     case 'user':\r
177                     case 'pass':\r
178                     case 'host':\r
179                     case 'port':\r
180                         $this->$key = $value;\r
181                         break;\r
182 \r
183                     case 'path':\r
184                         if ($value{0} == '/') {\r
185                             $this->path = $value;\r
186                         } else {\r
187                             $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);\r
188                             $this->path = sprintf('%s/%s', $path, $value);\r
189                         }\r
190                         break;\r
191 \r
192                     case 'query':\r
193                         $this->querystring = $this->_parseRawQueryString($value);\r
194                         break;\r
195 \r
196                     case 'fragment':\r
197                         $this->anchor = $value;\r
198                         break;\r
199                 }\r
200             }\r
201         }\r
202     }\r
203 \r
204     /**\r
205     * Returns full url\r
206     *\r
207     * @return string Full url\r
208     * @access public\r
209     */\r
210     function getURL()\r
211     {\r
212         $querystring = $this->getQueryString();\r
213 \r
214         $this->url = $this->protocol . '://'\r
215                    . $this->user . (!empty($this->pass) ? ':' : '')\r
216                    . $this->pass . (!empty($this->user) ? '@' : '')\r
217                    . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)\r
218                    . $this->path\r
219                    . (!empty($querystring) ? '?' . $querystring : '')\r
220                    . (!empty($this->anchor) ? '#' . $this->anchor : '');\r
221 \r
222         return $this->url;\r
223     }\r
224 \r
225     /**\r
226     * Adds a querystring item\r
227     *\r
228     * @param  string $name       Name of item\r
229     * @param  string $value      Value of item\r
230     * @param  bool   $preencoded Whether value is urlencoded or not, default = not\r
231     * @access public\r
232     */\r
233     function addQueryString($name, $value, $preencoded = false)\r
234     {\r
235         if ($preencoded) {\r
236             $this->querystring[$name] = $value;\r
237         } else {\r
238             $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);\r
239         }\r
240     }\r
241 \r
242     /**\r
243     * Removes a querystring item\r
244     *\r
245     * @param  string $name Name of item\r
246     * @access public\r
247     */\r
248     function removeQueryString($name)\r
249     {\r
250         if (isset($this->querystring[$name])) {\r
251             unset($this->querystring[$name]);\r
252         }\r
253     }\r
254 \r
255     /**\r
256     * Sets the querystring to literally what you supply\r
257     *\r
258     * @param  string $querystring The querystring data. Should be of the format foo=bar&x=y etc\r
259     * @access public\r
260     */\r
261     function addRawQueryString($querystring)\r
262     {\r
263         $this->querystring = $this->_parseRawQueryString($querystring);\r
264     }\r
265 \r
266     /**\r
267     * Returns flat querystring\r
268     *\r
269     * @return string Querystring\r
270     * @access public\r
271     */\r
272     function getQueryString()\r
273     {\r
274         if (!empty($this->querystring)) {\r
275             foreach ($this->querystring as $name => $value) {\r
276                 if (is_array($value)) {\r
277                     foreach ($value as $k => $v) {\r
278                         $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);\r
279                     }\r
280                 } elseif (!is_null($value)) {\r
281                     $querystring[] = $name . '=' . $value;\r
282                 } else {\r
283                     $querystring[] = $name;\r
284                 }\r
285             }\r
286             $querystring = implode(ini_get('arg_separator.output'), $querystring);\r
287         } else {\r
288             $querystring = '';\r
289         }\r
290 \r
291         return $querystring;\r
292     }\r
293 \r
294     /**\r
295     * Parses raw querystring and returns an array of it\r
296     *\r
297     * @param  string  $querystring The querystring to parse\r
298     * @return array                An array of the querystring data\r
299     * @access private\r
300     */\r
301     function _parseRawQuerystring($querystring)\r
302     {\r
303         $parts  = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);\r
304         $return = array();\r
305 \r
306         foreach ($parts as $part) {\r
307             if (strpos($part, '=') !== false) {\r
308                 $value = substr($part, strpos($part, '=') + 1);\r
309                 $key   = substr($part, 0, strpos($part, '='));\r
310             } else {\r
311                 $value = null;\r
312                 $key   = $part;\r
313             }\r
314             if (substr($key, -2) == '[]') {\r
315                 $key = substr($key, 0, -2);\r
316                 if (@!is_array($return[$key])) {\r
317                     $return[$key]   = array();\r
318                     $return[$key][] = $value;\r
319                 } else {\r
320                     $return[$key][] = $value;\r
321                 }\r
322             } elseif (!$this->useBrackets AND !empty($return[$key])) {\r
323                 $return[$key]   = (array)$return[$key];\r
324                 $return[$key][] = $value;\r
325             } else {\r
326                 $return[$key] = $value;\r
327             }\r
328         }\r
329 \r
330         return $return;\r
331     }\r
332 \r
333     /**\r
334     * Resolves //, ../ and ./ from a path and returns\r
335     * the result. Eg:\r
336     *\r
337     * /foo/bar/../boo.php    => /foo/boo.php\r
338     * /foo/bar/../../boo.php => /boo.php\r
339     * /foo/bar/.././/boo.php => /foo/boo.php\r
340     *\r
341     * This method can also be called statically.\r
342     *\r
343     * @param  string $url URL path to resolve\r
344     * @return string      The result\r
345     */\r
346     function resolvePath($path)\r
347     {\r
348         $path = explode('/', str_replace('//', '/', $path));\r
349 \r
350         for ($i=0; $i<count($path); $i++) {\r
351             if ($path[$i] == '.') {\r
352                 unset($path[$i]);\r
353                 $path = array_values($path);\r
354                 $i--;\r
355 \r
356             } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {\r
357                 unset($path[$i]);\r
358                 unset($path[$i-1]);\r
359                 $path = array_values($path);\r
360                 $i -= 2;\r
361 \r
362             } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {\r
363                 unset($path[$i]);\r
364                 $path = array_values($path);\r
365                 $i--;\r
366 \r
367             } else {\r
368                 continue;\r
369             }\r
370         }\r
371 \r
372         return implode('/', $path);\r
373     }\r
374 \r
375     /**\r
376     * Returns the standard port number for a protocol\r
377     *\r
378     * @param  string  $scheme The protocol to lookup\r
379     * @return integer         Port number or NULL if no scheme matches\r
380     *\r
381     * @author Philippe Jausions <Philippe.Jausions@11abacus.com>\r
382     */\r
383     function getStandardPort($scheme)\r
384     {\r
385         switch (strtolower($scheme)) {\r
386             case 'http':    return 80;\r
387             case 'https':   return 443;\r
388             case 'ftp':     return 21;\r
389             case 'imap':    return 143;\r
390             case 'imaps':   return 993;\r
391             case 'pop3':    return 110;\r
392             case 'pop3s':   return 995;\r
393             default:        return null;\r
394        }\r
395     }\r
396 \r
397     /**\r
398     * Forces the URL to a particular protocol\r
399     *\r
400     * @param string  $protocol Protocol to force the URL to\r
401     * @param integer $port     Optional port (standard port is used by default)\r
402     */\r
403     function setProtocol($protocol, $port = null)\r
404     {\r
405         $this->protocol = $protocol;\r
406         $this->port = is_null($port) ? $this->getStandardPort() : $port;\r
407     }\r
408 \r
409 }\r
410 ?>\r