1<?php 2/** 3 * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl> 4 * 5 * @author Christoph Wurst <christoph@winzerhof-wurst.at> 6 * @author Joas Schilling <coding@schilljs.com> 7 * @author Lukas Reschke <lukas@statuscode.ch> 8 * @author Roeland Jago Douma <roeland@famdouma.nl> 9 * 10 * @license GNU AGPL version 3 or any later version 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU Affero General Public License as 14 * published by the Free Software Foundation, either version 3 of the 15 * License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU Affero General Public License for more details. 21 * 22 * You should have received a copy of the GNU Affero General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * 25 */ 26namespace OC\AppFramework\Middleware; 27 28use OC\AppFramework\Http; 29use OC\AppFramework\OCS\BaseResponse; 30use OC\AppFramework\OCS\V1Response; 31use OC\AppFramework\OCS\V2Response; 32use OCP\AppFramework\Controller; 33use OCP\AppFramework\Http\DataResponse; 34use OCP\AppFramework\Http\JSONResponse; 35use OCP\AppFramework\Http\Response; 36use OCP\AppFramework\Middleware; 37use OCP\AppFramework\OCS\OCSException; 38use OCP\AppFramework\OCSController; 39use OCP\IRequest; 40 41class OCSMiddleware extends Middleware { 42 43 /** @var IRequest */ 44 private $request; 45 46 /** @var int */ 47 private $ocsVersion; 48 49 /** 50 * @param IRequest $request 51 */ 52 public function __construct(IRequest $request) { 53 $this->request = $request; 54 } 55 56 /** 57 * @param Controller $controller 58 * @param string $methodName 59 */ 60 public function beforeController($controller, $methodName) { 61 if ($controller instanceof OCSController) { 62 if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) { 63 $this->ocsVersion = 2; 64 } else { 65 $this->ocsVersion = 1; 66 } 67 $controller->setOCSVersion($this->ocsVersion); 68 } 69 } 70 71 /** 72 * @param Controller $controller 73 * @param string $methodName 74 * @param \Exception $exception 75 * @throws \Exception 76 * @return BaseResponse 77 */ 78 public function afterException($controller, $methodName, \Exception $exception) { 79 if ($controller instanceof OCSController && $exception instanceof OCSException) { 80 $code = $exception->getCode(); 81 if ($code === 0) { 82 $code = \OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR; 83 } 84 85 return $this->buildNewResponse($controller, $code, $exception->getMessage()); 86 } 87 88 throw $exception; 89 } 90 91 /** 92 * @param Controller $controller 93 * @param string $methodName 94 * @param Response $response 95 * @return \OCP\AppFramework\Http\Response 96 */ 97 public function afterController($controller, $methodName, Response $response) { 98 /* 99 * If a different middleware has detected that a request unauthorized or forbidden 100 * we need to catch the response and convert it to a proper OCS response. 101 */ 102 if ($controller instanceof OCSController && !($response instanceof BaseResponse)) { 103 if ($response->getStatus() === Http::STATUS_UNAUTHORIZED) { 104 $message = ''; 105 if ($response instanceof JSONResponse) { 106 /** @var DataResponse $response */ 107 $message = $response->getData()['message']; 108 } 109 110 return $this->buildNewResponse($controller, OCSController::RESPOND_UNAUTHORISED, $message); 111 } 112 if ($response->getStatus() === Http::STATUS_FORBIDDEN) { 113 $message = ''; 114 if ($response instanceof JSONResponse) { 115 /** @var DataResponse $response */ 116 $message = $response->getData()['message']; 117 } 118 119 return $this->buildNewResponse($controller, Http::STATUS_FORBIDDEN, $message); 120 } 121 } 122 123 return $response; 124 } 125 126 /** 127 * @param Controller $controller 128 * @param int $code 129 * @param string $message 130 * @return V1Response|V2Response 131 */ 132 private function buildNewResponse(Controller $controller, $code, $message) { 133 $format = $this->getFormat($controller); 134 135 $data = new DataResponse(); 136 $data->setStatus($code); 137 if ($this->ocsVersion === 1) { 138 $response = new V1Response($data, $format, $message); 139 } else { 140 $response = new V2Response($data, $format, $message); 141 } 142 143 return $response; 144 } 145 146 /** 147 * @param Controller $controller 148 * @return string 149 */ 150 private function getFormat(Controller $controller) { 151 // get format from the url format or request format parameter 152 $format = $this->request->getParam('format'); 153 154 // if none is given try the first Accept header 155 if ($format === null) { 156 $headers = $this->request->getHeader('Accept'); 157 $format = $controller->getResponderByHTTPHeader($headers, 'xml'); 158 } 159 160 return $format; 161 } 162} 163