485 lines
18 KiB
PHP
485 lines
18 KiB
PHP
|
|
<?php
|
||
|
|
/*
|
||
|
|
* Copyright (C) 2025 Xibo Signage Ltd
|
||
|
|
*
|
||
|
|
* Xibo - Digital Signage - https://xibosignage.com
|
||
|
|
*
|
||
|
|
* This file is part of Xibo.
|
||
|
|
*
|
||
|
|
* Xibo is free software: you can redistribute it and/or modify
|
||
|
|
* it under the terms of the GNU Affero General Public License as published by
|
||
|
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
|
* any later version.
|
||
|
|
*
|
||
|
|
* Xibo is distributed in the hope that it will be useful,
|
||
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
* GNU Affero General Public License for more details.
|
||
|
|
*
|
||
|
|
* You should have received a copy of the GNU Affero General Public License
|
||
|
|
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
|
||
|
|
use Monolog\Logger;
|
||
|
|
use Nyholm\Psr7\ServerRequest;
|
||
|
|
use Slim\Http\ServerRequest as Request;
|
||
|
|
use Xibo\Factory\ContainerFactory;
|
||
|
|
use Xibo\Helper\LinkSigner;
|
||
|
|
use Xibo\Support\Exception\NotFoundException;
|
||
|
|
|
||
|
|
define('XIBO', true);
|
||
|
|
define('PROJECT_ROOT', realpath(__DIR__ . '/..'));
|
||
|
|
|
||
|
|
error_reporting(0);
|
||
|
|
ini_set('display_errors', 0);
|
||
|
|
|
||
|
|
require PROJECT_ROOT . '/vendor/autoload.php';
|
||
|
|
|
||
|
|
if (!file_exists(PROJECT_ROOT . '/web/settings.php')) {
|
||
|
|
die('Not configured');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create the container for dependency injection.
|
||
|
|
try {
|
||
|
|
$container = ContainerFactory::create();
|
||
|
|
} catch (Exception $e) {
|
||
|
|
die($e->getMessage());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Logger
|
||
|
|
$uidProcessor = new \Monolog\Processor\UidProcessor(7);
|
||
|
|
$container->set('logger', function () use ($uidProcessor) {
|
||
|
|
return (new Logger('XMDS'))
|
||
|
|
->pushProcessor($uidProcessor)
|
||
|
|
->pushHandler(new \Xibo\Helper\DatabaseLogHandler());
|
||
|
|
});
|
||
|
|
|
||
|
|
// Create a Slim application
|
||
|
|
$app = \DI\Bridge\Slim\Bridge::create($container);
|
||
|
|
$app->setBasePath($container->get('basePath'));
|
||
|
|
|
||
|
|
// Mock a request
|
||
|
|
$request = new Request(new ServerRequest('GET', $app->getBasePath()));
|
||
|
|
$request = $request->withAttribute('_entryPoint', 'xmds');
|
||
|
|
$container->set('name', 'xmds');
|
||
|
|
|
||
|
|
// Start time of transaction (for logs)
|
||
|
|
$startTime = microtime(true);
|
||
|
|
|
||
|
|
// Set state
|
||
|
|
\Xibo\Middleware\State::setState($app, $request);
|
||
|
|
|
||
|
|
// Set XMR
|
||
|
|
\Xibo\Middleware\Xmr::setXmr($app, false);
|
||
|
|
|
||
|
|
// Set listeners
|
||
|
|
\Xibo\Middleware\ListenersMiddleware::setListeners($app);
|
||
|
|
|
||
|
|
// Set connectors
|
||
|
|
\Xibo\Middleware\ConnectorMiddleware::setConnectors($app);
|
||
|
|
|
||
|
|
// XMDS specific listeners
|
||
|
|
\Xibo\Middleware\ListenersMiddleware::setXmdsListeners($app);
|
||
|
|
|
||
|
|
// Configure
|
||
|
|
$container->get('configService')->setDependencies($container->get('store'), '/');
|
||
|
|
|
||
|
|
// Check to see if the instance has been suspended
|
||
|
|
$instanceSuspended = $container->get('configService')->getSetting('INSTANCE_SUSPENDED');
|
||
|
|
if ($instanceSuspended == 'yes' || $instanceSuspended == 'partial') {
|
||
|
|
header('HTTP/1.0 503 Service Unavailable');
|
||
|
|
die('CMS suspended');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Load the theme
|
||
|
|
$container->get('configService')->loadTheme();
|
||
|
|
|
||
|
|
// Register Middleware Dispatchers
|
||
|
|
// Handle additional Middleware
|
||
|
|
if (isset($container->get('configService')->middleware) && is_array($container->get('configService')->middleware)) {
|
||
|
|
foreach ($container->get('configService')->middleware as $object) {
|
||
|
|
if (method_exists($object, 'registerDispatcher')) {
|
||
|
|
$object::registerDispatcher($app);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Always have a version defined
|
||
|
|
$sanitizer = $container->get('sanitizerService')->getSanitizer($_REQUEST);
|
||
|
|
$version = $sanitizer->getInt('v', ['default' => 3]);
|
||
|
|
|
||
|
|
// Version Request?
|
||
|
|
if (isset($_GET['what'])) {
|
||
|
|
die(\Xibo\Helper\Environment::$XMDS_VERSION);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Is the WSDL being requested.
|
||
|
|
if (isset($_GET['wsdl']) || isset($_GET['WSDL'])) {
|
||
|
|
$wsdl = new \Xibo\Xmds\Wsdl(PROJECT_ROOT . '/lib/Xmds/service_v' . $version . '.wsdl', $version);
|
||
|
|
$wsdl->output();
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check to see if we have a file attribute set (for HTTP file downloads)
|
||
|
|
if (isset($_GET['file'])) {
|
||
|
|
$logger = $container->get('logService');
|
||
|
|
|
||
|
|
// Check send file mode is enabled
|
||
|
|
$sendFileMode = $container->get('configService')->getSetting('SENDFILE_MODE');
|
||
|
|
|
||
|
|
if ($sendFileMode == 'Off') {
|
||
|
|
$logger->notice('HTTP GetFile: request received but SendFile Mode is Off. Issuing 404');
|
||
|
|
header('HTTP/1.0 404 Not Found');
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check nonce, output appropriate headers, log bandwidth and stop.
|
||
|
|
try {
|
||
|
|
if (!isset($_REQUEST['displayId']) || !isset($_REQUEST['type']) || !isset($_REQUEST['itemId'])) {
|
||
|
|
$logger->error('HTTP GetFile: Missing params');
|
||
|
|
throw new NotFoundException(__('Missing params'));
|
||
|
|
}
|
||
|
|
|
||
|
|
$displayId = intval($_REQUEST['displayId']);
|
||
|
|
|
||
|
|
// Has the URL expired
|
||
|
|
if (time() > $_REQUEST['X-Amz-Expires']) {
|
||
|
|
$logger->error('HTTP GetFile: Access denied: Pre-signed S3 URL expired');
|
||
|
|
throw new NotFoundException(__('Expired'));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate the URL.
|
||
|
|
$encryptionKey = $container->get('configService')->getApiKeyDetails()['encryptionKey'];
|
||
|
|
$signature = $_REQUEST['X-Amz-Signature'];
|
||
|
|
$calculatedSignature = \Xibo\Helper\LinkSigner::getSignature(
|
||
|
|
parse_url(\Xibo\Xmds\Wsdl::getRoot(), PHP_URL_HOST),
|
||
|
|
$_GET['file'],
|
||
|
|
$_REQUEST['X-Amz-Expires'],
|
||
|
|
$encryptionKey,
|
||
|
|
$_REQUEST['X-Amz-Date'],
|
||
|
|
true,
|
||
|
|
);
|
||
|
|
|
||
|
|
if ($signature !== $calculatedSignature) {
|
||
|
|
$logger->error('HTTP GetFile: Invalid URL');
|
||
|
|
throw new NotFoundException(__('Invalid URL'));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @var \Xibo\Factory\RequiredFileFactory $requiredFileFactory */
|
||
|
|
$requiredFileFactory = $container->get('requiredFileFactory');
|
||
|
|
$file = $requiredFileFactory->resolveRequiredFileFromRequest($_REQUEST);
|
||
|
|
|
||
|
|
// Check that we've not used all of our bandwidth already (if we have an allowance)
|
||
|
|
if ($container->get('bandwidthFactory')->isBandwidthExceeded(
|
||
|
|
$container->get('configService')->getSetting('MONTHLY_XMDS_TRANSFER_LIMIT_KB')
|
||
|
|
)) {
|
||
|
|
$logger->error('HTTP GetFile: Bandwidth Exceeded');
|
||
|
|
throw new \Xibo\Support\Exception\InstanceSuspendedException('Bandwidth Exceeded');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the display
|
||
|
|
/** @var \Xibo\Entity\Display $display */
|
||
|
|
$display = $container->get('displayFactory')->getById($displayId);
|
||
|
|
|
||
|
|
// Check it is still authorised.
|
||
|
|
if ($display->licensed == 0) {
|
||
|
|
$logger->error('HTTP GetFile: Display unauthorised');
|
||
|
|
throw new NotFoundException(__('Display unauthorised'));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check the display specific limit next.
|
||
|
|
$usage = 0;
|
||
|
|
if ($container->get('bandwidthFactory')->isBandwidthExceeded(
|
||
|
|
$display->bandwidthLimit,
|
||
|
|
$usage,
|
||
|
|
$displayId
|
||
|
|
)) {
|
||
|
|
$logger->error('HTTP GetFile: Bandwidth Exceeded for Display ID: ' . $displayId);
|
||
|
|
throw new \Xibo\Support\Exception\InstanceSuspendedException('Bandwidth Exceeded');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bandwidth
|
||
|
|
// Add the size to the bytes we have already requested.
|
||
|
|
$file->bytesRequested = $file->bytesRequested + $file->size;
|
||
|
|
$file->save(['useTransaction' => false]);
|
||
|
|
|
||
|
|
// Issue magic packet
|
||
|
|
$libraryLocation = $container->get('configService')->getSetting('LIBRARY_LOCATION');
|
||
|
|
$cdnUrl = $container->get('configService')->getSetting('CDN_URL');
|
||
|
|
|
||
|
|
// Issue content type header
|
||
|
|
$isCss = false;
|
||
|
|
if ($file->type === 'L') {
|
||
|
|
// Layouts are always XML
|
||
|
|
header('Content-Type: text/xml');
|
||
|
|
} else if ($file->fileType === 'bundle' || \Illuminate\Support\Str::endsWith($file->path, '.js')) {
|
||
|
|
header('Content-Type: application/javascript');
|
||
|
|
} else if ($file->fileType === 'fontCss' || \Illuminate\Support\Str::endsWith($file->path, '.css')) {
|
||
|
|
$isCss = true;
|
||
|
|
header('Content-Type: text/css');
|
||
|
|
} else {
|
||
|
|
$contentType = mime_content_type($libraryLocation . $file->path);
|
||
|
|
if ($contentType !== false) {
|
||
|
|
header('Content-Type: ' . $contentType);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Are we a special request that needs modification before sending?
|
||
|
|
// For CSS, we look up the files to replace in required files using their stored path
|
||
|
|
if ($display->isPwa() && $isCss) {
|
||
|
|
$logger->debug('Rewriting CSS for PWA: ' . $file->path);
|
||
|
|
|
||
|
|
// Rewrite CSS for PWAs
|
||
|
|
$cssFile = file_get_contents($libraryLocation . $file->path);
|
||
|
|
$matches = [];
|
||
|
|
preg_match_all('/url\(\'?(.*?)\'?\)/', $cssFile, $matches);
|
||
|
|
foreach ($matches[1] as $match) {
|
||
|
|
// Look up the file to get the right ID/path.
|
||
|
|
try {
|
||
|
|
$replacementFile = $requiredFileFactory->getByDisplayAndDependencyPath($displayId, $match);
|
||
|
|
|
||
|
|
$url = LinkSigner::generateSignedLink(
|
||
|
|
$display,
|
||
|
|
$encryptionKey,
|
||
|
|
$cdnUrl,
|
||
|
|
'P',
|
||
|
|
$replacementFile->realId,
|
||
|
|
$replacementFile->path,
|
||
|
|
$file->fileType === 'fontCss' ? 'font' : 'asset',
|
||
|
|
);
|
||
|
|
$cssFile = str_replace(
|
||
|
|
$match,
|
||
|
|
$url,
|
||
|
|
$cssFile,
|
||
|
|
);
|
||
|
|
} catch (Exception $exception) {
|
||
|
|
$logger->error('CSS has dependency which does not exist in Required Files: ' . $match);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$file->size = strlen($cssFile);
|
||
|
|
|
||
|
|
echo $cssFile;
|
||
|
|
} else {
|
||
|
|
$logger->info('HTTP GetFile request redirecting to ' . $libraryLocation . $file->path);
|
||
|
|
|
||
|
|
// Normal send
|
||
|
|
if ($sendFileMode == 'Apache') {
|
||
|
|
// Send via Apache X-Sendfile header
|
||
|
|
header('X-Sendfile: ' . $libraryLocation . $file->path);
|
||
|
|
} else if ($sendFileMode == 'Nginx') {
|
||
|
|
// Send via Nginx X-Accel-Redirect
|
||
|
|
header('X-Accel-Redirect: /download/' . $file->path);
|
||
|
|
} else {
|
||
|
|
header('HTTP/1.0 404 Not Found');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Also add to the overall bandwidth used by get file
|
||
|
|
$container->get('bandwidthFactory')->createAndSave(
|
||
|
|
\Xibo\Entity\Bandwidth::$GETFILE,
|
||
|
|
$file->displayId,
|
||
|
|
$file->size
|
||
|
|
);
|
||
|
|
}
|
||
|
|
} catch (\Xibo\Support\Exception\NotFoundException|\Xibo\Support\Exception\ExpiredException $e) {
|
||
|
|
$logger->notice('HTTP GetFile: request received but unable to find XMDS Nonce. Issuing 404. '
|
||
|
|
. $e->getMessage());
|
||
|
|
|
||
|
|
// 404
|
||
|
|
header('HTTP/1.0 404 Not Found');
|
||
|
|
} catch (\Xibo\Support\Exception\InstanceSuspendedException $e) {
|
||
|
|
$logger->debug('HTTP GetFile: Bandwidth exceeded');
|
||
|
|
header('HTTP/1.0 403 Forbidden');
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
$logger->error('HTTP GetFile: Unknown Error: ' . $e->getMessage());
|
||
|
|
$logger->debug($e->getTraceAsString());
|
||
|
|
|
||
|
|
// Issue a 500
|
||
|
|
header('HTTP/1.0 500 Internal Server Error');
|
||
|
|
}
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Are we a CDN bandwidth log
|
||
|
|
if (isset($_GET['cdn'])) {
|
||
|
|
$logger = $container->get('logService');
|
||
|
|
|
||
|
|
try {
|
||
|
|
// We expect a PSK CONSTANT to be defined in our configuration
|
||
|
|
if (!defined('CDN_PSK')) {
|
||
|
|
throw new \Xibo\Support\Exception\ConfigurationException('Missing CDN config');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!array_key_exists('HTTP_X_CDN_PSK', $_SERVER) || $_SERVER['HTTP_X_CDN_PSK'] !== CDN_PSK) {
|
||
|
|
throw new NotFoundException('Invalid Token');
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @var \Xibo\Factory\RequiredFileFactory $requiredFileFactory */
|
||
|
|
$requiredFileFactory = $container->get('requiredFileFactory');
|
||
|
|
$file = $requiredFileFactory->resolveRequiredFileFromRequest($_REQUEST);
|
||
|
|
|
||
|
|
$container->get('logService')->info('CDN bandwidth request for ' . $file->path);
|
||
|
|
|
||
|
|
// Do we have a usage amount provided?
|
||
|
|
if (array_key_exists('HTTP_X_CDN_BW', $_SERVER) && is_numeric($_SERVER['HTTP_X_CDN_BW'])) {
|
||
|
|
$usedBandwidth = intval($_SERVER['HTTP_X_CDN_BW']);
|
||
|
|
|
||
|
|
// Don't allow this if we get bandwidth lower than 0
|
||
|
|
if ($usedBandwidth < 0) {
|
||
|
|
$usedBandwidth = $file->size;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bandwidth
|
||
|
|
// Add the size to the bytes we have already requested.
|
||
|
|
$file->bytesRequested = $file->bytesRequested + $file->size;
|
||
|
|
$file->save(['useTransaction' => false]);
|
||
|
|
|
||
|
|
// Also add to the overall bandwidth used by get file
|
||
|
|
$container->get('bandwidthFactory')->createAndSave(
|
||
|
|
\Xibo\Entity\Bandwidth::$GETFILE,
|
||
|
|
$file->displayId,
|
||
|
|
$file->size
|
||
|
|
);
|
||
|
|
} catch (Exception $e) {
|
||
|
|
$logger->error('Unknown Error: ' . $e->getMessage());
|
||
|
|
$logger->debug($e->getTraceAsString());
|
||
|
|
}
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Connector request?
|
||
|
|
if (isset($_GET['connector'])) {
|
||
|
|
try {
|
||
|
|
if (!isset($_GET['token'])) {
|
||
|
|
header('HTTP/1.0 403 Forbidden');
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Dispatch an event to check the token
|
||
|
|
$tokenEvent = new \Xibo\Event\XmdsConnectorTokenEvent();
|
||
|
|
$tokenEvent->setToken($_GET['token']);
|
||
|
|
$container->get('dispatcher')->dispatch($tokenEvent, \Xibo\Event\XmdsConnectorTokenEvent::$NAME);
|
||
|
|
|
||
|
|
if (empty($tokenEvent->getWidgetId())) {
|
||
|
|
header('HTTP/1.0 403 Forbidden');
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the display
|
||
|
|
/** @var \Xibo\Entity\Display $display */
|
||
|
|
$display = $container->get('displayFactory')->getById($tokenEvent->getDisplayId());
|
||
|
|
|
||
|
|
// Check it is still authorised.
|
||
|
|
if ($display->licensed == 0) {
|
||
|
|
throw new NotFoundException(__('Display unauthorised'));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check the widgetId is permissible, and in required files for the display.
|
||
|
|
/** @var \Xibo\Entity\RequiredFile $file */
|
||
|
|
$file = $container->get('requiredFileFactory')->getByDisplayAndWidget(
|
||
|
|
$tokenEvent->getDisplayId(),
|
||
|
|
$tokenEvent->getWidgetId()
|
||
|
|
);
|
||
|
|
|
||
|
|
// Get the widget
|
||
|
|
$widget = $container->get('widgetFactory')->getById($tokenEvent->getWidgetId());
|
||
|
|
|
||
|
|
// It has been found, so we raise an event here to see if any connector can provide a file for it.
|
||
|
|
$event = new \Xibo\Event\XmdsConnectorFileEvent($widget);
|
||
|
|
$container->get('dispatcher')->dispatch($event, \Xibo\Event\XmdsConnectorFileEvent::$NAME);
|
||
|
|
|
||
|
|
// What now?
|
||
|
|
$emitter = new \Slim\ResponseEmitter();
|
||
|
|
$emitter->emit($event->getResponse());
|
||
|
|
} catch (\Xibo\Support\Exception\GeneralException $e) {
|
||
|
|
header('HTTP/1.0 500 Internal Server Error');
|
||
|
|
echo $e->getMessage();
|
||
|
|
} catch (Exception $e) {
|
||
|
|
$container->get('logService')->error('Unknown Error: ' . $e->getMessage());
|
||
|
|
$container->get('logService')->debug($e->getTraceAsString());
|
||
|
|
header('HTTP/1.0 500 Internal Server Error');
|
||
|
|
}
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Town down all logging
|
||
|
|
$container->get('logService')->setLevel(\Xibo\Service\LogService::resolveLogLevel('error'));
|
||
|
|
|
||
|
|
try {
|
||
|
|
$wsdl = PROJECT_ROOT . '/lib/Xmds/service_v' . $version . '.wsdl';
|
||
|
|
|
||
|
|
if (!file_exists($wsdl)) {
|
||
|
|
throw new InvalidArgumentException(__('Your client is not the correct version to communicate with this CMS.'));
|
||
|
|
}
|
||
|
|
|
||
|
|
// logProcessor
|
||
|
|
$logProcessor = new \Xibo\Xmds\LogProcessor($container->get('logger'), $uidProcessor->getUid());
|
||
|
|
$container->get('logger')->pushProcessor($logProcessor);
|
||
|
|
|
||
|
|
// Create a SoapServer
|
||
|
|
// explicitly define caching.
|
||
|
|
if (\Xibo\Helper\Environment::isDevMode()) {
|
||
|
|
// No cache - our WSDL might change in development
|
||
|
|
$soap = new SoapServer($wsdl, ['cache_wsdl' => WSDL_CACHE_NONE]);
|
||
|
|
} else {
|
||
|
|
$soap = new SoapServer($wsdl, ['cache_wsdl' => WSDL_CACHE_MEMORY]);
|
||
|
|
}
|
||
|
|
$soap->setClass(
|
||
|
|
'\Xibo\Xmds\Soap' . $version,
|
||
|
|
$logProcessor,
|
||
|
|
$container->get('pool'),
|
||
|
|
$container->get('store'),
|
||
|
|
$container->get('timeSeriesStore'),
|
||
|
|
$container->get('logService'),
|
||
|
|
$container->get('sanitizerService'),
|
||
|
|
$container->get('configService'),
|
||
|
|
$container->get('requiredFileFactory'),
|
||
|
|
$container->get('moduleFactory'),
|
||
|
|
$container->get('layoutFactory'),
|
||
|
|
$container->get('dataSetFactory'),
|
||
|
|
$container->get('displayFactory'),
|
||
|
|
$container->get('userGroupFactory'),
|
||
|
|
$container->get('bandwidthFactory'),
|
||
|
|
$container->get('mediaFactory'),
|
||
|
|
$container->get('widgetFactory'),
|
||
|
|
$container->get('regionFactory'),
|
||
|
|
$container->get('notificationFactory'),
|
||
|
|
$container->get('displayEventFactory'),
|
||
|
|
$container->get('scheduleFactory'),
|
||
|
|
$container->get('dayPartFactory'),
|
||
|
|
$container->get('playerVersionFactory'),
|
||
|
|
$container->get('dispatcher'),
|
||
|
|
$container->get('campaignFactory'),
|
||
|
|
$container->get('syncGroupFactory'),
|
||
|
|
$container->get('playerFaultFactory')
|
||
|
|
);
|
||
|
|
|
||
|
|
// Add manual raw post data parsing, as HTTP_RAW_POST_DATA is deprecated.
|
||
|
|
$soap->handle(file_get_contents('php://input'));
|
||
|
|
|
||
|
|
// Get the stats for this connection
|
||
|
|
$stats = $container->get('store')->stats();
|
||
|
|
|
||
|
|
$stats['length'] = microtime(true) - $startTime;
|
||
|
|
|
||
|
|
$container->get('logService')->info('PDO stats: %s.', json_encode($stats, JSON_PRETTY_PRINT));
|
||
|
|
|
||
|
|
if ($container->get('store')->getConnection()->inTransaction()) {
|
||
|
|
$container->get('store')->getConnection()->commit();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Finish any XMR work that has been logged during the request
|
||
|
|
\Xibo\Middleware\Xmr::finish($app);
|
||
|
|
} catch (Exception $e) {
|
||
|
|
$container->get('logService')->error($e->getMessage());
|
||
|
|
|
||
|
|
if ($container->get('store')->getConnection()->inTransaction()) {
|
||
|
|
$container->get('store')->getConnection()->rollBack();
|
||
|
|
}
|
||
|
|
|
||
|
|
header('HTTP/1.1 500 Internal Server Error');
|
||
|
|
header('Content-Type: text/plain');
|
||
|
|
die('There has been an unknown error with XMDS, it has been logged. Please contact your administrator.');
|
||
|
|
}
|