summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTom Needham <needham.thomas@gmail.com>2013-03-09 16:59:13 -0800
committerTom Needham <needham.thomas@gmail.com>2013-03-09 16:59:13 -0800
commitdfbf57207d2d47a843b514728b7254e76930b20c (patch)
treee1c2037a39247d5e170dac90d2ce8d708ef13441 /lib
parent6bdb84ab288a2ef2087c8daa2255071cf45d26b4 (diff)
parente58dbd46fc4648ca6f33b83e7ce7745f07217477 (diff)
downloadnextcloud-server-dfbf57207d2d47a843b514728b7254e76930b20c.tar.gz
nextcloud-server-dfbf57207d2d47a843b514728b7254e76930b20c.zip
Merge pull request #1584 from owncloud/ocs_multiple_methods
Allow registering of multiple methods on each api route. Add /cloud/capabilities route.
Diffstat (limited to 'lib')
-rw-r--r--lib/api.php150
-rw-r--r--lib/ocs/cloud.php60
-rw-r--r--lib/ocs/result.php48
3 files changed, 166 insertions, 92 deletions
diff --git a/lib/api.php b/lib/api.php
index 70e3028b68a..8d6bbb7cc09 100644
--- a/lib/api.php
+++ b/lib/api.php
@@ -33,21 +33,20 @@ class OC_API {
const USER_AUTH = 1;
const SUBADMIN_AUTH = 2;
const ADMIN_AUTH = 3;
-
- private static $server;
-
+
/**
- * initialises the OAuth store and server
+ * API Response Codes
*/
- private static function init() {
- self::$server = new OC_OAuth_Server(new OC_OAuth_Store());
- }
-
+ const RESPOND_UNAUTHORISED = 997;
+ const RESPOND_SERVER_ERROR = 996;
+ const RESPOND_NOT_FOUND = 998;
+ const RESPOND_UNKNOWN_ERROR = 999;
+
/**
* api actions
*/
protected static $actions = array();
-
+
/**
* registers an api call
* @param string $method the http method
@@ -58,7 +57,7 @@ class OC_API {
* @param array $defaults
* @param array $requirements
*/
- public static function register($method, $url, $action, $app,
+ public static function register($method, $url, $action, $app,
$authLevel = OC_API::USER_AUTH,
$defaults = array(),
$requirements = array()) {
@@ -71,9 +70,9 @@ class OC_API {
->action('OC_API', 'call');
self::$actions[$name] = array();
}
- self::$actions[$name] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
+ self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
}
-
+
/**
* handles an api call
* @param array $parameters
@@ -86,29 +85,97 @@ class OC_API {
parse_str(file_get_contents("php://input"), $parameters['_delete']);
}
$name = $parameters['_route'];
- // Check authentication and availability
- if(self::isAuthorised(self::$actions[$name])) {
- if(is_callable(self::$actions[$name]['action'])) {
- $response = call_user_func(self::$actions[$name]['action'], $parameters);
- if(!($response instanceof OC_OCS_Result)) {
- $response = new OC_OCS_Result(null, 996, 'Internal Server Error');
- }
- } else {
- $response = new OC_OCS_Result(null, 998, 'Api method not found');
+ // Foreach registered action
+ $responses = array();
+ foreach(self::$actions[$name] as $action) {
+ // Check authentication and availability
+ if(!self::isAuthorised(self::$actions[$name])) {
+ $responses[] = array(
+ 'app' => $action['app'],
+ 'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'),
+ );
+ continue;
}
- } else {
- header('WWW-Authenticate: Basic realm="Authorization Required"');
- header('HTTP/1.0 401 Unauthorized');
- $response = new OC_OCS_Result(null, 997, 'Unauthorised');
+ if(!is_callable($action['action'])) {
+ $responses[] = array(
+ 'app' => $action['app'],
+ 'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'),
+ );
+ continue;
+ }
+ // Run the action
+ $responses[] = array(
+ 'app' => $action['app'],
+ 'response' => call_user_func($action['action'], $parameters),
+ );
}
- // Send the response
+ $response = self::mergeResponses($responses);
$formats = array('json', 'xml');
$format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml';
- self::respond($response, $format);
- // logout the user to be stateless
+ self::respond($response);
OC_User::logout();
}
+
+ /**
+ * merge the returned result objects into one response
+ * @param array $responses
+ */
+ private static function mergeResponses($responses) {
+ $response = array();
+ // Sort into shipped and thirdparty
+ $shipped = array(
+ 'succeeded' => array(),
+ 'failed' => array(),
+ );
+ $thirdparty = array(
+ 'succeeded' => array(),
+ 'failed' => array(),
+ );
+ foreach($responses as $response) {
+ if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) {
+ if($response['response']->succeeded()) {
+ $shipped['succeeded'][$response['app']] = $response['response'];
+ } else {
+ $shipped['failed'][$response['app']] = $response['response'];
+ }
+ } else {
+ if($response['response']->succeeded()) {
+ $thirdparty['succeeded'][$response['app']] = $response['response'];
+ } else {
+ $thirdparty['failed'][$response['app']] = $response['response'];
+ }
+ }
+ }
+ // Remove any error responses if there is one shipped response that succeeded
+ if(!empty($shipped['succeeded'])) {
+ $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
+ } else if(!empty($shipped['failed'])) {
+ // Which shipped response do we use if they all failed?
+ // They may have failed for different reasons (different status codes)
+ // Which reponse code should we return?
+ // Maybe any that are not OC_API::RESPOND_SERVER_ERROR
+ $response = $shipped['failed'][0];
+ return $response;
+ } else {
+ // Return the third party failure result
+ $response = $thirdparty['failed'][0];
+ return $response;
+ }
+ // Merge the successful responses
+ $meta = array();
+ $data = array();
+ foreach($responses as $app => $response) {
+ if(OC_App::isShipped($app)) {
+ $data = array_merge_recursive($response->getData(), $data);
+ } else {
+ $data = array_merge_recursive($data, $response->getData());
+ }
+ }
+ $result = new OC_OCS_Result($data, 100);
+ return $result;
+ }
+
/**
* authenticate the api call
* @param array $action the action details as supplied to OC_API::register()
@@ -132,7 +199,8 @@ class OC_API {
return false;
} else {
$subAdmin = OC_SubAdmin::isSubAdmin($user);
- if($subAdmin) {
+ $admin = OC_User::isAdminUser($user);
+ if($subAdmin || $admin) {
return true;
} else {
return false;
@@ -153,25 +221,35 @@ class OC_API {
return false;
break;
}
- }
-
+ }
+
/**
* http basic auth
* @return string|false (username, or false on failure)
*/
- private static function loginUser(){
+ private static function loginUser(){
$authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
$authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
return OC_User::login($authUser, $authPw) ? $authUser : false;
}
-
+
/**
* respond to a call
- * @param int|array $result the result from the api method
+ * @param OC_OCS_Result $result
* @param string $format the format xml|json
*/
private static function respond($result, $format='xml') {
- $response = array('ocs' => $result->getResult());
+ // Send 401 headers if unauthorised
+ if($result->getStatusCode() === self::RESPOND_UNAUTHORISED) {
+ header('WWW-Authenticate: Basic realm="Authorisation Required"');
+ header('HTTP/1.0 401 Unauthorized');
+ }
+ $response = array(
+ 'ocs' => array(
+ 'meta' => $result->getMeta(),
+ 'data' => $result->getData(),
+ ),
+ );
if ($format == 'json') {
OC_JSON::encodedPrint($response);
} else if ($format == 'xml') {
@@ -203,5 +281,5 @@ class OC_API {
}
}
}
-
+
}
diff --git a/lib/ocs/cloud.php b/lib/ocs/cloud.php
index 5553ae38215..132d923d960 100644
--- a/lib/ocs/cloud.php
+++ b/lib/ocs/cloud.php
@@ -24,49 +24,23 @@
class OC_OCS_Cloud {
- public static function getSystemWebApps() {
- OC_Util::checkLoggedIn();
- $apps = OC_App::getEnabledApps();
- $values = array();
- foreach($apps as $app) {
- $info = OC_App::getAppInfo($app);
- if(isset($info['standalone'])) {
- $newValue = array('name'=>$info['name'], 'url'=>OC_Helper::linkToAbsolute($app, ''), 'icon'=>'');
- $values[] = $newValue;
- }
- }
- return new OC_OCS_Result($values);
- }
-
- public static function getUserQuota($parameters) {
- $user = OC_User::getUser();
- if(OC_User::isAdminUser($user) or ($user==$parameters['user'])) {
-
- if(OC_User::userExists($parameters['user'])) {
- // calculate the disc space
- $userDir = '/'.$parameters['user'].'/files';
- \OC\Files\Filesystem::init($parameters['user'], $userDir);
- $rootInfo = \OC\Files\Filesystem::getFileInfo('');
- $sharedInfo = \OC\Files\Filesystem::getFileInfo('/Shared');
- $used = $rootInfo['size'] - $sharedInfo['size'];
- $free = \OC\Files\Filesystem::free_space();
- $total = $free + $used;
- if($total===0) $total = 1; // prevent division by zero
- $relative = round(($used/$total)*10000)/100;
-
- $xml = array();
- $xml['quota'] = $total;
- $xml['free'] = $free;
- $xml['used'] = $used;
- $xml['relative'] = $relative;
-
- return new OC_OCS_Result($xml);
- } else {
- return new OC_OCS_Result(null, 300);
- }
- } else {
- return new OC_OCS_Result(null, 300);
- }
+ public static function getCapabilities($parameters) {
+ $result = array();
+ list($major, $minor, $micro) = OC_Util::getVersion();
+ $result['version'] = array(
+ 'major' => $major,
+ 'minor' => $minor,
+ 'micro' => $micro,
+ 'string' => OC_Util::getVersionString(),
+ 'edition' => OC_Util::getEditionString(),
+ );
+
+ $result['capabilities'] = array(
+ 'core' => array(
+ 'pollinterval' => OC_Config::getValue('pollinterval', 60),
+ ),
+ );
+ return new OC_OCS_Result($result);
}
public static function getUserPublickey($parameters) {
diff --git a/lib/ocs/result.php b/lib/ocs/result.php
index 65b2067fc3f..8ab378d79c5 100644
--- a/lib/ocs/result.php
+++ b/lib/ocs/result.php
@@ -49,26 +49,48 @@ class OC_OCS_Result{
public function setItemsPerPage(int $items) {
$this->perPage = $items;
}
-
+
+ /**
+ * get the status code
+ * @return int
+ */
+ public function getStatusCode() {
+ return $this->statusCode;
+ }
+
/**
- * returns the data associated with the api result
+ * get the meta data for the result
* @return array
*/
- public function getResult() {
- $return = array();
- $return['meta'] = array();
- $return['meta']['status'] = ($this->statusCode === 100) ? 'ok' : 'failure';
- $return['meta']['statuscode'] = $this->statusCode;
- $return['meta']['message'] = $this->message;
+ public function getMeta() {
+ $meta = array();
+ $meta['status'] = ($this->statusCode === 100) ? 'ok' : 'failure';
+ $meta['statuscode'] = $this->statusCode;
+ $meta['message'] = $this->message;
if(isset($this->items)) {
- $return['meta']['totalitems'] = $this->items;
+ $meta['totalitems'] = $this->items;
}
if(isset($this->perPage)) {
- $return['meta']['itemsperpage'] = $this->perPage;
+ $meta['itemsperpage'] = $this->perPage;
}
- $return['data'] = $this->data;
- // Return the result data.
- return $return;
+ return $meta;
+
+ }
+
+ /**
+ * get the result data
+ * @return array|string|int
+ */
+ public function getData() {
+ return $this->data;
+ }
+
+ /**
+ * return bool if the method succedded
+ * @return bool
+ */
+ public function succeeded() {
+ return (substr($this->statusCode, 0, 1) === '1');
}