parent
33bb2238ae
commit
fde9cabe97
@ -0,0 +1,97 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework; |
||||
|
||||
use OC\AppFramework\DependencyInjection\DIContainer; |
||||
|
||||
|
||||
/** |
||||
* Entry point for every request in your app. You can consider this as your |
||||
* public static void main() method |
||||
* |
||||
* Handles all the dependency injection, controllers and output flow |
||||
*/ |
||||
class App { |
||||
|
||||
|
||||
/** |
||||
* Shortcut for calling a controller method and printing the result |
||||
* @param string $controllerName the name of the controller under which it is |
||||
* stored in the DI container |
||||
* @param string $methodName the method that you want to call |
||||
* @param array $urlParams an array with variables extracted from the routes |
||||
* @param DIContainer $container an instance of a pimple container. |
||||
*/ |
||||
public static function main($controllerName, $methodName, array $urlParams, |
||||
DIContainer $container) { |
||||
$container['urlParams'] = $urlParams; |
||||
$controller = $container[$controllerName]; |
||||
|
||||
// initialize the dispatcher and run all the middleware before the controller |
||||
$dispatcher = $container['Dispatcher']; |
||||
|
||||
list($httpHeaders, $responseHeaders, $output) = |
||||
$dispatcher->dispatch($controller, $methodName); |
||||
|
||||
if(!is_null($httpHeaders)) { |
||||
header($httpHeaders); |
||||
} |
||||
|
||||
foreach($responseHeaders as $name => $value) { |
||||
header($name . ': ' . $value); |
||||
} |
||||
|
||||
if(!is_null($output)) { |
||||
header('Content-Length: ' . strlen($output)); |
||||
print($output); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Shortcut for calling a controller method and printing the result. |
||||
* Similar to App:main except that no headers will be sent. |
||||
* This should be used for example when registering sections via |
||||
* \OC\AppFramework\Core\API::registerAdmin() |
||||
* |
||||
* @param string $controllerName the name of the controller under which it is |
||||
* stored in the DI container |
||||
* @param string $methodName the method that you want to call |
||||
* @param array $urlParams an array with variables extracted from the routes |
||||
* @param DIContainer $container an instance of a pimple container. |
||||
*/ |
||||
public static function part($controllerName, $methodName, array $urlParams, |
||||
DIContainer $container){ |
||||
|
||||
$container['urlParams'] = $urlParams; |
||||
$controller = $container[$controllerName]; |
||||
|
||||
$dispatcher = $container['Dispatcher']; |
||||
|
||||
list(, , $output) = $dispatcher->dispatch($controller, $methodName); |
||||
return $output; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,154 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Controller; |
||||
|
||||
use OC\AppFramework\Http\TemplateResponse; |
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Core\API; |
||||
|
||||
|
||||
/** |
||||
* Base class to inherit your controllers from |
||||
*/ |
||||
abstract class Controller { |
||||
|
||||
/** |
||||
* @var API instance of the api layer |
||||
*/ |
||||
protected $api; |
||||
|
||||
protected $request; |
||||
|
||||
/** |
||||
* @param API $api an api wrapper instance |
||||
* @param Request $request an instance of the request |
||||
*/ |
||||
public function __construct(API $api, Request $request){ |
||||
$this->api = $api; |
||||
$this->request = $request; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Lets you access post and get parameters by the index |
||||
* @param string $key the key which you want to access in the URL Parameter |
||||
* placeholder, $_POST or $_GET array. |
||||
* The priority how they're returned is the following: |
||||
* 1. URL parameters |
||||
* 2. POST parameters |
||||
* 3. GET parameters |
||||
* @param mixed $default If the key is not found, this value will be returned |
||||
* @return mixed the content of the array |
||||
*/ |
||||
public function params($key, $default=null){ |
||||
return isset($this->request->parameters[$key]) |
||||
? $this->request->parameters[$key] |
||||
: $default; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns all params that were received, be it from the request |
||||
* (as GET or POST) or throuh the URL by the route |
||||
* @return array the array with all parameters |
||||
*/ |
||||
public function getParams() { |
||||
return $this->request->parameters; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the method of the request |
||||
* @return string the method of the request (POST, GET, etc) |
||||
*/ |
||||
public function method() { |
||||
return $this->request->method; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for accessing an uploaded file through the $_FILES array |
||||
* @param string $key the key that will be taken from the $_FILES array |
||||
* @return array the file in the $_FILES element |
||||
*/ |
||||
public function getUploadedFile($key) { |
||||
return isset($this->request->files[$key]) ? $this->request->files[$key] : null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for getting env variables |
||||
* @param string $key the key that will be taken from the $_ENV array |
||||
* @return array the value in the $_ENV element |
||||
*/ |
||||
public function env($key) { |
||||
return isset($this->request->env[$key]) ? $this->request->env[$key] : null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for getting session variables |
||||
* @param string $key the key that will be taken from the $_SESSION array |
||||
* @return array the value in the $_SESSION element |
||||
*/ |
||||
public function session($key) { |
||||
return isset($this->request->session[$key]) ? $this->request->session[$key] : null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for getting cookie variables |
||||
* @param string $key the key that will be taken from the $_COOKIE array |
||||
* @return array the value in the $_COOKIE element |
||||
*/ |
||||
public function cookie($key) { |
||||
return isset($this->request->cookies[$key]) ? $this->request->cookies[$key] : null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for rendering a template |
||||
* @param string $templateName the name of the template |
||||
* @param array $params the template parameters in key => value structure |
||||
* @param string $renderAs user renders a full page, blank only your template |
||||
* admin an entry in the admin settings |
||||
* @param array $headers set additional headers in name/value pairs |
||||
* @return \OC\AppFramework\Http\TemplateResponse containing the page |
||||
*/ |
||||
public function render($templateName, array $params=array(), |
||||
$renderAs='user', array $headers=array()){ |
||||
$response = new TemplateResponse($this->api, $templateName); |
||||
$response->setParams($params); |
||||
$response->renderAs($renderAs); |
||||
|
||||
foreach($headers as $name => $value){ |
||||
$response->addHeader($name, $value); |
||||
} |
||||
|
||||
return $response; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,524 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Core; |
||||
|
||||
|
||||
/** |
||||
* This is used to wrap the owncloud static api calls into an object to make the |
||||
* code better abstractable for use in the dependency injection container |
||||
* |
||||
* Should you find yourself in need for more methods, simply inherit from this |
||||
* class and add your methods |
||||
*/ |
||||
class API { |
||||
|
||||
private $appName; |
||||
|
||||
/** |
||||
* constructor |
||||
* @param string $appName the name of your application |
||||
*/ |
||||
public function __construct($appName){ |
||||
$this->appName = $appName; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* used to return the appname of the set application |
||||
* @return string the name of your application |
||||
*/ |
||||
public function getAppName(){ |
||||
return $this->appName; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Creates a new navigation entry |
||||
* @param array $entry containing: id, name, order, icon and href key |
||||
*/ |
||||
public function addNavigationEntry(array $entry){ |
||||
\OCP\App::addNavigationEntry($entry); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Gets the userid of the current user |
||||
* @return string the user id of the current user |
||||
*/ |
||||
public function getUserId(){ |
||||
return \OCP\User::getUser(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the current navigation entry to the currently running app |
||||
*/ |
||||
public function activateNavigationEntry(){ |
||||
\OCP\App::setActiveNavigationEntry($this->appName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a new javascript file |
||||
* @param string $scriptName the name of the javascript in js/ without the suffix |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
*/ |
||||
public function addScript($scriptName, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
\OCP\Util::addScript($appName, $scriptName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a new css file |
||||
* @param string $styleName the name of the css file in css/without the suffix |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
*/ |
||||
public function addStyle($styleName, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
\OCP\Util::addStyle($appName, $styleName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* shorthand for addScript for files in the 3rdparty directory |
||||
* @param string $name the name of the file without the suffix |
||||
*/ |
||||
public function add3rdPartyScript($name){ |
||||
\OCP\Util::addScript($this->appName . '/3rdparty', $name); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* shorthand for addStyle for files in the 3rdparty directory |
||||
* @param string $name the name of the file without the suffix |
||||
*/ |
||||
public function add3rdPartyStyle($name){ |
||||
\OCP\Util::addStyle($this->appName . '/3rdparty', $name); |
||||
} |
||||
|
||||
/** |
||||
* Looks up a systemwide defined value |
||||
* @param string $key the key of the value, under which it was saved |
||||
* @return string the saved value |
||||
*/ |
||||
public function getSystemValue($key){ |
||||
return \OCP\Config::getSystemValue($key, ''); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets a new systemwide value |
||||
* @param string $key the key of the value, under which will be saved |
||||
* @param string $value the value that should be stored |
||||
*/ |
||||
public function setSystemValue($key, $value){ |
||||
return \OCP\Config::setSystemValue($key, $value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Looks up an appwide defined value |
||||
* @param string $key the key of the value, under which it was saved |
||||
* @return string the saved value |
||||
*/ |
||||
public function getAppValue($key, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
return \OCP\Config::getAppValue($appName, $key, ''); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Writes a new appwide value |
||||
* @param string $key the key of the value, under which will be saved |
||||
* @param string $value the value that should be stored |
||||
*/ |
||||
public function setAppValue($key, $value, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
return \OCP\Config::setAppValue($appName, $key, $value); |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* Shortcut for setting a user defined value |
||||
* @param string $key the key under which the value is being stored |
||||
* @param string $value the value that you want to store |
||||
* @param string $userId the userId of the user that we want to store the value under, defaults to the current one |
||||
*/ |
||||
public function setUserValue($key, $value, $userId=null){ |
||||
if($userId === null){ |
||||
$userId = $this->getUserId(); |
||||
} |
||||
\OCP\Config::setUserValue($userId, $this->appName, $key, $value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shortcut for getting a user defined value |
||||
* @param string $key the key under which the value is being stored |
||||
* @param string $userId the userId of the user that we want to store the value under, defaults to the current one |
||||
*/ |
||||
public function getUserValue($key, $userId=null){ |
||||
if($userId === null){ |
||||
$userId = $this->getUserId(); |
||||
} |
||||
return \OCP\Config::getUserValue($userId, $this->appName, $key); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the translation object |
||||
* @return \OC_L10N the translation object |
||||
*/ |
||||
public function getTrans(){ |
||||
# TODO: use public api |
||||
return \OC_L10N::get($this->appName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Used to abstract the owncloud database access away |
||||
* @param string $sql the sql query with ? placeholder for params |
||||
* @param int $limit the maximum number of rows |
||||
* @param int $offset from which row we want to start |
||||
* @return \OCP\DB a query object |
||||
*/ |
||||
public function prepareQuery($sql, $limit=null, $offset=null){ |
||||
return \OCP\DB::prepare($sql, $limit, $offset); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Used to get the id of the just inserted element |
||||
* @param string $tableName the name of the table where we inserted the item |
||||
* @return int the id of the inserted element |
||||
*/ |
||||
public function getInsertId($tableName){ |
||||
return \OCP\DB::insertid($tableName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the URL for a route |
||||
* @param string $routeName the name of the route |
||||
* @param array $arguments an array with arguments which will be filled into the url |
||||
* @return string the url |
||||
*/ |
||||
public function linkToRoute($routeName, $arguments=array()){ |
||||
return \OCP\Util::linkToRoute($routeName, $arguments); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns an URL for an image or file |
||||
* @param string $file the name of the file |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
*/ |
||||
public function linkTo($file, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
return \OCP\Util::linkTo($appName, $file); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the link to an image, like link to but only with prepending img/ |
||||
* @param string $file the name of the file |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
*/ |
||||
public function imagePath($file, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
return \OCP\Util::imagePath($appName, $file); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Makes an URL absolute |
||||
* @param string $url the url |
||||
* @return string the absolute url |
||||
*/ |
||||
public function getAbsoluteURL($url){ |
||||
# TODO: use public api |
||||
return \OC_Helper::makeURLAbsolute($url); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* links to a file |
||||
* @param string $file the name of the file |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
* @deprecated replaced with linkToRoute() |
||||
* @return string the url |
||||
*/ |
||||
public function linkToAbsolute($file, $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
return \OCP\Util::linkToAbsolute($appName, $file); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Checks if the current user is logged in |
||||
* @return bool true if logged in |
||||
*/ |
||||
public function isLoggedIn(){ |
||||
return \OCP\User::isLoggedIn(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Checks if a user is an admin |
||||
* @param string $userId the id of the user |
||||
* @return bool true if admin |
||||
*/ |
||||
public function isAdminUser($userId){ |
||||
# TODO: use public api |
||||
return \OC_User::isAdminUser($userId); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Checks if a user is an subadmin |
||||
* @param string $userId the id of the user |
||||
* @return bool true if subadmin |
||||
*/ |
||||
public function isSubAdminUser($userId){ |
||||
# TODO: use public api |
||||
return \OC_SubAdmin::isSubAdmin($userId); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Checks if the CSRF check was correct |
||||
* @return bool true if CSRF check passed |
||||
*/ |
||||
public function passesCSRFCheck(){ |
||||
# TODO: use public api |
||||
return \OC_Util::isCallRegistered(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Checks if an app is enabled |
||||
* @param string $appName the name of an app |
||||
* @return bool true if app is enabled |
||||
*/ |
||||
public function isAppEnabled($appName){ |
||||
return \OCP\App::isEnabled($appName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Writes a function into the error log |
||||
* @param string $msg the error message to be logged |
||||
* @param int $level the error level |
||||
*/ |
||||
public function log($msg, $level=null){ |
||||
switch($level){ |
||||
case 'debug': |
||||
$level = \OCP\Util::DEBUG; |
||||
break; |
||||
case 'info': |
||||
$level = \OCP\Util::INFO; |
||||
break; |
||||
case 'warn': |
||||
$level = \OCP\Util::WARN; |
||||
break; |
||||
case 'fatal': |
||||
$level = \OCP\Util::FATAL; |
||||
break; |
||||
default: |
||||
$level = \OCP\Util::ERROR; |
||||
break; |
||||
} |
||||
\OCP\Util::writeLog($this->appName, $msg, $level); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a template |
||||
* @param string $templateName the name of the template |
||||
* @param string $renderAs how it should be rendered |
||||
* @param string $appName the name of the app |
||||
* @return \OCP\Template a new template |
||||
*/ |
||||
public function getTemplate($templateName, $renderAs='user', $appName=null){ |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
|
||||
if($renderAs === 'blank'){ |
||||
return new \OCP\Template($appName, $templateName); |
||||
} else { |
||||
return new \OCP\Template($appName, $templateName, $renderAs); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* turns an owncloud path into a path on the filesystem |
||||
* @param string path the path to the file on the oc filesystem |
||||
* @return string the filepath in the filesystem |
||||
*/ |
||||
public function getLocalFilePath($path){ |
||||
# TODO: use public api |
||||
return \OC_Filesystem::getLocalFile($path); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* used to return and open a new eventsource |
||||
* @return \OC_EventSource a new open EventSource class |
||||
*/ |
||||
public function openEventSource(){ |
||||
# TODO: use public api |
||||
return new \OC_EventSource(); |
||||
} |
||||
|
||||
/** |
||||
* @brief connects a function to a hook |
||||
* @param string $signalClass class name of emitter |
||||
* @param string $signalName name of signal |
||||
* @param string $slotClass class name of slot |
||||
* @param string $slotName name of slot, in another word, this is the |
||||
* name of the method that will be called when registered |
||||
* signal is emitted. |
||||
* @return bool, always true |
||||
*/ |
||||
public function connectHook($signalClass, $signalName, $slotClass, $slotName) { |
||||
return \OCP\Util::connectHook($signalClass, $signalName, $slotClass, $slotName); |
||||
} |
||||
|
||||
/** |
||||
* @brief Emits a signal. To get data from the slot use references! |
||||
* @param string $signalClass class name of emitter |
||||
* @param string $signalName name of signal |
||||
* @param array $params defautl: array() array with additional data |
||||
* @return bool, true if slots exists or false if not |
||||
*/ |
||||
public function emitHook($signalClass, $signalName, $params = array()) { |
||||
return \OCP\Util::emitHook($signalClass, $signalName, $params); |
||||
} |
||||
|
||||
/** |
||||
* @brief clear hooks |
||||
* @param string $signalClass |
||||
* @param string $signalName |
||||
*/ |
||||
public function clearHook($signalClass=false, $signalName=false) { |
||||
if ($signalClass) { |
||||
\OC_Hook::clear($signalClass, $signalName); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets the content of an URL by using CURL or a fallback if it is not |
||||
* installed |
||||
* @param string $url the url that should be fetched |
||||
* @return string the content of the webpage |
||||
*/ |
||||
public function getUrlContent($url) { |
||||
return \OC_Util::getUrlContent($url); |
||||
} |
||||
|
||||
/** |
||||
* Register a backgroundjob task |
||||
* @param string $className full namespace and class name of the class |
||||
* @param string $methodName the name of the static method that should be |
||||
* called |
||||
*/ |
||||
public function addRegularTask($className, $methodName) { |
||||
\OCP\Backgroundjob::addRegularTask($className, $methodName); |
||||
} |
||||
|
||||
/** |
||||
* Tells ownCloud to include a template in the admin overview |
||||
* @param string $mainPath the path to the main php file without the php |
||||
* suffix, relative to your apps directory! not the template directory |
||||
* @param string $appName the name of the app, defaults to the current one |
||||
*/ |
||||
public function registerAdmin($mainPath, $appName=null) { |
||||
if($appName === null){ |
||||
$appName = $this->appName; |
||||
} |
||||
|
||||
\OCP\App::registerAdmin($appName, $mainPath); |
||||
} |
||||
|
||||
/** |
||||
* Do a user login |
||||
* @param string $user the username |
||||
* @param string $password the password |
||||
* @return bool true if successful |
||||
*/ |
||||
public function login($user, $password) { |
||||
return \OC_User::login($user, $password); |
||||
} |
||||
|
||||
/** |
||||
* @brief Loggs the user out including all the session data |
||||
* Logout, destroys session |
||||
*/ |
||||
public function logout() { |
||||
return \OCP\User::logout(); |
||||
} |
||||
|
||||
/** |
||||
* get the filesystem info |
||||
* |
||||
* @param string $path |
||||
* @return array with the following keys: |
||||
* - size |
||||
* - mtime |
||||
* - mimetype |
||||
* - encrypted |
||||
* - versioned |
||||
*/ |
||||
public function getFileInfo($path) { |
||||
return \OC\Files\Filesystem::getFileInfo($path); |
||||
} |
||||
|
||||
/** |
||||
* get the view |
||||
* |
||||
* @return OC\Files\View instance |
||||
*/ |
||||
public function getView() { |
||||
return \OC\Files\Filesystem::getView(); |
||||
} |
||||
} |
||||
@ -0,0 +1,125 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\DependencyInjection; |
||||
|
||||
use OC\AppFramework\Http\Http; |
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Http\Dispatcher; |
||||
use OC\AppFramework\Core\API; |
||||
use OC\AppFramework\Middleware\MiddlewareDispatcher; |
||||
use OC\AppFramework\Middleware\Http\HttpMiddleware; |
||||
use OC\AppFramework\Middleware\Security\SecurityMiddleware; |
||||
use OC\AppFramework\Utility\TimeFactory; |
||||
|
||||
// register 3rdparty autoloaders |
||||
require_once __DIR__ . '/../../../../3rdparty/Pimple/Pimple.php'; |
||||
|
||||
|
||||
/** |
||||
* This class extends Pimple (http://pimple.sensiolabs.org/) for reusability |
||||
* To use this class, extend your own container from this. Should you require it |
||||
* you can overwrite the dependencies with your own classes by simply redefining |
||||
* a dependency |
||||
*/ |
||||
class DIContainer extends \Pimple { |
||||
|
||||
|
||||
/** |
||||
* Put your class dependencies in here |
||||
* @param string $appName the name of the app |
||||
*/ |
||||
public function __construct($appName){ |
||||
|
||||
$this['AppName'] = $appName; |
||||
|
||||
$this['API'] = $this->share(function($c){ |
||||
return new API($c['AppName']); |
||||
}); |
||||
|
||||
/** |
||||
* Http |
||||
*/ |
||||
$this['Request'] = $this->share(function($c) { |
||||
$params = json_decode(file_get_contents('php://input'), true); |
||||
$params = is_array($params) ? $params: array(); |
||||
|
||||
return new Request( |
||||
array( |
||||
'get' => $_GET, |
||||
'post' => $_POST, |
||||
'files' => $_FILES, |
||||
'server' => $_SERVER, |
||||
'env' => $_ENV, |
||||
'session' => $_SESSION, |
||||
'cookies' => $_COOKIE, |
||||
'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD'])) |
||||
? $_SERVER['REQUEST_METHOD'] |
||||
: null, |
||||
'params' => $params, |
||||
'urlParams' => $c['urlParams'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
$this['Protocol'] = $this->share(function($c){ |
||||
if(isset($_SERVER['SERVER_PROTOCOL'])) { |
||||
return new Http($_SERVER, $_SERVER['SERVER_PROTOCOL']); |
||||
} else { |
||||
return new Http($_SERVER); |
||||
} |
||||
}); |
||||
|
||||
$this['Dispatcher'] = $this->share(function($c) { |
||||
return new Dispatcher($c['Protocol'], $c['MiddlewareDispatcher']); |
||||
}); |
||||
|
||||
|
||||
/** |
||||
* Middleware |
||||
*/ |
||||
$this['SecurityMiddleware'] = $this->share(function($c){ |
||||
return new SecurityMiddleware($c['API'], $c['Request']); |
||||
}); |
||||
|
||||
$this['MiddlewareDispatcher'] = $this->share(function($c){ |
||||
$dispatcher = new MiddlewareDispatcher(); |
||||
$dispatcher->registerMiddleware($c['SecurityMiddleware']); |
||||
|
||||
return $dispatcher; |
||||
}); |
||||
|
||||
|
||||
/** |
||||
* Utilities |
||||
*/ |
||||
$this['TimeFactory'] = $this->share(function($c){ |
||||
return new TimeFactory(); |
||||
}); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,98 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt, Thomas Tanghus, Bart Visscher |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
use \OC\AppFramework\Controller\Controller; |
||||
use \OC\AppFramework\Middleware\MiddlewareDispatcher; |
||||
|
||||
|
||||
/** |
||||
* Class to dispatch the request to the middleware disptacher |
||||
*/ |
||||
class Dispatcher { |
||||
|
||||
private $middlewareDispatcher; |
||||
private $protocol; |
||||
|
||||
|
||||
/** |
||||
* @param Http $protocol the http protocol with contains all status headers |
||||
* @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which |
||||
* runs the middleware |
||||
*/ |
||||
public function __construct(Http $protocol, |
||||
MiddlewareDispatcher $middlewareDispatcher) { |
||||
$this->protocol = $protocol; |
||||
$this->middlewareDispatcher = $middlewareDispatcher; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Handles a request and calls the dispatcher on the controller |
||||
* @param Controller $controller the controller which will be called |
||||
* @param string $methodName the method name which will be called on |
||||
* the controller |
||||
* @return array $array[0] contains a string with the http main header, |
||||
* $array[1] contains headers in the form: $key => value, $array[2] contains |
||||
* the response output |
||||
*/ |
||||
public function dispatch(Controller $controller, $methodName) { |
||||
$out = array(null, array(), null); |
||||
|
||||
try { |
||||
|
||||
$this->middlewareDispatcher->beforeController($controller, |
||||
$methodName); |
||||
$response = $controller->$methodName(); |
||||
|
||||
|
||||
// if an exception appears, the middleware checks if it can handle the |
||||
// exception and creates a response. If no response is created, it is |
||||
// assumed that theres no middleware who can handle it and the error is |
||||
// thrown again |
||||
} catch(\Exception $exception){ |
||||
$response = $this->middlewareDispatcher->afterException( |
||||
$controller, $methodName, $exception); |
||||
} |
||||
|
||||
$response = $this->middlewareDispatcher->afterController( |
||||
$controller, $methodName, $response); |
||||
|
||||
// get the output which should be printed and run the after output |
||||
// middleware to modify the response |
||||
$output = $response->render(); |
||||
$out[2] = $this->middlewareDispatcher->beforeOutput( |
||||
$controller, $methodName, $output); |
||||
|
||||
// depending on the cache object the headers need to be changed |
||||
$out[0] = $this->protocol->getStatusHeader($response->getStatus(), |
||||
$response->getLastModified(), $response->getETag()); |
||||
$out[1] = $response->getHeaders(); |
||||
|
||||
return $out; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
/** |
||||
* Prompts the user to download the a file |
||||
*/ |
||||
abstract class DownloadResponse extends Response { |
||||
|
||||
private $content; |
||||
private $filename; |
||||
private $contentType; |
||||
|
||||
/** |
||||
* Creates a response that prompts the user to download the file |
||||
* @param string $filename the name that the downloaded file should have |
||||
* @param string $contentType the mimetype that the downloaded file should have |
||||
*/ |
||||
public function __construct($filename, $contentType) { |
||||
$this->filename = $filename; |
||||
$this->contentType = $contentType; |
||||
|
||||
$this->addHeader('Content-Disposition', 'attachment; filename="' . $filename . '"'); |
||||
$this->addHeader('Content-Type', $contentType); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,208 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt, Thomas Tanghus, Bart Visscher |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
class Http { |
||||
|
||||
const STATUS_CONTINUE = 100; |
||||
const STATUS_SWITCHING_PROTOCOLS = 101; |
||||
const STATUS_PROCESSING = 102; |
||||
const STATUS_OK = 200; |
||||
const STATUS_CREATED = 201; |
||||
const STATUS_ACCEPTED = 202; |
||||
const STATUS_NON_AUTHORATIVE_INFORMATION = 203; |
||||
const STATUS_NO_CONTENT = 204; |
||||
const STATUS_RESET_CONTENT = 205; |
||||
const STATUS_PARTIAL_CONTENT = 206; |
||||
const STATUS_MULTI_STATUS = 207; |
||||
const STATUS_ALREADY_REPORTED = 208; |
||||
const STATUS_IM_USED = 226; |
||||
const STATUS_MULTIPLE_CHOICES = 300; |
||||
const STATUS_MOVED_PERMANENTLY = 301; |
||||
const STATUS_FOUND = 302; |
||||
const STATUS_SEE_OTHER = 303; |
||||
const STATUS_NOT_MODIFIED = 304; |
||||
const STATUS_USE_PROXY = 305; |
||||
const STATUS_RESERVED = 306; |
||||
const STATUS_TEMPORARY_REDIRECT = 307; |
||||
const STATUS_BAD_REQUEST = 400; |
||||
const STATUS_UNAUTHORIZED = 401; |
||||
const STATUS_PAYMENT_REQUIRED = 402; |
||||
const STATUS_FORBIDDEN = 403; |
||||
const STATUS_NOT_FOUND = 404; |
||||
const STATUS_METHOD_NOT_ALLOWED = 405; |
||||
const STATUS_NOT_ACCEPTABLE = 406; |
||||
const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407; |
||||
const STATUS_REQUEST_TIMEOUT = 408; |
||||
const STATUS_CONFLICT = 409; |
||||
const STATUS_GONE = 410; |
||||
const STATUS_LENGTH_REQUIRED = 411; |
||||
const STATUS_PRECONDITION_FAILED = 412; |
||||
const STATUS_REQUEST_ENTITY_TOO_LARGE = 413; |
||||
const STATUS_REQUEST_URI_TOO_LONG = 414; |
||||
const STATUS_UNSUPPORTED_MEDIA_TYPE = 415; |
||||
const STATUS_REQUEST_RANGE_NOT_SATISFIABLE = 416; |
||||
const STATUS_EXPECTATION_FAILED = 417; |
||||
const STATUS_IM_A_TEAPOT = 418; |
||||
const STATUS_UNPROCESSABLE_ENTITY = 422; |
||||
const STATUS_LOCKED = 423; |
||||
const STATUS_FAILED_DEPENDENCY = 424; |
||||
const STATUS_UPGRADE_REQUIRED = 426; |
||||
const STATUS_PRECONDITION_REQUIRED = 428; |
||||
const STATUS_TOO_MANY_REQUESTS = 429; |
||||
const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; |
||||
const STATUS_INTERNAL_SERVER_ERROR = 500; |
||||
const STATUS_NOT_IMPLEMENTED = 501; |
||||
const STATUS_BAD_GATEWAY = 502; |
||||
const STATUS_SERVICE_UNAVAILABLE = 503; |
||||
const STATUS_GATEWAY_TIMEOUT = 504; |
||||
const STATUS_HTTP_VERSION_NOT_SUPPORTED = 505; |
||||
const STATUS_VARIANT_ALSO_NEGOTIATES = 506; |
||||
const STATUS_INSUFFICIENT_STORAGE = 507; |
||||
const STATUS_LOOP_DETECTED = 508; |
||||
const STATUS_BANDWIDTH_LIMIT_EXCEEDED = 509; |
||||
const STATUS_NOT_EXTENDED = 510; |
||||
const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511; |
||||
|
||||
private $server; |
||||
private $protocolVersion; |
||||
protected $headers; |
||||
|
||||
/** |
||||
* @param $_SERVER $server |
||||
* @param string $protocolVersion the http version to use defaults to HTTP/1.1 |
||||
*/ |
||||
public function __construct($server, $protocolVersion='HTTP/1.1') { |
||||
$this->server = $server; |
||||
$this->protocolVersion = $protocolVersion; |
||||
|
||||
$this->headers = array( |
||||
self::STATUS_CONTINUE => 'Continue', |
||||
self::STATUS_SWITCHING_PROTOCOLS => 'Switching Protocols', |
||||
self::STATUS_PROCESSING => 'Processing', |
||||
self::STATUS_OK => 'OK', |
||||
self::STATUS_CREATED => 'Created', |
||||
self::STATUS_ACCEPTED => 'Accepted', |
||||
self::STATUS_NON_AUTHORATIVE_INFORMATION => 'Non-Authorative Information', |
||||
self::STATUS_NO_CONTENT => 'No Content', |
||||
self::STATUS_RESET_CONTENT => 'Reset Content', |
||||
self::STATUS_PARTIAL_CONTENT => 'Partial Content', |
||||
self::STATUS_MULTI_STATUS => 'Multi-Status', // RFC 4918 |
||||
self::STATUS_ALREADY_REPORTED => 'Already Reported', // RFC 5842 |
||||
self::STATUS_IM_USED => 'IM Used', // RFC 3229 |
||||
self::STATUS_MULTIPLE_CHOICES => 'Multiple Choices', |
||||
self::STATUS_MOVED_PERMANENTLY => 'Moved Permanently', |
||||
self::STATUS_FOUND => 'Found', |
||||
self::STATUS_SEE_OTHER => 'See Other', |
||||
self::STATUS_NOT_MODIFIED => 'Not Modified', |
||||
self::STATUS_USE_PROXY => 'Use Proxy', |
||||
self::STATUS_RESERVED => 'Reserved', |
||||
self::STATUS_TEMPORARY_REDIRECT => 'Temporary Redirect', |
||||
self::STATUS_BAD_REQUEST => 'Bad request', |
||||
self::STATUS_UNAUTHORIZED => 'Unauthorized', |
||||
self::STATUS_PAYMENT_REQUIRED => 'Payment Required', |
||||
self::STATUS_FORBIDDEN => 'Forbidden', |
||||
self::STATUS_NOT_FOUND => 'Not Found', |
||||
self::STATUS_METHOD_NOT_ALLOWED => 'Method Not Allowed', |
||||
self::STATUS_NOT_ACCEPTABLE => 'Not Acceptable', |
||||
self::STATUS_PROXY_AUTHENTICATION_REQUIRED => 'Proxy Authentication Required', |
||||
self::STATUS_REQUEST_TIMEOUT => 'Request Timeout', |
||||
self::STATUS_CONFLICT => 'Conflict', |
||||
self::STATUS_GONE => 'Gone', |
||||
self::STATUS_LENGTH_REQUIRED => 'Length Required', |
||||
self::STATUS_PRECONDITION_FAILED => 'Precondition failed', |
||||
self::STATUS_REQUEST_ENTITY_TOO_LARGE => 'Request Entity Too Large', |
||||
self::STATUS_REQUEST_URI_TOO_LONG => 'Request-URI Too Long', |
||||
self::STATUS_UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type', |
||||
self::STATUS_REQUEST_RANGE_NOT_SATISFIABLE => 'Requested Range Not Satisfiable', |
||||
self::STATUS_EXPECTATION_FAILED => 'Expectation Failed', |
||||
self::STATUS_IM_A_TEAPOT => 'I\'m a teapot', // RFC 2324 |
||||
self::STATUS_UNPROCESSABLE_ENTITY => 'Unprocessable Entity', // RFC 4918 |
||||
self::STATUS_LOCKED => 'Locked', // RFC 4918 |
||||
self::STATUS_FAILED_DEPENDENCY => 'Failed Dependency', // RFC 4918 |
||||
self::STATUS_UPGRADE_REQUIRED => 'Upgrade required', |
||||
self::STATUS_PRECONDITION_REQUIRED => 'Precondition required', // draft-nottingham-http-new-status |
||||
self::STATUS_TOO_MANY_REQUESTS => 'Too Many Requests', // draft-nottingham-http-new-status |
||||
self::STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE => 'Request Header Fields Too Large', // draft-nottingham-http-new-status |
||||
self::STATUS_INTERNAL_SERVER_ERROR => 'Internal Server Error', |
||||
self::STATUS_NOT_IMPLEMENTED => 'Not Implemented', |
||||
self::STATUS_BAD_GATEWAY => 'Bad Gateway', |
||||
self::STATUS_SERVICE_UNAVAILABLE => 'Service Unavailable', |
||||
self::STATUS_GATEWAY_TIMEOUT => 'Gateway Timeout', |
||||
self::STATUS_HTTP_VERSION_NOT_SUPPORTED => 'HTTP Version not supported', |
||||
self::STATUS_VARIANT_ALSO_NEGOTIATES => 'Variant Also Negotiates', |
||||
self::STATUS_INSUFFICIENT_STORAGE => 'Insufficient Storage', // RFC 4918 |
||||
self::STATUS_LOOP_DETECTED => 'Loop Detected', // RFC 5842 |
||||
self::STATUS_BANDWIDTH_LIMIT_EXCEEDED => 'Bandwidth Limit Exceeded', // non-standard |
||||
self::STATUS_NOT_EXTENDED => 'Not extended', |
||||
self::STATUS_NETWORK_AUTHENTICATION_REQUIRED => 'Network Authentication Required', // draft-nottingham-http-new-status |
||||
); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Gets the correct header |
||||
* @param Http::CONSTANT $status the constant from the Http class |
||||
* @param \DateTime $lastModified formatted last modified date |
||||
* @param string $Etag the etag |
||||
*/ |
||||
public function getStatusHeader($status, \DateTime $lastModified=null, |
||||
$ETag=null) { |
||||
|
||||
if(!is_null($lastModified)) { |
||||
$lastModified = $lastModified->format(\DateTime::RFC2822); |
||||
} |
||||
|
||||
// if etag or lastmodified have not changed, return a not modified |
||||
if ((isset($this->server['HTTP_IF_NONE_MATCH']) |
||||
&& trim($this->server['HTTP_IF_NONE_MATCH']) === $ETag) |
||||
|
||||
|| |
||||
|
||||
(isset($this->server['HTTP_IF_MODIFIED_SINCE']) |
||||
&& trim($this->server['HTTP_IF_MODIFIED_SINCE']) === |
||||
$lastModified)) { |
||||
|
||||
$status = self::STATUS_NOT_MODIFIED; |
||||
} |
||||
|
||||
// we have one change currently for the http 1.0 header that differs |
||||
// from 1.1: STATUS_TEMPORARY_REDIRECT should be STATUS_FOUND |
||||
// if this differs any more, we want to create childclasses for this |
||||
if($status === self::STATUS_TEMPORARY_REDIRECT |
||||
&& $this->protocolVersion === 'HTTP/1.0') { |
||||
|
||||
$status = self::STATUS_FOUND; |
||||
} |
||||
|
||||
return $this->protocolVersion . ' ' . $status . ' ' . |
||||
$this->headers[$status]; |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
@ -0,0 +1,74 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
/** |
||||
* A renderer for JSON calls |
||||
*/ |
||||
class JSONResponse extends Response { |
||||
|
||||
protected $data; |
||||
|
||||
|
||||
/** |
||||
* @param array|object $data the object or array that should be transformed |
||||
* @param int $statusCode the Http status code, defaults to 200 |
||||
*/ |
||||
public function __construct($data=array(), $statusCode=Http::STATUS_OK) { |
||||
$this->data = $data; |
||||
$this->setStatus($statusCode); |
||||
$this->addHeader('X-Content-Type-Options', 'nosniff'); |
||||
$this->addHeader('Content-type', 'application/json; charset=utf-8'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the rendered json |
||||
* @return string the rendered json |
||||
*/ |
||||
public function render(){ |
||||
return json_encode($this->data); |
||||
} |
||||
|
||||
/** |
||||
* Sets values in the data json array |
||||
* @param array|object $params an array or object which will be transformed |
||||
* to JSON |
||||
*/ |
||||
public function setData($data){ |
||||
$this->data = $data; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Used to get the set parameters |
||||
* @return array the data |
||||
*/ |
||||
public function getData(){ |
||||
return $this->data; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
/** |
||||
* Redirects to a different URL |
||||
*/ |
||||
class RedirectResponse extends Response { |
||||
|
||||
private $redirectURL; |
||||
|
||||
/** |
||||
* Creates a response that redirects to a url |
||||
* @param string $redirectURL the url to redirect to |
||||
*/ |
||||
public function __construct($redirectURL) { |
||||
$this->redirectURL = $redirectURL; |
||||
$this->setStatus(Http::STATUS_TEMPORARY_REDIRECT); |
||||
$this->addHeader('Location', $redirectURL); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return string the url to redirect |
||||
*/ |
||||
public function getRedirectURL() { |
||||
return $this->redirectURL; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,217 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - Request |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2013 Thomas Tanghus (thomas@tanghus.net) |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
/** |
||||
* Class for accessing variables in the request. |
||||
* This class provides an immutable object with request variables. |
||||
*/ |
||||
|
||||
class Request implements \ArrayAccess, \Countable { |
||||
|
||||
protected $items = array(); |
||||
protected $allowedKeys = array( |
||||
'get', |
||||
'post', |
||||
'files', |
||||
'server', |
||||
'env', |
||||
'session', |
||||
'cookies', |
||||
'urlParams', |
||||
'params', |
||||
'parameters', |
||||
'method' |
||||
); |
||||
|
||||
/** |
||||
* @param array $vars An associative array with the following optional values: |
||||
* @param array 'params' the parsed json array |
||||
* @param array 'urlParams' the parameters which were matched from the URL |
||||
* @param array 'get' the $_GET array |
||||
* @param array 'post' the $_POST array |
||||
* @param array 'files' the $_FILES array |
||||
* @param array 'server' the $_SERVER array |
||||
* @param array 'env' the $_ENV array |
||||
* @param array 'session' the $_SESSION array |
||||
* @param array 'cookies' the $_COOKIE array |
||||
* @param string 'method' the request method (GET, POST etc) |
||||
* @see http://www.php.net/manual/en/reserved.variables.php |
||||
*/ |
||||
public function __construct(array $vars=array()) { |
||||
|
||||
foreach($this->allowedKeys as $name) { |
||||
$this->items[$name] = isset($vars[$name]) |
||||
? $vars[$name] |
||||
: array(); |
||||
} |
||||
|
||||
$this->items['parameters'] = array_merge( |
||||
$this->items['params'], |
||||
$this->items['get'], |
||||
$this->items['post'], |
||||
$this->items['urlParams'] |
||||
); |
||||
|
||||
} |
||||
|
||||
// Countable method. |
||||
public function count() { |
||||
return count(array_keys($this->items['parameters'])); |
||||
} |
||||
|
||||
/** |
||||
* ArrayAccess methods |
||||
* |
||||
* Gives access to the combined GET, POST and urlParams arrays |
||||
* |
||||
* Examples: |
||||
* |
||||
* $var = $request['myvar']; |
||||
* |
||||
* or |
||||
* |
||||
* if(!isset($request['myvar']) { |
||||
* // Do something |
||||
* } |
||||
* |
||||
* $request['myvar'] = 'something'; // This throws an exception. |
||||
* |
||||
* @param string $offset The key to lookup |
||||
* @return string|null |
||||
*/ |
||||
public function offsetExists($offset) { |
||||
return isset($this->items['parameters'][$offset]); |
||||
} |
||||
|
||||
/** |
||||
* @see offsetExists |
||||
*/ |
||||
public function offsetGet($offset) { |
||||
return isset($this->items['parameters'][$offset]) |
||||
? $this->items['parameters'][$offset] |
||||
: null; |
||||
} |
||||
|
||||
/** |
||||
* @see offsetExists |
||||
*/ |
||||
public function offsetSet($offset, $value) { |
||||
throw new \RuntimeException('You cannot change the contents of the request object'); |
||||
} |
||||
|
||||
/** |
||||
* @see offsetExists |
||||
*/ |
||||
public function offsetUnset($offset) { |
||||
throw new \RuntimeException('You cannot change the contents of the request object'); |
||||
} |
||||
|
||||
// Magic property accessors |
||||
public function __set($name, $value) { |
||||
throw new \RuntimeException('You cannot change the contents of the request object'); |
||||
} |
||||
|
||||
/** |
||||
* Access request variables by method and name. |
||||
* Examples: |
||||
* |
||||
* $request->post['myvar']; // Only look for POST variables |
||||
* $request->myvar; or $request->{'myvar'}; or $request->{$myvar} |
||||
* Looks in the combined GET, POST and urlParams array. |
||||
* |
||||
* if($request->method !== 'POST') { |
||||
* throw new Exception('This function can only be invoked using POST'); |
||||
* } |
||||
* |
||||
* @param string $name The key to look for. |
||||
* @return mixed|null |
||||
*/ |
||||
public function __get($name) { |
||||
switch($name) { |
||||
case 'get': |
||||
case 'post': |
||||
case 'files': |
||||
case 'server': |
||||
case 'env': |
||||
case 'session': |
||||
case 'cookies': |
||||
case 'parameters': |
||||
case 'params': |
||||
case 'urlParams': |
||||
return isset($this->items[$name]) |
||||
? $this->items[$name] |
||||
: null; |
||||
break; |
||||
case 'method': |
||||
return $this->items['method']; |
||||
break; |
||||
default; |
||||
return isset($this[$name]) |
||||
? $this[$name] |
||||
: null; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
public function __isset($name) { |
||||
return isset($this->items['parameters'][$name]); |
||||
} |
||||
|
||||
|
||||
public function __unset($id) { |
||||
throw new \RunTimeException('You cannot change the contents of the request object'); |
||||
} |
||||
|
||||
/** |
||||
* Returns the value for a specific http header. |
||||
* |
||||
* This method returns null if the header did not exist. |
||||
* |
||||
* @param string $name |
||||
* @return string |
||||
*/ |
||||
public function getHeader($name) { |
||||
|
||||
$name = strtoupper(str_replace(array('-'),array('_'),$name)); |
||||
if (isset($this->server['HTTP_' . $name])) { |
||||
return $this->server['HTTP_' . $name]; |
||||
} |
||||
|
||||
// There's a few headers that seem to end up in the top-level |
||||
// server array. |
||||
switch($name) { |
||||
case 'CONTENT_TYPE' : |
||||
case 'CONTENT_LENGTH' : |
||||
if (isset($this->server[$name])) { |
||||
return $this->server[$name]; |
||||
} |
||||
break; |
||||
|
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,169 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt, Thomas Tanghus, Bart Visscher |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
/** |
||||
* Base class for responses. Also used to just send headers |
||||
*/ |
||||
class Response { |
||||
|
||||
/** |
||||
* @var array default headers |
||||
*/ |
||||
private $headers = array( |
||||
'Cache-Control' => 'no-cache, must-revalidate' |
||||
); |
||||
|
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $status = Http::STATUS_OK; |
||||
|
||||
|
||||
/** |
||||
* @var \DateTime |
||||
*/ |
||||
private $lastModified; |
||||
|
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $ETag; |
||||
|
||||
|
||||
/** |
||||
* Caches the response |
||||
* @param int $cacheSeconds the amount of seconds that should be cached |
||||
* if 0 then caching will be disabled |
||||
*/ |
||||
public function cacheFor($cacheSeconds) { |
||||
|
||||
if($cacheSeconds > 0) { |
||||
$this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . |
||||
', must-revalidate'); |
||||
} else { |
||||
$this->addHeader('Cache-Control', 'no-cache, must-revalidate'); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a new header to the response that will be called before the render |
||||
* function |
||||
* @param string $name The name of the HTTP header |
||||
* @param string $value The value, null will delete it |
||||
*/ |
||||
public function addHeader($name, $value) { |
||||
if(is_null($value)) { |
||||
unset($this->headers[$name]); |
||||
} else { |
||||
$this->headers[$name] = $value; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the set headers |
||||
* @return array the headers |
||||
*/ |
||||
public function getHeaders() { |
||||
$mergeWith = array(); |
||||
|
||||
if($this->lastModified) { |
||||
$mergeWith['Last-Modified'] = |
||||
$this->lastModified->format(\DateTime::RFC2822); |
||||
} |
||||
|
||||
if($this->ETag) { |
||||
$mergeWith['ETag'] = '"' . $this->ETag . '"'; |
||||
} |
||||
|
||||
return array_merge($mergeWith, $this->headers); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* By default renders no output |
||||
* @return null |
||||
*/ |
||||
public function render() { |
||||
return null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set response status |
||||
* @param int $status a HTTP status code, see also the STATUS constants |
||||
*/ |
||||
public function setStatus($status) { |
||||
$this->status = $status; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get response status |
||||
*/ |
||||
public function getStatus() { |
||||
return $this->status; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return string the etag |
||||
*/ |
||||
public function getETag() { |
||||
return $this->ETag; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return string RFC2822 formatted last modified date |
||||
*/ |
||||
public function getLastModified() { |
||||
return $this->lastModified; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param string $ETag |
||||
*/ |
||||
public function setETag($ETag) { |
||||
$this->ETag = $ETag; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param \DateTime $lastModified |
||||
*/ |
||||
public function setLastModified($lastModified) { |
||||
$this->lastModified = $lastModified; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,126 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
use OC\AppFramework\Core\API; |
||||
|
||||
|
||||
/** |
||||
* Response for a normal template |
||||
*/ |
||||
class TemplateResponse extends Response { |
||||
|
||||
protected $templateName; |
||||
protected $params; |
||||
protected $api; |
||||
protected $renderAs; |
||||
protected $appName; |
||||
|
||||
/** |
||||
* @param API $api an API instance |
||||
* @param string $templateName the name of the template |
||||
* @param string $appName optional if you want to include a template from |
||||
* a different app |
||||
*/ |
||||
public function __construct(API $api, $templateName, $appName=null) { |
||||
$this->templateName = $templateName; |
||||
$this->appName = $appName; |
||||
$this->api = $api; |
||||
$this->params = array(); |
||||
$this->renderAs = 'user'; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets template parameters |
||||
* @param array $params an array with key => value structure which sets template |
||||
* variables |
||||
*/ |
||||
public function setParams(array $params){ |
||||
$this->params = $params; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Used for accessing the set parameters |
||||
* @return array the params |
||||
*/ |
||||
public function getParams(){ |
||||
return $this->params; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Used for accessing the name of the set template |
||||
* @return string the name of the used template |
||||
*/ |
||||
public function getTemplateName(){ |
||||
return $this->templateName; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the template page |
||||
* @param string $renderAs admin, user or blank. Admin also prints the admin |
||||
* settings header and footer, user renders the normal |
||||
* normal page including footer and header and blank |
||||
* just renders the plain template |
||||
*/ |
||||
public function renderAs($renderAs){ |
||||
$this->renderAs = $renderAs; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the set renderAs |
||||
* @return string the renderAs value |
||||
*/ |
||||
public function getRenderAs(){ |
||||
return $this->renderAs; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the rendered html |
||||
* @return string the rendered html |
||||
*/ |
||||
public function render(){ |
||||
|
||||
if($this->appName !== null){ |
||||
$appName = $this->appName; |
||||
} else { |
||||
$appName = $this->api->getAppName(); |
||||
} |
||||
|
||||
$template = $this->api->getTemplate($this->templateName, $this->renderAs, $appName); |
||||
|
||||
foreach($this->params as $key => $value){ |
||||
$template->assign($key, $value); |
||||
} |
||||
|
||||
return $template->fetchPage(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,100 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Middleware; |
||||
|
||||
use OC\AppFramework\Http\Response; |
||||
|
||||
|
||||
/** |
||||
* Middleware is used to provide hooks before or after controller methods and |
||||
* deal with possible exceptions raised in the controller methods. |
||||
* They're modeled after Django's middleware system: |
||||
* https://docs.djangoproject.com/en/dev/topics/http/middleware/ |
||||
*/ |
||||
abstract class Middleware { |
||||
|
||||
|
||||
/** |
||||
* This is being run in normal order before the controller is being |
||||
* called which allows several modifications and checks |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
*/ |
||||
public function beforeController($controller, $methodName){ |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run when either the beforeController method or the |
||||
* controller method itself is throwing an exception. The middleware is |
||||
* asked in reverse order to handle the exception and to return a response. |
||||
* If the response is null, it is assumed that the exception could not be |
||||
* handled and the error will be thrown again |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param \Exception $exception the thrown exception |
||||
* @throws \Exception the passed in exception if it cant handle it |
||||
* @return Response a Response object in case that the exception was handled |
||||
*/ |
||||
public function afterException($controller, $methodName, \Exception $exception){ |
||||
throw $exception; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run after a successful controllermethod call and allows |
||||
* the manipulation of a Response object. The middleware is run in reverse order |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param Response $response the generated response from the controller |
||||
* @return Response a Response object |
||||
*/ |
||||
public function afterController($controller, $methodName, Response $response){ |
||||
return $response; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run after the response object has been rendered and |
||||
* allows the manipulation of the output. The middleware is run in reverse order |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param string $output the generated output from a response |
||||
* @return string the output that should be printed |
||||
*/ |
||||
public function beforeOutput($controller, $methodName, $output){ |
||||
return $output; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,159 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Middleware; |
||||
|
||||
use OC\AppFramework\Controller\Controller; |
||||
use OC\AppFramework\Http\Response; |
||||
|
||||
|
||||
/** |
||||
* This class is used to store and run all the middleware in correct order |
||||
*/ |
||||
class MiddlewareDispatcher { |
||||
|
||||
/** |
||||
* @var array array containing all the middlewares |
||||
*/ |
||||
private $middlewares; |
||||
|
||||
/** |
||||
* @var int counter which tells us what middlware was executed once an |
||||
* exception occurs |
||||
*/ |
||||
private $middlewareCounter; |
||||
|
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
public function __construct(){ |
||||
$this->middlewares = array(); |
||||
$this->middlewareCounter = 0; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a new middleware |
||||
* @param Middleware $middleware the middleware which will be added |
||||
*/ |
||||
public function registerMiddleware(Middleware $middleWare){ |
||||
array_push($this->middlewares, $middleWare); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* returns an array with all middleware elements |
||||
* @return array the middlewares |
||||
*/ |
||||
public function getMiddlewares(){ |
||||
return $this->middlewares; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run in normal order before the controller is being |
||||
* called which allows several modifications and checks |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
*/ |
||||
public function beforeController(Controller $controller, $methodName){ |
||||
// we need to count so that we know which middlewares we have to ask in |
||||
// case theres an exception |
||||
for($i=0; $i<count($this->middlewares); $i++){ |
||||
$this->middlewareCounter++; |
||||
$middleware = $this->middlewares[$i]; |
||||
$middleware->beforeController($controller, $methodName); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run when either the beforeController method or the |
||||
* controller method itself is throwing an exception. The middleware is asked |
||||
* in reverse order to handle the exception and to return a response. |
||||
* If the response is null, it is assumed that the exception could not be |
||||
* handled and the error will be thrown again |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param \Exception $exception the thrown exception |
||||
* @return Response a Response object if the middleware can handle the |
||||
* exception |
||||
* @throws \Exception the passed in exception if it cant handle it |
||||
*/ |
||||
public function afterException(Controller $controller, $methodName, \Exception $exception){ |
||||
for($i=$this->middlewareCounter-1; $i>=0; $i--){ |
||||
$middleware = $this->middlewares[$i]; |
||||
try { |
||||
return $middleware->afterException($controller, $methodName, $exception); |
||||
} catch(\Exception $exception){ |
||||
continue; |
||||
} |
||||
} |
||||
throw $exception; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run after a successful controllermethod call and allows |
||||
* the manipulation of a Response object. The middleware is run in reverse order |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param Response $response the generated response from the controller |
||||
* @return Response a Response object |
||||
*/ |
||||
public function afterController(Controller $controller, $methodName, Response $response){ |
||||
for($i=count($this->middlewares)-1; $i>=0; $i--){ |
||||
$middleware = $this->middlewares[$i]; |
||||
$response = $middleware->afterController($controller, $methodName, $response); |
||||
} |
||||
return $response; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This is being run after the response object has been rendered and |
||||
* allows the manipulation of the output. The middleware is run in reverse order |
||||
* |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param string $output the generated output from a response |
||||
* @return string the output that should be printed |
||||
*/ |
||||
public function beforeOutput(Controller $controller, $methodName, $output){ |
||||
for($i=count($this->middlewares)-1; $i>=0; $i--){ |
||||
$middleware = $this->middlewares[$i]; |
||||
$output = $middleware->beforeOutput($controller, $methodName, $output); |
||||
} |
||||
return $output; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Middleware\Security; |
||||
|
||||
|
||||
/** |
||||
* Thrown when the security middleware encounters a security problem |
||||
*/ |
||||
class SecurityException extends \Exception { |
||||
|
||||
/** |
||||
* @param string $msg the security error message |
||||
* @param bool $ajax true if it resulted because of an ajax request |
||||
*/ |
||||
public function __construct($msg, $code = 0) { |
||||
parent::__construct($msg, $code); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,141 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Middleware\Security; |
||||
|
||||
use OC\AppFramework\Controller\Controller; |
||||
use OC\AppFramework\Http\Http; |
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Http\Response; |
||||
use OC\AppFramework\Http\JSONResponse; |
||||
use OC\AppFramework\Http\RedirectResponse; |
||||
use OC\AppFramework\Utility\MethodAnnotationReader; |
||||
use OC\AppFramework\Middleware\Middleware; |
||||
use OC\AppFramework\Core\API; |
||||
|
||||
|
||||
/** |
||||
* Used to do all the authentication and checking stuff for a controller method |
||||
* It reads out the annotations of a controller method and checks which if |
||||
* security things should be checked and also handles errors in case a security |
||||
* check fails |
||||
*/ |
||||
class SecurityMiddleware extends Middleware { |
||||
|
||||
private $api; |
||||
|
||||
/** |
||||
* @var \OC\AppFramework\Http\Request |
||||
*/ |
||||
private $request; |
||||
|
||||
/** |
||||
* @param API $api an instance of the api |
||||
*/ |
||||
public function __construct(API $api, Request $request){ |
||||
$this->api = $api; |
||||
$this->request = $request; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This runs all the security checks before a method call. The |
||||
* security checks are determined by inspecting the controller method |
||||
* annotations |
||||
* @param string/Controller $controller the controllername or string |
||||
* @param string $methodName the name of the method |
||||
* @throws SecurityException when a security check fails |
||||
*/ |
||||
public function beforeController($controller, $methodName){ |
||||
|
||||
// get annotations from comments |
||||
$annotationReader = new MethodAnnotationReader($controller, $methodName); |
||||
|
||||
// this will set the current navigation entry of the app, use this only |
||||
// for normal HTML requests and not for AJAX requests |
||||
$this->api->activateNavigationEntry(); |
||||
|
||||
// security checks |
||||
if(!$annotationReader->hasAnnotation('IsLoggedInExemption')) { |
||||
if(!$this->api->isLoggedIn()) { |
||||
throw new SecurityException('Current user is not logged in', Http::STATUS_UNAUTHORIZED); |
||||
} |
||||
} |
||||
|
||||
if(!$annotationReader->hasAnnotation('IsAdminExemption')) { |
||||
if(!$this->api->isAdminUser($this->api->getUserId())) { |
||||
throw new SecurityException('Logged in user must be an admin', Http::STATUS_FORBIDDEN); |
||||
} |
||||
} |
||||
|
||||
if(!$annotationReader->hasAnnotation('IsSubAdminExemption')) { |
||||
if(!$this->api->isSubAdminUser($this->api->getUserId())) { |
||||
throw new SecurityException('Logged in user must be a subadmin', Http::STATUS_FORBIDDEN); |
||||
} |
||||
} |
||||
|
||||
if(!$annotationReader->hasAnnotation('CSRFExemption')) { |
||||
if(!$this->api->passesCSRFCheck()) { |
||||
throw new SecurityException('CSRF check failed', Http::STATUS_PRECONDITION_FAILED); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* If an SecurityException is being caught, ajax requests return a JSON error |
||||
* response and non ajax requests redirect to the index |
||||
* @param Controller $controller the controller that is being called |
||||
* @param string $methodName the name of the method that will be called on |
||||
* the controller |
||||
* @param \Exception $exception the thrown exception |
||||
* @throws \Exception the passed in exception if it cant handle it |
||||
* @return Response a Response object or null in case that the exception could not be handled |
||||
*/ |
||||
public function afterException($controller, $methodName, \Exception $exception){ |
||||
if($exception instanceof SecurityException){ |
||||
|
||||
if (stripos($this->request->getHeader('Accept'),'html')===false) { |
||||
|
||||
$response = new JSONResponse( |
||||
array('message' => $exception->getMessage()), |
||||
$exception->getCode() |
||||
); |
||||
$this->api->log($exception->getMessage(), 'debug'); |
||||
} else { |
||||
|
||||
$url = $this->api->linkToAbsolute('index.php', ''); // TODO: replace with link to route |
||||
$response = new RedirectResponse($url); |
||||
$this->api->log($exception->getMessage(), 'debug'); |
||||
} |
||||
|
||||
return $response; |
||||
|
||||
} |
||||
|
||||
throw $exception; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Thomas Müller |
||||
* @copyright 2013 Thomas Müller thomas.mueller@tmit.eu |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OC\AppFramework\routing; |
||||
|
||||
use \OC\AppFramework\App; |
||||
use \OC\AppFramework\DependencyInjection\DIContainer; |
||||
|
||||
class RouteActionHandler { |
||||
private $controllerName; |
||||
private $actionName; |
||||
private $container; |
||||
|
||||
public function __construct(DIContainer $container, $controllerName, $actionName) { |
||||
$this->controllerName = $controllerName; |
||||
$this->actionName = $actionName; |
||||
$this->container = $container; |
||||
} |
||||
|
||||
public function __invoke($params) { |
||||
App::main($this->controllerName, $this->actionName, $params, $this->container); |
||||
} |
||||
} |
||||
@ -0,0 +1,186 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Thomas Müller |
||||
* @copyright 2013 Thomas Müller thomas.mueller@tmit.eu |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OC\AppFramework\routing; |
||||
|
||||
use OC\AppFramework\DependencyInjection\DIContainer; |
||||
|
||||
/** |
||||
* Class RouteConfig |
||||
* @package OC\AppFramework\routing |
||||
*/ |
||||
class RouteConfig { |
||||
private $container; |
||||
private $router; |
||||
private $routes; |
||||
private $appName; |
||||
|
||||
/** |
||||
* @param \OC\AppFramework\DependencyInjection\DIContainer $container |
||||
* @param \OC_Router $router |
||||
* @param string $pathToYml |
||||
* @internal param $appName |
||||
*/ |
||||
public function __construct(DIContainer $container, \OC_Router $router, $routes) { |
||||
$this->routes = $routes; |
||||
$this->container = $container; |
||||
$this->router = $router; |
||||
$this->appName = $container['AppName']; |
||||
} |
||||
|
||||
/** |
||||
* The routes and resource will be registered to the \OC_Router |
||||
*/ |
||||
public function register() { |
||||
|
||||
// parse simple |
||||
$this->processSimpleRoutes($this->routes); |
||||
|
||||
// parse resources |
||||
$this->processResources($this->routes); |
||||
} |
||||
|
||||
/** |
||||
* Creates one route base on the give configuration |
||||
* @param $routes |
||||
* @throws \UnexpectedValueException |
||||
*/ |
||||
private function processSimpleRoutes($routes) |
||||
{ |
||||
$simpleRoutes = isset($routes['routes']) ? $routes['routes'] : array(); |
||||
foreach ($simpleRoutes as $simpleRoute) { |
||||
$name = $simpleRoute['name']; |
||||
$url = $simpleRoute['url']; |
||||
$verb = isset($simpleRoute['verb']) ? strtoupper($simpleRoute['verb']) : 'GET'; |
||||
|
||||
$split = explode('#', $name, 2); |
||||
if (count($split) != 2) { |
||||
throw new \UnexpectedValueException('Invalid route name'); |
||||
} |
||||
$controller = $split[0]; |
||||
$action = $split[1]; |
||||
|
||||
$controllerName = $this->buildControllerName($controller); |
||||
$actionName = $this->buildActionName($action); |
||||
|
||||
// register the route |
||||
$handler = new RouteActionHandler($this->container, $controllerName, $actionName); |
||||
$this->router->create($this->appName.'.'.$controller.'.'.$action, $url)->method($verb)->action($handler); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* For a given name and url restful routes are created: |
||||
* - index |
||||
* - show |
||||
* - new |
||||
* - create |
||||
* - update |
||||
* - destroy |
||||
* |
||||
* @param $routes |
||||
*/ |
||||
private function processResources($routes) |
||||
{ |
||||
// declaration of all restful actions |
||||
$actions = array( |
||||
array('name' => 'index', 'verb' => 'GET', 'on-collection' => true), |
||||
array('name' => 'show', 'verb' => 'GET'), |
||||
array('name' => 'create', 'verb' => 'POST', 'on-collection' => true), |
||||
array('name' => 'update', 'verb' => 'PUT'), |
||||
array('name' => 'destroy', 'verb' => 'DELETE'), |
||||
); |
||||
|
||||
$resources = isset($routes['resources']) ? $routes['resources'] : array(); |
||||
foreach ($resources as $resource => $config) { |
||||
|
||||
// the url parameter used as id to the resource |
||||
$resourceId = $this->buildResourceId($resource); |
||||
foreach($actions as $action) { |
||||
$url = $config['url']; |
||||
$method = $action['name']; |
||||
$verb = isset($action['verb']) ? strtoupper($action['verb']) : 'GET'; |
||||
$collectionAction = isset($action['on-collection']) ? $action['on-collection'] : false; |
||||
if (!$collectionAction) { |
||||
$url = $url . '/' . $resourceId; |
||||
} |
||||
if (isset($action['url-postfix'])) { |
||||
$url = $url . '/' . $action['url-postfix']; |
||||
} |
||||
|
||||
$controller = $resource; |
||||
|
||||
$controllerName = $this->buildControllerName($controller); |
||||
$actionName = $this->buildActionName($method); |
||||
|
||||
$routeName = $this->appName . '.' . strtolower($resource) . '.' . strtolower($method); |
||||
|
||||
$this->router->create($routeName, $url)->method($verb)->action( |
||||
new RouteActionHandler($this->container, $controllerName, $actionName) |
||||
); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Based on a given route name the controller name is generated |
||||
* @param $controller |
||||
* @return string |
||||
*/ |
||||
private function buildControllerName($controller) |
||||
{ |
||||
return $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller'; |
||||
} |
||||
|
||||
/** |
||||
* Based on the action part of the route name the controller method name is generated |
||||
* @param $action |
||||
* @return string |
||||
*/ |
||||
private function buildActionName($action) { |
||||
return $this->underScoreToCamelCase($action); |
||||
} |
||||
|
||||
/** |
||||
* Generates the id used in the url part o the route url |
||||
* @param $resource |
||||
* @return string |
||||
*/ |
||||
private function buildResourceId($resource) { |
||||
return '{'.$this->underScoreToCamelCase(rtrim($resource, 's')).'Id}'; |
||||
} |
||||
|
||||
/** |
||||
* Underscored strings are converted to camel case strings |
||||
* @param $str string |
||||
* @return string |
||||
*/ |
||||
private function underScoreToCamelCase($str) { |
||||
$pattern = "/_[a-z]?/"; |
||||
return preg_replace_callback( |
||||
$pattern, |
||||
function ($matches) { |
||||
return strtoupper(ltrim($matches[0], "_")); |
||||
}, |
||||
$str); |
||||
} |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Utility; |
||||
|
||||
|
||||
/** |
||||
* Reads and parses annotations from doc comments |
||||
*/ |
||||
class MethodAnnotationReader { |
||||
|
||||
private $annotations; |
||||
|
||||
/** |
||||
* @param object $object an object or classname |
||||
* @param string $method the method which we want to inspect for annotations |
||||
*/ |
||||
public function __construct($object, $method){ |
||||
$this->annotations = array(); |
||||
|
||||
$reflection = new \ReflectionMethod($object, $method); |
||||
$docs = $reflection->getDocComment(); |
||||
|
||||
// extract everything prefixed by @ and first letter uppercase |
||||
preg_match_all('/@([A-Z]\w+)/', $docs, $matches); |
||||
$this->annotations = $matches[1]; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Check if a method contains an annotation |
||||
* @param string $name the name of the annotation |
||||
* @return bool true if the annotation is found |
||||
*/ |
||||
public function hasAnnotation($name){ |
||||
return in_array($name, $this->annotations); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Utility; |
||||
|
||||
|
||||
/** |
||||
* Needed to mock calls to time() |
||||
*/ |
||||
class TimeFactory { |
||||
|
||||
|
||||
/** |
||||
* @return int the result of a call to time() |
||||
*/ |
||||
public function getTime() { |
||||
return time(); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,107 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework; |
||||
|
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Core\API; |
||||
use OC\AppFramework\Middleware\MiddlewareDispatcher; |
||||
|
||||
// FIXME: loading pimpl correctly from 3rdparty repo |
||||
require_once __DIR__ . '/../../../../3rdparty/Pimple/Pimple.php'; |
||||
require_once __DIR__ . "/classloader.php"; |
||||
|
||||
|
||||
class AppTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $container; |
||||
private $api; |
||||
private $controller; |
||||
private $dispatcher; |
||||
private $params; |
||||
private $headers; |
||||
private $output; |
||||
private $controllerName; |
||||
private $controllerMethod; |
||||
|
||||
protected function setUp() { |
||||
$this->container = new \Pimple(); |
||||
$this->controller = $this->getMockBuilder( |
||||
'OC\AppFramework\Controller\Controller') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$this->dispatcher = $this->getMockBuilder( |
||||
'OC\AppFramework\Http\Dispatcher') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
|
||||
$this->headers = array('key' => 'value'); |
||||
$this->output = 'hi'; |
||||
$this->controllerName = 'Controller'; |
||||
$this->controllerMethod = 'method'; |
||||
|
||||
$this->container[$this->controllerName] = $this->controller; |
||||
$this->container['Dispatcher'] = $this->dispatcher; |
||||
} |
||||
|
||||
|
||||
public function testControllerNameAndMethodAreBeingPassed(){ |
||||
$return = array(null, array(), null); |
||||
$this->dispatcher->expects($this->once()) |
||||
->method('dispatch') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod)) |
||||
->will($this->returnValue($return)); |
||||
|
||||
$this->expectOutputString(''); |
||||
|
||||
App::main($this->controllerName, $this->controllerMethod, array(), |
||||
$this->container); |
||||
} |
||||
|
||||
|
||||
/* |
||||
FIXME: this complains about shit headers which are already sent because |
||||
of the content length. Would be cool if someone could fix this |
||||
|
||||
public function testOutputIsPrinted(){ |
||||
$return = array(null, array(), $this->output); |
||||
$this->dispatcher->expects($this->once()) |
||||
->method('dispatch') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod)) |
||||
->will($this->returnValue($return)); |
||||
|
||||
$this->expectOutputString($this->output); |
||||
|
||||
App::main($this->controllerName, $this->controllerMethod, array(), |
||||
$this->container); |
||||
} |
||||
*/ |
||||
|
||||
// FIXME: if someone manages to test the headers output, I'd be grateful |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,45 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
// to execute without ownCloud, we need to create our own class loader |
||||
spl_autoload_register(function ($className){ |
||||
if (strpos($className, 'OC\\AppFramework') === 0) { |
||||
$path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); |
||||
$relPath = __DIR__ . '/../../../lib/' . $path; |
||||
|
||||
if(file_exists($relPath)){ |
||||
require_once $relPath; |
||||
} |
||||
} |
||||
|
||||
// FIXME: this will most probably not work anymore |
||||
if (strpos($className, 'OCA\\') === 0) { |
||||
|
||||
$path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); |
||||
$relPath = __DIR__ . '/../..' . $path; |
||||
|
||||
if(file_exists($relPath)){ |
||||
require_once $relPath; |
||||
} |
||||
} |
||||
}); |
||||
@ -0,0 +1,161 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace Test\AppFramework\Controller; |
||||
|
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Http\JSONResponse; |
||||
use OC\AppFramework\Http\TemplateResponse; |
||||
use OC\AppFramework\Controller\Controller; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class ChildController extends Controller {}; |
||||
|
||||
class ControllerTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
/** |
||||
* @var Controller |
||||
*/ |
||||
private $controller; |
||||
private $api; |
||||
|
||||
protected function setUp(){ |
||||
$request = new Request( |
||||
array( |
||||
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), |
||||
'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'), |
||||
'urlParams' => array('name' => 'Johnny Weissmüller'), |
||||
'files' => array('file' => 'filevalue'), |
||||
'env' => array('PATH' => 'daheim'), |
||||
'session' => array('sezession' => 'kein'), |
||||
'method' => 'hi', |
||||
) |
||||
); |
||||
|
||||
$this->api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName'), array('test')); |
||||
$this->api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('apptemplate_advanced')); |
||||
|
||||
$this->controller = new ChildController($this->api, $request); |
||||
} |
||||
|
||||
|
||||
public function testParamsGet(){ |
||||
$this->assertEquals('Johnny Weissmüller', $this->controller->params('name', 'Tarzan')); |
||||
} |
||||
|
||||
|
||||
public function testParamsGetDefault(){ |
||||
$this->assertEquals('Tarzan', $this->controller->params('Ape Man', 'Tarzan')); |
||||
} |
||||
|
||||
|
||||
public function testParamsFile(){ |
||||
$this->assertEquals('filevalue', $this->controller->params('file', 'filevalue')); |
||||
} |
||||
|
||||
|
||||
public function testGetUploadedFile(){ |
||||
$this->assertEquals('filevalue', $this->controller->getUploadedFile('file')); |
||||
} |
||||
|
||||
|
||||
|
||||
public function testGetUploadedFileDefault(){ |
||||
$this->assertEquals('default', $this->controller->params('files', 'default')); |
||||
} |
||||
|
||||
|
||||
public function testGetParams(){ |
||||
$params = array( |
||||
'name' => 'Johnny Weissmüller', |
||||
'nickname' => 'Janey', |
||||
); |
||||
|
||||
$this->assertEquals($params, $this->controller->getParams()); |
||||
} |
||||
|
||||
|
||||
public function testRender(){ |
||||
$this->assertTrue($this->controller->render('') instanceof TemplateResponse); |
||||
} |
||||
|
||||
|
||||
public function testSetParams(){ |
||||
$params = array('john' => 'foo'); |
||||
$response = $this->controller->render('home', $params); |
||||
|
||||
$this->assertEquals($params, $response->getParams()); |
||||
} |
||||
|
||||
|
||||
public function testRenderRenderAs(){ |
||||
$ocTpl = $this->getMock('Template', array('fetchPage')); |
||||
$ocTpl->expects($this->once()) |
||||
->method('fetchPage'); |
||||
|
||||
$api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName', 'getTemplate'), array('app')); |
||||
$api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
$api->expects($this->once()) |
||||
->method('getTemplate') |
||||
->with($this->equalTo('home'), $this->equalTo('admin'), $this->equalTo('app')) |
||||
->will($this->returnValue($ocTpl)); |
||||
|
||||
$this->controller = new ChildController($api, new Request()); |
||||
$this->controller->render('home', array(), 'admin')->render(); |
||||
} |
||||
|
||||
|
||||
public function testRenderHeaders(){ |
||||
$headers = array('one', 'two'); |
||||
$response = $this->controller->render('', array(), '', $headers); |
||||
|
||||
$this->assertTrue(in_array($headers[0], $response->getHeaders())); |
||||
$this->assertTrue(in_array($headers[1], $response->getHeaders())); |
||||
} |
||||
|
||||
|
||||
public function testGetRequestMethod(){ |
||||
$this->assertEquals('hi', $this->controller->method()); |
||||
} |
||||
|
||||
|
||||
public function testGetEnvVariable(){ |
||||
$this->assertEquals('daheim', $this->controller->env('PATH')); |
||||
} |
||||
|
||||
public function testGetSessionVariable(){ |
||||
$this->assertEquals('kein', $this->controller->session('sezession')); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,98 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @author Morris Jobke |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* @copyright 2013 Morris Jobke morris.jobke@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\DependencyInjection; |
||||
|
||||
use \OC\AppFramework\Http\Request; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class DIContainerTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $container; |
||||
|
||||
protected function setUp(){ |
||||
$this->container = new DIContainer('name'); |
||||
$this->api = $this->getMock('OC\AppFramework\Core\API', array('getTrans'), array('hi')); |
||||
} |
||||
|
||||
private function exchangeAPI(){ |
||||
$this->api->expects($this->any()) |
||||
->method('getTrans') |
||||
->will($this->returnValue('yo')); |
||||
$this->container['API'] = $this->api; |
||||
} |
||||
|
||||
public function testProvidesAPI(){ |
||||
$this->assertTrue(isset($this->container['API'])); |
||||
} |
||||
|
||||
|
||||
public function testProvidesRequest(){ |
||||
$this->assertTrue(isset($this->container['Request'])); |
||||
} |
||||
|
||||
|
||||
public function testProvidesSecurityMiddleware(){ |
||||
$this->assertTrue(isset($this->container['SecurityMiddleware'])); |
||||
} |
||||
|
||||
|
||||
public function testProvidesMiddlewareDispatcher(){ |
||||
$this->assertTrue(isset($this->container['MiddlewareDispatcher'])); |
||||
} |
||||
|
||||
|
||||
public function testProvidesAppName(){ |
||||
$this->assertTrue(isset($this->container['AppName'])); |
||||
} |
||||
|
||||
|
||||
public function testAppNameIsSetCorrectly(){ |
||||
$this->assertEquals('name', $this->container['AppName']); |
||||
} |
||||
|
||||
|
||||
public function testMiddlewareDispatcherIncludesSecurityMiddleware(){ |
||||
$this->container['Request'] = new Request(); |
||||
$security = $this->container['SecurityMiddleware']; |
||||
$dispatcher = $this->container['MiddlewareDispatcher']; |
||||
|
||||
$this->assertContains($security, $dispatcher->getMiddlewares()); |
||||
} |
||||
|
||||
|
||||
public function testMiddlewareDispatcherDoesNotIncludeTwigWhenTplDirectoryNotSet(){ |
||||
$this->container['Request'] = new Request(); |
||||
$this->exchangeAPI(); |
||||
$dispatcher = $this->container['MiddlewareDispatcher']; |
||||
|
||||
$this->assertEquals(1, count($dispatcher->getMiddlewares())); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,218 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
use OC\AppFramework\Core\API; |
||||
use OC\AppFramework\Middleware\MiddlewareDispatcher; |
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class DispatcherTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
|
||||
private $middlewareDispatcher; |
||||
private $dispatcher; |
||||
private $controllerMethod; |
||||
private $response; |
||||
private $lastModified; |
||||
private $etag; |
||||
private $http; |
||||
|
||||
protected function setUp() { |
||||
$this->controllerMethod = 'test'; |
||||
|
||||
$api = $this->getMockBuilder( |
||||
'\OC\AppFramework\Core\API') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$request = $this->getMockBuilder( |
||||
'\OC\AppFramework\Http\Request') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$this->http = $this->getMockBuilder( |
||||
'\OC\AppFramework\Http\Http') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
$this->middlewareDispatcher = $this->getMockBuilder( |
||||
'\OC\AppFramework\Middleware\MiddlewareDispatcher') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$this->controller = $this->getMock( |
||||
'\OC\AppFramework\Controller\Controller', |
||||
array($this->controllerMethod), array($api, $request)); |
||||
|
||||
$this->dispatcher = new Dispatcher( |
||||
$this->http, $this->middlewareDispatcher); |
||||
|
||||
$this->response = $this->getMockBuilder( |
||||
'\OC\AppFramework\Http\Response') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
$this->lastModified = new \DateTime(null, new \DateTimeZone('GMT')); |
||||
$this->etag = 'hi'; |
||||
} |
||||
|
||||
|
||||
private function setMiddlewareExpections($out=null, |
||||
$httpHeaders=null, $responseHeaders=array(), |
||||
$ex=false, $catchEx=true) { |
||||
|
||||
if($ex) { |
||||
$exception = new \Exception(); |
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('beforeController') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod)) |
||||
->will($this->throwException($exception)); |
||||
if($catchEx) { |
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('afterException') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod), |
||||
$this->equalTo($exception)) |
||||
->will($this->returnValue($this->response)); |
||||
} else { |
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('afterException') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod), |
||||
$this->equalTo($exception)) |
||||
->will($this->returnValue(null)); |
||||
return; |
||||
} |
||||
} else { |
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('beforeController') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod)); |
||||
$this->controller->expects($this->once()) |
||||
->method($this->controllerMethod) |
||||
->will($this->returnValue($this->response)); |
||||
} |
||||
|
||||
$this->response->expects($this->once()) |
||||
->method('render') |
||||
->will($this->returnValue($out)); |
||||
$this->response->expects($this->once()) |
||||
->method('getStatus') |
||||
->will($this->returnValue(Http::STATUS_OK)); |
||||
$this->response->expects($this->once()) |
||||
->method('getLastModified') |
||||
->will($this->returnValue($this->lastModified)); |
||||
$this->response->expects($this->once()) |
||||
->method('getETag') |
||||
->will($this->returnValue($this->etag)); |
||||
$this->response->expects($this->once()) |
||||
->method('getHeaders') |
||||
->will($this->returnValue($responseHeaders)); |
||||
$this->http->expects($this->once()) |
||||
->method('getStatusHeader') |
||||
->with($this->equalTo(Http::STATUS_OK), |
||||
$this->equalTo($this->lastModified), |
||||
$this->equalTo($this->etag)) |
||||
->will($this->returnValue($httpHeaders)); |
||||
|
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('afterController') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod), |
||||
$this->equalTo($this->response)) |
||||
->will($this->returnValue($this->response)); |
||||
|
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('afterController') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod), |
||||
$this->equalTo($this->response)) |
||||
->will($this->returnValue($this->response)); |
||||
|
||||
$this->middlewareDispatcher->expects($this->once()) |
||||
->method('beforeOutput') |
||||
->with($this->equalTo($this->controller), |
||||
$this->equalTo($this->controllerMethod), |
||||
$this->equalTo($out)) |
||||
->will($this->returnValue($out)); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
public function testDispatcherReturnsArrayWith2Entries() { |
||||
$this->setMiddlewareExpections(); |
||||
|
||||
$response = $this->dispatcher->dispatch($this->controller, |
||||
$this->controllerMethod); |
||||
$this->assertNull($response[0]); |
||||
$this->assertEquals(array(), $response[1]); |
||||
$this->assertNull($response[2]); |
||||
} |
||||
|
||||
|
||||
public function testHeadersAndOutputAreReturned(){ |
||||
$out = 'yo'; |
||||
$httpHeaders = 'Http'; |
||||
$responseHeaders = array('hell' => 'yeah'); |
||||
$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders); |
||||
|
||||
$response = $this->dispatcher->dispatch($this->controller, |
||||
$this->controllerMethod); |
||||
|
||||
$this->assertEquals($httpHeaders, $response[0]); |
||||
$this->assertEquals($responseHeaders, $response[1]); |
||||
$this->assertEquals($out, $response[2]); |
||||
} |
||||
|
||||
|
||||
public function testExceptionCallsAfterException() { |
||||
$out = 'yo'; |
||||
$httpHeaders = 'Http'; |
||||
$responseHeaders = array('hell' => 'yeah'); |
||||
$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true); |
||||
|
||||
$response = $this->dispatcher->dispatch($this->controller, |
||||
$this->controllerMethod); |
||||
|
||||
$this->assertEquals($httpHeaders, $response[0]); |
||||
$this->assertEquals($responseHeaders, $response[1]); |
||||
$this->assertEquals($out, $response[2]); |
||||
} |
||||
|
||||
|
||||
public function testExceptionThrowsIfCanNotBeHandledByAfterException() { |
||||
$out = 'yo'; |
||||
$httpHeaders = 'Http'; |
||||
$responseHeaders = array('hell' => 'yeah'); |
||||
$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true, false); |
||||
|
||||
$this->setExpectedException('\Exception'); |
||||
$response = $this->dispatcher->dispatch($this->controller, |
||||
$this->controllerMethod); |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class ChildDownloadResponse extends DownloadResponse {}; |
||||
|
||||
|
||||
class DownloadResponseTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
protected $response; |
||||
|
||||
protected function setUp(){ |
||||
$this->response = new ChildDownloadResponse('file', 'content'); |
||||
} |
||||
|
||||
|
||||
public function testHeaders() { |
||||
$headers = $this->response->getHeaders(); |
||||
|
||||
$this->assertContains('attachment; filename="file"', $headers['Content-Disposition']); |
||||
$this->assertContains('content', $headers['Content-Type']); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,87 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
|
||||
class HttpTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $server; |
||||
private $http; |
||||
|
||||
protected function setUp(){ |
||||
$this->server = array(); |
||||
$this->http = new Http($this->server); |
||||
} |
||||
|
||||
|
||||
public function testProtocol() { |
||||
$header = $this->http->getStatusHeader(Http::STATUS_TEMPORARY_REDIRECT); |
||||
$this->assertEquals('HTTP/1.1 307 Temporary Redirect', $header); |
||||
} |
||||
|
||||
|
||||
public function testProtocol10() { |
||||
$this->http = new Http($this->server, 'HTTP/1.0'); |
||||
$header = $this->http->getStatusHeader(Http::STATUS_OK); |
||||
$this->assertEquals('HTTP/1.0 200 OK', $header); |
||||
} |
||||
|
||||
|
||||
public function testEtagMatchReturnsNotModified() { |
||||
$http = new Http(array('HTTP_IF_NONE_MATCH' => 'hi')); |
||||
|
||||
$header = $http->getStatusHeader(Http::STATUS_OK, null, 'hi'); |
||||
$this->assertEquals('HTTP/1.1 304 Not Modified', $header); |
||||
} |
||||
|
||||
|
||||
public function testLastModifiedMatchReturnsNotModified() { |
||||
$dateTime = new \DateTime(null, new \DateTimeZone('GMT')); |
||||
$dateTime->setTimestamp('12'); |
||||
|
||||
$http = new Http( |
||||
array( |
||||
'HTTP_IF_MODIFIED_SINCE' => 'Thu, 01 Jan 1970 00:00:12 +0000') |
||||
); |
||||
|
||||
$header = $http->getStatusHeader(Http::STATUS_OK, $dateTime); |
||||
$this->assertEquals('HTTP/1.1 304 Not Modified', $header); |
||||
} |
||||
|
||||
|
||||
|
||||
public function testTempRedirectBecomesFoundInHttp10() { |
||||
$http = new Http(array(), 'HTTP/1.0'); |
||||
|
||||
$header = $http->getStatusHeader(Http::STATUS_TEMPORARY_REDIRECT); |
||||
$this->assertEquals('HTTP/1.0 302 Found', $header); |
||||
} |
||||
// TODO: write unittests for http codes |
||||
|
||||
} |
||||
@ -0,0 +1,96 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @author Morris Jobke |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* @copyright 2013 Morris Jobke morris.jobke@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
|
||||
class JSONResponseTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
/** |
||||
* @var JSONResponse |
||||
*/ |
||||
private $json; |
||||
|
||||
protected function setUp() { |
||||
$this->json = new JSONResponse(); |
||||
} |
||||
|
||||
|
||||
public function testHeader() { |
||||
$headers = $this->json->getHeaders(); |
||||
$this->assertEquals('application/json; charset=utf-8', $headers['Content-type']); |
||||
} |
||||
|
||||
|
||||
public function testSetData() { |
||||
$params = array('hi', 'yo'); |
||||
$this->json->setData($params); |
||||
|
||||
$this->assertEquals(array('hi', 'yo'), $this->json->getData()); |
||||
} |
||||
|
||||
|
||||
public function testSetRender() { |
||||
$params = array('test' => 'hi'); |
||||
$this->json->setData($params); |
||||
|
||||
$expected = '{"test":"hi"}'; |
||||
|
||||
$this->assertEquals($expected, $this->json->render()); |
||||
} |
||||
|
||||
|
||||
public function testRender() { |
||||
$params = array('test' => 'hi'); |
||||
$this->json->setData($params); |
||||
|
||||
$expected = '{"test":"hi"}'; |
||||
|
||||
$this->assertEquals($expected, $this->json->render()); |
||||
} |
||||
|
||||
|
||||
public function testShouldHaveXContentHeaderByDefault() { |
||||
$headers = $this->json->getHeaders(); |
||||
$this->assertEquals('nosniff', $headers['X-Content-Type-Options']); |
||||
} |
||||
|
||||
|
||||
public function testConstructorAllowsToSetData() { |
||||
$data = array('hi'); |
||||
$code = 300; |
||||
$response = new JSONResponse($data, $code); |
||||
|
||||
$expected = '["hi"]'; |
||||
$this->assertEquals($expected, $response->render()); |
||||
$this->assertEquals($code, $response->getStatus()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
|
||||
class RedirectResponseTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
|
||||
protected $response; |
||||
|
||||
protected function setUp(){ |
||||
$this->response = new RedirectResponse('/url'); |
||||
} |
||||
|
||||
|
||||
public function testHeaders() { |
||||
$headers = $this->response->getHeaders(); |
||||
$this->assertEquals('/url', $headers['Location']); |
||||
$this->assertEquals(Http::STATUS_TEMPORARY_REDIRECT, |
||||
$this->response->getStatus()); |
||||
} |
||||
|
||||
|
||||
public function testGetRedirectUrl(){ |
||||
$this->assertEquals('/url', $this->response->getRedirectUrl()); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,78 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net) |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
class RequestTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
public function testRequestAccessors() { |
||||
$vars = array( |
||||
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), |
||||
); |
||||
|
||||
$request = new Request($vars); |
||||
|
||||
// Countable |
||||
$this->assertEquals(2, count($request)); |
||||
// Array access |
||||
$this->assertEquals('Joey', $request['nickname']); |
||||
// "Magic" accessors |
||||
$this->assertEquals('Joey', $request->{'nickname'}); |
||||
$this->assertTrue(isset($request['nickname'])); |
||||
$this->assertTrue(isset($request->{'nickname'})); |
||||
$this->assertEquals(false, isset($request->{'flickname'})); |
||||
// Only testing 'get', but same approach for post, files etc. |
||||
$this->assertEquals('Joey', $request->get['nickname']); |
||||
// Always returns null if variable not set. |
||||
$this->assertEquals(null, $request->{'flickname'}); |
||||
} |
||||
|
||||
// urlParams has precedence over POST which has precedence over GET |
||||
public function testPrecedence() { |
||||
$vars = array( |
||||
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), |
||||
'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'), |
||||
'urlParams' => array('user' => 'jw', 'name' => 'Johnny Weissmüller'), |
||||
); |
||||
|
||||
$request = new Request($vars); |
||||
|
||||
$this->assertEquals(3, count($request)); |
||||
$this->assertEquals('Janey', $request->{'nickname'}); |
||||
$this->assertEquals('Johnny Weissmüller', $request->{'name'}); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testImmutableArrayAccess() { |
||||
$vars = array( |
||||
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), |
||||
); |
||||
|
||||
$request = new Request($vars); |
||||
$request['nickname'] = 'Janey'; |
||||
} |
||||
|
||||
/** |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testImmutableMagicAccess() { |
||||
$vars = array( |
||||
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), |
||||
); |
||||
|
||||
$request = new Request($vars); |
||||
$request->{'nickname'} = 'Janey'; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,119 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
|
||||
class ResponseTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
|
||||
private $childResponse; |
||||
|
||||
protected function setUp(){ |
||||
$this->childResponse = new Response(); |
||||
} |
||||
|
||||
|
||||
public function testAddHeader(){ |
||||
$this->childResponse->addHeader('hello', 'world'); |
||||
$headers = $this->childResponse->getHeaders(); |
||||
$this->assertEquals('world', $headers['hello']); |
||||
} |
||||
|
||||
|
||||
public function testAddHeaderValueNullDeletesIt(){ |
||||
$this->childResponse->addHeader('hello', 'world'); |
||||
$this->childResponse->addHeader('hello', null); |
||||
$this->assertEquals(1, count($this->childResponse->getHeaders())); |
||||
} |
||||
|
||||
|
||||
public function testCacheHeadersAreDisabledByDefault(){ |
||||
$headers = $this->childResponse->getHeaders(); |
||||
$this->assertEquals('no-cache, must-revalidate', $headers['Cache-Control']); |
||||
} |
||||
|
||||
|
||||
public function testRenderReturnNullByDefault(){ |
||||
$this->assertEquals(null, $this->childResponse->render()); |
||||
} |
||||
|
||||
|
||||
public function testGetStatus() { |
||||
$default = $this->childResponse->getStatus(); |
||||
|
||||
$this->childResponse->setStatus(Http::STATUS_NOT_FOUND); |
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $default); |
||||
$this->assertEquals(Http::STATUS_NOT_FOUND, $this->childResponse->getStatus()); |
||||
} |
||||
|
||||
|
||||
public function testGetEtag() { |
||||
$this->childResponse->setEtag('hi'); |
||||
$this->assertEquals('hi', $this->childResponse->getEtag()); |
||||
} |
||||
|
||||
|
||||
public function testGetLastModified() { |
||||
$lastModified = new \DateTime(null, new \DateTimeZone('GMT')); |
||||
$lastModified->setTimestamp(1); |
||||
$this->childResponse->setLastModified($lastModified); |
||||
$this->assertEquals($lastModified, $this->childResponse->getLastModified()); |
||||
} |
||||
|
||||
|
||||
|
||||
public function testCacheSecondsZero() { |
||||
$this->childResponse->cacheFor(0); |
||||
|
||||
$headers = $this->childResponse->getHeaders(); |
||||
$this->assertEquals('no-cache, must-revalidate', $headers['Cache-Control']); |
||||
} |
||||
|
||||
|
||||
public function testCacheSeconds() { |
||||
$this->childResponse->cacheFor(33); |
||||
|
||||
$headers = $this->childResponse->getHeaders(); |
||||
$this->assertEquals('max-age=33, must-revalidate', |
||||
$headers['Cache-Control']); |
||||
} |
||||
|
||||
|
||||
|
||||
public function testEtagLastModifiedHeaders() { |
||||
$lastModified = new \DateTime(null, new \DateTimeZone('GMT')); |
||||
$lastModified->setTimestamp(1); |
||||
$this->childResponse->setLastModified($lastModified); |
||||
$headers = $this->childResponse->getHeaders(); |
||||
$this->assertEquals('Thu, 01 Jan 1970 00:00:01 +0000', $headers['Last-Modified']); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,157 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Http; |
||||
|
||||
use OC\AppFramework\Core\API; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class TemplateResponseTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $tpl; |
||||
private $api; |
||||
|
||||
protected function setUp() { |
||||
$this->api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName'), array('test')); |
||||
$this->api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
|
||||
$this->tpl = new TemplateResponse($this->api, 'home'); |
||||
} |
||||
|
||||
|
||||
public function testSetParams(){ |
||||
$params = array('hi' => 'yo'); |
||||
$this->tpl->setParams($params); |
||||
|
||||
$this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); |
||||
} |
||||
|
||||
|
||||
public function testGetTemplateName(){ |
||||
$this->assertEquals('home', $this->tpl->getTemplateName()); |
||||
} |
||||
|
||||
|
||||
public function testRender(){ |
||||
$ocTpl = $this->getMock('Template', array('fetchPage')); |
||||
$ocTpl->expects($this->once()) |
||||
->method('fetchPage'); |
||||
|
||||
$api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName', 'getTemplate'), array('app')); |
||||
$api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
$api->expects($this->once()) |
||||
->method('getTemplate') |
||||
->with($this->equalTo('home'), $this->equalTo('user'), $this->equalTo('app')) |
||||
->will($this->returnValue($ocTpl)); |
||||
|
||||
$tpl = new TemplateResponse($api, 'home'); |
||||
|
||||
$tpl->render(); |
||||
} |
||||
|
||||
|
||||
public function testRenderAssignsParams(){ |
||||
$params = array('john' => 'doe'); |
||||
|
||||
$ocTpl = $this->getMock('Template', array('assign', 'fetchPage')); |
||||
$ocTpl->expects($this->once()) |
||||
->method('assign') |
||||
->with($this->equalTo('john'), $this->equalTo('doe')); |
||||
|
||||
$api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName', 'getTemplate'), array('app')); |
||||
$api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
$api->expects($this->once()) |
||||
->method('getTemplate') |
||||
->with($this->equalTo('home'), $this->equalTo('user'), $this->equalTo('app')) |
||||
->will($this->returnValue($ocTpl)); |
||||
|
||||
$tpl = new TemplateResponse($api, 'home'); |
||||
$tpl->setParams($params); |
||||
|
||||
$tpl->render(); |
||||
} |
||||
|
||||
|
||||
public function testRenderDifferentApp(){ |
||||
$ocTpl = $this->getMock('Template', array('fetchPage')); |
||||
$ocTpl->expects($this->once()) |
||||
->method('fetchPage'); |
||||
|
||||
$api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName', 'getTemplate'), array('app')); |
||||
$api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
$api->expects($this->once()) |
||||
->method('getTemplate') |
||||
->with($this->equalTo('home'), $this->equalTo('user'), $this->equalTo('app2')) |
||||
->will($this->returnValue($ocTpl)); |
||||
|
||||
$tpl = new TemplateResponse($api, 'home', 'app2'); |
||||
|
||||
$tpl->render(); |
||||
} |
||||
|
||||
|
||||
public function testRenderDifferentRenderAs(){ |
||||
$ocTpl = $this->getMock('Template', array('fetchPage')); |
||||
$ocTpl->expects($this->once()) |
||||
->method('fetchPage'); |
||||
|
||||
$api = $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName', 'getTemplate'), array('app')); |
||||
$api->expects($this->any()) |
||||
->method('getAppName') |
||||
->will($this->returnValue('app')); |
||||
$api->expects($this->once()) |
||||
->method('getTemplate') |
||||
->with($this->equalTo('home'), $this->equalTo('admin'), $this->equalTo('app')) |
||||
->will($this->returnValue($ocTpl)); |
||||
|
||||
$tpl = new TemplateResponse($api, 'home'); |
||||
$tpl->renderAs('admin'); |
||||
|
||||
$tpl->render(); |
||||
} |
||||
|
||||
|
||||
public function testGetRenderAs(){ |
||||
$render = 'myrender'; |
||||
$this->tpl->renderAs($render); |
||||
$this->assertEquals($render, $this->tpl->getRenderAs()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,280 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework; |
||||
|
||||
use OC\AppFramework\Controller\Controller; |
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Http\Response; |
||||
use OC\AppFramework\Middleware\Middleware; |
||||
use OC\AppFramework\Middleware\MiddlewareDispatcher; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
// needed to test ordering |
||||
class TestMiddleware extends Middleware { |
||||
public static $beforeControllerCalled = 0; |
||||
public static $afterControllerCalled = 0; |
||||
public static $afterExceptionCalled = 0; |
||||
public static $beforeOutputCalled = 0; |
||||
|
||||
public $beforeControllerOrder = 0; |
||||
public $afterControllerOrder = 0; |
||||
public $afterExceptionOrder = 0; |
||||
public $beforeOutputOrder = 0; |
||||
|
||||
public $controller; |
||||
public $methodName; |
||||
public $exception; |
||||
public $response; |
||||
public $output; |
||||
|
||||
private $beforeControllerThrowsEx; |
||||
|
||||
public function __construct($beforeControllerThrowsEx) { |
||||
self::$beforeControllerCalled = 0; |
||||
self::$afterControllerCalled = 0; |
||||
self::$afterExceptionCalled = 0; |
||||
self::$beforeOutputCalled = 0; |
||||
$this->beforeControllerThrowsEx = $beforeControllerThrowsEx; |
||||
} |
||||
|
||||
public function beforeController($controller, $methodName){ |
||||
self::$beforeControllerCalled++; |
||||
$this->beforeControllerOrder = self::$beforeControllerCalled; |
||||
$this->controller = $controller; |
||||
$this->methodName = $methodName; |
||||
if($this->beforeControllerThrowsEx){ |
||||
throw new \Exception(); |
||||
} |
||||
} |
||||
|
||||
public function afterException($controller, $methodName, \Exception $exception){ |
||||
self::$afterExceptionCalled++; |
||||
$this->afterExceptionOrder = self::$afterExceptionCalled; |
||||
$this->controller = $controller; |
||||
$this->methodName = $methodName; |
||||
$this->exception = $exception; |
||||
parent::afterException($controller, $methodName, $exception); |
||||
} |
||||
|
||||
public function afterController($controller, $methodName, Response $response){ |
||||
self::$afterControllerCalled++; |
||||
$this->afterControllerOrder = self::$afterControllerCalled; |
||||
$this->controller = $controller; |
||||
$this->methodName = $methodName; |
||||
$this->response = $response; |
||||
return parent::afterController($controller, $methodName, $response); |
||||
} |
||||
|
||||
public function beforeOutput($controller, $methodName, $output){ |
||||
self::$beforeOutputCalled++; |
||||
$this->beforeOutputOrder = self::$beforeOutputCalled; |
||||
$this->controller = $controller; |
||||
$this->methodName = $methodName; |
||||
$this->output = $output; |
||||
return parent::beforeOutput($controller, $methodName, $output); |
||||
} |
||||
} |
||||
|
||||
|
||||
class MiddlewareDispatcherTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $dispatcher; |
||||
|
||||
|
||||
public function setUp() { |
||||
$this->dispatcher = new MiddlewareDispatcher(); |
||||
$this->controller = $this->getControllerMock(); |
||||
$this->method = 'method'; |
||||
$this->response = new Response(); |
||||
$this->output = 'hi'; |
||||
$this->exception = new \Exception(); |
||||
} |
||||
|
||||
|
||||
private function getAPIMock(){ |
||||
return $this->getMock('OC\AppFramework\Core\API', |
||||
array('getAppName'), array('app')); |
||||
} |
||||
|
||||
|
||||
private function getControllerMock(){ |
||||
return $this->getMock('OC\AppFramework\Controller\Controller', array('method'), |
||||
array($this->getAPIMock(), new Request())); |
||||
} |
||||
|
||||
|
||||
private function getMiddleware($beforeControllerThrowsEx=false){ |
||||
$m1 = new TestMiddleware($beforeControllerThrowsEx); |
||||
$this->dispatcher->registerMiddleware($m1); |
||||
return $m1; |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionShouldReturnResponseOfMiddleware(){ |
||||
$response = new Response(); |
||||
$m1 = $this->getMock('\OC\AppFramework\Middleware\Middleware', |
||||
array('afterException', 'beforeController')); |
||||
$m1->expects($this->never()) |
||||
->method('afterException'); |
||||
|
||||
$m2 = $this->getMock('OC\AppFramework\Middleware\Middleware', |
||||
array('afterException', 'beforeController')); |
||||
$m2->expects($this->once()) |
||||
->method('afterException') |
||||
->will($this->returnValue($response)); |
||||
|
||||
$this->dispatcher->registerMiddleware($m1); |
||||
$this->dispatcher->registerMiddleware($m2); |
||||
|
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
$this->assertEquals($response, $this->dispatcher->afterException($this->controller, $this->method, $this->exception)); |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionShouldThrowAgainWhenNotHandled(){ |
||||
$m1 = new TestMiddleware(false); |
||||
$m2 = new TestMiddleware(true); |
||||
|
||||
$this->dispatcher->registerMiddleware($m1); |
||||
$this->dispatcher->registerMiddleware($m2); |
||||
|
||||
$this->setExpectedException('\Exception'); |
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
$this->dispatcher->afterException($this->controller, $this->method, $this->exception); |
||||
} |
||||
|
||||
|
||||
public function testBeforeControllerCorrectArguments(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
|
||||
$this->assertEquals($this->controller, $m1->controller); |
||||
$this->assertEquals($this->method, $m1->methodName); |
||||
} |
||||
|
||||
|
||||
public function testAfterControllerCorrectArguments(){ |
||||
$m1 = $this->getMiddleware(); |
||||
|
||||
$this->dispatcher->afterController($this->controller, $this->method, $this->response); |
||||
|
||||
$this->assertEquals($this->controller, $m1->controller); |
||||
$this->assertEquals($this->method, $m1->methodName); |
||||
$this->assertEquals($this->response, $m1->response); |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionCorrectArguments(){ |
||||
$m1 = $this->getMiddleware(); |
||||
|
||||
$this->setExpectedException('\Exception'); |
||||
|
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
$this->dispatcher->afterException($this->controller, $this->method, $this->exception); |
||||
|
||||
$this->assertEquals($this->controller, $m1->controller); |
||||
$this->assertEquals($this->method, $m1->methodName); |
||||
$this->assertEquals($this->exception, $m1->exception); |
||||
} |
||||
|
||||
|
||||
public function testBeforeOutputCorrectArguments(){ |
||||
$m1 = $this->getMiddleware(); |
||||
|
||||
$this->dispatcher->beforeOutput($this->controller, $this->method, $this->output); |
||||
|
||||
$this->assertEquals($this->controller, $m1->controller); |
||||
$this->assertEquals($this->method, $m1->methodName); |
||||
$this->assertEquals($this->output, $m1->output); |
||||
} |
||||
|
||||
|
||||
public function testBeforeControllerOrder(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$m2 = $this->getMiddleware(); |
||||
|
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
|
||||
$this->assertEquals(1, $m1->beforeControllerOrder); |
||||
$this->assertEquals(2, $m2->beforeControllerOrder); |
||||
} |
||||
|
||||
public function testAfterControllerOrder(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$m2 = $this->getMiddleware(); |
||||
|
||||
$this->dispatcher->afterController($this->controller, $this->method, $this->response); |
||||
|
||||
$this->assertEquals(2, $m1->afterControllerOrder); |
||||
$this->assertEquals(1, $m2->afterControllerOrder); |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionOrder(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$m2 = $this->getMiddleware(); |
||||
|
||||
$this->setExpectedException('\Exception'); |
||||
$this->dispatcher->beforeController($this->controller, $this->method); |
||||
$this->dispatcher->afterException($this->controller, $this->method, $this->exception); |
||||
|
||||
$this->assertEquals(1, $m1->afterExceptionOrder); |
||||
$this->assertEquals(1, $m2->afterExceptionOrder); |
||||
} |
||||
|
||||
|
||||
public function testBeforeOutputOrder(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$m2 = $this->getMiddleware(); |
||||
|
||||
$this->dispatcher->beforeOutput($this->controller, $this->method, $this->output); |
||||
|
||||
$this->assertEquals(2, $m1->beforeOutputOrder); |
||||
$this->assertEquals(1, $m2->beforeOutputOrder); |
||||
} |
||||
|
||||
|
||||
public function testExceptionShouldRunAfterExceptionOfOnlyPreviouslyExecutedMiddlewares(){ |
||||
$m1 = $this->getMiddleware(); |
||||
$m2 = $this->getMiddleware(true); |
||||
$m3 = $this->getMock('\OC\AppFramework\Middleware\Middleware'); |
||||
$m3->expects($this->never()) |
||||
->method('afterException'); |
||||
$m3->expects($this->never()) |
||||
->method('beforeController'); |
||||
$m3->expects($this->never()) |
||||
->method('afterController'); |
||||
|
||||
$this->dispatcher->registerMiddleware($m3); |
||||
|
||||
$this->dispatcher->beforeOutput($this->controller, $this->method, $this->output); |
||||
|
||||
$this->assertEquals(2, $m1->beforeOutputOrder); |
||||
$this->assertEquals(1, $m2->beforeOutputOrder); |
||||
} |
||||
} |
||||
@ -0,0 +1,82 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework; |
||||
|
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Middleware\Middleware; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
|
||||
class ChildMiddleware extends Middleware {}; |
||||
|
||||
|
||||
class MiddlewareTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $middleware; |
||||
private $controller; |
||||
private $exception; |
||||
private $api; |
||||
|
||||
protected function setUp(){ |
||||
$this->middleware = new ChildMiddleware(); |
||||
|
||||
$this->api = $this->getMock('OC\AppFramework\Core\API', |
||||
array(), array('test')); |
||||
|
||||
$this->controller = $this->getMock('OC\AppFramework\Controller\Controller', |
||||
array(), array($this->api, new Request())); |
||||
$this->exception = new \Exception(); |
||||
$this->response = $this->getMock('OC\AppFramework\Http\Response'); |
||||
} |
||||
|
||||
|
||||
public function testBeforeController() { |
||||
$this->middleware->beforeController($this->controller, null, $this->exception); |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionRaiseAgainWhenUnhandled() { |
||||
$this->setExpectedException('Exception'); |
||||
$afterEx = $this->middleware->afterException($this->controller, null, $this->exception); |
||||
} |
||||
|
||||
|
||||
public function testAfterControllerReturnResponseWhenUnhandled() { |
||||
$response = $this->middleware->afterController($this->controller, null, $this->response); |
||||
|
||||
$this->assertEquals($this->response, $response); |
||||
} |
||||
|
||||
|
||||
public function testBeforeOutputReturnOutputhenUnhandled() { |
||||
$output = $this->middleware->beforeOutput($this->controller, null, 'test'); |
||||
|
||||
$this->assertEquals('test', $output); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,388 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Middleware\Security; |
||||
|
||||
use OC\AppFramework\Http\Http; |
||||
use OC\AppFramework\Http\Request; |
||||
use OC\AppFramework\Http\RedirectResponse; |
||||
use OC\AppFramework\Http\JSONResponse; |
||||
use OC\AppFramework\Middleware\Middleware; |
||||
|
||||
|
||||
require_once(__DIR__ . "/../../classloader.php"); |
||||
|
||||
|
||||
class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private $middleware; |
||||
private $controller; |
||||
private $secException; |
||||
private $secAjaxException; |
||||
private $request; |
||||
|
||||
public function setUp() { |
||||
$api = $this->getMock('OC\AppFramework\Core\API', array(), array('test')); |
||||
$this->controller = $this->getMock('OC\AppFramework\Controller\Controller', |
||||
array(), array($api, new Request())); |
||||
|
||||
$this->request = new Request(); |
||||
$this->middleware = new SecurityMiddleware($api, $this->request); |
||||
$this->secException = new SecurityException('hey', false); |
||||
$this->secAjaxException = new SecurityException('hey', true); |
||||
} |
||||
|
||||
|
||||
private function getAPI(){ |
||||
return $this->getMock('OC\AppFramework\Core\API', |
||||
array('isLoggedIn', 'passesCSRFCheck', 'isAdminUser', |
||||
'isSubAdminUser', 'activateNavigationEntry', |
||||
'getUserId'), |
||||
array('app')); |
||||
} |
||||
|
||||
|
||||
private function checkNavEntry($method, $shouldBeActivated=false){ |
||||
$api = $this->getAPI(); |
||||
|
||||
if($shouldBeActivated){ |
||||
$api->expects($this->once()) |
||||
->method('activateNavigationEntry'); |
||||
} else { |
||||
$api->expects($this->never()) |
||||
->method('activateNavigationEntry'); |
||||
} |
||||
|
||||
$sec = new SecurityMiddleware($api, $this->request); |
||||
$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testSetNavigationEntry(){ |
||||
$this->checkNavEntry('testSetNavigationEntry', true); |
||||
} |
||||
|
||||
|
||||
private function ajaxExceptionCheck($method, $shouldBeAjax=false){ |
||||
$api = $this->getAPI(); |
||||
$api->expects($this->any()) |
||||
->method('passesCSRFCheck') |
||||
->will($this->returnValue(false)); |
||||
|
||||
$sec = new SecurityMiddleware($api, $this->request); |
||||
|
||||
try { |
||||
$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', |
||||
$method); |
||||
} catch (SecurityException $ex){ |
||||
if($shouldBeAjax){ |
||||
$this->assertTrue($ex->isAjax()); |
||||
} else { |
||||
$this->assertFalse($ex->isAjax()); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @Ajax |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testAjaxException(){ |
||||
$this->ajaxExceptionCheck('testAjaxException'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testNoAjaxException(){ |
||||
$this->ajaxExceptionCheck('testNoAjaxException'); |
||||
} |
||||
|
||||
|
||||
private function ajaxExceptionStatus($method, $test, $status) { |
||||
$api = $this->getAPI(); |
||||
$api->expects($this->any()) |
||||
->method($test) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$sec = new SecurityMiddleware($api, $this->request); |
||||
|
||||
try { |
||||
$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', |
||||
$method); |
||||
} catch (SecurityException $ex){ |
||||
$this->assertEquals($status, $ex->getCode()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @Ajax |
||||
*/ |
||||
public function testAjaxStatusLoggedInCheck() { |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusLoggedInCheck', |
||||
'isLoggedIn', |
||||
Http::STATUS_UNAUTHORIZED |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @Ajax |
||||
* @IsLoggedInExemption |
||||
*/ |
||||
public function testAjaxNotAdminCheck() { |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxNotAdminCheck', |
||||
'isAdminUser', |
||||
Http::STATUS_FORBIDDEN |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @Ajax |
||||
* @IsLoggedInExemption |
||||
* @IsAdminExemption |
||||
*/ |
||||
public function testAjaxNotSubAdminCheck() { |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxNotSubAdminCheck', |
||||
'isSubAdminUser', |
||||
Http::STATUS_FORBIDDEN |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @Ajax |
||||
* @IsLoggedInExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testAjaxStatusCSRFCheck() { |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusCSRFCheck', |
||||
'passesCSRFCheck', |
||||
Http::STATUS_PRECONDITION_FAILED |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @Ajax |
||||
* @CSRFExemption |
||||
* @IsLoggedInExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testAjaxStatusAllGood() { |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusAllGood', |
||||
'isLoggedIn', |
||||
0 |
||||
); |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusAllGood', |
||||
'isAdminUser', |
||||
0 |
||||
); |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusAllGood', |
||||
'isSubAdminUser', |
||||
0 |
||||
); |
||||
$this->ajaxExceptionStatus( |
||||
'testAjaxStatusAllGood', |
||||
'passesCSRFCheck', |
||||
0 |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testNoChecks(){ |
||||
$api = $this->getAPI(); |
||||
$api->expects($this->never()) |
||||
->method('passesCSRFCheck') |
||||
->will($this->returnValue(true)); |
||||
$api->expects($this->never()) |
||||
->method('isAdminUser') |
||||
->will($this->returnValue(true)); |
||||
$api->expects($this->never()) |
||||
->method('isSubAdminUser') |
||||
->will($this->returnValue(true)); |
||||
$api->expects($this->never()) |
||||
->method('isLoggedIn') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$sec = new SecurityMiddleware($api, $this->request); |
||||
$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', |
||||
'testNoChecks'); |
||||
} |
||||
|
||||
|
||||
private function securityCheck($method, $expects, $shouldFail=false){ |
||||
$api = $this->getAPI(); |
||||
$api->expects($this->once()) |
||||
->method($expects) |
||||
->will($this->returnValue(!$shouldFail)); |
||||
|
||||
$sec = new SecurityMiddleware($api, $this->request); |
||||
|
||||
if($shouldFail){ |
||||
$this->setExpectedException('\OC\AppFramework\Middleware\Security\SecurityException'); |
||||
} |
||||
|
||||
$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testCsrfCheck(){ |
||||
$this->securityCheck('testCsrfCheck', 'passesCSRFCheck'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testFailCsrfCheck(){ |
||||
$this->securityCheck('testFailCsrfCheck', 'passesCSRFCheck', true); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testLoggedInCheck(){ |
||||
$this->securityCheck('testLoggedInCheck', 'isLoggedIn'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testFailLoggedInCheck(){ |
||||
$this->securityCheck('testFailLoggedInCheck', 'isLoggedIn', true); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testIsAdminCheck(){ |
||||
$this->securityCheck('testIsAdminCheck', 'isAdminUser'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsSubAdminExemption |
||||
*/ |
||||
public function testFailIsAdminCheck(){ |
||||
$this->securityCheck('testFailIsAdminCheck', 'isAdminUser', true); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
*/ |
||||
public function testIsSubAdminCheck(){ |
||||
$this->securityCheck('testIsSubAdminCheck', 'isSubAdminUser'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @IsLoggedInExemption |
||||
* @CSRFExemption |
||||
* @IsAdminExemption |
||||
*/ |
||||
public function testFailIsSubAdminCheck(){ |
||||
$this->securityCheck('testFailIsSubAdminCheck', 'isSubAdminUser', true); |
||||
} |
||||
|
||||
|
||||
|
||||
public function testAfterExceptionNotCaughtThrowsItAgain(){ |
||||
$ex = new \Exception(); |
||||
$this->setExpectedException('\Exception'); |
||||
$this->middleware->afterException($this->controller, 'test', $ex); |
||||
} |
||||
|
||||
|
||||
public function testAfterExceptionReturnsRedirect(){ |
||||
$api = $this->getMock('OC\AppFramework\Core\API', array(), array('test')); |
||||
$this->controller = $this->getMock('OC\AppFramework\Controller\Controller', |
||||
array(), array($api, new Request())); |
||||
|
||||
$this->request = new Request( |
||||
array('server' => array('HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'))); |
||||
$this->middleware = new SecurityMiddleware($api, $this->request); |
||||
$response = $this->middleware->afterException($this->controller, 'test', |
||||
$this->secException); |
||||
|
||||
$this->assertTrue($response instanceof RedirectResponse); |
||||
} |
||||
|
||||
|
||||
public function testAfterAjaxExceptionReturnsJSONError(){ |
||||
$response = $this->middleware->afterException($this->controller, 'test', |
||||
$this->secAjaxException); |
||||
|
||||
$this->assertTrue($response instanceof JSONResponse); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,214 @@ |
||||
<?php |
||||
|
||||
namespace OC\AppFramework\Routing; |
||||
|
||||
use OC\AppFramework\DependencyInjection\DIContainer; |
||||
use OC\AppFramework\routing\RouteConfig; |
||||
|
||||
require_once(__DIR__ . "/../classloader.php"); |
||||
|
||||
class RouteConfigTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
public function testSimpleRoute() |
||||
{ |
||||
$routes = array('routes' => array( |
||||
array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'GET') |
||||
)); |
||||
|
||||
$this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open'); |
||||
} |
||||
|
||||
public function testSimpleRouteWithMissingVerb() |
||||
{ |
||||
$routes = array('routes' => array( |
||||
array('name' => 'folders#open', 'url' => '/folders/{folderId}/open') |
||||
)); |
||||
|
||||
$this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open'); |
||||
} |
||||
|
||||
public function testSimpleRouteWithLowercaseVerb() |
||||
{ |
||||
$routes = array('routes' => array( |
||||
array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete') |
||||
)); |
||||
|
||||
$this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException \UnexpectedValueException |
||||
*/ |
||||
public function testSimpleRouteWithBrokenName() |
||||
{ |
||||
$routes = array('routes' => array( |
||||
array('name' => 'folders_open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete') |
||||
)); |
||||
|
||||
// router mock |
||||
$router = $this->getMock("\OC_Router", array('create')); |
||||
|
||||
// load route configuration |
||||
$container = new DIContainer('app1'); |
||||
$config = new RouteConfig($container, $router, $routes); |
||||
|
||||
$config->register(); |
||||
} |
||||
|
||||
public function testSimpleRouteWithUnderScoreNames() |
||||
{ |
||||
$routes = array('routes' => array( |
||||
array('name' => 'admin_folders#open_current', 'url' => '/folders/{folderId}/open', 'verb' => 'delete') |
||||
)); |
||||
|
||||
$this->assertSimpleRoute($routes, 'admin_folders.open_current', 'DELETE', '/folders/{folderId}/open', 'AdminFoldersController', 'openCurrent'); |
||||
} |
||||
|
||||
public function testResource() |
||||
{ |
||||
$routes = array('resources' => array('accounts' => array('url' => '/accounts'))); |
||||
|
||||
$this->assertResource($routes, 'accounts', '/accounts', 'AccountsController', 'accountId'); |
||||
} |
||||
|
||||
public function testResourceWithUnderScoreName() |
||||
{ |
||||
$routes = array('resources' => array('admin_accounts' => array('url' => '/admin/accounts'))); |
||||
|
||||
$this->assertResource($routes, 'admin_accounts', '/admin/accounts', 'AdminAccountsController', 'adminAccountId'); |
||||
} |
||||
|
||||
private function assertSimpleRoute($routes, $name, $verb, $url, $controllerName, $actionName) |
||||
{ |
||||
// route mocks |
||||
$route = $this->mockRoute($verb, $controllerName, $actionName); |
||||
|
||||
// router mock |
||||
$router = $this->getMock("\OC_Router", array('create')); |
||||
|
||||
// we expect create to be called once: |
||||
$router |
||||
->expects($this->once()) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $name), $this->equalTo($url)) |
||||
->will($this->returnValue($route)); |
||||
|
||||
// load route configuration |
||||
$container = new DIContainer('app1'); |
||||
$config = new RouteConfig($container, $router, $routes); |
||||
|
||||
$config->register(); |
||||
} |
||||
|
||||
private function assertResource($yaml, $resourceName, $url, $controllerName, $paramName) |
||||
{ |
||||
// router mock |
||||
$router = $this->getMock("\OC_Router", array('create')); |
||||
|
||||
// route mocks |
||||
$indexRoute = $this->mockRoute('GET', $controllerName, 'index'); |
||||
$showRoute = $this->mockRoute('GET', $controllerName, 'show'); |
||||
$createRoute = $this->mockRoute('POST', $controllerName, 'create'); |
||||
$updateRoute = $this->mockRoute('PUT', $controllerName, 'update'); |
||||
$destroyRoute = $this->mockRoute('DELETE', $controllerName, 'destroy'); |
||||
|
||||
$urlWithParam = $url . '/{' . $paramName . '}'; |
||||
|
||||
// we expect create to be called once: |
||||
$router |
||||
->expects($this->at(0)) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $resourceName . '.index'), $this->equalTo($url)) |
||||
->will($this->returnValue($indexRoute)); |
||||
|
||||
$router |
||||
->expects($this->at(1)) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $resourceName . '.show'), $this->equalTo($urlWithParam)) |
||||
->will($this->returnValue($showRoute)); |
||||
|
||||
$router |
||||
->expects($this->at(2)) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $resourceName . '.create'), $this->equalTo($url)) |
||||
->will($this->returnValue($createRoute)); |
||||
|
||||
$router |
||||
->expects($this->at(3)) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $resourceName . '.update'), $this->equalTo($urlWithParam)) |
||||
->will($this->returnValue($updateRoute)); |
||||
|
||||
$router |
||||
->expects($this->at(4)) |
||||
->method('create') |
||||
->with($this->equalTo('app1.' . $resourceName . '.destroy'), $this->equalTo($urlWithParam)) |
||||
->will($this->returnValue($destroyRoute)); |
||||
|
||||
// load route configuration |
||||
$container = new DIContainer('app1'); |
||||
$config = new RouteConfig($container, $router, $yaml); |
||||
|
||||
$config->register(); |
||||
} |
||||
|
||||
/** |
||||
* @param $verb |
||||
* @param $controllerName |
||||
* @param $actionName |
||||
* @return \PHPUnit_Framework_MockObject_MockObject |
||||
*/ |
||||
private function mockRoute($verb, $controllerName, $actionName) |
||||
{ |
||||
$container = new DIContainer('app1'); |
||||
$route = $this->getMock("\OC_Route", array('method', 'action'), array(), '', false); |
||||
$route |
||||
->expects($this->exactly(1)) |
||||
->method('method') |
||||
->with($this->equalTo($verb)) |
||||
->will($this->returnValue($route)); |
||||
|
||||
$route |
||||
->expects($this->exactly(1)) |
||||
->method('action') |
||||
->with($this->equalTo(new RouteActionHandler($container, $controllerName, $actionName))) |
||||
->will($this->returnValue($route)); |
||||
return $route; |
||||
} |
||||
|
||||
} |
||||
|
||||
/* |
||||
# |
||||
# sample routes.yaml for ownCloud |
||||
# |
||||
# the section simple describes one route |
||||
|
||||
routes: |
||||
- name: folders#open |
||||
url: /folders/{folderId}/open |
||||
verb: GET |
||||
# controller: name.split()[0] |
||||
# action: name.split()[1] |
||||
|
||||
# for a resource following actions will be generated: |
||||
# - index |
||||
# - create |
||||
# - show |
||||
# - update |
||||
# - destroy |
||||
# - new |
||||
resources: |
||||
accounts: |
||||
url: /accounts |
||||
|
||||
folders: |
||||
url: /accounts/{accountId}/folders |
||||
# actions can be used to define additional actions on the resource |
||||
actions: |
||||
- name: validate |
||||
verb: GET |
||||
on-collection: false |
||||
|
||||
* */ |
||||
@ -0,0 +1,58 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - App Framework |
||||
* |
||||
* @author Bernhard Posselt |
||||
* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\AppFramework\Utility; |
||||
|
||||
|
||||
require_once __DIR__ . "/../classloader.php"; |
||||
|
||||
|
||||
class MethodAnnotationReaderTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
|
||||
/** |
||||
* @Annotation |
||||
*/ |
||||
public function testReadAnnotation(){ |
||||
$reader = new MethodAnnotationReader('\OC\AppFramework\Utility\MethodAnnotationReaderTest', |
||||
'testReadAnnotation'); |
||||
|
||||
$this->assertTrue($reader->hasAnnotation('Annotation')); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @Annotation |
||||
* @param test |
||||
*/ |
||||
public function testReadAnnotationNoLowercase(){ |
||||
$reader = new MethodAnnotationReader('\OC\AppFramework\Utility\MethodAnnotationReaderTest', |
||||
'testReadAnnotationNoLowercase'); |
||||
|
||||
$this->assertTrue($reader->hasAnnotation('Annotation')); |
||||
$this->assertFalse($reader->hasAnnotation('param')); |
||||
} |
||||
|
||||
|
||||
} |
||||
Loading…
Reference in new issue