ApiHelper.php 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  6. * SPDX-License-Identifier: AGPL-3.0-only
  7. */
  8. namespace OC\OCS;
  9. use OC\AppFramework\OCS\V1Response;
  10. use OC\AppFramework\OCS\V2Response;
  11. use OCP\AppFramework\Http\DataResponse;
  12. use OCP\AppFramework\OCSController;
  13. use OCP\IRequest;
  14. use OCP\Server;
  15. class ApiHelper {
  16. /**
  17. * Respond to a call
  18. * @psalm-taint-escape html
  19. * @param int $overrideHttpStatusCode force the HTTP status code, only used for the special case of maintenance mode which return 503 even for v1
  20. */
  21. public static function respond(int $statusCode, string $statusMessage, array $headers = [], ?int $overrideHttpStatusCode = null): void {
  22. $request = Server::get(IRequest::class);
  23. $format = $request->getParam('format', 'xml');
  24. if (self::isV2($request)) {
  25. $response = new V2Response(new DataResponse([], $statusCode, $headers), $format, $statusMessage);
  26. } else {
  27. $response = new V1Response(new DataResponse([], $statusCode, $headers), $format, $statusMessage);
  28. }
  29. // Send 401 headers if unauthorised
  30. if ($response->getOCSStatus() === OCSController::RESPOND_UNAUTHORISED) {
  31. // If request comes from JS return dummy auth request
  32. if ($request->getHeader('X-Requested-With') === 'XMLHttpRequest') {
  33. header('WWW-Authenticate: DummyBasic realm="Authorisation Required"');
  34. } else {
  35. header('WWW-Authenticate: Basic realm="Authorisation Required"');
  36. }
  37. http_response_code(401);
  38. }
  39. foreach ($response->getHeaders() as $name => $value) {
  40. header($name . ': ' . $value);
  41. }
  42. http_response_code($overrideHttpStatusCode ?? $response->getStatus());
  43. self::setContentType($format);
  44. $body = $response->render();
  45. echo $body;
  46. }
  47. /**
  48. * Based on the requested format the response content type is set
  49. */
  50. public static function setContentType(?string $format = null): void {
  51. $format ??= Server::get(IRequest::class)->getParam('format', 'xml');
  52. if ($format === 'xml') {
  53. header('Content-type: text/xml; charset=UTF-8');
  54. return;
  55. }
  56. if ($format === 'json') {
  57. header('Content-Type: application/json; charset=utf-8');
  58. return;
  59. }
  60. header('Content-Type: application/octet-stream; charset=utf-8');
  61. }
  62. protected static function isV2(IRequest $request): bool {
  63. $script = $request->getScriptName();
  64. return str_ends_with($script, '/ocs/v2.php');
  65. }
  66. }