Anonymous avatar Anonymous committed 0039291

security improvements and small fixes

Comments (0)

Files changed (3)

 	final public function getView() { return empty($this->view) ? $this->action : $this->view; }
 
 	/**
-	 * Overwrite the template lookup path for this controller.
+	 * Overwrites the template lookup path for this controller.
 	 *
 	 * @var string
 	 */
 	var $args = array();
 
 	/**
-	 * @var string Name of the layout template (without extension).
+	 * Name of the layout template (without extension).
+	 *
+	 * @var string
 	 */
 	var $pageTitle = "";
 
 	final public function get($key) { return maread($key, $this->vars); }
 
 	/**
-	 * @var array Page HTTP headers.
+	 * Page HTTP headers.
+	 *
+	 * @var array
 	 * @since 0.2
 	 */
 	protected $headers = array();
 
 
 	/**
-	 * Perform a controller action.
+	 * Performs a controller action.
 	 *
 	 * @param string $action Action name or null.
 	 * @uses beforeAction()
 	{
 		$action = empty($action) ? $this->action : $action;
 		$this->action = $action;
+
+		// check the action method
+		if (!is_string($action) || empty($action))
+			// action is not a string or empty
+			throw new Exception("Invalid action: '$action'");
+		if (method_exists($this, $action))
+		{
+			$class = new ReflectionClass(get_class());
+			$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);
+			$internal = false;
+			foreach ($methods as $item)
+				if (in_array($item['name'], $methods))
+				{
+					$internal = true;
+					break;
+				}
+			if ($internal)
+				// internally defined Controller method
+				throw new Exception("Invalid action: '$action'");
+			$method = new ReflectionMethod($this, $sMethod);
+			if (!$method->isPublic() || $action[0] == '_')
+				// method is not public or starts with _
+				throw new Exception("Invalid action: '$action'");
+		} else
+			// method does not exist
+			throw new Exception("Invalid action: '$action'");
 		$this->beforeAction();
-		foreach ($this->helpers as $helper_id => $helper_opts)
-			if (is_numeric($helper_id))
-				$this->components []= $helper_opts;
-			else
-				$this->components[$helper_id] = $this->helpers[$helper_id];
 		$this->loadComponents();
 		$this->loadModels();
-		$code = sprintf('$this->%s(%s);', $action, implode(", ", quotes($this->args)));
-		eval($code);
+		call_user_func_array(array($this, $action), $this->args);
 		$this->afterAction();
 	}
 
 			// look for an appropriate content type
 			$types = Config::get("content_types");
 			$fallback = false;
-
 			foreach ($types as $alias => $mime)
 			{
 				if ($this->accepts($alias))
 					break;
 				}
 			}
-
 			if (!$fallback)
 				htthrow(406);
 		}
 	 */
 	public function afterRender() { }
 }
-?>
+?>
 	{
 		if ($this->loaded)
 			return;
+		// load the helpers as other components
+		foreach ($this->helpers as $helper_id => $helper_opts)
+			if (is_numeric($helper_id))
+				$this->components []= $helper_opts;
+			else
+				$this->components[$helper_id] = $this->helpers[$helper_id];
 		foreach ($this->components as $name => $opts)
 		{
 			$options = array();
 			}
 		}
 
-		$ctrl->doAction();
-		$ctrl->render();
-		$ctrl->sendHeaders();
-		echo $ctrl->content;
+		try {
+			$ctrl->doAction();
+			$ctrl->render();
+			$ctrl->sendHeaders();
+			echo $ctrl->content;
+		} catch (Exception $e)
+		{
+			if (Config::debug() > 0)
+				self::launchErrorController("action_not_found");
+			else
+				self::launchErrorController("not_found");
+		}
 	}
 
 	/**
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.