root/trunk/lib/SGL/Url.php

Revision 3125, 29.3 kB (checked in by demian, 3 weeks ago)

bugfix to trunk merge -3

  • Property svn:eol-style set to native
Line 
1 <?php
2 /* Reminder: always indent with 4 spaces (no tabs). */
3 // +---------------------------------------------------------------------------+
4 // | Copyright (c) 2002-2004, Richard Heyes                                    |
5 // | All rights reserved.                                                      |
6 // |                                                                           |
7 // | Redistribution and use in source and binary forms, with or without        |
8 // | modification, are permitted provided that the following conditions        |
9 // | are met:                                                                  |
10 // |                                                                           |
11 // | o Redistributions of source code must retain the above copyright          |
12 // |   notice, this list of conditions and the following disclaimer.           |
13 // | o Redistributions in binary form must reproduce the above copyright       |
14 // |   notice, this list of conditions and the following disclaimer in the     |
15 // |   documentation and/or other materials provided with the distribution.    |
16 // | o The names of the authors may not be used to endorse or promote          |
17 // |   products derived from this software without specific prior written      |
18 // |   permission.                                                             |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
21 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
22 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
23 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
24 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
25 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
26 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
27 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
28 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
29 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
30 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
31 // |                                                                           |
32 // +---------------------------------------------------------------------------+
33 // | Seagull 0.6                                                               |
34 // +---------------------------------------------------------------------------+
35 // | Url.php                                                                   |
36 // +---------------------------------------------------------------------------+
37 // | Authors:   Richard Heyes <richard at php net>                             |
38 // |            Demian Turner <demian@phpkitchen.com>                          |
39 // +---------------------------------------------------------------------------+
40 // $Id: Url.php,v 1.32 2005/05/29 21:32:17 demian Exp $
41 //
42
43 /**
44  * Url related functionality.
45  *
46  * @package SGL
47  * @author  Demian Turner <demian@phpkitchen.com>
48  * @version $Revision: 1.32 $
49  * @see seagull/lib/SGL/tests/UrlTest.ndb.php
50  */
51 class SGL_URL
52 {
53     /**
54     * Full url
55     * @var string
56     */
57     var $url;
58
59     /**
60     * Protocol
61     * @var string
62     */
63     var $protocol;
64
65     /**
66     * Username
67     * @var string
68     */
69     var $username;
70
71     /**
72     * Password
73     * @var string
74     */
75     var $password;
76
77     /**
78     * Host
79     * @var string
80     */
81     var $host;
82
83     /**
84     * Port
85     * @var integer
86     */
87     var $port;
88
89     /**
90     * Path
91     * @var string
92     */
93     var $path;
94
95     /**
96     * Query string.
97     *
98     * The querystring is defined as everthing from the frontScriptName
99     * to the end of the URI, not including anchors, examples:
100     *
101     *   - http://example.com/index.php/foo/bar/baz/fluux
102     *   -> qs = foo/bar/baz/fluux
103     *
104     *   - http://example.com/foo/bar/baz/fluux?sess=a&rand=123
105     *   -> qs = foo/bar/baz/fluux?sess=a&rand=123
106     *
107     *   - http://example.com/?sess=a&rand=123
108     *   -> qs = sess=a&rand=123
109     *
110     *   - http://example.com/2006/02/07/my_interesting_blog.html
111     *   -> qs - 2006/02/07/my_interesting_blog.html
112     * @var array
113     */
114     var $querystring;
115     var $aQueryData;
116     var $frontScriptName;
117     var $aStrategies = array();
118     var $aRes = array();
119
120     /**
121     * Anchor
122     * @var string
123     */
124     var $anchor;
125
126     /**
127     * Whether to use []
128     * @var bool
129     */
130     var $useBrackets;
131
132     /**
133     * PHP4 Constructor
134     *
135     * @see __construct()
136     */
137     function SGL_URL(
138         $url = null,
139         $useBrackets = true,
140         /*SGL_UrlParserStrategy*/ $parserStrategy = null,
141         $conf = null)
142     {
143         $this->__construct($url, $useBrackets, $parserStrategy, $conf);
144     }
145
146     /**
147     * PHP5 Constructor
148     *
149     * Parses the given url and stores the various parts
150     * Defaults are used in certain cases
151     *
152     * @param string $url         Optional URL
153     * @param bool   $useBrackets Whether to use square brackets when
154     *                            multiple querystrings with the same name
155     *                            exist
156     * @param SGL_UrlParserStrategy  The strategy object to be used, optional
157     * @param array               An array of config elements, optional
158     *
159     * @todo the main URL attributes always get set twice, this needs to be optimised
160     */
161     function __construct($url = null, $useBrackets = true, $parserStrategy = null, $conf = null)
162     {
163         $this->useBrackets = $useBrackets;
164         $this->url         = $url;
165         $this->user        = '';
166         $this->pass        = '';
167         $this->host        = '';
168         $this->port        = 80;
169         $this->path        = '';
170         $this->aQueryData = array();
171         $this->anchor      = '';
172         //  get default config
173         if (is_null($conf)) {
174             $c = &SGL_Config::singleton();
175             $this->conf = $c->getAll();
176         } else {
177             $this->conf = $conf;
178         }
179         //  setup strategies array
180         //  if no strats are provided, use native SEF strategy
181         if (is_null($parserStrategy)) {
182             $this->aStrategies[] = new SGL_UrlParser_SefStrategy();
183         }
184         if (!is_array($parserStrategy) && is_a($parserStrategy, 'SGL_UrlParserStrategy')) {
185             $this->aStrategies[] = $parserStrategy;
186
187         } elseif (is_array($parserStrategy)) {
188             $this->aStrategies = $parserStrategy;
189
190         } else {
191             SGL::raiseError('unrecognised url strategy');
192         }
193         $this->frontScriptName = $this->conf['site']['frontScriptName'];
194     }
195
196     /**
197      * Attempts to parse URI elements.
198      *
199      * @return true on success, PEAR_Error on failure
200      */
201     function init()
202     {
203         // Only set defaults if $url is not an absolute URL
204         if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
205
206             // FIXME: get rid of this
207             if (is_a($this->aStrategies[0], 'SGL_UrlParser_SimpleStrategy')) {
208                 $this->aQueryData = $this->parseQueryString($this->conf);
209                 return;
210             }
211
212             $this->protocol = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
213                 ? 'https'
214                 : 'http';
215
216             /**
217             * Figure out host/port
218             */
219             if (!empty($_SERVER['HTTP_HOST']) && preg_match('/^(.*)(:([0-9]+))?$/U',
220                     $_SERVER['HTTP_HOST'], $matches)) {
221                 $host = $matches[1];
222                 if (!empty($matches[3])) {
223                     $port = $matches[3];
224                 } else {
225                     $port = $this->getStandardPort($this->protocol);
226                 }
227             }
228
229             $this->user        = '';
230             $this->pass        = '';
231             $this->host        = !empty($host)
232                                     ? $host
233                                     : (isset($_SERVER['SERVER_NAME'])
234                                         ? $_SERVER['SERVER_NAME']
235                                         : 'localhost');
236             $this->port        = !empty($port)
237                                     ? $port
238                                     : (isset($_SERVER['SERVER_PORT'])
239                                         ? $_SERVER['SERVER_PORT']
240                                         : $this->getStandardPort($this->protocol));
241             $this->path        = !empty($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/';
242 #FIXME: $_SERVER['PHP_SELF'] != $this->path when redir is appended, needs to be cleaned up
243 # refactor removal of frontScriptName with routine use in switch below
244 //            if (isset($this->path{0}) && $this->path{0} == '/') {
245 //                if ($this->frontScriptName != false) {
246 //                    $frontScriptStartIndex = strpos($this->path, $this->frontScriptName);
247 //                    $frontScriptEndIndex = $frontScriptStartIndex + strlen($this->frontScriptName);
248 //                    if ($frontScriptStartIndex) {
249 //                        $this->path = substr($this->path, 0, $frontScriptStartIndex);
250 //                    }
251 //                }
252 //            }
253         }
254
255         // Parse the URI and store the various parts
256         if (!is_null($this->url)) {
257             //  if we have a relative URI, enforce FQDN as required by parse_url
258             $target = (preg_match('/^[a-z0-9]+:\/\//i', $this->url))
259                 ? $this->url
260                 : $this->toString();
261             $urlinfo = parse_url($target);
262
263             //  if a ? is present in frontScriptName, it gets stripped by calling $_SERVER['PHP_SELF']
264             //  and needs to be re-added
265             if (preg_match("/\?/", $this->frontScriptName)) {
266                 $urlinfo['path'] = preg_replace("/index.php/", "index.php?", $urlinfo['path']);
267             }
268
269             // Default query data
270             $this->aQueryData = array();
271
272             foreach ($urlinfo as $key => $value) {
273                 switch ($key) {
274
275                 case 'scheme':
276                     $this->protocol = $value;
277                     $this->port     = $this->getStandardPort($value);
278                     break;
279
280                 case 'user':
281                 case 'pass':
282                 case 'host':
283                 case 'port':
284                     $this->$key = $value;
285                     break;
286
287                 case 'path':
288                     //  the 'path' is deemed to be everything after the hostname,
289                     //  but before the frontScriptName, including initial and final
290                     //  slashes, ie: /seagull/trunk/www/
291                     if (isset($value{0}) && $value{0} == '/') {
292                         if ($this->frontScriptName != false) {
293                             $frontScriptStartIndex = strpos($value, $this->frontScriptName);
294                             $frontScriptEndIndex = $frontScriptStartIndex + strlen($this->frontScriptName);
295                             if (!$frontScriptStartIndex) {
296
297                                 //  this is an install and index.php was omitted
298                                 $this->path = $urlinfo['path'];
299                                 $this->querystring = @$urlinfo['query'];
300                             } else {
301                                 $this->path = substr($value, 0, $frontScriptStartIndex);
302                                 $this->querystring = substr($value, $frontScriptEndIndex);
303                             }
304                         } else {
305                             $this->path = dirname($_SERVER['SCRIPT_NAME']) == DIRECTORY_SEPARATOR
306                                 ? ''
307                                 : dirname($_SERVER['SCRIPT_NAME']);
308                             $this->querystring = str_replace($this->path, '', $urlinfo['path']);
309                         }
310                     } else {
311                         $path = dirname($this->path) == DIRECTORY_SEPARATOR
312                             ? ''
313                             : dirname($this->path);
314                         $this->path = sprintf('%s/%s', $path, $value);
315                     }
316                     break;
317
318                 case 'query':
319                     if (isset($urlinfo['query']) && empty($this->querystring)) {
320                         $this->querystring = $urlinfo['query'];
321                     }
322                     $ret = $this->parseQueryString($this->conf);
323
324                     if (PEAR::isError($ret)) {
325                         return $ret;
326                     } else {
327                         $this->aQueryData = $ret;
328                     }
329                     //  populate querystring property
330                     $this->querystring =    $this->getModuleName() .'/'.
331                                             $this->getManagerName() .'/'.
332                                             SGL_Array::implodeWithKeys('/', $this->getQueryData(true));
333                     break;
334
335                 case 'fragment':
336                     $this->anchor = $value;
337                     break;
338                 }
339             }
340             if (!array_key_exists('query', $urlinfo)) {
341                 $ret = $this->parseQueryString($this->conf);
342
343                 if (PEAR::isError($ret)) {
344                     return $ret;
345                 } else {
346                     $this->aQueryData = $ret;
347                 }
348             }
349             //  remove strategy objects to streamline for storage
350             $this->removeStrategies();
351             return true;
352         }
353         return SGL::raiseError('no URI data', SGL_ERROR_NODATA);
354     }
355
356
357     /**
358      * SGL_Url singletons are currently only used for output URLs, so the output
359      * format is taken from $conf.
360      *
361      * @return SGL_Url
362      */
363     function &singleton()
364     {
365         static $instance;
366         if (!isset($instance)) {
367             $c = &SGL_Config::singleton();
368             $conf = $c->getAll();
369             $parserStrategy = $conf['site']['outputUrlHandler'];
370             $class = __CLASS__;
371             $instance = new $class(null, true, new $parserStrategy());
372         }
373         return $instance;
374     }
375
376     function getManagerName()
377     {
378         return @$this->aQueryData['managerName'];
379     }
380
381     function getModuleName()
382     {
383         return @$this->aQueryData['moduleName'];
384     }
385
386     /**
387      * Returns querystring data as an array.
388      *
389      * @param boolean $strict If strict is true, managerName and moduleName are removed
390      * @return array
391      */
392     function getQueryData($strict = false)
393     {
394         $aRet = $this->aQueryData;
395
396         if (PEAR::isError($aRet)) {
397             return $aRet;
398         }
399         if ($strict) {
400             if (isset($aRet['moduleName'])) {
401                 unset($aRet['moduleName']);
402             }
403             if (isset($aRet['managerName'])) {
404                 unset($aRet['managerName']);
405             }
406         }
407         //  zend debug cleanup
408         $aZendDebugParams = array('debug_fastfile', 'debug_host', 'debug_new_session',
409             'debug_no_cache', 'debug_port', 'debug_stop', 'debug_url', 'send_sess_end',
410             'start_debug');
411         foreach ($aZendDebugParams as $param) {
412             if (isset($aRet[$param])) {
413                 unset($aRet[$param]);
414             }
415         }
416         //  remove querystring data
417         foreach ($aRet as $k => $v) {
418             if (stristr($k, '?start_debug')) {
419                 unset($aRet[$k]);
420             }
421         }
422         return $aRet;
423     }
424
425     /**
426      * Returns querystring portion of url.
427      *
428      * @return string
429      */
430     function getQueryString()
431     {
432         return $this->querystring;
433     }
434
435     /**
436      * Build array of strategies and executes parsers.
437      *
438      * @param array $conf
439      * @return array
440      */
441     function parseQueryString($conf)
442     {
443         foreach ($this->aStrategies as $strategy) {
444
445             //  all strategies will attempt to parse url, overwriting
446             //  previous results as they do
447             $res = $strategy->parseQueryString($this, $conf);
448             if (PEAR::isError($res)) {
449                 return $res;
450             } else {
451                 $this->aRes[] = $res;
452             }
453         }
454         //  reverse order of strats so Classic comes last in array and overrides SEF
455         if (!empty($conf['site']['outputUrlHandler'])
456                 && $conf['site']['outputUrlHandler'] == 'SGL_UrlParser_ClassicStrategy') {
457             $tmp = array_reverse($this->aRes);
458             $this->aRes = $tmp;
459         }
460         $ret = call_user_func_array('array_merge', $this->aRes);
461         return $ret;
462     }
463
464     /**
465      * Parses an array of querystring param names and values and returns a
466      * key/value hash.
467      *
468      * @param array $aUriParts  The list of candidate values.
469      * @param array $aParsedUri The list of existing valid value, to avoid overwriting
470      * @return array            A hash of k/v pairs
471      */
472     function querystringArrayToHash($aUriParts, $aParsedUri = array())
473     {
474         $numParts = count($aUriParts);
475
476         //  if varName/varValue don't match, assign a null varValue to the last varName
477         if ($numParts % 2) {
478             array_push($aUriParts, null);
479             ++ $numParts;
480         }
481
482         //  parse FC querystring params
483         $aQsParams = array();
484
485         for ($i = 0; $i < $numParts; $i += 2) {
486             $varName  = urldecode($aUriParts[$i]);
487             $varValue = urldecode($aUriParts[$i+1]);
488
489             //  check if the variable is an array
490             if ((strpos($varName, '[') !== false) &&
491                 (strpos($varName, ']') !== false))
492             {
493                 //  retrieve the array name ($matches[1]) and its eventual key ($matches[2])
494                 preg_match('/([^\[]*)\[([^\]]*)\]/', $varName, $matches);
495                 $aRequestVars = array_merge($_REQUEST, $aParsedUri);
496                 if (    !array_key_exists($matches[1], $aRequestVars)
497                     &&  !array_key_exists($matches[1], $aQsParams)) {
498                         $aQsParams[$matches[1]] = array();
499                 }
500                 //  no key given => append to array
501                 if (empty($matches[2])) {
502                     array_push($aQsParams[$matches[1]], $varValue);
503                 } else {
504                     $aQsParams[$matches[1]][$matches[2]] = $varValue;
505                 }
506             } else {
507                 $aQsParams[$varName] = $varValue;
508             }
509         }
510         return $aQsParams;
511     }
512
513     function getStrategiesFingerprint($aStrats)
514     {
515         $aStratNames = array();
516         foreach ($aStrats as $strategy) {
517             $aStratNames[] = get_class($strategy);
518         }
519         $fingerprint = implode('', $aStratNames);
520         return $fingerprint;
521     }
522
523     /**
524     * Returns the full URI as a string.
525     *
526     * @return string Full URI
527     * @access public
528     */
529     function toString()
530     {
531         $retUrl = $this->protocol . '://'
532                    . $this->user . (!empty($this->pass) ? ':' : '')
533                    . $this->pass . (!empty($this->user) ? '@' : '')
534                    . $this->getHostName() . ($this->port == $this->getStandardPort($this->protocol)
535                         ? ''
536                         : ':' . $this->port)
537                    . $this->getPath();
538
539         //  append front script name if not already present
540         if ($this->frontScriptName != false) {
541             if (!preg_match("/$this->frontScriptName/", $retUrl)) {
542                 $retUrl .= $this->getFrontScriptName();
543             }
544         }
545
546         //  add a trailing slash if one is not present
547         $qs  = $this->getQueryString();
548         $qs .= !empty($this->anchor) ? '#' . $this->anchor : '';
549         if (!empty($qs) && $qs{0} != '/' && substr($retUrl, -1) != '/') {
550             $qs = '/' . $qs . (!empty($this->anchor) ? '#' . $this->anchor : '');
551         }
552         $retUrl .= $qs;
553         return $retUrl;
554     }
555
556     function makeLink($action = '', $mgr = '', $mod = '', $aList = array(),
557         $params = '', $idx = 0, $output = '')
558     {
559         //  a workaround for 0.4.x style of building SEF URLs
560         $url = & SGL_Url::singleton();
561         return $url->aStrategies[0]->makeLink(
562             $action, $mgr, $mod, $aList, $params, $idx, $output);
563     }
564
565     /**
566     * Returns the standard port number for a protocol.
567     *
568     * @param  string  $scheme The protocol to lookup
569     * @return integer         Port number or NULL if no scheme matches
570     *
571     * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
572     */
573     function getStandardPort($scheme)
574     {
575         switch (strtolower($scheme)) {
576
577         case 'http':    return 80;
578         case 'https':   return 443;
579         case 'ftp':     return 21;
580         case 'imap':    return 143;
581         case 'imaps':   return 993;
582         case 'pop3':    return 110;
583         case 'pop3s':   return 995;
584         default:        return null;
585        }
586     }
587
588     /**
589     * Forces the URL to a particular protocol.
590     *
591     * @param string  $protocol Protocol to force the URL to
592     * @param integer $port     Optional port (standard port is used by default)
593     */
594     function setProtocol($protocol, $port = null)
595     {
596         $this->protocol = $protocol;
597         $this->port = is_null($port) ? $this->getStandardPort() : $port;
598     }
599
600     /**
601      * Resolves PHP_SELF var depending on implementation, ie apache, iis, cgi, etc.
602      *
603      * @abstract
604      */
605     function resolveServerVars($conf = null)
606     {
607         //  cgi SERVER vars hack causes probs w/quickform
608         if (!is_file(SGL_VAR_DIR . '/INSTALL_COMPLETE.php')) {
609             return;
610         }
611         //  it's apache
612         if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI'])) {
613
614             //  however we're running from cgi, so populate PHP_SELF info from REQUEST_URI
615             if (strpos(php_sapi_name(), 'cgi') !== false) {
616                 $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'];
617
618             //  a ? is part of $conf['site']['frontScriptName'] and REQUEST_URI has more info
619             } elseif ((strlen($_SERVER['REQUEST_URI']) > strlen($_SERVER['PHP_SELF'])
620                     && strstr($_SERVER['REQUEST_URI'], '?')
621                     && !isset($conf['setup']))) {
622                 $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'];
623
624             // we don't want to have index.php in our url, so REQUEST_URI as more info
625             } elseif ($conf['site']['frontScriptName'] == false) {
626                 $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'];
627             } else {
628                 //  do nothing, PHP_SELF is valid
629             }
630
631         //  it's IIS
632         } else {
633             $frontScriptName = is_null($conf) ? 'index.php' : $conf['site']['frontScriptName'];
634             if (substr($_SERVER['SCRIPT_NAME'], -1, 1) != substr($frontScriptName, -1, 1)) {
635                 $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'] . '?' . @$_SERVER['QUERY_STRING'];
636             } else {
637                 $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'] . @$_SERVER['QUERY_STRING'];
638             }
639
640         }
641     }
642
643     function getHostName()
644     {
645         return $this->host;
646     }
647
648     function getPath()
649     {
650         return $this->path;
651     }
652
653     /**
654      * Returns the front controller script name.
655      *
656      * @return string
657      */
658     function getFrontScriptName()
659     {
660         return $this->frontScriptName;
661     }
662
663     /**
664      * Ensures URL is fully qualified.
665      *
666      * @access  public
667      * @param   string  $url    The relative URL string
668      * @return  void
669      */
670     function toAbsolute(&$url)
671     {
672         $aUrl = parse_url($url);
673         if (!(isset($aUrl['scheme']))) {
674             $url = SGL_BASE_URL . '/' . $url;
675         }
676     }
677
678     /**
679      * Returns hostname + path with final slashes removed if present.
680      *
681      * @return string   The base url
682      * @todo make logic more generic
683      */
684     function getBase()
685     {
686         $aParts = explode('/', $this->path);
687
688         //  accomodate setup exception
689         if (in_array('setup.php', $aParts)) {
690             array_pop($aParts);
691             $this->path = implode('/', $aParts);
692         }
693
694         $retUrl = $this->protocol . '://'
695                    . $this->user . (!empty($this->pass) ? ':' : '')
696                    . $this->pass . (!empty($this->user) ? '@' : '')
697                    . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
698                    . $this->path;
699
700         //  handle case for user's homedir, ie, presence of tilda: example.com/~seagull
701         if (preg_match('/~/', $retUrl)) {
702             $retUrl = str_replace('~', '%7E', $retUrl);
703         }
704         //  remove trailing slash
705         if (substr($retUrl, -1) == '/') {
706             $retUrl = substr($retUrl, 0, -1);
707         }
708         return $retUrl;
709     }
710
711     /**
712      * Parse string stored in resource_uri field in section table.
713      *
714      * This will always contain URL elements after the frontScriptName (index.php), never
715      * a FQDN, and never simplified names, ie section table must specify module name and
716      * manager name explicitly, even if they are the same, ie user/user
717      *
718      * @param string $str
719      * @return array  A hash containing URL info
720      *
721      * @todo this method is VERY similar to parseQueryString and should be consolidated
722      */
723     function parseResourceUri($str)
724     {
725         $ret = array();
726         $default = array(
727             'module' => 'default',
728             'manager' => 'default');
729
730         //  catch case for default page, ie, home
731         if (empty($str)) {
732             return $default;
733         }
734         $parts = array_filter(explode('/', $str), 'strlen');
735         $numElems = count($parts);
736
737         //  we need at least 2 elements
738         if ($numElems < 2) {
739             return $default;
740         }
741         $ret['module'] = $parts[0];
742         $ret['manager'] = $parts[1];
743         $actionExists = (isset($parts[2]) && $parts[2] == 'action') ? true : false;
744         $ret['actionMapping'] = ($actionExists) ? $parts[3] : null;
745
746         //  parse params
747         $idx = ($actionExists) ? 4 : 2;
748
749         //  break out if no params detected
750         if ($numElems <= $idx) {
751             return $ret;
752         }
753         $aTmp = array();
754         for ($x = $idx; $x < $numElems; $x++) {
755             if ($x % 2) { // if index is odd
756                 $aTmp['varValue'] = urldecode($parts[$x]);
757             } else {
758                 // parsing the parameters
759                 $aTmp['varName'] = urldecode($parts[$x]);
760             }
761             //  if a name/value pair exists, add it to request
762             if (count($aTmp) == 2) {
763                 $ret['parsed_params'][$aTmp['varName']] = $aTmp['varValue'];
764                 $aTmp = array();
765             }
766         }
767         return $ret;
768     }
769
770     /**
771      * Checks to see if cookies are enabled, if not, session id is added to URL.
772      *
773      * PHP's magic querystring functionality is negated in SimpleNav::getTabsByRid(),
774      * in other words, the ?PHPSESSID=aeff023230323 is stripped out
775      *
776      * @param string $url
777      * @return void
778      */
779     function addSessionInfo(&$url)
780     {
781         $c = &SGL_Config::singleton();
782         $conf = $c->getAll();
783         if ($conf['session']['allowedInUri']) {
784
785             //  determine is session propagated in cookies or URL
786             $sessionInfo = defined('SID') ? SID : '';
787             if (!empty($sessionInfo)) {
788
789                 //  determine glue
790                 $glue = (preg_match("/\?pageID/i", $url)) ? '&' : '?';
791                 $url .= $glue . $sessionInfo . '&/1/';
792             }
793         }
794     }
795
796     /**
797      * Removes the session name and session value elements from an array.
798      *
799      * @param array $aUrl
800      */
801     function removeSessionInfo(&$aUrl)
802     {
803         $c = &SGL_Config::singleton();
804         $conf = $c->getAll();
805         $key = array_search($conf['cookie']['name'], $aUrl);
806         if ($key !== false) {
807             unset($aUrl[$key], $aUrl[$key + 1]);
808         }
809     }
810
811     function removeStrategies()
812     {
813         unset($this->aStrategies);
814     }
815
816     /**
817      * Returns an array of all elements from the front controller script name onwards,
818      * including the frontScriptName.
819      *
820      * @access  public
821      * @static
822      *
823      * @param   string  $url        Url to be parsed
824      * @return  array   $aUriParts  An array of all significant parts of the URL, ie
825      *                              from the front controller script name onwards
826      */
827     function toPartialArray($url, $frontScriptName)
828     {
829         //  split elements (remove eventual leading/trailing slashes)
830         $aUriParts = explode('/', trim($url, '/'));
831
832         if ($frontScriptName != false) {
833             //  step through array and strip until fc element is reached
834             foreach ($aUriParts as $elem) {
835                 if ($elem != $frontScriptName) {
836                     array_shift($aUriParts);
837                 } else {
838                     break;
839                 }
840             }
841         } else {
842             $pathFromServer = (dirname($_SERVER['SCRIPT_NAME']) == DIRECTORY_SEPARATOR)
843                 ? ''
844                 : dirname($_SERVER['SCRIPT_NAME']); //=> /seagull/trunk/www
845             if (!empty($pathFromServer)) {
846                 foreach ($aUriParts as $elem) {
847                     if (stristr($pathFromServer, $elem)) {
848                         array_shift($aUriParts);
849                     } else {
850                         break;
851                     }
852                 }
853             }
854         }
855         return $aUriParts;
856     }
857 }
858
859 /**
860  * Abstract url parser strategy
861  *
862  * @abstract
863  */
864 class SGL_UrlParserStrategy
865 {
866     function parseQueryString() {}
867
868     function makeLink($action, $mgr, $mod, $aList, $params, $idx, $output) {}
869 }
870 ?>
871
Note: See TracBrowser for help on using the browser.