From fde9cabe9774b67e88ee8aa8fa39fe044fe2da2f Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Sat, 17 Aug 2013 11:16:48 +0200 Subject: initial import of appframework --- lib/appframework/app.php | 97 ++++ lib/appframework/controller/controller.php | 154 ++++++ lib/appframework/core/api.php | 524 +++++++++++++++++++++ .../dependencyinjection/dicontainer.php | 125 +++++ lib/appframework/http/dispatcher.php | 98 ++++ lib/appframework/http/downloadresponse.php | 51 ++ lib/appframework/http/http.php | 208 ++++++++ lib/appframework/http/jsonresponse.php | 74 +++ lib/appframework/http/redirectresponse.php | 54 +++ lib/appframework/http/request.php | 217 +++++++++ lib/appframework/http/response.php | 169 +++++++ lib/appframework/http/templateresponse.php | 126 +++++ lib/appframework/middleware/middleware.php | 100 ++++ .../middleware/middlewaredispatcher.php | 159 +++++++ .../middleware/security/securityexception.php | 41 ++ .../middleware/security/securitymiddleware.php | 141 ++++++ lib/appframework/routing/routeactionhandler.php | 42 ++ lib/appframework/routing/routeconfig.php | 186 ++++++++ .../utility/methodannotationreader.php | 61 +++ lib/appframework/utility/timefactory.php | 42 ++ 20 files changed, 2669 insertions(+) create mode 100644 lib/appframework/app.php create mode 100644 lib/appframework/controller/controller.php create mode 100644 lib/appframework/core/api.php create mode 100644 lib/appframework/dependencyinjection/dicontainer.php create mode 100644 lib/appframework/http/dispatcher.php create mode 100644 lib/appframework/http/downloadresponse.php create mode 100644 lib/appframework/http/http.php create mode 100644 lib/appframework/http/jsonresponse.php create mode 100644 lib/appframework/http/redirectresponse.php create mode 100644 lib/appframework/http/request.php create mode 100644 lib/appframework/http/response.php create mode 100644 lib/appframework/http/templateresponse.php create mode 100644 lib/appframework/middleware/middleware.php create mode 100644 lib/appframework/middleware/middlewaredispatcher.php create mode 100644 lib/appframework/middleware/security/securityexception.php create mode 100644 lib/appframework/middleware/security/securitymiddleware.php create mode 100644 lib/appframework/routing/routeactionhandler.php create mode 100644 lib/appframework/routing/routeconfig.php create mode 100644 lib/appframework/utility/methodannotationreader.php create mode 100644 lib/appframework/utility/timefactory.php (limited to 'lib/appframework') diff --git a/lib/appframework/app.php b/lib/appframework/app.php new file mode 100644 index 00000000000..6224b858bbf --- /dev/null +++ b/lib/appframework/app.php @@ -0,0 +1,97 @@ +. + * + */ + + +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; + } + +} diff --git a/lib/appframework/controller/controller.php b/lib/appframework/controller/controller.php new file mode 100644 index 00000000000..3e8166050d7 --- /dev/null +++ b/lib/appframework/controller/controller.php @@ -0,0 +1,154 @@ +. + * + */ + + +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; + } + + +} diff --git a/lib/appframework/core/api.php b/lib/appframework/core/api.php new file mode 100644 index 00000000000..eb8ee01e5db --- /dev/null +++ b/lib/appframework/core/api.php @@ -0,0 +1,524 @@ +. + * + */ + + +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(); + } +} diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php new file mode 100644 index 00000000000..34f64e72cb9 --- /dev/null +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -0,0 +1,125 @@ +. + * + */ + + +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(); + }); + + + } + + +} diff --git a/lib/appframework/http/dispatcher.php b/lib/appframework/http/dispatcher.php new file mode 100644 index 00000000000..ab5644274fa --- /dev/null +++ b/lib/appframework/http/dispatcher.php @@ -0,0 +1,98 @@ +. + * + */ + + +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; + } + + +} diff --git a/lib/appframework/http/downloadresponse.php b/lib/appframework/http/downloadresponse.php new file mode 100644 index 00000000000..5a0db325fe6 --- /dev/null +++ b/lib/appframework/http/downloadresponse.php @@ -0,0 +1,51 @@ +. + * + */ + + +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); + } + + +} diff --git a/lib/appframework/http/http.php b/lib/appframework/http/http.php new file mode 100644 index 00000000000..73f32d13b38 --- /dev/null +++ b/lib/appframework/http/http.php @@ -0,0 +1,208 @@ +. + * + */ + + +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]; + } + + +} + + diff --git a/lib/appframework/http/jsonresponse.php b/lib/appframework/http/jsonresponse.php new file mode 100644 index 00000000000..750f8a2ad15 --- /dev/null +++ b/lib/appframework/http/jsonresponse.php @@ -0,0 +1,74 @@ +. + * + */ + + +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; + } + +} diff --git a/lib/appframework/http/redirectresponse.php b/lib/appframework/http/redirectresponse.php new file mode 100644 index 00000000000..727e0fb642e --- /dev/null +++ b/lib/appframework/http/redirectresponse.php @@ -0,0 +1,54 @@ +. + * + */ + + +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; + } + + +} diff --git a/lib/appframework/http/request.php b/lib/appframework/http/request.php new file mode 100644 index 00000000000..7d024c8605f --- /dev/null +++ b/lib/appframework/http/request.php @@ -0,0 +1,217 @@ +. + * + */ + +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; + } + +} diff --git a/lib/appframework/http/response.php b/lib/appframework/http/response.php new file mode 100644 index 00000000000..50778105f24 --- /dev/null +++ b/lib/appframework/http/response.php @@ -0,0 +1,169 @@ +. + * + */ + + +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; + } + + +} diff --git a/lib/appframework/http/templateresponse.php b/lib/appframework/http/templateresponse.php new file mode 100644 index 00000000000..0a32da4b1b4 --- /dev/null +++ b/lib/appframework/http/templateresponse.php @@ -0,0 +1,126 @@ +. + * + */ + + +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(); + } + +} diff --git a/lib/appframework/middleware/middleware.php b/lib/appframework/middleware/middleware.php new file mode 100644 index 00000000000..4df88490468 --- /dev/null +++ b/lib/appframework/middleware/middleware.php @@ -0,0 +1,100 @@ +. + * + */ + + +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; + } + +} diff --git a/lib/appframework/middleware/middlewaredispatcher.php b/lib/appframework/middleware/middlewaredispatcher.php new file mode 100644 index 00000000000..c2d16134dc5 --- /dev/null +++ b/lib/appframework/middleware/middlewaredispatcher.php @@ -0,0 +1,159 @@ +. + * + */ + + +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; $imiddlewares); $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; + } + +} diff --git a/lib/appframework/middleware/security/securityexception.php b/lib/appframework/middleware/security/securityexception.php new file mode 100644 index 00000000000..b32a2769ff5 --- /dev/null +++ b/lib/appframework/middleware/security/securityexception.php @@ -0,0 +1,41 @@ +. + * + */ + + +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); + } + +} diff --git a/lib/appframework/middleware/security/securitymiddleware.php b/lib/appframework/middleware/security/securitymiddleware.php new file mode 100644 index 00000000000..7a715f309a0 --- /dev/null +++ b/lib/appframework/middleware/security/securitymiddleware.php @@ -0,0 +1,141 @@ +. + * + */ + + +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; + } + +} diff --git a/lib/appframework/routing/routeactionhandler.php b/lib/appframework/routing/routeactionhandler.php new file mode 100644 index 00000000000..7fb56f14eab --- /dev/null +++ b/lib/appframework/routing/routeactionhandler.php @@ -0,0 +1,42 @@ +. + * + */ + +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); + } +} diff --git a/lib/appframework/routing/routeconfig.php b/lib/appframework/routing/routeconfig.php new file mode 100644 index 00000000000..53ab11bf2f5 --- /dev/null +++ b/lib/appframework/routing/routeconfig.php @@ -0,0 +1,186 @@ +. + * + */ + +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); + } +} diff --git a/lib/appframework/utility/methodannotationreader.php b/lib/appframework/utility/methodannotationreader.php new file mode 100644 index 00000000000..42060a08529 --- /dev/null +++ b/lib/appframework/utility/methodannotationreader.php @@ -0,0 +1,61 @@ +. + * + */ + + +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); + } + + +} diff --git a/lib/appframework/utility/timefactory.php b/lib/appframework/utility/timefactory.php new file mode 100644 index 00000000000..2c3dd6cf5e3 --- /dev/null +++ b/lib/appframework/utility/timefactory.php @@ -0,0 +1,42 @@ +. + * + */ + + +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(); + } + + +} -- cgit v1.2.3 From 72e1a8d83b3a21875cac6948879471661d120c52 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 12:47:23 +0200 Subject: fixing require to Pimple --- lib/appframework/dependencyinjection/dicontainer.php | 2 +- tests/lib/appframework/AppTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 34f64e72cb9..d6cf4d55020 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -34,7 +34,7 @@ use OC\AppFramework\Middleware\Security\SecurityMiddleware; use OC\AppFramework\Utility\TimeFactory; // register 3rdparty autoloaders -require_once __DIR__ . '/../../../../3rdparty/Pimple/Pimple.php'; +require_once __DIR__ . '/../../../3rdparty/Pimple/Pimple.php'; /** diff --git a/tests/lib/appframework/AppTest.php b/tests/lib/appframework/AppTest.php index 000094d07c8..6e647f68e6f 100644 --- a/tests/lib/appframework/AppTest.php +++ b/tests/lib/appframework/AppTest.php @@ -29,7 +29,7 @@ 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__ . '/../../../3rdparty/Pimple/Pimple.php'; require_once __DIR__ . "/classloader.php"; -- cgit v1.2.3 From 0fa2e1b3d91d243452ffdfd36dbd0bed3f27e387 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 12:48:45 +0200 Subject: there is no HttpMiddleware --- lib/appframework/dependencyinjection/dicontainer.php | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index d6cf4d55020..69c645b1be3 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -29,7 +29,6 @@ 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; -- cgit v1.2.3 From cdada78aa4acd2880e0344a476d3c1d838645ae5 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 17:20:36 +0200 Subject: typos & unused var fixed --- lib/appframework/http/dispatcher.php | 11 +++++------ lib/appframework/http/downloadresponse.php | 1 - 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/http/dispatcher.php b/lib/appframework/http/dispatcher.php index ab5644274fa..183854650fb 100644 --- a/lib/appframework/http/dispatcher.php +++ b/lib/appframework/http/dispatcher.php @@ -29,7 +29,7 @@ use \OC\AppFramework\Middleware\MiddlewareDispatcher; /** - * Class to dispatch the request to the middleware disptacher + * Class to dispatch the request to the middleware dispatcher */ class Dispatcher { @@ -67,11 +67,10 @@ class Dispatcher { $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 + // 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); diff --git a/lib/appframework/http/downloadresponse.php b/lib/appframework/http/downloadresponse.php index 5a0db325fe6..096e4fc8331 100644 --- a/lib/appframework/http/downloadresponse.php +++ b/lib/appframework/http/downloadresponse.php @@ -30,7 +30,6 @@ namespace OC\AppFramework\Http; */ abstract class DownloadResponse extends Response { - private $content; private $filename; private $contentType; -- cgit v1.2.3 From 93194bb39617d4b11a0a84b8cd4caf0491155961 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 17:21:14 +0200 Subject: Introducing IContainer into public api --- .../dependencyinjection/dicontainer.php | 22 +++++------ lib/appframework/utility/simplecontainer.php | 44 ++++++++++++++++++++++ tests/lib/appframework/classloader.php | 9 +++++ 3 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 lib/appframework/utility/simplecontainer.php (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 69c645b1be3..88ad2cd414a 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -30,19 +30,11 @@ use OC\AppFramework\Http\Dispatcher; use OC\AppFramework\Core\API; use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Middleware\Security\SecurityMiddleware; +use OC\AppFramework\Utility\SimpleContainer; 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 { +class DIContainer extends SimpleContainer { /** @@ -61,8 +53,14 @@ class DIContainer extends \Pimple { * Http */ $this['Request'] = $this->share(function($c) { - $params = json_decode(file_get_contents('php://input'), true); - $params = is_array($params) ? $params: array(); + + $params = array(); + + // we json decode the body only in case of content type json + if (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'],'json') === true ) { + $params = json_decode(file_get_contents('php://input'), true); + $params = is_array($params) ? $params: array(); + } return new Request( array( diff --git a/lib/appframework/utility/simplecontainer.php b/lib/appframework/utility/simplecontainer.php new file mode 100644 index 00000000000..04b6cd727b8 --- /dev/null +++ b/lib/appframework/utility/simplecontainer.php @@ -0,0 +1,44 @@ +offsetGet($name); + } + + function registerParameter($name, $value) + { + $this[$name] = $value; + } + + /** + * The given closure is call the first time the given service is queried. + * The closure has to return the instance for the given service. + * Created instance will be cached in case $shared is true. + * + * @param string $name name of the service to register another backend for + * @param callable $closure the closure to be called on service creation + */ + function registerService($name, \Closure $closure, $shared = true) + { + if ($shared) { + $this[$name] = \Pimple::share($closure); + } else { + $this[$name] = $closure; + } + } +} diff --git a/tests/lib/appframework/classloader.php b/tests/lib/appframework/classloader.php index ae485e67b2c..cd9f893df30 100644 --- a/tests/lib/appframework/classloader.php +++ b/tests/lib/appframework/classloader.php @@ -32,6 +32,15 @@ spl_autoload_register(function ($className){ } } + if (strpos($className, 'OCP\\') === 0) { + $path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); + $relPath = __DIR__ . '/../../../lib/public' . $path; + + if(file_exists($relPath)){ + require_once $relPath; + } + } + // FIXME: this will most probably not work anymore if (strpos($className, 'OCA\\') === 0) { -- cgit v1.2.3 From f115b94927fedb4fd0c74c534e3766dae3244411 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 17:53:58 +0200 Subject: Introducing IRequest --- lib/appframework/http/request.php | 111 +++++++++++++++++++++++++++++++++++++- lib/public/core/irequest.php | 88 ++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 lib/public/core/irequest.php (limited to 'lib/appframework') diff --git a/lib/appframework/http/request.php b/lib/appframework/http/request.php index 7d024c8605f..ab72a8db697 100644 --- a/lib/appframework/http/request.php +++ b/lib/appframework/http/request.php @@ -22,12 +22,14 @@ namespace OC\AppFramework\Http; +use OCP\Core\IRequest; + /** * Class for accessing variables in the request. * This class provides an immutable object with request variables. */ -class Request implements \ArrayAccess, \Countable { +class Request implements \ArrayAccess, \Countable, IRequest { protected $items = array(); protected $allowedKeys = array( @@ -214,4 +216,111 @@ class Request implements \ArrayAccess, \Countable { return null; } + /** + * Lets you access post and get parameters by the index + * In case of json requests the encoded json body is accessed + * + * @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 getParam($key, $default = null) + { + return isset($this->parameters[$key]) + ? $this->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->parameters; + } + + /** + * Returns the method of the request + * @return string the method of the request (POST, GET, etc) + */ + public function getMethod() + { + return $this->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->files[$key]) ? $this->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 getEnv($key) + { + return isset($this->env[$key]) ? $this->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 + */ + function getSession($key) + { + return isset($this->session[$key]) ? $this->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 + */ + function getCookie($key) + { + return isset($this->cookies[$key]) ? $this->cookies[$key] : null; + } + + /** + * Returns the request body content. + * + * @param Boolean $asResource If true, a resource will be returned + * + * @return string|resource The request body content or a resource to read the body stream. + * + * @throws \LogicException + */ + function getContent($asResource = false) + { + return null; +// if (false === $this->content || (true === $asResource && null !== $this->content)) { +// throw new \LogicException('getContent() can only be called once when using the resource return type.'); +// } +// +// if (true === $asResource) { +// $this->content = false; +// +// return fopen('php://input', 'rb'); +// } +// +// if (null === $this->content) { +// $this->content = file_get_contents('php://input'); +// } +// +// return $this->content; + } } diff --git a/lib/public/core/irequest.php b/lib/public/core/irequest.php new file mode 100644 index 00000000000..f283e9cb25c --- /dev/null +++ b/lib/public/core/irequest.php @@ -0,0 +1,88 @@ + Date: Tue, 20 Aug 2013 21:05:55 +0200 Subject: controller reuses IRequest methods --- lib/appframework/controller/controller.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/controller/controller.php b/lib/appframework/controller/controller.php index 3e8166050d7..f6f34618ec6 100644 --- a/lib/appframework/controller/controller.php +++ b/lib/appframework/controller/controller.php @@ -63,9 +63,7 @@ abstract class Controller { * @return mixed the content of the array */ public function params($key, $default=null){ - return isset($this->request->parameters[$key]) - ? $this->request->parameters[$key] - : $default; + return $this->request->getParam($key, $default); } @@ -75,7 +73,7 @@ abstract class Controller { * @return array the array with all parameters */ public function getParams() { - return $this->request->parameters; + return $this->request->getParams(); } @@ -84,7 +82,7 @@ abstract class Controller { * @return string the method of the request (POST, GET, etc) */ public function method() { - return $this->request->method; + return $this->request->getMethod(); } @@ -94,7 +92,7 @@ abstract class Controller { * @return array the file in the $_FILES element */ public function getUploadedFile($key) { - return isset($this->request->files[$key]) ? $this->request->files[$key] : null; + return $this->request->getUploadedFile($key); } @@ -104,7 +102,7 @@ abstract class Controller { * @return array the value in the $_ENV element */ public function env($key) { - return isset($this->request->env[$key]) ? $this->request->env[$key] : null; + return $this->request->getEnv($key); } @@ -114,7 +112,7 @@ abstract class Controller { * @return array the value in the $_SESSION element */ public function session($key) { - return isset($this->request->session[$key]) ? $this->request->session[$key] : null; + return $this->request->getSession($key); } @@ -124,7 +122,7 @@ abstract class Controller { * @return array the value in the $_COOKIE element */ public function cookie($key) { - return isset($this->request->cookies[$key]) ? $this->request->cookies[$key] : null; + return $this->request->getCookie($key); } -- cgit v1.2.3 From 395deacc6760564544a76338023d9b0bf39e0bfe Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 20 Aug 2013 21:21:21 +0200 Subject: reducing controller annotations to: @PublicPage - No user logon is expected @NoAdminRequired - the login user requires no admin rights @NoCSRFRequired - the incoming request will not check for CSRF token --- .../middleware/security/securitymiddleware.php | 19 +-- .../middleware/security/SecurityMiddlewareTest.php | 156 +++++---------------- 2 files changed, 41 insertions(+), 134 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/middleware/security/securitymiddleware.php b/lib/appframework/middleware/security/securitymiddleware.php index 7a715f309a0..52818b1b53e 100644 --- a/lib/appframework/middleware/security/securitymiddleware.php +++ b/lib/appframework/middleware/security/securitymiddleware.php @@ -77,25 +77,20 @@ class SecurityMiddleware extends Middleware { $this->api->activateNavigationEntry(); // security checks - if(!$annotationReader->hasAnnotation('IsLoggedInExemption')) { + $isPublicPage = $annotationReader->hasAnnotation('PublicPage'); + if(!$isPublicPage) { 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('NoAdminRequired')) { + if(!$this->api->isAdminUser($this->api->getUserId())) { + throw new SecurityException('Logged in user must be an admin', Http::STATUS_FORBIDDEN); + } } } - if(!$annotationReader->hasAnnotation('CSRFExemption')) { + if(!$annotationReader->hasAnnotation('NoCSRFRequired')) { if(!$this->api->passesCSRFCheck()) { throw new SecurityException('CSRF check failed', Http::STATUS_PRECONDITION_FAILED); } diff --git a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php index 0b2103564e4..90a19c9999d 100644 --- a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php +++ b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php @@ -80,67 +80,27 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @IsLoggedInExemption - * @CSRFExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage + * @NoCSRFRequired */ 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)); + // isAdminUser requires isLoggedIn call to return true + if ($test === 'isAdminUser') { + $api->expects($this->any()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + } + $sec = new SecurityMiddleware($api, $this->request); try { @@ -151,9 +111,6 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { } } - /** - * @Ajax - */ public function testAjaxStatusLoggedInCheck() { $this->ajaxExceptionStatus( 'testAjaxStatusLoggedInCheck', @@ -163,8 +120,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { } /** - * @Ajax - * @IsLoggedInExemption + * @NoCSRFRequired + * @NoAdminRequired */ public function testAjaxNotAdminCheck() { $this->ajaxExceptionStatus( @@ -175,23 +132,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { } /** - * @Ajax - * @IsLoggedInExemption - * @IsAdminExemption - */ - public function testAjaxNotSubAdminCheck() { - $this->ajaxExceptionStatus( - 'testAjaxNotSubAdminCheck', - 'isSubAdminUser', - Http::STATUS_FORBIDDEN - ); - } - - /** - * @Ajax - * @IsLoggedInExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage */ public function testAjaxStatusCSRFCheck() { $this->ajaxExceptionStatus( @@ -202,11 +143,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { } /** - * @Ajax - * @CSRFExemption - * @IsLoggedInExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage + * @NoCSRFRequired */ public function testAjaxStatusAllGood() { $this->ajaxExceptionStatus( @@ -231,11 +169,10 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ); } + /** - * @IsLoggedInExemption - * @CSRFExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage + * @NoCSRFRequired */ public function testNoChecks(){ $api = $this->getAPI(); @@ -245,9 +182,6 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { $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)); @@ -264,10 +198,19 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->method($expects) ->will($this->returnValue(!$shouldFail)); + // admin check requires login + if ($expects === 'isAdminUser') { + $api->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + } + $sec = new SecurityMiddleware($api, $this->request); if($shouldFail){ $this->setExpectedException('\OC\AppFramework\Middleware\Security\SecurityException'); + } else { + $this->setExpectedException(null); } $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); @@ -275,9 +218,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @IsLoggedInExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage */ public function testCsrfCheck(){ $this->securityCheck('testCsrfCheck', 'passesCSRFCheck'); @@ -285,9 +226,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @IsLoggedInExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @PublicPage */ public function testFailCsrfCheck(){ $this->securityCheck('testFailCsrfCheck', 'passesCSRFCheck', true); @@ -295,9 +234,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @CSRFExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @NoCSRFRequired + * @NoAdminRequired */ public function testLoggedInCheck(){ $this->securityCheck('testLoggedInCheck', 'isLoggedIn'); @@ -305,9 +243,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @CSRFExemption - * @IsAdminExemption - * @IsSubAdminExemption + * @NoCSRFRequired + * @NoAdminRequired */ public function testFailLoggedInCheck(){ $this->securityCheck('testFailLoggedInCheck', 'isLoggedIn', true); @@ -315,9 +252,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @IsLoggedInExemption - * @CSRFExemption - * @IsSubAdminExemption + * @NoCSRFRequired */ public function testIsAdminCheck(){ $this->securityCheck('testIsAdminCheck', 'isAdminUser'); @@ -325,36 +260,13 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { /** - * @IsLoggedInExemption - * @CSRFExemption - * @IsSubAdminExemption + * @NoCSRFRequired */ 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'); -- cgit v1.2.3 From 911bd3c16f508eb8f3cb9b03a5a21e2aa72ebf79 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Wed, 21 Aug 2013 01:00:26 +0200 Subject: moving response classes over to OCP --- lib/appframework/controller/controller.php | 4 +- lib/appframework/http/dispatcher.php | 3 + lib/appframework/http/downloadresponse.php | 2 +- lib/appframework/http/http.php | 62 +------- lib/appframework/http/jsonresponse.php | 74 --------- lib/appframework/http/redirectresponse.php | 2 + lib/appframework/http/response.php | 169 --------------------- lib/appframework/http/templateresponse.php | 126 --------------- lib/appframework/middleware/middleware.php | 2 +- .../middleware/middlewaredispatcher.php | 2 +- .../middleware/security/securitymiddleware.php | 4 +- lib/public/appframework/http/http.php | 89 +++++++++++ lib/public/appframework/http/jsonresponse.php | 74 +++++++++ lib/public/appframework/http/response.php | 169 +++++++++++++++++++++ lib/public/appframework/http/templateresponse.php | 126 +++++++++++++++ 15 files changed, 471 insertions(+), 437 deletions(-) delete mode 100644 lib/appframework/http/jsonresponse.php delete mode 100644 lib/appframework/http/response.php delete mode 100644 lib/appframework/http/templateresponse.php create mode 100644 lib/public/appframework/http/http.php create mode 100644 lib/public/appframework/http/jsonresponse.php create mode 100644 lib/public/appframework/http/response.php create mode 100644 lib/public/appframework/http/templateresponse.php (limited to 'lib/appframework') diff --git a/lib/appframework/controller/controller.php b/lib/appframework/controller/controller.php index f6f34618ec6..a7498ba0e1e 100644 --- a/lib/appframework/controller/controller.php +++ b/lib/appframework/controller/controller.php @@ -24,9 +24,9 @@ namespace OC\AppFramework\Controller; -use OC\AppFramework\Http\TemplateResponse; use OC\AppFramework\Http\Request; use OC\AppFramework\Core\API; +use OCP\AppFramework\Http\TemplateResponse; /** @@ -133,7 +133,7 @@ abstract class Controller { * @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 + * @return \OCP\AppFramework\Http\TemplateResponse containing the page */ public function render($templateName, array $params=array(), $renderAs='user', array $headers=array()){ diff --git a/lib/appframework/http/dispatcher.php b/lib/appframework/http/dispatcher.php index 183854650fb..ea57a6860cc 100644 --- a/lib/appframework/http/dispatcher.php +++ b/lib/appframework/http/dispatcher.php @@ -74,6 +74,9 @@ class Dispatcher { } catch(\Exception $exception){ $response = $this->middlewareDispatcher->afterException( $controller, $methodName, $exception); + if (is_null($response)) { + throw $exception; + } } $response = $this->middlewareDispatcher->afterController( diff --git a/lib/appframework/http/downloadresponse.php b/lib/appframework/http/downloadresponse.php index 096e4fc8331..67b9542dba6 100644 --- a/lib/appframework/http/downloadresponse.php +++ b/lib/appframework/http/downloadresponse.php @@ -28,7 +28,7 @@ namespace OC\AppFramework\Http; /** * Prompts the user to download the a file */ -abstract class DownloadResponse extends Response { +class DownloadResponse extends \OCP\AppFramework\Http\Response { private $filename; private $contentType; diff --git a/lib/appframework/http/http.php b/lib/appframework/http/http.php index 73f32d13b38..e00dc9cdc4a 100644 --- a/lib/appframework/http/http.php +++ b/lib/appframework/http/http.php @@ -25,67 +25,7 @@ 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; +class Http extends \OCP\AppFramework\Http\Http{ private $server; private $protocolVersion; diff --git a/lib/appframework/http/jsonresponse.php b/lib/appframework/http/jsonresponse.php deleted file mode 100644 index 750f8a2ad15..00000000000 --- a/lib/appframework/http/jsonresponse.php +++ /dev/null @@ -1,74 +0,0 @@ -. - * - */ - - -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; - } - -} diff --git a/lib/appframework/http/redirectresponse.php b/lib/appframework/http/redirectresponse.php index 727e0fb642e..688447f1618 100644 --- a/lib/appframework/http/redirectresponse.php +++ b/lib/appframework/http/redirectresponse.php @@ -24,6 +24,8 @@ namespace OC\AppFramework\Http; +use OCP\AppFramework\Http\Response; + /** * Redirects to a different URL diff --git a/lib/appframework/http/response.php b/lib/appframework/http/response.php deleted file mode 100644 index 50778105f24..00000000000 --- a/lib/appframework/http/response.php +++ /dev/null @@ -1,169 +0,0 @@ -. - * - */ - - -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; - } - - -} diff --git a/lib/appframework/http/templateresponse.php b/lib/appframework/http/templateresponse.php deleted file mode 100644 index 0a32da4b1b4..00000000000 --- a/lib/appframework/http/templateresponse.php +++ /dev/null @@ -1,126 +0,0 @@ -. - * - */ - - -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(); - } - -} diff --git a/lib/appframework/middleware/middleware.php b/lib/appframework/middleware/middleware.php index 4df88490468..b12c03c3eb8 100644 --- a/lib/appframework/middleware/middleware.php +++ b/lib/appframework/middleware/middleware.php @@ -24,7 +24,7 @@ namespace OC\AppFramework\Middleware; -use OC\AppFramework\Http\Response; +use OCP\AppFramework\Http\Response; /** diff --git a/lib/appframework/middleware/middlewaredispatcher.php b/lib/appframework/middleware/middlewaredispatcher.php index c2d16134dc5..70ab108e6b8 100644 --- a/lib/appframework/middleware/middlewaredispatcher.php +++ b/lib/appframework/middleware/middlewaredispatcher.php @@ -25,7 +25,7 @@ namespace OC\AppFramework\Middleware; use OC\AppFramework\Controller\Controller; -use OC\AppFramework\Http\Response; +use OCP\AppFramework\Http\Response; /** diff --git a/lib/appframework/middleware/security/securitymiddleware.php b/lib/appframework/middleware/security/securitymiddleware.php index 52818b1b53e..4f1447e1afb 100644 --- a/lib/appframework/middleware/security/securitymiddleware.php +++ b/lib/appframework/middleware/security/securitymiddleware.php @@ -27,12 +27,12 @@ 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; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\JSONResponse; /** diff --git a/lib/public/appframework/http/http.php b/lib/public/appframework/http/http.php new file mode 100644 index 00000000000..9eafe782726 --- /dev/null +++ b/lib/public/appframework/http/http.php @@ -0,0 +1,89 @@ +. + * + */ + + +namespace OCP\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; +} diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php new file mode 100644 index 00000000000..085fdbed2f9 --- /dev/null +++ b/lib/public/appframework/http/jsonresponse.php @@ -0,0 +1,74 @@ +. + * + */ + + +namespace OCP\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; + } + +} diff --git a/lib/public/appframework/http/response.php b/lib/public/appframework/http/response.php new file mode 100644 index 00000000000..64477258948 --- /dev/null +++ b/lib/public/appframework/http/response.php @@ -0,0 +1,169 @@ +. + * + */ + + +namespace OCP\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; + } + + +} diff --git a/lib/public/appframework/http/templateresponse.php b/lib/public/appframework/http/templateresponse.php new file mode 100644 index 00000000000..97678c96cba --- /dev/null +++ b/lib/public/appframework/http/templateresponse.php @@ -0,0 +1,126 @@ +. + * + */ + + +namespace OCP\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(); + } + +} -- cgit v1.2.3 From 38f9df429397619482e3e3f7ffb0db5274222e4c Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Wed, 21 Aug 2013 01:02:15 +0200 Subject: introducing OCP\AppFramework\App --- lib/appframework/app.php | 3 +- lib/appframework/core/api.php | 3 +- .../dependencyinjection/dicontainer.php | 21 +- lib/public/appframework/App.php | 61 ++++++ lib/public/appframework/iapi.php | 238 +++++++++++++++++++++ lib/public/appframework/iappcontainer.php | 25 +++ 6 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 lib/public/appframework/App.php create mode 100644 lib/public/appframework/iapi.php create mode 100644 lib/public/appframework/iappcontainer.php (limited to 'lib/appframework') diff --git a/lib/appframework/app.php b/lib/appframework/app.php index 6224b858bbf..7ff55bb809d 100644 --- a/lib/appframework/app.php +++ b/lib/appframework/app.php @@ -25,6 +25,7 @@ namespace OC\AppFramework; use OC\AppFramework\DependencyInjection\DIContainer; +use OCP\AppFramework\IAppContainer; /** @@ -45,7 +46,7 @@ class App { * @param DIContainer $container an instance of a pimple container. */ public static function main($controllerName, $methodName, array $urlParams, - DIContainer $container) { + IAppContainer $container) { $container['urlParams'] = $urlParams; $controller = $container[$controllerName]; diff --git a/lib/appframework/core/api.php b/lib/appframework/core/api.php index eb8ee01e5db..337e3b57d6d 100644 --- a/lib/appframework/core/api.php +++ b/lib/appframework/core/api.php @@ -23,6 +23,7 @@ namespace OC\AppFramework\Core; +use OCP\AppFramework\IApi; /** @@ -32,7 +33,7 @@ namespace OC\AppFramework\Core; * Should you find yourself in need for more methods, simply inherit from this * class and add your methods */ -class API { +class API implements IApi{ private $appName; diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 88ad2cd414a..43f6eee29b0 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -32,9 +32,11 @@ use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Middleware\Security\SecurityMiddleware; use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\TimeFactory; +use OCP\AppFramework\IApi; +use OCP\AppFramework\IAppContainer; -class DIContainer extends SimpleContainer { +class DIContainer extends SimpleContainer implements IAppContainer{ /** @@ -45,6 +47,8 @@ class DIContainer extends SimpleContainer { $this['AppName'] = $appName; + $this->registerParameter('ServerContainer', \OC::$server); + $this['API'] = $this->share(function($c){ return new API($c['AppName']); }); @@ -119,4 +123,19 @@ class DIContainer extends SimpleContainer { } + /** + * @return IApi + */ + function getCoreApi() + { + return $this->query('API'); + } + + /** + * @return \OCP\Core\IServerContainer + */ + function getServer() + { + return $this->query('ServerContainer'); + } } diff --git a/lib/public/appframework/App.php b/lib/public/appframework/App.php new file mode 100644 index 00000000000..0c27fcb2ac5 --- /dev/null +++ b/lib/public/appframework/App.php @@ -0,0 +1,61 @@ +container = new \OC\AppFramework\DependencyInjection\DIContainer($appName); + } + + private $container; + + /** + * @return IAppContainer + */ + public function getContainer() { + return $this->container; + } + + /** + * This function is called by the routing component to fire up the frameworks dispatch mechanism. + * + * Example code in routes.php of the task app: + * $this->create('tasks_index', '/')->get()->action( + * function($params){ + * $app = new TaskApp(); + * $app->dispatch('PageController', 'index', $params); + * } + * ); + * + * + * Example for for TaskApp implementation: + * class TaskApp extends \OCP\AppFramework\App { + * + * public function __construct(){ + * parent::__construct('tasks'); + * + * $this->getContainer()->registerService('PageController', function(IAppContainer $c){ + * $a = $c->query('API'); + * $r = $c->query('Request'); + * return new PageController($a, $r); + * }); + * } + * } + * + * @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 + */ + public function dispatch($controllerName, $methodName, array $urlParams) { + \OC\AppFramework\App::main($controllerName, $methodName, $urlParams, $this->container); + } +} diff --git a/lib/public/appframework/iapi.php b/lib/public/appframework/iapi.php new file mode 100644 index 00000000000..5374f0dcaf5 --- /dev/null +++ b/lib/public/appframework/iapi.php @@ -0,0 +1,238 @@ +. + * + */ + + +namespace OCP\AppFramework; + + +/** + * A few very basic and frequently used API functions are combined in here + */ +interface IApi { + + /** + * used to return the appname of the set application + * @return string the name of your application + */ + function getAppName(); + + + /** + * Creates a new navigation entry + * @param array $entry containing: id, name, order, icon and href key + */ + function addNavigationEntry(array $entry); + + + /** + * Gets the userid of the current user + * @return string the user id of the current user + */ + function getUserId(); + + + /** + * Sets the current navigation entry to the currently running app + */ + function activateNavigationEntry(); + + + /** + * 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 + */ + function addScript($scriptName, $appName = null); + + + /** + * 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 + */ + function addStyle($styleName, $appName = null); + + + /** + * shorthand for addScript for files in the 3rdparty directory + * @param string $name the name of the file without the suffix + */ + function add3rdPartyScript($name); + + + /** + * shorthand for addStyle for files in the 3rdparty directory + * @param string $name the name of the file without the suffix + */ + function add3rdPartyStyle($name); + + /** + * Looks up a system-wide defined value + * @param string $key the key of the value, under which it was saved + * @return string the saved value + */ + function getSystemValue($key); + + /** + * Sets a new system-wide value + * @param string $key the key of the value, under which will be saved + * @param string $value the value that should be stored + */ + function setSystemValue($key, $value); + + + /** + * Looks up an app-specific defined value + * @param string $key the key of the value, under which it was saved + * @return string the saved value + */ + function getAppValue($key, $appName = null); + + + /** + * Writes a new app-specific value + * @param string $key the key of the value, under which will be saved + * @param string $value the value that should be stored + */ + function setAppValue($key, $value, $appName = null); + + + /** + * 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 + */ + function setUserValue($key, $value, $userId = null); + + + /** + * 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 + */ + function getUserValue($key, $userId = null); + + /** + * Returns the translation object + * @return \OC_L10N the translation object + * + * FIXME: returns private object / should be retrieved from teh ServerContainer + */ + function getTrans(); + + + /** + * 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 + * + * FIXME: returns non public interface / object + */ + function prepareQuery($sql, $limit=null, $offset=null); + + + /** + * 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 + * + * FIXME: move to db object + */ + function getInsertId($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 + */ + function linkToRoute($routeName, $arguments=array()); + + + /** + * 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 + */ + function linkTo($file, $appName=null); + + + /** + * 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 + */ + function imagePath($file, $appName = null); + + + /** + * Makes an URL absolute + * @param string $url the url + * @return string the absolute url + * + * FIXME: function should live in Request / Response + */ + function getAbsoluteURL($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 + */ + function linkToAbsolute($file, $appName = null); + + + /** + * 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); + + + /** + * Writes a function into the error log + * @param string $msg the error message to be logged + * @param int $level the error level + * + * FIXME: add logger instance to ServerContainer + */ + function log($msg, $level = null); + + + /** + * 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 + */ + function getTemplate($templateName, $renderAs='user', $appName=null); +} diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php new file mode 100644 index 00000000000..c2faea07b95 --- /dev/null +++ b/lib/public/appframework/iappcontainer.php @@ -0,0 +1,25 @@ + Date: Sat, 31 Aug 2013 21:34:29 +0200 Subject: move new interfaces into lib/public and OCP --- .../dependencyinjection/dicontainer.php | 2 +- lib/appframework/http/request.php | 2 +- lib/appframework/utility/simplecontainer.php | 2 +- lib/contactsmanager.php | 2 +- lib/public/appframework/iappcontainer.php | 4 +- lib/public/contacts/imanager.php | 150 +++++++++++++++++++++ lib/public/core/contacts/imanager.php | 150 --------------------- lib/public/core/icontainer.php | 64 --------- lib/public/core/irequest.php | 105 --------------- lib/public/core/iservercontainer.php | 51 ------- lib/public/icontainer.php | 64 +++++++++ lib/public/irequest.php | 105 +++++++++++++++ lib/public/iservercontainer.php | 51 +++++++ lib/server.php | 16 ++- 14 files changed, 390 insertions(+), 378 deletions(-) create mode 100644 lib/public/contacts/imanager.php delete mode 100644 lib/public/core/contacts/imanager.php delete mode 100644 lib/public/core/icontainer.php delete mode 100644 lib/public/core/irequest.php delete mode 100644 lib/public/core/iservercontainer.php create mode 100644 lib/public/icontainer.php create mode 100644 lib/public/irequest.php create mode 100644 lib/public/iservercontainer.php (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 43f6eee29b0..2ef885d7b2c 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -132,7 +132,7 @@ class DIContainer extends SimpleContainer implements IAppContainer{ } /** - * @return \OCP\Core\IServerContainer + * @return \OCP\IServerContainer */ function getServer() { diff --git a/lib/appframework/http/request.php b/lib/appframework/http/request.php index ab72a8db697..4f1775182a1 100644 --- a/lib/appframework/http/request.php +++ b/lib/appframework/http/request.php @@ -22,7 +22,7 @@ namespace OC\AppFramework\Http; -use OCP\Core\IRequest; +use OCP\IRequest; /** * Class for accessing variables in the request. diff --git a/lib/appframework/utility/simplecontainer.php b/lib/appframework/utility/simplecontainer.php index 04b6cd727b8..a51ace83a37 100644 --- a/lib/appframework/utility/simplecontainer.php +++ b/lib/appframework/utility/simplecontainer.php @@ -10,7 +10,7 @@ require_once __DIR__ . '/../../../3rdparty/Pimple/Pimple.php'; * * SimpleContainer is a simple implementation of IContainer on basis of \Pimple */ -class SimpleContainer extends \Pimple implements \OCP\Core\IContainer { +class SimpleContainer extends \Pimple implements \OCP\IContainer { /** * @param string $name name of the service to query for diff --git a/lib/contactsmanager.php b/lib/contactsmanager.php index 59c413ec03b..fc6745b4505 100644 --- a/lib/contactsmanager.php +++ b/lib/contactsmanager.php @@ -22,7 +22,7 @@ namespace OC { - class ContactsManager implements \OCP\Core\Contacts\IManager { + class ContactsManager implements \OCP\Contacts\IManager { /** * This function is used to search and find contacts within the users address books. diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php index db909241e5d..c8f6229dd9e 100644 --- a/lib/public/appframework/iappcontainer.php +++ b/lib/public/appframework/iappcontainer.php @@ -23,7 +23,7 @@ namespace OCP\AppFramework; use OCP\AppFramework\IApi; -use OCP\Core\IContainer; +use OCP\IContainer; /** * Class IAppContainer @@ -39,7 +39,7 @@ interface IAppContainer extends IContainer{ function getCoreApi(); /** - * @return \OCP\Core\IServerContainer + * @return \OCP\IServerContainer */ function getServer(); } diff --git a/lib/public/contacts/imanager.php b/lib/public/contacts/imanager.php new file mode 100644 index 00000000000..3bfbca7be50 --- /dev/null +++ b/lib/public/contacts/imanager.php @@ -0,0 +1,150 @@ +. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Contacts Class + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Contacts { + + /** + * This class provides access to the contacts app. Use this class exclusively if you want to access contacts. + * + * Contacts in general will be expressed as an array of key-value-pairs. + * The keys will match the property names defined in https://tools.ietf.org/html/rfc2426#section-1 + * + * Proposed workflow for working with contacts: + * - search for the contacts + * - manipulate the results array + * - createOrUpdate will save the given contacts overwriting the existing data + * + * For updating it is mandatory to keep the id. + * Without an id a new contact will be created. + * + */ + interface IManager { + + /** + * This function is used to search and find contacts within the users address books. + * In case $pattern is empty all contacts will be returned. + * + * Example: + * Following function shows how to search for contacts for the name and the email address. + * + * public static function getMatchingRecipient($term) { + * $cm = \OC::$server->getContactsManager(); + * // The API is not active -> nothing to do + * if (!$cm->isEnabled()) { + * return array(); + * } + * + * $result = $cm->search($term, array('FN', 'EMAIL')); + * $receivers = array(); + * foreach ($result as $r) { + * $id = $r['id']; + * $fn = $r['FN']; + * $email = $r['EMAIL']; + * if (!is_array($email)) { + * $email = array($email); + * } + * + * // loop through all email addresses of this contact + * foreach ($email as $e) { + * $displayName = $fn . " <$e>"; + * $receivers[] = array( + * 'id' => $id, + * 'label' => $displayName, + * 'value' => $displayName); + * } + * } + * + * return $receivers; + * } + * + * + * @param string $pattern which should match within the $searchProperties + * @param array $searchProperties defines the properties within the query pattern should match + * @param array $options - for future use. One should always have options! + * @return array of contacts which are arrays of key-value-pairs + */ + function search($pattern, $searchProperties = array(), $options = array()); + + /** + * This function can be used to delete the contact identified by the given id + * + * @param object $id the unique identifier to a contact + * @param $address_book_key + * @return bool successful or not + */ + function delete($id, $address_book_key); + + /** + * This function is used to create a new contact if 'id' is not given or not present. + * Otherwise the contact will be updated by replacing the entire data set. + * + * @param array $properties this array if key-value-pairs defines a contact + * @param $address_book_key string to identify the address book in which the contact shall be created or updated + * @return array representing the contact just created or updated + */ + function createOrUpdate($properties, $address_book_key); + + /** + * Check if contacts are available (e.g. contacts app enabled) + * + * @return bool true if enabled, false if not + */ + function isEnabled(); + + /** + * @param \OCP\IAddressBook $address_book + */ + function registerAddressBook(\OCP\IAddressBook $address_book); + + /** + * @param \OCP\IAddressBook $address_book + */ + function unregisterAddressBook(\OCP\IAddressBook $address_book); + + /** + * In order to improve lazy loading a closure can be registered which will be called in case + * address books are actually requested + * + * @param string $key + * @param \Closure $callable + */ + function register($key, \Closure $callable); + + /** + * @return array + */ + function getAddressBooks(); + + /** + * removes all registered address book instances + */ + function clear(); + } +} diff --git a/lib/public/core/contacts/imanager.php b/lib/public/core/contacts/imanager.php deleted file mode 100644 index e8bb7bfd8e4..00000000000 --- a/lib/public/core/contacts/imanager.php +++ /dev/null @@ -1,150 +0,0 @@ -. - * - */ - -/** - * Public interface of ownCloud for apps to use. - * Contacts Class - * - */ - -// use OCP namespace for all classes that are considered public. -// This means that they should be used by apps instead of the internal ownCloud classes -namespace OCP\Core\Contacts { - - /** - * This class provides access to the contacts app. Use this class exclusively if you want to access contacts. - * - * Contacts in general will be expressed as an array of key-value-pairs. - * The keys will match the property names defined in https://tools.ietf.org/html/rfc2426#section-1 - * - * Proposed workflow for working with contacts: - * - search for the contacts - * - manipulate the results array - * - createOrUpdate will save the given contacts overwriting the existing data - * - * For updating it is mandatory to keep the id. - * Without an id a new contact will be created. - * - */ - interface IManager { - - /** - * This function is used to search and find contacts within the users address books. - * In case $pattern is empty all contacts will be returned. - * - * Example: - * Following function shows how to search for contacts for the name and the email address. - * - * public static function getMatchingRecipient($term) { - * $cm = \OC::$server->getContactsManager(); - * // The API is not active -> nothing to do - * if (!$cm->isEnabled()) { - * return array(); - * } - * - * $result = $cm->search($term, array('FN', 'EMAIL')); - * $receivers = array(); - * foreach ($result as $r) { - * $id = $r['id']; - * $fn = $r['FN']; - * $email = $r['EMAIL']; - * if (!is_array($email)) { - * $email = array($email); - * } - * - * // loop through all email addresses of this contact - * foreach ($email as $e) { - * $displayName = $fn . " <$e>"; - * $receivers[] = array( - * 'id' => $id, - * 'label' => $displayName, - * 'value' => $displayName); - * } - * } - * - * return $receivers; - * } - * - * - * @param string $pattern which should match within the $searchProperties - * @param array $searchProperties defines the properties within the query pattern should match - * @param array $options - for future use. One should always have options! - * @return array of contacts which are arrays of key-value-pairs - */ - function search($pattern, $searchProperties = array(), $options = array()); - - /** - * This function can be used to delete the contact identified by the given id - * - * @param object $id the unique identifier to a contact - * @param $address_book_key - * @return bool successful or not - */ - function delete($id, $address_book_key); - - /** - * This function is used to create a new contact if 'id' is not given or not present. - * Otherwise the contact will be updated by replacing the entire data set. - * - * @param array $properties this array if key-value-pairs defines a contact - * @param $address_book_key string to identify the address book in which the contact shall be created or updated - * @return array representing the contact just created or updated - */ - function createOrUpdate($properties, $address_book_key); - - /** - * Check if contacts are available (e.g. contacts app enabled) - * - * @return bool true if enabled, false if not - */ - function isEnabled(); - - /** - * @param \OCP\IAddressBook $address_book - */ - function registerAddressBook(\OCP\IAddressBook $address_book); - - /** - * @param \OCP\IAddressBook $address_book - */ - function unregisterAddressBook(\OCP\IAddressBook $address_book); - - /** - * In order to improve lazy loading a closure can be registered which will be called in case - * address books are actually requested - * - * @param string $key - * @param \Closure $callable - */ - function register($key, \Closure $callable); - - /** - * @return array - */ - function getAddressBooks(); - - /** - * removes all registered address book instances - */ - function clear(); - } -} diff --git a/lib/public/core/icontainer.php b/lib/public/core/icontainer.php deleted file mode 100644 index 88ebc6cf64d..00000000000 --- a/lib/public/core/icontainer.php +++ /dev/null @@ -1,64 +0,0 @@ -. - * - */ - -namespace OCP\Core; - -/** - * Class IContainer - * - * IContainer is the basic interface to be used for any internal dependency injection mechanism - * - * @package OCP\Core - */ -interface IContainer { - - /** - * Look up a service for a given name in the container. - * - * @param string $name - * @return mixed - */ - function query($name); - - /** - * A value is stored in the container with it's corresponding name - * - * @param string $name - * @param mixed $value - * @return void - */ - function registerParameter($name, $value); - - /** - * A service is registered in the container where a closure is passed in which will actually - * create the service on demand. - * In case the parameter $shared is set to true (the default usage) the once created service will remain in - * memory and be reused on subsequent calls. - * In case the parameter is false the service will be recreated on every call. - * - * @param string $name - * @param callable $closure - * @param bool $shared - * @return void - */ - function registerService($name, \Closure $closure, $shared = true); -} diff --git a/lib/public/core/irequest.php b/lib/public/core/irequest.php deleted file mode 100644 index be60978a3c3..00000000000 --- a/lib/public/core/irequest.php +++ /dev/null @@ -1,105 +0,0 @@ -. - * - */ - -namespace OCP\Core; - - -interface IRequest { - - function getHeader($name); - - /** - * Lets you access post and get parameters by the index - * In case of json requests the encoded json body is accessed - * - * @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 getParam($key, $default = null); - - - /** - * Returns all params that were received, be it from the request - * - * (as GET or POST) or through the URL by the route - * @return array the array with all parameters - */ - public function getParams(); - - /** - * Returns the method of the request - * - * @return string the method of the request (POST, GET, etc) - */ - public function getMethod(); - - /** - * 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); - - - /** - * 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 getEnv($key); - - - /** - * 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 - */ - function getSession($key); - - - /** - * 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 - */ - function getCookie($key); - - - /** - * Returns the request body content. - * - * @param Boolean $asResource If true, a resource will be returned - * @return string|resource The request body content or a resource to read the body stream. - * @throws \LogicException - */ - function getContent($asResource = false); -} diff --git a/lib/public/core/iservercontainer.php b/lib/public/core/iservercontainer.php deleted file mode 100644 index 0517cc53e09..00000000000 --- a/lib/public/core/iservercontainer.php +++ /dev/null @@ -1,51 +0,0 @@ -. - * - */ - -namespace OCP\Core; - - -/** - * Class IServerContainer - * @package OCP\Core - * - * This container holds all ownCloud services - */ -interface IServerContainer { - - /** - * The contacts manager will act as a broker between consumers for contacts information and - * providers which actual deliver the contact information. - * - * @return \OCP\Core\Contacts\IManager - */ - function getContactsManager(); - - /** - * The current request object holding all information about the request currently being processed - * is returned from this method. - * In case the current execution was not initiated by a web request null is returned - * - * @return \OCP\Core\IRequest|null - */ - function getRequest(); - -} diff --git a/lib/public/icontainer.php b/lib/public/icontainer.php new file mode 100644 index 00000000000..d43c1c90f11 --- /dev/null +++ b/lib/public/icontainer.php @@ -0,0 +1,64 @@ +. + * + */ + +namespace OCP; + +/** + * Class IContainer + * + * IContainer is the basic interface to be used for any internal dependency injection mechanism + * + * @package OCP + */ +interface IContainer { + + /** + * Look up a service for a given name in the container. + * + * @param string $name + * @return mixed + */ + function query($name); + + /** + * A value is stored in the container with it's corresponding name + * + * @param string $name + * @param mixed $value + * @return void + */ + function registerParameter($name, $value); + + /** + * A service is registered in the container where a closure is passed in which will actually + * create the service on demand. + * In case the parameter $shared is set to true (the default usage) the once created service will remain in + * memory and be reused on subsequent calls. + * In case the parameter is false the service will be recreated on every call. + * + * @param string $name + * @param callable $closure + * @param bool $shared + * @return void + */ + function registerService($name, \Closure $closure, $shared = true); +} diff --git a/lib/public/irequest.php b/lib/public/irequest.php new file mode 100644 index 00000000000..cd39855950b --- /dev/null +++ b/lib/public/irequest.php @@ -0,0 +1,105 @@ +. + * + */ + +namespace OCP; + + +interface IRequest { + + function getHeader($name); + + /** + * Lets you access post and get parameters by the index + * In case of json requests the encoded json body is accessed + * + * @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 getParam($key, $default = null); + + + /** + * Returns all params that were received, be it from the request + * + * (as GET or POST) or through the URL by the route + * @return array the array with all parameters + */ + public function getParams(); + + /** + * Returns the method of the request + * + * @return string the method of the request (POST, GET, etc) + */ + public function getMethod(); + + /** + * 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); + + + /** + * 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 getEnv($key); + + + /** + * 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 + */ + function getSession($key); + + + /** + * 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 + */ + function getCookie($key); + + + /** + * Returns the request body content. + * + * @param Boolean $asResource If true, a resource will be returned + * @return string|resource The request body content or a resource to read the body stream. + * @throws \LogicException + */ + function getContent($asResource = false); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php new file mode 100644 index 00000000000..5f5b9677549 --- /dev/null +++ b/lib/public/iservercontainer.php @@ -0,0 +1,51 @@ +. + * + */ + +namespace OCP; + + +/** + * Class IServerContainer + * @package OCP + * + * This container holds all ownCloud services + */ +interface IServerContainer { + + /** + * The contacts manager will act as a broker between consumers for contacts information and + * providers which actual deliver the contact information. + * + * @return \OCP\Contacts\IManager + */ + function getContactsManager(); + + /** + * The current request object holding all information about the request currently being processed + * is returned from this method. + * In case the current execution was not initiated by a web request null is returned + * + * @return \OCP\IRequest|null + */ + function getRequest(); + +} diff --git a/lib/server.php b/lib/server.php index 72c82efe16b..ad955bf5c65 100644 --- a/lib/server.php +++ b/lib/server.php @@ -3,7 +3,7 @@ namespace OC; use OC\AppFramework\Utility\SimpleContainer; -use OCP\Core\IServerContainer; +use OCP\IServerContainer; /** * Class Server @@ -20,9 +20,21 @@ class Server extends SimpleContainer implements IServerContainer { } /** - * @return \OCP\Core\Contacts\IManager + * @return \OCP\Contacts\IManager */ function getContactsManager() { return $this->query('ContactsManager'); } + + /** + * The current request object holding all information about the request currently being processed + * is returned from this method. + * In case the current execution was not initiated by a web request null is returned + * + * @return \OCP\IRequest|null + */ + function getRequest() + { + return $this->query('Request'); + } } -- cgit v1.2.3 From 5bddb5377a40c987223804e8c3846437b6cf120a Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 17 Sep 2013 18:38:18 +0200 Subject: Purge session from Request - and fix some styles --- lib/appframework/http/request.php | 51 ++++++++++++--------------------------- lib/public/irequest.php | 9 ------- lib/server.php | 1 - 3 files changed, 16 insertions(+), 45 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/http/request.php b/lib/appframework/http/request.php index 4f1775182a1..34605acdfea 100644 --- a/lib/appframework/http/request.php +++ b/lib/appframework/http/request.php @@ -33,16 +33,15 @@ class Request implements \ArrayAccess, \Countable, IRequest { protected $items = array(); protected $allowedKeys = array( - 'get', - 'post', - 'files', - 'server', - 'env', - 'session', - 'cookies', - 'urlParams', - 'params', - 'parameters', + 'get', + 'post', + 'files', + 'server', + 'env', + 'cookies', + 'urlParams', + 'params', + 'parameters', 'method' ); @@ -156,7 +155,6 @@ class Request implements \ArrayAccess, \Countable, IRequest { case 'files': case 'server': case 'env': - case 'session': case 'cookies': case 'parameters': case 'params': @@ -229,8 +227,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param mixed $default If the key is not found, this value will be returned * @return mixed the content of the array */ - public function getParam($key, $default = null) - { + public function getParam($key, $default = null) { return isset($this->parameters[$key]) ? $this->parameters[$key] : $default; @@ -241,8 +238,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * (as GET or POST) or throuh the URL by the route * @return array the array with all parameters */ - public function getParams() - { + public function getParams() { return $this->parameters; } @@ -250,8 +246,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * Returns the method of the request * @return string the method of the request (POST, GET, etc) */ - public function getMethod() - { + public function getMethod() { return $this->method; } @@ -260,8 +255,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @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) - { + public function getUploadedFile($key) { return isset($this->files[$key]) ? $this->files[$key] : null; } @@ -270,28 +264,16 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $key the key that will be taken from the $_ENV array * @return array the value in the $_ENV element */ - public function getEnv($key) - { + public function getEnv($key) { return isset($this->env[$key]) ? $this->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 - */ - function getSession($key) - { - return isset($this->session[$key]) ? $this->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 */ - function getCookie($key) - { + function getCookie($key) { return isset($this->cookies[$key]) ? $this->cookies[$key] : null; } @@ -304,8 +286,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * * @throws \LogicException */ - function getContent($asResource = false) - { + function getContent($asResource = false) { return null; // if (false === $this->content || (true === $asResource && null !== $this->content)) { // throw new \LogicException('getContent() can only be called once when using the resource return type.'); diff --git a/lib/public/irequest.php b/lib/public/irequest.php index cd39855950b..9f335b06f2a 100644 --- a/lib/public/irequest.php +++ b/lib/public/irequest.php @@ -76,15 +76,6 @@ interface IRequest { public function getEnv($key); - /** - * 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 - */ - function getSession($key); - - /** * Shortcut for getting cookie variables * diff --git a/lib/server.php b/lib/server.php index 0124ad72c02..0eee3e0f73a 100644 --- a/lib/server.php +++ b/lib/server.php @@ -36,7 +36,6 @@ class Server extends SimpleContainer implements IServerContainer { 'files' => $_FILES, 'server' => $_SERVER, 'env' => $_ENV, - 'session' => $_SESSION, 'cookies' => $_COOKIE, 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] -- cgit v1.2.3 From 8b4f4a79e22dc08cf7c13a91c926c229676d6522 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 17 Sep 2013 19:46:08 +0200 Subject: Still some session leftovers. --- lib/appframework/controller/controller.php | 10 ---------- tests/lib/appframework/controller/ControllerTest.php | 5 ----- 2 files changed, 15 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/controller/controller.php b/lib/appframework/controller/controller.php index a7498ba0e1e..0ea0a38cc09 100644 --- a/lib/appframework/controller/controller.php +++ b/lib/appframework/controller/controller.php @@ -106,16 +106,6 @@ abstract class Controller { } - /** - * 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 $this->request->getSession($key); - } - - /** * Shortcut for getting cookie variables * @param string $key the key that will be taken from the $_COOKIE array diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php index 246371d249c..4441bddfca9 100644 --- a/tests/lib/appframework/controller/ControllerTest.php +++ b/tests/lib/appframework/controller/ControllerTest.php @@ -152,9 +152,4 @@ class ControllerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('daheim', $this->controller->env('PATH')); } - public function testGetSessionVariable(){ - $this->assertEquals('kein', $this->controller->session('sezession')); - } - - } -- cgit v1.2.3 From b2ef978d1069d5e7e172806a9e2426de2717a1f2 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Wed, 25 Sep 2013 10:30:48 +0200 Subject: AppFramework: - get request from the server container - implement registerMiddleWare() - adding getAppName() to app container --- .../dependencyinjection/dicontainer.php | 50 +++++++++++----------- lib/public/appframework/iappcontainer.php | 12 ++++++ 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 2ef885d7b2c..54878266939 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -34,6 +34,8 @@ use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\TimeFactory; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; +use OCP\AppFramework\IMiddleWare; +use OCP\IServerContainer; class DIContainer extends SimpleContainer implements IAppContainer{ @@ -57,31 +59,10 @@ class DIContainer extends SimpleContainer implements IAppContainer{ * Http */ $this['Request'] = $this->share(function($c) { - - $params = array(); - - // we json decode the body only in case of content type json - if (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'],'json') === true ) { - $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'] - ) - ); + /** @var $c SimpleContainer */ + /** @var $server IServerContainer */ + $server = $c->query('ServerContainer'); + return $server->getRequest(); }); $this['Protocol'] = $this->share(function($c){ @@ -138,4 +119,23 @@ class DIContainer extends SimpleContainer implements IAppContainer{ { return $this->query('ServerContainer'); } + + /** + * @param IMiddleWare $middleWare + * @return boolean + */ + function registerMiddleWare(IMiddleWare $middleWare) { + /** @var $dispatcher MiddlewareDispatcher */ + $dispatcher = $this->query('MiddlewareDispatcher'); + $dispatcher->registerMiddleware($middleWare); + + } + + /** + * used to return the appname of the set application + * @return string the name of your application + */ + function getAppName() { + return $this->query('AppName'); + } } diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php index c8f6229dd9e..7d3b4b3bac7 100644 --- a/lib/public/appframework/iappcontainer.php +++ b/lib/public/appframework/iappcontainer.php @@ -33,6 +33,12 @@ use OCP\IContainer; */ interface IAppContainer extends IContainer{ + /** + * used to return the appname of the set application + * @return string the name of your application + */ + function getAppName(); + /** * @return IApi */ @@ -42,4 +48,10 @@ interface IAppContainer extends IContainer{ * @return \OCP\IServerContainer */ function getServer(); + + /** + * @param IMiddleWare $middleWare + * @return boolean + */ + function registerMiddleWare(IMiddleWare $middleWare); } -- cgit v1.2.3 From b168d5aa3b16501e9cb4eaa3b665939dde5de52b Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Wed, 25 Sep 2013 11:05:24 +0200 Subject: class API decommissioning part 1 --- lib/appframework/core/api.php | 217 ++++----------------------------------- lib/public/appframework/iapi.php | 89 +--------------- 2 files changed, 21 insertions(+), 285 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/core/api.php b/lib/appframework/core/api.php index 337e3b57d6d..39522ee3dd5 100644 --- a/lib/appframework/core/api.php +++ b/lib/appframework/core/api.php @@ -46,24 +46,6 @@ class API implements IApi{ } - /** - * 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 @@ -73,14 +55,6 @@ class API implements IApi{ } - /** - * 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 @@ -124,79 +98,6 @@ class API implements IApi{ \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 @@ -208,28 +109,6 @@ class API implements IApi{ } - /** - * 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 @@ -293,37 +172,6 @@ class API implements IApi{ } - /** - * 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 @@ -371,26 +219,6 @@ class API implements IApi{ } - /** - * 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 @@ -467,6 +295,26 @@ class API implements IApi{ \OCP\Backgroundjob::addRegularTask($className, $methodName); } + /** + * 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); + } + } + + /** * Tells ownCloud to include a template in the admin overview * @param string $mainPath the path to the main php file without the php @@ -481,23 +329,6 @@ class API implements IApi{ \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 @@ -514,12 +345,4 @@ class API implements IApi{ return \OC\Files\Filesystem::getFileInfo($path); } - /** - * get the view - * - * @return OC\Files\View instance - */ - public function getView() { - return \OC\Files\Filesystem::getView(); - } } diff --git a/lib/public/appframework/iapi.php b/lib/public/appframework/iapi.php index 5374f0dcaf5..fa6af5f5965 100644 --- a/lib/public/appframework/iapi.php +++ b/lib/public/appframework/iapi.php @@ -30,19 +30,6 @@ namespace OCP\AppFramework; */ interface IApi { - /** - * used to return the appname of the set application - * @return string the name of your application - */ - function getAppName(); - - - /** - * Creates a new navigation entry - * @param array $entry containing: id, name, order, icon and href key - */ - function addNavigationEntry(array $entry); - /** * Gets the userid of the current user @@ -51,12 +38,6 @@ interface IApi { function getUserId(); - /** - * Sets the current navigation entry to the currently running app - */ - function activateNavigationEntry(); - - /** * Adds a new javascript file * @param string $scriptName the name of the javascript in js/ without the suffix @@ -86,53 +67,6 @@ interface IApi { */ function add3rdPartyStyle($name); - /** - * Looks up a system-wide defined value - * @param string $key the key of the value, under which it was saved - * @return string the saved value - */ - function getSystemValue($key); - - /** - * Sets a new system-wide value - * @param string $key the key of the value, under which will be saved - * @param string $value the value that should be stored - */ - function setSystemValue($key, $value); - - - /** - * Looks up an app-specific defined value - * @param string $key the key of the value, under which it was saved - * @return string the saved value - */ - function getAppValue($key, $appName = null); - - - /** - * Writes a new app-specific value - * @param string $key the key of the value, under which will be saved - * @param string $value the value that should be stored - */ - function setAppValue($key, $value, $appName = null); - - - /** - * 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 - */ - function setUserValue($key, $value, $userId = null); - - - /** - * 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 - */ - function getUserValue($key, $userId = null); - /** * Returns the translation object * @return \OC_L10N the translation object @@ -142,28 +76,6 @@ interface IApi { function getTrans(); - /** - * 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 - * - * FIXME: returns non public interface / object - */ - function prepareQuery($sql, $limit=null, $offset=null); - - - /** - * 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 - * - * FIXME: move to db object - */ - function getInsertId($tableName); - - /** * Returns the URL for a route * @param string $routeName the name of the route @@ -235,4 +147,5 @@ interface IApi { * @return \OCP\Template a new template */ function getTemplate($templateName, $renderAs='user', $appName=null); + } -- cgit v1.2.3 From 57f37c876b59d11dae8b4325bed5fa57de52ecd4 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Fri, 27 Sep 2013 17:15:26 +0200 Subject: delay middleware registrations --- lib/appframework/dependencyinjection/dicontainer.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 54878266939..380a0ee6d4a 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -40,6 +40,10 @@ use OCP\IServerContainer; class DIContainer extends SimpleContainer implements IAppContainer{ + /** + * @var array + */ + private $middleWares; /** * Put your class dependencies in here @@ -89,6 +93,10 @@ class DIContainer extends SimpleContainer implements IAppContainer{ $dispatcher = new MiddlewareDispatcher(); $dispatcher->registerMiddleware($c['SecurityMiddleware']); + foreach($this->middleWares as $middleWare) { + $dispatcher->registerMiddleware($middleWare); + } + return $dispatcher; }); @@ -125,10 +133,7 @@ class DIContainer extends SimpleContainer implements IAppContainer{ * @return boolean */ function registerMiddleWare(IMiddleWare $middleWare) { - /** @var $dispatcher MiddlewareDispatcher */ - $dispatcher = $this->query('MiddlewareDispatcher'); - $dispatcher->registerMiddleware($middleWare); - + array_push($this->middleWares, $middleWare); } /** -- cgit v1.2.3 From adcb738e47566d94a173116e86e3f5abe249dac1 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Sat, 28 Sep 2013 20:40:25 +0200 Subject: initialize $middleWares --- lib/appframework/dependencyinjection/dicontainer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/appframework') diff --git a/lib/appframework/dependencyinjection/dicontainer.php b/lib/appframework/dependencyinjection/dicontainer.php index 380a0ee6d4a..3755d45fa09 100644 --- a/lib/appframework/dependencyinjection/dicontainer.php +++ b/lib/appframework/dependencyinjection/dicontainer.php @@ -43,7 +43,7 @@ class DIContainer extends SimpleContainer implements IAppContainer{ /** * @var array */ - private $middleWares; + private $middleWares = array(); /** * Put your class dependencies in here -- cgit v1.2.3