blob: abc253effd3c37d454e56a36dadc4a755242515c [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Router Class
20 *
21 * Parses URIs and determines routing
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @author Rick Ellis
26 * @category Libraries
27 * @link http://www.codeigniter.com/user_guide/general/routing.html
28 */
29class CI_Router {
30
31 var $config;
32 var $uri_string = '';
33 var $segments = array();
34 var $routes = array();
35 var $class = '';
36 var $method = 'index';
37 var $uri_protocol = 'auto';
38 var $default_controller;
39 var $scaffolding_request = FALSE; // Must be set to FALSE
40
41 /**
42 * Constructor
43 *
44 * Runs the route mapping function.
45 */
46 function CI_Router()
47 {
48 $this->config =& _load_class('CI_Config');
49 $this->_set_route_mapping();
50 log_message('debug', "Router Class Initialized");
51 }
52
53 // --------------------------------------------------------------------
54
55 /**
56 * Set the route mapping
57 *
58 * This function determies what should be served based on the URI request,
59 * as well as any "routes" that have been set in the routing config file.
60 *
61 * @access private
62 * @return void
63 */
64 function _set_route_mapping()
65 {
66 // Are query strings enabled? If so we're done...
67 if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
68 {
69 $this->set_class($_GET[$this->config->item('controller_trigger')]);
70
71 if (isset($_GET[$this->config->item('function_trigger')]))
72 {
73 $this->set_method($_GET[$this->config->item('function_trigger')]);
74 }
75
76 return;
77 }
78
79 // Load the routes.php file
80 include_once(APPPATH.'config/routes'.EXT);
81 $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
82 unset($route);
83
84 // Set the default controller
85 $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
86
87 // Fetch the URI string Depending on the server,
88 // the URI will be available in one of two globals
89 switch ($this->config->item('uri_protocol'))
90 {
91 case 'path_info' : $this->uri_string = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
92 break;
93 case 'query_string' : $this->uri_string = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
94 break;
95 default :
96 $path_info = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
97
98 if ($path_info != '' AND $path_info != "/".SELF)
99 {
100 $this->uri_string = $path_info;
101 }
102 else
103 {
104 $this->uri_string = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
105 }
106 break;
107 }
108
109 // Is there a URI string? If not, the default controller specified
110 // by the admin in the "routes" file will be shown.
111 if ($this->uri_string == '')
112 {
113 if ($this->default_controller === FALSE)
114 {
115 show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
116 }
117
118 $this->set_class($this->default_controller);
119 $this->set_method('index');
120
121 log_message('debug', "No URI present. Default controller set.");
122 return;
123 }
124
125 // Do we need to remove the suffix specified in the config file?
126 if ($this->config->item('url_suffix') != "")
127 {
128 $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
129 }
130
131 // Explode the URI Segments. The individual segments will
132 // be stored in the $this->segments array.
133 $this->_compile_segments(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)));
134
135
136 // Remap the class/method if a route exists
137 unset($this->routes['default_controller']);
138
139 if (count($this->routes) > 0)
140 {
141 $this->_parse_routes();
142 }
143 }
144 // END _set_route_mapping()
145
146 // --------------------------------------------------------------------
147
148 /**
149 * Compile Segments
150 *
151 * This function takes an array of URI segments as
152 * input, and puts it into the $this->segments array.
153 * It also sets the current class/method
154 *
155 * @access private
156 * @param array
157 * @param bool
158 * @return void
159 */
160 function _compile_segments($segs, $route = FALSE)
161 {
162 $segments = array();
163
164 $i = 1;
165 foreach($segs as $val)
166 {
167 $val = trim($this->_filter_uri($val));
168
169 if ($val != '')
170 $segments[$i++] = $val;
171 }
172
173 $this->set_class($segments['1']);
174
175 if (isset($segments['2']))
176 {
177 // A scaffolding request. No funny business with the URL
178 if ($this->routes['scaffolding_trigger'] == $segments['2'] AND $segments['2'] != '_ci_scaffolding')
179 {
180 $this->scaffolding_request = TRUE;
181 unset($this->routes['scaffolding_trigger']);
182 }
183 else
184 {
185 // A standard method request
186 $this->set_method($segments['2']);
187 }
188 }
189
190 if ($route == FALSE)
191 {
192 $this->segments = $segments;
193 }
194
195 unset($segments);
196 }
197 // END _compile_segments()
198
199 // --------------------------------------------------------------------
200
201 /**
202 * Filter segments for malicious characters
203 *
204 * @access private
205 * @param string
206 * @return string
207 */
208 function _filter_uri($str)
209 {
210 if ( ! preg_match("/^[a-z0-9~\s\%\.:_-]+$/i", $str))
211 {
212 exit('The URI you submitted has disallowed characters: '.$str);
213 }
214
215 return $str;
216 }
217 // END _filter_uri()
218
219 // --------------------------------------------------------------------
220
221 /**
222 * Set the class name
223 *
224 * @access public
225 * @param string
226 * @return void
227 */
228 function set_class($class)
229 {
230 $this->class = $class;
231 }
232 // END _filter_uri()
233
234 // --------------------------------------------------------------------
235
236 /**
237 * Fetch the current class
238 *
239 * @access public
240 * @return string
241 */
242 function fetch_class()
243 {
244 return $this->class;
245 }
246 // END _filter_uri()
247
248 // --------------------------------------------------------------------
249
250 /**
251 * Set the method name
252 *
253 * @access public
254 * @param string
255 * @return void
256 */
257 function set_method($method)
258 {
259 $this->method = $method;
260 }
261 // END set_method()
262
263 // --------------------------------------------------------------------
264
265 /**
266 * Fetch the current method
267 *
268 * @access public
269 * @return string
270 */
271 function fetch_method()
272 {
273 return $this->method;
274 }
275 // END set_method()
276
277 // --------------------------------------------------------------------
278
279 /**
280 * Parse Routes
281 *
282 * This function matches any routes that may exist in
283 * the config/routes.php file against the URI to
284 * determine if the class/method need to be remapped.
285 *
286 * @access private
287 * @return void
288 */
289 function _parse_routes()
290 {
291 // Turn the segment array into a URI string
292 $uri = implode('/', $this->segments);
293 $num = count($this->segments);
294
295 // Is there a literal match? If so we're done
296 if (isset($this->routes[$uri]))
297 {
298 $this->_compile_segments(explode('/', $this->routes[$uri]), TRUE);
299 return;
300 }
301
302 // Loop through the route array looking for wildcards
303 foreach ($this->routes as $key => $val)
304 {
305 if (count(explode('/', $key)) != $num)
306 continue;
307
308 if (preg_match("|".str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key))."$|", $uri))
309 {
310 $this->_compile_segments(explode('/', $val), TRUE);
311 break;
312 }
313 }
314 }
315 // END set_method()
316}
317// END Router Class
318?>