Fixes #149
[akelos.git] / lib / AkRouter.php
blobc83e71f4da4c9d9a648cfb30915f1b8451a6b4dd
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
11 ak_compat('http_build_query');
13 /**
14 * Native PHP URL rewriting for the Akelos Framework.
16 * @package ActionController
17 * @subpackage Request
18 * @author Bermi Ferrer <bermi a.t akelos c.om>
19 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
20 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
24 if(!defined('OPTIONAL')){
25 define('OPTIONAL', false);
28 if(!defined('COMPULSORY')){
29 define('COMPULSORY', true);
32 if(!defined('COMPULSORY_REGEX')){
33 define('COMPULSORY_REGEX', '([^\/]+){1}');
39 /**
40 * Native PHP URL rewriting for the Akelos Framework
42 * This class implements PHP based URL rewriting for the Akelos Framework, thus shifting the responsibility of URL parsing from the webserver to the Akelos Framework itself. This has been a requested feature for two primary reasons.
44 * - Not all webservers support rewriting. By moving this code to the core, the framework is able to function out of the box on almost all webservers.
46 * - A rewriting implementation in the Akelos Framework can also be used to generate custom URLs by linking it to the standard URL helpers such as url_for, link_to, and redirect_to.
48 * @author Bermi Ferrer <bermi a.t akelos d.t c.om>
49 * @copyright Copyright (c) 2002-2005, Akelos Media, S.L. http://www.akelos.org
50 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
52 class AkRouter extends AkObject
55 /**
56 * Routes setting container
58 * @see getRoutes
59 * @access private
60 * @var array $_loaded_routes
62 var $_loaded_routes = array();
65 function __construct()
67 /**
68 * We will try to guess if mod_rewrite is enabled.
69 * Set AK_ENABLE_URL_REWRITE in your config
70 * to avoid the overhead this function causes
72 if(!defined('AK_ENABLE_URL_REWRITE') || (defined('AK_ENABLE_URL_REWRITE') && AK_ENABLE_URL_REWRITE !== false)){
73 $this->_loadUrlRewriteSettings();
77 /**
78 * $this->_loaded_routes getter
80 * Use this method to get $this->_loaded_routes value
82 * @access public
83 * @return array Returns Loaded Routes array.
85 function getRoutes()
87 return $this->_loaded_routes;
91 /**
92 * Generates a custom URL, depending on current rewrite rules.
94 * Generates a custom URL, depending on current rewrite rules.
96 * @access public
97 * @param array $params An array with parameters to include in the url.
98 * - <code>array('controller'=>'post','action'=>'view','id'=>'10')</code>
99 * - <code>array('controller'=>'page','action'=>'view_page','webpage'=>'contact_us')</code>
100 * @return string Having the following rewrite rules:
101 * <code>
102 * $Router =& new AkRouter();
104 * $Router->map('/setup/*config_settings',array('controller'=>'setup'));
105 * $Router->map('/customize/*options/:action',array('controller'=>'themes','options'=>3));
106 * $Router->map('/blog/:action/:id',array('controller'=>'post','action'=>'list','id'=>OPTIONAL),array('id'=>'/\d{1,}/'));
107 * $Router->map('/:year/:month/:day', array('controller' => 'articles','action' => 'view_headlines','year' => COMPULSORY,'month' => 'all','day' => OPTIONAL) , array('year'=>'/(20){1}\d{2}/','month'=>'/((1)?\d{1,2}){2}/','day'=>'/(([1-3])?\d{1,2}){2}/'));
108 * $Router->map('/:webpage', array('controller' => 'page', 'action' => 'view_page', 'webpage' => 'index'),array('webpage'=>'/(\w|_)+/'));
109 * $Router->map('/', array('controller' => 'page', 'action' => 'view_page', 'webpage'=>'index'));
110 * $Router->map('/:controller/:action/:id');
111 * </code>
113 * We get the following results:
115 * <code>$Router->toUrl(array('controller'=>'page','action'=>'view_page','webpage'=>'contact_us'));</code>
116 * Produces: /contact_us/
118 * <code>$Router->toUrl(array('controller'=>'page','action'=>'view_page','webpage'=>'index'));</code>
119 * Produces: /
121 * <code>$Router->toUrl(array('controller'=>'post','action'=>'list','id'=>null));</code>
122 * Produces: /blog/
124 * <code>$Router->toUrl(array('controller'=>'post','action'=>'view','id'=>null));</code>
125 * Produces: /blog/view/
127 * <code>$Router->toUrl(array('controller'=>'post','action'=>'view','id'=>'10'));</code>
128 * Produces: /blog/view/10/
130 * <code>$Router->toUrl(array('controller'=>'blog','action'=>'view','id'=>'newest'));</code>
131 * Produces: /blog/view/newest/
133 * <code>$Router->toUrl(array('controller' => 'articles','action' => 'view_headlines','year' => '2005','month' => '10', 'day' => null));</code>
134 * Produces: /2005/10/
136 * <code>$Router->toUrl(array('controller'</code> => 'articles','action' => 'view_headlines','year' => '2006','month' => 'all', 'day' => null));</code>
137 * Produces: /2006/
139 * <code>$Router->toUrl(array('controller' => 'user','action' => 'list','id' => '12'));</code>
140 * Produces: /user/list/12/
142 * <code>$Router->toUrl(array('controller' => 'setup','config_settings' => array('themes','clone','12')));</code>
143 * Produces: /setup/themes/clone/12/
145 * <code>$Router->toUrl(array('controller' => 'themes','options' => array('blue','css','sans_serif'), 'action'=>'clone'));</code>
146 * Produces: /customize/blue/css/sans_serif/clone/
148 function toUrl($params=array())
150 static $_cache;
151 $_cache_key = md5(serialize($params));
152 if(!isset($_cache[$_cache_key])){
153 $_parsed = '';
155 if(isset($params[AK_SESSION_NAME]) && isset($_COOKIE)){
156 unset($params[AK_SESSION_NAME]);
159 $params = array_map(array(&$this, '_urlEncode'), $params);
161 foreach ($this->_loaded_routes as $_route){
162 $params_copy = $params;
163 $_parsed = '';
164 $_controller = '';
165 foreach ($params_copy as $_k=>$_v){
166 if(isset($$_k)){
167 unset($$_k);
170 extract($params);
172 if(isset($_route['options'])){
173 foreach ($_route['options'] as $_option=>$_value){
175 !empty($_route['url_pieces']) &&
176 isset($_route['options'][$_option]) &&
177 array_search(':'.$_option, $_route['url_pieces']) === false &&
178 array_search('*'.$_option, $_route['url_pieces']) === false &&
180 is_string($_value) ||
181 is_integer($_value)) &&
183 !isset($params_copy[$_option]
184 ) ||
185 $params_copy[$_option] != $_value
189 continue 2;
191 if(isset($params_copy[$_option]) &&
192 $_value == $params_copy[$_option] &&
193 $_value !== OPTIONAL &&
194 $_value !== COMPULSORY)
196 if($_option == 'controller'){
197 $_controller = $_value;
199 unset($params_copy[$_option]);
200 unset($$_option);
206 foreach ($_route['arr_params'] as $arr_route){
207 if(isset($$arr_route) && is_array($$arr_route)){
208 $$arr_route = join('/',$$arr_route);
212 $_url_pieces = array();
213 foreach (array_reverse($_route['url_pieces']) as $_v){
214 if(strstr($_v,':') || strstr($_v,'*')){
215 $_v = substr($_v,1);
216 if(isset($params[$_v])){
217 if (count($_url_pieces) || isset($_route['options'][$_v]) && $params[$_v] != $_route['options'][$_v] || !isset($_route['options'][$_v]) || isset($_route['options'][$_v]) && $_route['options'][$_v] === COMPULSORY){
218 $_url_pieces[] = is_array($params[$_v]) ? join('/',$params[$_v]) : $params[$_v];
221 }else{
222 $_url_pieces[] = is_array($_v) ? join('/',$_v) : $_v;
226 $_parsed = str_replace('//','/','/'.join('/',array_reverse($_url_pieces)).'/');
228 // This might be faster but using eval here might cause security issues
229 //@eval('$_parsed = "/".trim(str_replace("//","/","'.str_replace(array('/:','/*'),'/$','/'.join('/',$_route['url_pieces']).'/').'"),"/")."/";');
231 if($_parsed == '//'){
232 $_parsed = '/';
235 if(is_string($_parsed)){
236 if($_parsed_arr = $this->toParams($_parsed)){
238 if($_parsed == '/' && count(array_diff($params,$_parsed_arr)) == 0){
239 $_cache[$_cache_key] = '/';
240 return $_cache[$_cache_key];
243 if( isset($_parsed_arr['controller']) &&
244 ((isset($controller) && $_parsed_arr['controller'] == $controller) ||
245 (isset($_controller) && $_parsed_arr['controller'] == $_controller))){
248 if( isset($_route['options']['controller']) &&
249 $_route['options']['controller'] !== OPTIONAL &&
250 $_route['options']['controller'] !== COMPULSORY &&
251 $_parsed_arr['controller'] != $_route['options']['controller'] &&
252 count(array_diff(array_keys($_route['options']),array_keys($_parsed_arr))) > 0){
253 continue;
256 $url_params = array_merge($_parsed_arr, $params_copy);
258 if($_parsed != '/'){
259 foreach ($_parsed_arr as $_k=>$_v){
260 if(isset($url_params[$_k]) && $url_params[$_k] == $_v){
261 unset($url_params[$_k]);
266 foreach (array_reverse($_route['url_pieces'], true) as $position => $piece){
267 $piece = str_replace(array(':','*'),'', $piece);
268 if(isset($$piece)){
269 if(strstr($_parsed,'/'.$$piece.'/')){
270 unset($url_params[$piece]);
275 foreach ($url_params as $_k=>$_v){
276 if($_v == null){
277 unset($url_params[$_k]);
281 if($_parsed == '/' && !empty($url_params['controller'])){
282 $_parsed = '/'.join('/',array_diff(array($url_params['controller'],@$url_params['action'],@$url_params['id']),array('')));
283 unset($url_params['controller'],$url_params['action'],$url_params['id']);
286 if(defined('AK_URL_REWRITE_ENABLED') && AK_URL_REWRITE_ENABLED === true){
287 if(isset($url_params['ak'])){
288 unset($url_params['ak']);
290 if(isset($url_params['lang'])){
291 $_parsed = '/'.$url_params['lang'].$_parsed;
292 unset($url_params['lang']);
294 $_parsed .= count($url_params) ? '?'.http_build_query($url_params) : '';
295 }else{
296 $_parsed = count($url_params) ? '/?ak='.$_parsed.'&'.http_build_query($url_params) : '/?ak='.$_parsed;
298 $_cache[$_cache_key] = $_parsed;
299 return $_parsed;
305 (array)$extra_parameters = @array_diff($params_copy,$_parsed_arr);
308 if($_parsed == '' && is_array($params)){
309 $_parsed = '?'.http_build_query(array_merge($params,(array)$extra_parameters));
311 if($_parsed == '//'){
312 $_parsed = '/';
315 if(defined('AK_URL_REWRITE_ENABLED') && AK_URL_REWRITE_ENABLED === false && $_parsed{0} != '?'){
316 $_parsed = '?ak='.trim($_parsed,'/');
319 $_parsed .= empty($extra_parameters) ? '' : (strstr($_parsed,'?') ? '&' : '?').http_build_query($extra_parameters);
320 $_cache[$_cache_key] = $_parsed;
322 return $_cache[$_cache_key];
326 * Gets the parameters from a Akelos Framework friendly URL.
328 * This method returns the parameters found in an Akelos Framework friendly URL.
330 * This function will inspect the rewrite rules and will return the params that match the first one.
332 * @access public
333 * @param string $url URL to get params from.
334 * @return mixed Having the following rewrite rules:
335 * <code>
336 * $Router =& new AkRouter();
338 * $Router->map('/setup/*config_settings',array('controller'=>'setup'));
339 * $Router->map('/customize/*options/:action',array('controller'=>'themes','options'=>3));
340 * $Router->map('/blog/:action/:id',array('controller'=>'post','action'=>'list','id'=>OPTIONAL),array('id'=>'/\d{1,}/'));
341 * $Router->map('/:year/:month/:day', array('controller' => 'articles','action' => 'view_headlines','year' => COMPULSORY,'month' => 'all','day' => OPTIONAL) , array('year'=>'/(20){1}\d{2}/','month'=>'/((1)?\d{1,2}){2}/','day'=>'/(([1-3])?\d{1,2}){2}/'));
342 * $Router->map('/:webpage', array('controller' => 'page', 'action' => 'view_page', 'webpage' => 'index'),array('webpage'=>'/(\w|_)+/'));
343 * $Router->map('/', array('controller' => 'page', 'action' => 'view_page', 'webpage'=>'index'));
344 * $Router->map('/:controller/:action/:id');
345 * </code>
347 * We get the following results:
349 * <code>$Router->toParams('/contact_us');</code>
350 * Produces: array('controller'=>'page','action'=>'view_page','webpage'=>'contact_us');
352 * <code>$Router->toParams('/');</code>
353 * Produces: array('controller'=>'page','action'=>'view_page','webpage'=>'index');
355 * <code>$Router->toParams('');</code>
356 * Produces: array('controller'=>'page','action'=>'view_page','webpage'=>'index');
358 * <code>$Router->toParams('/blog/');</code>
359 * Produces: array('controller'=>'post','action'=>'list','id'=>null);
361 * <code>$Router->toParams('/blog/view');</code>
362 * Produces: array('controller'=>'post','action'=>'view','id'=>null);
364 * <code>$Router->toParams('/blog/view/10/');</code>
365 * Produces: array('controller'=>'post','action'=>'view','id'=>'10');
367 * <code>$Router->toParams('/blog/view/newest/');</code>
368 * Produces: array('controller'=>'blog','action'=>'view','id'=>'newest');
370 * <code>$Router->toParams('/2005/10/');</code>
371 * Produces: array('controller' => 'articles','action' => 'view_headlines','year' => '2005','month' => '10', 'day' => null);
373 * <code>$Router->toParams('/2006/');</code>
374 * Produces: array('controller' => 'articles','action' => 'view_headlines','year' => '2006','month' => 'all', 'day' => null);
376 * <code>$Router->toParams('/user/list/12');</code>
377 * Produces: array('controller' => 'user','action' => 'list','id' => '12');
379 * <code>$Router->toParams('/setup/themes/clone/12/');</code>
380 * Produces: array('controller' => 'setup','config_settings' => array('themes','clone','12'));
382 * <code>$Router->toParams('/customize/blue/css/sans_serif/clone/');</code>
383 * Produces: array('controller' => 'themes','options' => array('blue','css','sans_serif'), 'action'=>'clone');
385 * This function returns false in case no rule is found for selected URL
387 function toParams($url)
389 $url = $url == '/' || $url == '' ? '/' : '/'.trim($url,'/').'/';
390 $nurl = $url;
392 foreach ($this->_loaded_routes as $_route){
393 $params = array();
395 if(preg_match($_route['regex'], $url)){
396 foreach ($_route['regex_array'] as $single_regex_arr){
398 $k = key($single_regex_arr);
400 $single_regex = $single_regex_arr[$k];
401 $single_regex = '/^(\/'.$single_regex.'){1}/';
402 preg_match($single_regex, $url, $got);
404 if(in_array($k,$_route['arr_params'])){
405 $url_parts = strstr(trim($url,'/'),'/') ? explode('/',trim($url,'/')) : array(trim($url,'/'));
407 $pieces = (isset($_route['options'][$k]) && $_route['options'][$k] > 0) ? $_route['options'][$k] : count($url_parts);
408 while ($pieces>0) {
409 $pieces--;
410 $url_part = array_shift($url_parts);
411 $url = substr_replace($url,'',1,strlen($url_part)+1);
413 if(preg_match($single_regex, '/'.$url_part)){
414 $params[$k][] = $url_part;
417 }elseif(!empty($got[0])){
418 $url = substr_replace($url,'',1,strlen($got[0]));
419 if(in_array($k,$_route['var_params'] )){
420 $param = trim($got[0],'/');
421 $params[$k] = $param;
424 if(isset($_route['options'][$k])){
426 if($_route['options'][$k] !== COMPULSORY &&
427 $_route['options'][$k] !== OPTIONAL &&
428 $_route['options'][$k] != '' &&
429 ((!isset($params[$k]))||(isset($params[$k]) && $params[$k] == ''))){
430 $params[$k] = $_route['options'][$k];
435 if(isset($_route['options'])){
436 foreach ($_route['options'] as $_option => $_value){
437 if($_value !== COMPULSORY && $_value !== OPTIONAL && $_value != '' && !isset($params[$_option])){
438 $params[$_option] = $_value;
443 if(count($params)){
444 $params = array_map(array(&$this,'_urlDecode'), $params);
445 return $params;
448 return false;
452 * Add a rewrite rule
454 * Rewrite rules are defined on the file <code>config/routes.php</code>
456 * Rules that are defined first take precedence over the rest.
458 * @access public
459 * @param string $url_pattern URL patterns have the following format:
461 * - <b>/static_text</b>
462 * - <b>/:variable</b> (will load $variable)
463 * - <b>/*array</b> (will load $array as an array)
464 * @param array $options Options is an array with and array pair of field=>value
465 * The following example <code>array('controller' => 'page')</code> sets var 'controler' to 'page' if no 'controller' is specified in the $url_pattern param this value will be used.
467 * The following constants can be used as values:
468 * <code>
469 * OPTIONAL // 'var_name'=> OPTIONAL, will set 'var_name' as an option
470 * COMPULSORY // 'var_name'=> COMPULSORY, will require 'var_name' to be set
471 * </code>
472 * @param array $requirements $requirements holds an array with and array pair of field=>value where value is a perl compatible regular expression that will be used to validate rewrite rules
473 * The following example <code>array('id'=>'/\d+/')</code> will require that var 'id' must be a numeric field.
475 * NOTE:If option <b>'id'=>OPTIONAL</b> this requirement will be used in case 'id' is set to something
476 * @return void
478 function connect($url_pattern, $options = array(), $requirements = null)
481 if(!empty($options['requirements'])){
482 $requirements = empty($requirements) ? $options['requirements'] : array_merge($options['requirements'],$requirements);
483 unset($options['requirements']);
486 preg_match_all('/(([^\/]){1}(\/\/)?){1,}/',$url_pattern,$found);
487 $url_pieces = $found[0];
489 $regex_arr = array();
490 $optional_pieces = array();
491 $var_params = array();
492 $arr_params = array();
493 foreach ($url_pieces as $piece){
494 $is_var = $piece[0] == ':';
495 $is_arr = $piece[0] == '*';
496 $is_constant = !$is_var && !$is_arr;
498 $piece = $is_constant ? $piece : substr($piece,1);
500 if($is_var && !isset($options[$piece])){
501 $options[$piece] = OPTIONAL;
504 if($is_arr && !isset($options[$piece])){
505 $options[$piece] = OPTIONAL;
508 if(($is_arr || $is_var) && $piece == 'this'){
509 trigger_error(Ak::t('You can\'t use the reserved word this for mapping URLs'), E_USER_ERROR);
512 //COMPULSORY
514 if($is_constant){
515 $regex_arr[] = array('_constant_'.$piece => '('.$piece.'(?=(\/|$))){1}');
516 }elseif(isset($requirements[$piece])){
517 if (isset($options[$piece]) && $options[$piece] !== COMPULSORY){
518 $regex_arr[] = array($piece=> '(('.trim($requirements[$piece],'/').'){1})?');
519 }elseif(isset($options[$piece]) && $options[$piece] !== OPTIONAL){
520 $regex_arr[] = array($piece=> '(('.trim($requirements[$piece],'/').'){1}|('.$options[$piece].'){1}){1}');
521 }else{
522 $regex_arr[] = array($piece=> '('.trim($requirements[$piece],'/').'){1}');
524 }elseif(isset($options[$piece])){
525 if($options[$piece] === OPTIONAL){
526 $regex_arr[] = array($piece=>'[^\/]*');
527 }elseif ($options[$piece] === COMPULSORY){
528 $regex_arr[] = array($piece=> COMPULSORY_REGEX);
529 }elseif(is_string($options[$piece]) && $options[$piece][0] == '/' &&
530 ($_tmp_close_char = strlen($options[$piece])-1 || $options[$piece][$_tmp_close_char] == '/')){
531 $regex_arr[] = array($piece=> substr($options[$piece],1,$_tmp_close_char*-1));
532 }elseif ($options[$piece] != ''){
533 $regex_arr[] = array($piece=>'[^\/]*');
534 $optional_pieces[$piece] = $piece;
536 }else{
537 $regex_arr[] = array($piece => $piece);
541 if($is_var){
542 $var_params[] = $piece;
544 if($is_arr){
545 $arr_params[] = $piece;
548 if(isset($options[$piece]) && $options[$piece] === OPTIONAL){
549 $optional_pieces[$piece] = $piece;
553 foreach (array_reverse($regex_arr) as $pos=>$single_regex_arr){
554 $var_name = key($single_regex_arr);
555 if((isset($options[$var_name]) && $options[$var_name] === COMPULSORY) || (isset($requirements[$var_name]) && $requirements[$var_name] === COMPULSORY)){
556 $last_optional_var = $pos;
557 break;
561 $regex = '/^((\/)?';
562 $pieces_count = count($regex_arr);
564 foreach ($regex_arr as $pos=>$single_regex_arr){
565 $k = key($single_regex_arr);
566 $single_regex = $single_regex_arr[$k];
568 $slash_delimiter = isset($last_optional_var) && ($last_optional_var <= $pos) ? '{1}' : '?';
570 if(isset($optional_pieces[$k])){
571 $terminal = (is_numeric($options[$k]) && $options[$k] > 0 && in_array($k,$arr_params)) ? '{'.$options[$k].'}' : ($pieces_count == $pos+1 ? '?' : '{1}');
572 $regex .= $is_arr ? '('.$single_regex.'\/'.$slash_delimiter.')+' : '('.$single_regex.'\/'.$slash_delimiter.')'.$terminal;
573 }else{
574 $regex .= $is_arr ? $single_regex.'\/+' : $single_regex.'\/'.($pieces_count == $pos+1 ? '?' : $slash_delimiter);
577 $regex = rtrim($regex ,'/').'){1}$/';
578 $regex = str_replace('/^\$/','/^\\/?$/',$regex);
581 $this->_loaded_routes[] = array(
582 'url_path' => $url_pattern,
583 'options' => $options,
584 'requirements' => $requirements,
585 'url_pieces' => $url_pieces,
586 'regex' => $regex,
587 'regex_array' => $regex_arr,
588 'optional_params' => $optional_pieces,
589 'var_params' => $var_params,
590 'arr_params' => $arr_params
597 * Alias for map
599 * @see map
601 function map($url_pattern, $options = array(), $requirements = null)
603 return $this->connect($url_pattern, $options, $requirements);
607 * Url decode a string or an array of strings
609 function _urlDecode($input)
611 if(!empty($input)){
612 if (is_scalar($input)){
613 return urldecode($input);
614 }elseif (is_array($input)){
615 return array_map(array(&$this,'_urlDecode'),$input);
618 return '';
622 * Url encodes a string or an array of strings
624 function _urlEncode($input)
626 if(!empty($input)){
627 if (is_scalar($input)){
628 return urlencode($input);
629 }elseif (is_array($input)){
630 return array_map(array(&$this,'_urlEncode'),$input);
633 return '';
637 * This method tries to determine if url rewrite is enabled on this server.
638 * It has only been tested on apache.
639 * It is strongly recomended that you manually define the constant
640 * AK_URL_REWRITE_ENABLED on your config file to the avoid overload
641 * this function causes and to prevent from missfunctioning
643 function _loadUrlRewriteSettings()
645 static $result;
646 if(isset($result)){
647 return $result;
650 if(defined('AK_URL_REWRITE_ENABLED')){
651 $result = AK_URL_REWRITE_ENABLED;
652 return AK_URL_REWRITE_ENABLED;
654 if(AK_DESKTOP){
655 if(!defined('AK_URL_REWRITE_ENABLED')){
656 define('AK_URL_REWRITE_ENABLED',false);
657 $result = AK_URL_REWRITE_ENABLED;
658 return false;
661 if(defined('AK_ENABLE_URL_REWRITE') && AK_ENABLE_URL_REWRITE == false){
662 if(!defined('AK_URL_REWRITE_ENABLED')){
663 define('AK_URL_REWRITE_ENABLED',false);
665 $result = AK_URL_REWRITE_ENABLED;
666 return false;
669 $url_rewrite_status = false;
671 //echo '<pre>'.print_r(get_defined_functions(), true).'</pre>';
673 if( isset($_SERVER['REDIRECT_STATUS'])
674 && $_SERVER['REDIRECT_STATUS'] == 200
675 && isset($_SERVER['REDIRECT_QUERY_STRING'])
676 && strstr($_SERVER['REDIRECT_QUERY_STRING'],'ak=')){
678 if(strstr($_SERVER['REDIRECT_QUERY_STRING'],'&')){
679 $tmp_arr = explode('&',$_SERVER['REDIRECT_QUERY_STRING']);
680 $ak_request = $tmp_arr[0];
681 }else{
682 $ak_request = $_SERVER['REDIRECT_QUERY_STRING'];
684 $ak_request = trim(str_replace('ak=','',$ak_request),'/');
686 if(strstr($_SERVER['REDIRECT_URL'],$ak_request)){
687 $url_rewrite_status = true;
688 }else {
689 $url_rewrite_status = false;
693 // We check if available by investigating the .htaccess file if no query has been set yet
694 elseif(function_exists('apache_get_modules')){
696 $available_modules = apache_get_modules();
698 if(in_array('mod_rewrite',(array)$available_modules)){
700 // Local session name is changed intentionally from .htaccess
701 // So we can see if the file has been loaded.
702 // if so, we restore the session.name to its original
703 // value
704 if(ini_get('session.name') == 'AK_SESSID'){
705 $session_name = defined('AK_SESSION_NAME') ? AK_SESSION_NAME : get_cfg_var('session.name');
706 ini_set('session.name',$session_name);
707 $url_rewrite_status = true;
709 // In some cases where session.name cant be set up by htaccess file,
710 // we can check for modrewrite status on this file
711 }elseif (file_exists(AK_BASE_DIR.DS.'.htaccess')){
712 $htaccess_file = Ak::file_get_contents(AK_BASE_DIR.DS.'.htaccess');
713 if(stristr($htaccess_file,'RewriteEngine on')){
714 $url_rewrite_status = true;
719 // If none of the above works we try to fetch a file that should be remaped
720 }elseif (isset($_SERVER['REDIRECT_URL']) && $_SERVER['REDIRECT_URL'] == '/' && isset($_SERVER['REDIRECT_STATUS']) && $_SERVER['REDIRECT_STATUS'] == 200){
721 $url_rewrite_test_url = AK_URL.'mod_rewrite_test';
722 if(!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])){
723 $url_rewrite_test_url = AK_PROTOCOL.$_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW'].'@'.AK_HOST.'/mod_rewrite_test';
726 $url_rewrite_status = strstr(@file_get_contents($url_rewrite_test_url), 'AK_URL_REWRITE_ENABLED');
727 $AK_URL_REWRITE_ENABLED = "define(\\'AK_URL_REWRITE_ENABLED\\', ".($url_rewrite_status ? 'true' : 'false').");\n";
729 register_shutdown_function(create_function('',"Ak::file_put_contents(AK_CONFIG_DIR.DS.'config.php',
730 str_replace('<?php\n','<?php\n\n$AK_URL_REWRITE_ENABLED',Ak::file_get_contents(AK_CONFIG_DIR.DS.'config.php')));"));
735 if(!defined('AK_URL_REWRITE_ENABLED')){
736 define('AK_URL_REWRITE_ENABLED', $url_rewrite_status);
738 $result = AK_URL_REWRITE_ENABLED;
739 return AK_URL_REWRITE_ENABLED;
744 function &AkRouter()
746 $null = null;
747 $AkRouter =& Ak::singleton('AkRouter', $null);
748 return $AkRouter;