diff options
-rw-r--r-- | apps/files/ajax/newfile.php | 2 | ||||
-rw-r--r-- | apps/files/ajax/scan.php | 6 | ||||
-rw-r--r-- | core/ajax/update.php | 2 | ||||
-rw-r--r-- | lib/private/appframework/core/api.php | 7 | ||||
-rw-r--r-- | lib/private/eventsource.php | 93 | ||||
-rw-r--r-- | lib/private/server.php | 9 | ||||
-rw-r--r-- | lib/public/ieventsource.php | 34 | ||||
-rw-r--r-- | lib/public/iservercontainer.php | 7 |
8 files changed, 108 insertions, 52 deletions
diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 606576760ec..46629e1b602 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -16,7 +16,7 @@ $content = isset( $_REQUEST['content'] ) ? $_REQUEST['content'] : ''; $source = isset( $_REQUEST['source'] ) ? trim($_REQUEST['source'], '/\\') : ''; if($source) { - $eventSource=new OC_EventSource(); + $eventSource = \OC::$server->createEventSource(); } else { OC_JSON::callCheck(); } diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 3ec7f9394b1..da5a2ce6f26 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -15,7 +15,7 @@ if (isset($_GET['users'])) { $users = array(OC_User::getUser()); } -$eventSource = new OC_EventSource(); +$eventSource = \OC::$server->createEventSource(); $listener = new ScanListener($eventSource); foreach ($users as $user) { @@ -39,12 +39,12 @@ class ScanListener { private $lastCount = 0; /** - * @var \OC_EventSource event source to pass events to + * @var \OCP\IEventSource event source to pass events to */ private $eventSource; /** - * @param \OC_EventSource $eventSource + * @param \OCP\IEventSource $eventSource */ public function __construct($eventSource) { $this->eventSource = $eventSource; diff --git a/core/ajax/update.php b/core/ajax/update.php index 1e280a82227..419992c9891 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -8,7 +8,7 @@ if (OC::checkUpgrade(false)) { \OC_User::setIncognitoMode(true); $l = new \OC_L10N('core'); - $eventSource = new OC_EventSource(); + $eventSource = \OC::$server->createEventSource(); $updater = new \OC\Updater(\OC_Log::$object); $updater->listen('\OC\Updater', 'maintenanceStart', function () use ($eventSource, $l) { $eventSource->send('success', (string)$l->t('Turned on maintenance mode')); diff --git a/lib/private/appframework/core/api.php b/lib/private/appframework/core/api.php index ba6b9f95cb2..279f4bf97f7 100644 --- a/lib/private/appframework/core/api.php +++ b/lib/private/appframework/core/api.php @@ -110,12 +110,11 @@ class API implements IApi{ /** - * used to return and open a new eventsource - * @return \OC_EventSource a new open EventSource class + * used to return and open a new event source + * @return \OCP\IEventSource a new open EventSource class */ public function openEventSource(){ - # TODO: use public api - return new \OC_EventSource(); + return \OC::$server->createEventSource(); } /** diff --git a/lib/private/eventsource.php b/lib/private/eventsource.php index 192c1446b5a..53947f3a2f2 100644 --- a/lib/private/eventsource.php +++ b/lib/private/eventsource.php @@ -1,25 +1,10 @@ <?php - /** -* ownCloud -* -* @author Robin Appelman -* @copyright 2012 Robin Appelman icewind1991@gmail.com -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library 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 this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ /** * wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) @@ -27,51 +12,73 @@ * * use server side events with caution, to many open requests can hang the server */ -class OC_EventSource{ +class OC_EventSource implements \OCP\IEventSource { + /** + * @var bool + */ private $fallback; - private $fallBackId=0; - public function __construct() { + /** + * @var int + */ + private $fallBackId = 0; + + /** + * @var bool + */ + private $started = false; + + protected function init() { + if ($this->started) { + return; + } + $this->started = true; + + // prevent php output buffering, caching and nginx buffering OC_Util::obEnd(); header('Cache-Control: no-cache'); header('X-Accel-Buffering: no'); - $this->fallback=isset($_GET['fallback']) and $_GET['fallback']=='true'; - if($this->fallback) { - $this->fallBackId=$_GET['fallback_id']; + $this->fallback = isset($_GET['fallback']) and $_GET['fallback'] == 'true'; + if ($this->fallback) { + $this->fallBackId = (int)$_GET['fallback_id']; header("Content-Type: text/html"); - echo str_repeat('<span></span>'.PHP_EOL, 10); //dummy data to keep IE happy - }else{ + echo str_repeat('<span></span>' . PHP_EOL, 10); //dummy data to keep IE happy + } else { header("Content-Type: text/event-stream"); } - if( !OC_Util::isCallRegistered()) { + if (!OC_Util::isCallRegistered()) { $this->send('error', 'Possible CSRF attack. Connection will be closed.'); $this->close(); exit(); } flush(); - } /** * send a message to the client + * * @param string $type * @param mixed $data * + * @throws \BadMethodCallException * if only one parameter is given, a typeless message will be send with that parameter as data */ - public function send($type, $data=null) { - if(is_null($data)) { - $data=$type; - $type=null; + public function send($type, $data = null) { + if ($data and !preg_match('/^[A-Za-z0-9_]+$/', $type)) { + throw new BadMethodCallException('Type needs to be alphanumeric ('. $type .')'); + } + $this->init(); + if (is_null($data)) { + $data = $type; + $type = null; } - if($this->fallback) { - $fallBackId = OC_Util::sanitizeHTML($this->fallBackId); - $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' - .$fallBackId.',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; + if ($this->fallback) { + $response = '<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' + . $this->fallBackId . ',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; echo $response; - }else{ - if($type) { - echo 'event: ' . $type.PHP_EOL; + } else { + if ($type) { + echo 'event: ' . $type . PHP_EOL; } echo 'data: ' . OCP\JSON::encode($data) . PHP_EOL; } @@ -80,9 +87,9 @@ class OC_EventSource{ } /** - * close the connection of the even source + * close the connection of the event source */ public function close() { - $this->send('__internal__', 'close');//server side closing can be an issue, let the client do it + $this->send('__internal__', 'close'); //server side closing can be an issue, let the client do it } } diff --git a/lib/private/server.php b/lib/private/server.php index 71a098f9074..912d5c4f635 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -518,4 +518,13 @@ class Server extends SimpleContainer implements IServerContainer { } return new CertificateManager($user); } + + /** + * Create a new event source + * + * @return \OCP\IEventSource + */ + function createEventSource() { + return new \OC_EventSource(); + } } diff --git a/lib/public/ieventsource.php b/lib/public/ieventsource.php new file mode 100644 index 00000000000..eb7853c5e90 --- /dev/null +++ b/lib/public/ieventsource.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +/** + * wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) + * includes a fallback for older browsers and IE + * + * use server side events with caution, to many open requests can hang the server + * + * The event source will initialize the connection to the client when the first data is sent + */ +interface IEventSource { + /** + * send a message to the client + * + * @param string $type + * @param mixed $data + * + * if only one parameter is given, a typeless message will be send with that parameter as data + */ + public function send($type, $data = null); + + /** + * close the connection of the event source + */ + public function close(); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 60b0b497c54..1abf0d9938d 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -235,4 +235,11 @@ interface IServerContainer { * @return \OCP\ICertificateManager */ function getCertificateManager($user = null); + + /** + * Create a new event source + * + * @return \OCP\IEventSource + */ + function createEventSource(); } |