Development

/branches/1.0/lib/filter/sfExecutionFilter.class.php

You must first sign up to be able to contribute.

root/branches/1.0/lib/filter/sfExecutionFilter.class.php

Revision 8922, 7.4 kB (checked in by fabien, 6 years ago)

fixed yml validator file can be overriden by a remote attacker (closes #1617 - based on a patch from Carl.Vondrick)

  • 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  * sfExecutionFilter is the last filter registered for each filter chain. This
14  * filter does all action and view execution.
15  *
16  * @package    symfony
17  * @subpackage filter
18  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
19  * @author     Sean Kerr <sean@code-box.org>
20  * @version    SVN: $Id$
21  */
22 class sfExecutionFilter extends sfFilter
23 {
24   /**
25    * Executes this filter.
26    *
27    * @param sfFilterChain The filter chain
28    *
29    * @throws <b>sfInitializeException</b> If an error occurs during view initialization.
30    * @throws <b>sfViewException</b>       If an error occurs while executing the view.
31    */
32   public function execute($filterChain)
33   {
34     // get the context and controller
35     $context    = $this->getContext();
36     $controller = $context->getController();
37
38     // get the current action instance
39     $actionEntry    = $controller->getActionStack()->getLastEntry();
40     $actionInstance = $actionEntry->getActionInstance();
41
42     // get the current action information
43     $moduleName = $context->getModuleName();
44     $actionName = $context->getActionName();
45
46     // get the request method
47     $method = $context->getRequest()->getMethod();
48
49     $viewName = null;
50
51     if (sfConfig::get('sf_cache'))
52     {
53       $uri = sfRouting::getInstance()->getCurrentInternalUri();
54       if (null !== $context->getResponse()->getParameter($uri.'_action', null, 'symfony/cache'))
55       {
56         // action in cache, so go to the view
57         $viewName = sfView::SUCCESS;
58       }
59     }
60
61     if (!$viewName)
62     {
63       if (($actionInstance->getRequestMethods() & $method) != $method)
64       {
65         // this action will skip validation/execution for this method
66         // get the default view
67         $viewName = $actionInstance->getDefaultView();
68       }
69       else
70       {
71         // set default validated status
72         $validated = true;
73
74         // the case of the first letter of the action is insignificant
75         // get the current action validation configuration
76         $validationConfigWithFirstLetterLower = $moduleName.'/'.sfConfig::get('sf_app_module_validate_dir_name').'/'.strtolower(substr($actionName, 0, 1)).substr($actionName, 1).'.yml';
77         $validationConfigWithFirstLetterUpper = $moduleName.'/'.sfConfig::get('sf_app_module_validate_dir_name').'/'.ucfirst($actionName).'.yml';
78
79         // determine $validateFile by testing both the uppercase and lowercase
80         // types of validation configurations.
81         $validateFile = null;
82         if (!is_null($testValidateFile = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$validationConfigWithFirstLetterLower, true)))
83         {
84           $validateFile = $testValidateFile;
85         }
86         else if (!is_null($testValidateFile = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$validationConfigWithFirstLetterUpper, true)))
87         {
88           $validateFile = $testValidateFile;
89         }
90
91         // load validation configuration
92         // do NOT use require_once
93         if (!is_null($validateFile))
94         {
95           // create validator manager
96           $validatorManager = new sfValidatorManager();
97           $validatorManager->initialize($context);
98
99           require($validateFile);
100
101           // process validators
102           $validated = $validatorManager->execute();
103         }
104
105         // process manual validation
106         $validateToRun = 'validate'.ucfirst($actionName);
107         $manualValidated = method_exists($actionInstance, $validateToRun) ? $actionInstance->$validateToRun() : $actionInstance->validate();
108
109         // action is validated if:
110         // - all validation methods (manual and automatic) return true
111         // - or automatic validation returns false but errors have been 'removed' by manual validation
112         $validated = ($manualValidated && $validated) || ($manualValidated && !$validated && !$context->getRequest()->hasErrors());
113
114         // register fill-in filter
115         if (null !== ($parameters = $context->getRequest()->getAttribute('fillin', null, 'symfony/filter')))
116         {
117           $this->registerFillInFilter($filterChain, $parameters);
118         }
119
120         if ($validated)
121         {
122           if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
123           {
124             $timer = sfTimerManager::getTimer(sprintf('Action "%s/%s"', $moduleName, $actionName));
125           }
126
127           // execute the action
128           $actionInstance->preExecute();
129           $viewName = $actionInstance->execute();
130           if ($viewName == '')
131           {
132             $viewName = sfView::SUCCESS;
133           }
134           $actionInstance->postExecute();
135
136           if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
137           {
138             $timer->addTime();
139           }
140         }
141         else
142         {
143           if (sfConfig::get('sf_logging_enabled'))
144           {
145             $this->context->getLogger()->info('{sfFilter} action validation failed');
146           }
147
148           // validation failed
149           $handleErrorToRun = 'handleError'.ucfirst($actionName);
150           $viewName = method_exists($actionInstance, $handleErrorToRun) ? $actionInstance->$handleErrorToRun() : $actionInstance->handleError();
151           if ($viewName == '')
152           {
153             $viewName = sfView::ERROR;
154           }
155         }
156       }
157     }
158
159     if ($viewName == sfView::HEADER_ONLY)
160     {
161       $context->getResponse()->setHeaderOnly(true);
162
163       // execute next filter
164       $filterChain->execute();
165     }
166     else if ($viewName != sfView::NONE)
167     {
168       if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
169       {
170         $timer = sfTimerManager::getTimer(sprintf('View "%s" for "%s/%s"', $viewName, $moduleName, $actionName));
171       }
172
173       // get the view instance
174       $viewInstance = $controller->getView($moduleName, $actionName, $viewName);
175
176       $viewInstance->initialize($context, $moduleName, $actionName, $viewName);
177
178       $viewInstance->execute();
179
180       // render the view and if data is returned, stick it in the
181       // action entry which was retrieved from the execution chain
182       $viewData = $viewInstance->render();
183
184       if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
185       {
186         $timer->addTime();
187       }
188
189       if ($controller->getRenderMode() == sfView::RENDER_VAR)
190       {
191         $actionEntry->setPresentation($viewData);
192       }
193       else
194       {
195         // execute next filter
196         $filterChain->execute();
197       }
198     }
199   }
200
201   /**
202    * Registers the fill in filter in the filter chain.
203    *
204    * @param sfFilterChain A sfFilterChain implementation instance
205    * @param array An array of parameters to pass to the fill in filter.
206    */
207   protected function registerFillInFilter($filterChain, $parameters)
208   {
209     // automatically register the fill in filter if it is not already loaded in the chain
210     if (isset($parameters['enabled']) && $parameters['enabled'] && !$filterChain->hasFilter('sfFillInFormFilter'))
211     {
212       // register the fill in form filter
213       $fillInFormFilter = new sfFillInFormFilter();
214       $fillInFormFilter->initialize($this->context, isset($parameters['param']) ? $parameters['param'] : array());
215       $filterChain->register($fillInFormFilter);
216     }
217   }
218 }
219
Note: See TracBrowser for help on using the browser.