Development

/branches/1.1/lib/controller/sfWebController.class.php

You must first sign up to be able to contribute.

root/branches/1.1/lib/controller/sfWebController.class.php

Revision 9956, 5.4 kB (checked in by fabien, 6 years ago)

fixed convertUrlStringToParameters breaks urlencoded parameter (closes #3788)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev Date
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  * (c) 2004-2006 Sean Kerr <sean@code-box.org>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * sfWebController provides web specific methods to sfController such as, url redirection.
14  *
15  * @package    symfony
16  * @subpackage controller
17  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
18  * @author     Sean Kerr <sean@code-box.org>
19  * @version    SVN: $Id$
20  */
21 abstract class sfWebController extends sfController
22 {
23   /**
24    * Generates an URL from an array of parameters.
25    *
26    * @param mixed   $parameters An associative array of URL parameters or an internal URI as a string.
27    * @param boolean $absolute   Whether to generate an absolute URL
28    *
29    * @return string A URL to a symfony resource
30    */
31   public function genUrl($parameters = array(), $absolute = false)
32   {
33     // absolute URL or symfony URL?
34     if (!is_array($parameters) && preg_match('#^[a-z][a-z0-9\+.\-]*\://#i', $parameters))
35     {
36       return $parameters;
37     }
38
39     if (!is_array($parameters) && $parameters == '#')
40     {
41       return $parameters;
42     }
43
44     $url = $this->context->getRequest()->getRelativeUrlRoot();
45
46     if (!sfConfig::get('sf_no_script_name'))
47     {
48       $scriptName = $this->context->getRequest()->getScriptName();
49       $url = is_null($url) ? $scriptName : $url.'/'.basename($scriptName);
50     }
51
52     $route_name = '';
53     $fragment = '';
54
55     if (!is_array($parameters))
56     {
57       // strip fragment
58       if (false !== ($pos = strpos($parameters, '#')))
59       {
60         $fragment = substr($parameters, $pos + 1);
61         $parameters = substr($parameters, 0, $pos);
62       }
63
64       list($route_name, $parameters) = $this->convertUrlStringToParameters($parameters);
65     }
66
67     if (sfConfig::get('sf_url_format') == 'PATH')
68     {
69       // use PATH format
70       $divider = '/';
71       $equals  = '/';
72       $querydiv = '/';
73     }
74     else
75     {
76       // use GET format
77       $divider = ini_get('arg_separator.output');
78       $equals  = '=';
79       $querydiv = '?';
80     }
81
82     // routing to generate path
83     $url .= $this->context->getRouting()->generate($route_name, $parameters, $querydiv, $divider, $equals);
84
85     if ($absolute)
86     {
87       $request = $this->context->getRequest();
88       $url = 'http'.($request->isSecure() ? 's' : '').'://'.$request->getHost().$url;
89     }
90
91     if ($fragment)
92     {
93       $url .= '#'.$fragment;
94     }
95
96     return $url;
97   }
98
99   /**
100    * Converts an internal URI string to an array of parameters.
101    *
102    * @param string $url An internal URI
103    *
104    * @return array An array of parameters
105    */
106   public function convertUrlStringToParameters($url)
107   {
108     $givenUrl = $url;
109
110     $params       = array();
111     $query_string = '';
112     $route_name   = '';
113
114     // empty url?
115     if (!$url)
116     {
117       $url = '/';
118     }
119
120     // we get the query string out of the url
121     if ($pos = strpos($url, '?'))
122     {
123       $query_string = substr($url, $pos + 1);
124       $url = substr($url, 0, $pos);
125     }
126
127     // 2 url forms
128     // @route_name?key1=value1&key2=value2...
129     // module/action?key1=value1&key2=value2...
130
131     // first slash optional
132     if ($url[0] == '/')
133     {
134       $url = substr($url, 1);
135     }
136
137
138     // route_name?
139     if ($url[0] == '@')
140     {
141       $route_name = substr($url, 1);
142     }
143     else if (false !== strpos($url, '/'))
144     {
145       list($params['module'], $params['action']) = explode('/', $url);
146     }
147     else
148     {
149       throw new InvalidArgumentException(sprintf('An internal URI must contain a module and an action (module/action) ("%s" given).', $givenUrl));
150     }
151
152     // split the query string
153     if ($query_string)
154     {
155       $matched = preg_match_all('/
156         ([^&=]+)            # key
157         =                   # =
158         (.*?)               # value
159         (?:
160           (?=&[^&=]+=) | $  # followed by another key= or the end of the string
161         )
162       /x', $query_string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
163       foreach ($matches as $match)
164       {
165         $params[urldecode($match[1][0])] = urldecode($match[2][0]);
166       }
167
168       // check that all string is matched
169       if (!$matched)
170       {
171         throw new sfParseException(sprintf('Unable to parse query string "%s".', $query_string));
172       }
173     }
174
175     return array($route_name, $params);
176   }
177
178   /**
179    * Redirects the request to another URL.
180    *
181    * @param string $url         An existing URL
182    * @param int    $delay       A delay in seconds before redirecting. This is only needed on
183    *                            browsers that do not support HTTP headers
184    * @param int    $statusCode  The status code
185    */
186   public function redirect($url, $delay = 0, $statusCode = 302)
187   {
188     $url = $this->genUrl($url, true);
189
190     if (sfConfig::get('sf_logging_enabled'))
191     {
192       $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Redirect to "%s"', $url))));
193     }
194
195     // redirect
196     $response = $this->context->getResponse();
197     $response->clearHttpHeaders();
198     $response->setStatusCode($statusCode);
199     $response->setHttpHeader('Location', $url);
200     $response->setContent(sprintf('<html><head><meta http-equiv="refresh" content="%d;url=%s"/></head></html>', $delay, htmlspecialchars($url, ENT_QUOTES, sfConfig::get('sf_charset'))));
201     $response->send();
202   }
203 }
204
Note: See TracBrowser for help on using the browser.