diff --git a/appinfo/application.php b/appinfo/application.php
index 636ce71b..be738441 100644
--- a/appinfo/application.php
+++ b/appinfo/application.php
@@ -247,7 +247,9 @@ public function __construct(array $urlParams=array()){
return new ContactsStoreUserProvider(
$c->query('OCP\Contacts\ContactsMenu\IContactsStore'),
$c->query('ServerContainer')->getUserSession(),
- $c->query('ServerContainer')->getUserManager()
+ $c->query('ServerContainer')->getUserManager(),
+ $c->query('OCP\IGroupManager'),
+ $c->query('OCP\IConfig')
);
} else {
return new UserManagerUserProvider(
diff --git a/js/jsxc b/js/jsxc
index 4c2e01bf..c804418a 160000
--- a/js/jsxc
+++ b/js/jsxc
@@ -1 +1 @@
-Subproject commit 4c2e01bfb6396b73a0e4abcfe4b91110af7cb918
+Subproject commit c804418ad58358469fe192674cad74de6247077d
diff --git a/js/ojsxc.js b/js/ojsxc.js
index dbc37c59..ed5ca3be 100644
--- a/js/ojsxc.js
+++ b/js/ojsxc.js
@@ -325,6 +325,16 @@
jsxc.storage.removeUserItem('defaultAvatars');
});
+ $(document).on('connfail.jsxc', function(ev, condition) {
+ if (condition === 'x-nc-not_allowed_to_chat') {
+ jsxc.gui.roster.toggle(jsxc.CONST.HIDDEN);
+ $('.jsxc_chatIcon').remove();
+ jsxc.storage.removeItem('jid');
+ jsxc.storage.removeItem('sid');
+ jsxc.storage.removeItem('rid');
+ }
+ });
+
$(document).on('status.contacts.count status.contact.updated', function() {
if (jsxc.restoreCompleted) {
setTimeout(function() {
@@ -388,5 +398,7 @@
if ($('#contactsmenu').length > 0) {
observeContactsMenu();
}
+
});
+
}(jQuery));
diff --git a/lib/ContactsStoreUserProvider.php b/lib/ContactsStoreUserProvider.php
index 6f06d4ce..feac35fb 100644
--- a/lib/ContactsStoreUserProvider.php
+++ b/lib/ContactsStoreUserProvider.php
@@ -2,6 +2,9 @@
namespace OCA\OJSXC;
+use OCP\IConfig;
+use OCP\IGroup;
+use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\IUserSession;
@@ -28,11 +31,23 @@ class ContactsStoreUserProvider implements IUserProvider
*/
private $userManager;
- public function __construct($contactsStore, IUserSession $userSession, IUserManager $userManager)
+ /**
+ * @var IGroupManager
+ */
+ private $groupManager;
+
+ /**
+ * @var IConfig
+ */
+ private $config;
+
+ public function __construct($contactsStore, IUserSession $userSession, IUserManager $userManager, IGroupManager $groupManager, IConfig $config)
{
$this->contactsStore = $contactsStore;
$this->userSession = $userSession;
$this->userManager = $userManager;
+ $this->groupManager = $groupManager;
+ $this->config = $config;
}
public function getAllUsers()
@@ -87,4 +102,21 @@ public function hasUserForUserByUID($uid1, $uid2)
{
return !is_null($this->contactsStore->findOne($this->userManager->get($uid1), 0, $uid2));
}
+
+ public function isUserExcluded($userId)
+ {
+ if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
+ $user = $this->userManager->get($userId);
+ $user_groups = $this->groupManager->getUserGroupIds($user);
+ $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
+ $decodedExcludeGroups = json_decode($excludedGroups, true);
+ $excludeGroupsList = ($decodedExcludeGroups !== null) ? $decodedExcludeGroups : [];
+
+ if (count(array_intersect($excludeGroupsList, $user_groups)) !== 0) {
+ // a group of the current user is excluded -> filter all local users
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/lib/Controller/HttpBindController.php b/lib/Controller/HttpBindController.php
index f5206e30..a7e9e063 100644
--- a/lib/Controller/HttpBindController.php
+++ b/lib/Controller/HttpBindController.php
@@ -5,6 +5,7 @@
use OCA\OJSXC\Db\Presence;
use OCA\OJSXC\Db\PresenceMapper;
use OCA\OJSXC\Db\StanzaMapper;
+use OCA\OJSXC\Exceptions\TerminateException;
use OCA\OJSXC\Http\XMPPResponse;
use OCA\OJSXC\ILock;
use OCA\OJSXC\NewContentContainer;
@@ -162,51 +163,56 @@ public function index()
$input = $this->body;
$longpoll = true; // set to false when the response should directly be returned and no polling should be done
$longpollStart = true; // start the first long poll cycle
- if (!empty($input)) {
- // replace invalid XML by valid XML one
- $input = str_replace("", "", $input);
- $reader = new Reader();
- $reader->xml($input);
- $reader->elementMap = [
- '{jabber:client}message' => 'Sabre\Xml\Element\KeyValue',
- '{jabber:client}presence' => function (Reader $reader) {
- return Presence::createFromXml($reader, $this->userId);
+ try {
+ if (!empty($input)) {
+ // replace invalid XML by valid XML one
+ $input = str_replace("", "", $input);
+ $reader = new Reader();
+ $reader->xml($input);
+ $reader->elementMap = [
+ '{jabber:client}message' => 'Sabre\Xml\Element\KeyValue',
+ '{jabber:client}presence' => function (Reader $reader) {
+ return Presence::createFromXml($reader, $this->userId);
+ }
+ ];
+ $stanzas = null;
+ try {
+ $stanzas = $reader->parse();
+ } catch (LibXMLException $e) {
}
- ];
- $stanzas = null;
- try {
- $stanzas = $reader->parse();
- } catch (LibXMLException $e) {
- }
- if (!is_null($stanzas) && count($stanzas['value']) > 0) {
- $this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING);
- }
- if (!is_null($stanzas)) {
- $stanzas = $stanzas['value'];
- if (is_array($stanzas)) {
- foreach ($stanzas as $stanza) {
- $stanzaType = $this->getStanzaType($stanza);
- if ($stanzaType === self::MESSAGE) {
- $this->messageHandler->handle($stanza);
- } elseif ($stanzaType === self::IQ) {
- $result = $this->iqHandler->handle($stanza);
- if (!is_null($result)) {
- $longpoll = false;
- $this->response->write($result);
- }
- } elseif ($stanza['value'] instanceof Presence) {
- $results = $this->presenceHandler->handle($stanza['value']);
- if (!is_null($results) && is_array($results)) {
- $longpoll = false;
- $longpollStart = false;
- foreach ($results as $r) {
- $this->response->write($r);
+ if (!is_null($stanzas) && count($stanzas['value']) > 0) {
+ $this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING);
+ }
+ if (!is_null($stanzas)) {
+ $stanzas = $stanzas['value'];
+ if (is_array($stanzas)) {
+ foreach ($stanzas as $stanza) {
+ $stanzaType = $this->getStanzaType($stanza);
+ if ($stanzaType === self::MESSAGE) {
+ $this->messageHandler->handle($stanza);
+ } elseif ($stanzaType === self::IQ) {
+ $result = $this->iqHandler->handle($stanza);
+ if (!is_null($result)) {
+ $longpoll = false;
+ $this->response->write($result);
+ }
+ } elseif ($stanza['value'] instanceof Presence) {
+ $results = $this->presenceHandler->handle($stanza['value']);
+ if (!is_null($results) && is_array($results)) {
+ $longpoll = false;
+ $longpollStart = false;
+ foreach ($results as $r) {
+ $this->response->write($r);
+ }
}
}
}
}
}
}
+ } catch (TerminateException $e) {
+ $this->response->terminate();
+ return $this->response;
}
// Start long polling
diff --git a/lib/Exceptions/TerminateException.php b/lib/Exceptions/TerminateException.php
new file mode 100644
index 00000000..1b7fdb4c
--- /dev/null
+++ b/lib/Exceptions/TerminateException.php
@@ -0,0 +1,8 @@
+hasUserByUID($uid2);
}
+
+ public function isUserExcluded($userId)
+ {
+ // to limit inconsistency we only support the settings in NC > 13.0.0
+ return false;
+ }
}
diff --git a/lib/http/xmppresponse.php b/lib/http/xmppresponse.php
index 349016f0..8680bd7b 100644
--- a/lib/http/xmppresponse.php
+++ b/lib/http/xmppresponse.php
@@ -60,4 +60,17 @@ public function render()
$this->writer->endElement();
return $this->writer->outputMemory();
}
+
+ /**
+ * Terminates the Chat connection with the `x-nc-not_allowed_to_chat` condition.
+ */
+ public function terminate()
+ {
+ $this->writer = new Writer();
+ $this->writer->openMemory();
+ $this->writer->startElement('body');
+ $this->writer->writeAttribute('xmlns', 'http://jabber.org/protocol/httpbind');
+ $this->writer->writeAttribute('type', 'terminate');
+ $this->writer->writeAttribute('condition', 'x-nc-not_allowed_to_chat');
+ }
}
diff --git a/lib/stanzahandlers/iq.php b/lib/stanzahandlers/iq.php
index f2d33de2..70f5428e 100644
--- a/lib/stanzahandlers/iq.php
+++ b/lib/stanzahandlers/iq.php
@@ -3,7 +3,9 @@
namespace OCA\OJSXC\StanzaHandlers;
use OCA\OJSXC\Db\IQRoster;
+use OCA\OJSXC\Exceptions\TerminateException;
use OCA\OJSXC\IUserProvider;
+use OCA\OJSXC\NewContentContainer;
use OCP\IConfig;
use OCP\IUserManager;
use Sabre\Xml\Reader;
@@ -39,6 +41,8 @@ class IQ extends StanzaHandler
* @param string $host
* @param IUserManager $userManager
* @param IConfig $config
+ * @param IUserProvider $userProvider
+ * @param NewContentContainer $newContentContainer
*/
public function __construct($userId, $host, IUserManager $userManager, IConfig $config, IUserProvider $userProvider)
{
@@ -52,6 +56,7 @@ public function __construct($userId, $host, IUserManager $userManager, IConfig $
/**
* @param array $stanza
* @return IQRoster
+ * @throws TerminateException TODO
*/
public function handle(array $stanza)
{
@@ -60,7 +65,13 @@ public function handle(array $stanza)
// if in debug mode we show the own username in the roster for testing
$debugMode = $this->config->getSystemValue("debug");
- if ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') {
+ if ($stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#items}query' || $stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#info}query') {
+ // the disco queries are currently not implemented but these are the first stanzas send to the server so
+ // they are ideal to terminate the connection if a user is excluded from chatting.
+ if ($this->userProvider->isUserExcluded($this->userId)) {
+ throw new TerminateException();
+ }
+ } elseif ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') {
$id = $stanza['attributes']['id'];
$iqRoster = new IQRoster();
$iqRoster->setType('result');
diff --git a/lib/stanzahandlers/presence.php b/lib/stanzahandlers/presence.php
index 97a49c27..efbfd945 100644
--- a/lib/stanzahandlers/presence.php
+++ b/lib/stanzahandlers/presence.php
@@ -4,6 +4,7 @@
use OCA\OJSXC\Db\MessageMapper;
use OCA\OJSXC\Db\PresenceMapper;
+use OCA\OJSXC\Exceptions\TerminateException;
use Sabre\Xml\Reader;
use Sabre\Xml\Writer;
use OCA\OJSXC\Db\Presence as PresenceEntity;
@@ -47,11 +48,14 @@ public function __construct($userId, $host, PresenceMapper $presenceMapper, Mess
* - update the presence in the database
* - broadcast the presence
* - return the active presence if the type isn't equal to unavailable
+ *
* @param PresenceEntity $presence
* @return PresenceEntity[]
+ * @throws TerminateException
*/
public function handle(PresenceEntity $presence)
{
+
// update the presence
$this->presenceMapper->setPresence($presence);