router.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: router_8php-source.html 675 2008-12-26 00:27:14Z gwoo $ */
00003 /**
00004  * Parses the request URL into controller, action, and parameters.
00005  *
00006  * PHP versions 4 and 5
00007  *
00008  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00009  * Copyright 2005-2008, Cake Software Foundation, Inc.
00010  *                              1785 E. Sahara Avenue, Suite 490-204
00011  *                              Las Vegas, Nevada 89104
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00018  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package         cake
00020  * @subpackage      cake.cake.libs
00021  * @since           CakePHP(tm) v 0.2.9
00022  * @version         $Revision: 675 $
00023  * @modifiedby      $LastChangedBy: gwoo $
00024  * @lastmodified    $Date: 2008-12-25 16:27:14 -0800 (Thu, 25 Dec 2008) $
00025  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 /**
00028  * Included libraries.
00029  *
00030  */
00031     if (!class_exists('Object')) {
00032          uses ('object');
00033     }
00034 /**
00035  * Parses the request URL into controller, action, and parameters.
00036  *
00037  * @package     cake
00038  * @subpackage  cake.cake.libs
00039  */
00040 class Router extends Object {
00041 /**
00042  * Array of routes
00043  *
00044  * @var array
00045  * @access public
00046  */
00047      var $routes = array();
00048 /**
00049  * CAKE_ADMIN route
00050  *
00051  * @var array
00052  * @access private
00053  */
00054      var $__admin = null;
00055 /**
00056  * Constructor
00057  *
00058  * @access public
00059  */
00060     function __construct() {
00061         if (defined('CAKE_ADMIN')) {
00062             $admin = CAKE_ADMIN;
00063             if (!empty($admin)) {
00064                 $this->__admin = array('/:' . $admin . '/:controller/:action/* (default)',
00065                                         '/^(?:\/(?:(' . $admin . ')(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?)?))[\/]*$/',
00066                                         array($admin, 'controller', 'action'), array());
00067             }
00068         }
00069     }
00070 /**
00071  * Returns this object's routes array. Returns false if there are no routes available.
00072  *
00073  * @param string $route An empty string, or a route string "/"
00074  * @param array $default NULL or an array describing the default route
00075  * @return array Array of routes
00076  */
00077     function connect($route, $default = null) {
00078         $parsed = $names = array();
00079 
00080         if (defined('CAKE_ADMIN') && $default == null) {
00081             if ($route == CAKE_ADMIN) {
00082                 $this->routes[] = $this->__admin;
00083                 $this->__admin = null;
00084             }
00085         }
00086         $r = null;
00087         if (($route == '') || ($route == '/')) {
00088             $regexp='/^[\/]*$/';
00089             $this->routes[] = array($route, $regexp, array(), $default);
00090         } else {
00091             $elements = array();
00092 
00093             foreach (explode('/', $route)as $element) {
00094                 if (trim($element))
00095                 $elements[] = $element;
00096             }
00097 
00098             if (!count($elements)) {
00099                 return false;
00100             }
00101 
00102             foreach ($elements as $element) {
00103 
00104                 if (preg_match('/^:(.+)$/', $element, $r)) {
00105                     $parsed[]='(?:\/([^\/]+))?';
00106                     $names[] =$r[1];
00107                 } elseif (preg_match('/^\*$/', $element, $r)) {
00108                     $parsed[] = '(?:\/(.*))?';
00109                 } else {
00110                     $parsed[] = '/' . $element;
00111                 }
00112             }
00113 
00114             $regexp='#^' . join('', $parsed) . '[\/]*$#';
00115             $this->routes[] = array($route, $regexp, $names, $default);
00116         }
00117         return $this->routes;
00118     }
00119 /**
00120  * Parses given URL and returns an array of controllers, action and parameters
00121  * taken from that URL.
00122  *
00123  * @param string $url URL to be parsed
00124  * @return array
00125  * @access public
00126  */
00127     function parse($url) {
00128         if (ini_get('magic_quotes_gpc') == 1) {
00129             $url = stripslashes_deep($url);
00130         }
00131 
00132         if ($url && ('/' != $url[0])) {
00133             if (!defined('SERVER_IIS')) {
00134                 $url = '/' . $url;
00135             }
00136         }
00137         $out = array('pass'=>array());
00138         $r = null;
00139         $default_route = array('/:controller/:action/* (default)',
00140                                 '/^(?:\/(?:([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?))[\\/]*$/',
00141                                 array('controller', 'action'), array());
00142 
00143         if (defined('CAKE_ADMIN') && $this->__admin != null) {
00144             $this->routes[]=$this->__admin;
00145             $this->__admin =null;
00146         }
00147         $this->connect('/bare/:controller/:action/*', array('bare' => '1'));
00148         $this->connect('/ajax/:controller/:action/*', array('bare' => '1'));
00149 
00150         if (defined('WEBSERVICES') && WEBSERVICES == 'on') {
00151             $this->connect('/rest/:controller/:action/*', array('webservices' => 'Rest'));
00152             $this->connect('/rss/:controller/:action/*', array('webservices' => 'Rss'));
00153             $this->connect('/soap/:controller/:action/*', array('webservices' => 'Soap'));
00154             $this->connect('/xml/:controller/:action/*', array('webservices' => 'Xml'));
00155             $this->connect('/xmlrpc/:controller/:action/*', array('webservices' => 'XmlRpc'));
00156         }
00157         $this->routes[] = $default_route;
00158 
00159         if (strpos($url, '?') !== false) {
00160             $url = substr($url, 0, strpos($url, '?'));
00161         }
00162 
00163         foreach ($this->routes as $route) {
00164             list($route, $regexp, $names, $defaults) = $route;
00165 
00166             if (preg_match($regexp, $url, $r)) {
00167                 // remove the first element, which is the url
00168                 array_shift ($r);
00169                 // hack, pre-fill the default route names
00170                 foreach ($names as $name) {
00171                     $out[$name] = null;
00172                 }
00173                 $ii=0;
00174 
00175                 if (is_array($defaults)) {
00176                     foreach ($defaults as $name => $value) {
00177                         if (preg_match('#[a-zA-Z_\-]#i', $name)) {
00178                             $out[$name] =  $this->stripEscape($value);
00179                         } else {
00180                             $out['pass'][] =  $this->stripEscape($value);
00181                         }
00182                     }
00183                 }
00184 
00185                 foreach ($r as $found) {
00186                     // if $found is a named url element (i.e. ':action')
00187                     if (isset($names[$ii])) {
00188                         $out[$names[$ii]] = $found;
00189                     } else {
00190                         // unnamed elements go in as 'pass'
00191                         $found = explode('/', $found);
00192                         $pass = array();
00193                         foreach ($found as $key => $value) {
00194                             if ($value == "0") {
00195                                 $pass[$key] =  $this->stripEscape($value);
00196                             } elseif ($value) {
00197                                 $pass[$key] =  $this->stripEscape($value);
00198                             }
00199                         }
00200                         $out['pass'] = am($out['pass'], $pass);
00201                     }
00202                     $ii++;
00203                 }
00204                 break;
00205             }
00206         }
00207         return $out;
00208     }
00209     function stripEscape($param) {
00210         if (!is_array($param) || empty($param)) {
00211             if (is_bool($param)) {
00212                 return $param;
00213             }
00214 
00215             $return = preg_replace('/^[\\t ]*(?:-!)+/', '', $param);
00216             return $return;
00217         }
00218         foreach ($param as $key => $value) {
00219             if (is_string($value)) {
00220                 $return[$key] = preg_replace('/^[\\t ]*(?:-!)+/', '', $value);
00221             } else {
00222                 foreach ($value as $array => $string) {
00223                     $return[$key][$array] = $this->stripEscape($string);
00224                 }
00225             }
00226         }
00227         return $return;
00228     }
00229 }
00230 ?>