Commit 8d1f0e8a authored by Martin's avatar Martin

import upstream hg snapshot 0.2.0+hg20180126

parents
v. 0.2 (02/12/2015):
- schema updated (unversioned => version 1)
- sync with Idavoll
- use of sat.tmp.wokkel as a workaround for change not merged upstream
- RSM (XEP-0059) implementation
- MAM (XEP-0313) implementation
- Namespace Delegation (XEP-0355) implementation
- Privileged Entity (XEP-0356) implementation
- removed remote-roster hack
- SàT PubSub can be used as a PEP service (PEP implementation not complete yet)
- item publisher is enforced
- categories handling (not complete)
v 0.1.1 (09/09/2014):
bugfix release
v 0.1.0 (24/02/2014):
** FIRST PUBLIC RELEASE **
This diff is collapsed.
Requirements
============
- Python 2.7.x
- Twisted >= 15.2.0:
- Twisted Core
- Twisted Words
- Wokkel >= 0.7.1 (http://wokkel.ik.nu/)
- A XMPP server that supports the component protocol (XEP-0114),
and, to enable the micro-blogging feature, Namespace Delegation (XEP-0355)
and privileged entity (XEP-0356) are needed.
We recommend using Prosody with mod_privilege and mod_delegation modules.
- SàT backend (http://repos.goffi.org/sat) is currently needed for MAM and RSM handling
For the PostgreSQL backend, the following is also required:
- PostgreSQL >= 9.5 (including development files for psycopg2)
- psycopg2
Installation
============
sat_pubsub uses setuptools for package building and installing.
To build from the source run:
python setup.py build
Then, to install run the following, possibly as root:
python setup.py install
See the setuptools documentation for further information on changing
installation locations.
Configuration
=============
sat_pubsub uses Twisted's twistd command for running its services.
Idavoll, on which sat_pubsub is based, provides two types of storage for the backend:
a memory-based storage facility, which is volatile, and a persistent storage facility
using PostgreSQL. For now, sat_pubsub only uses the persistent storage facility.
For using the PostgreSQL backend, create a database (for example named pubsub):
sudo -u postgres createuser -d -P `whoami`
createdb pubsub
psql pubsub < sat_pubsub/db/pubsub.sql
Your XMPP server must also be configured to accept component connections and,
to enable the micro-blogging feature, privileged entity and namespace delegation.
See below for details.
Running sat_pubsub
==================
The minimal example for running sat_pubsub is:
twistd sat_pubsub
This will start the service and run it in the background. It generates a
file twistd.pid that holds the PID of the service and a log file twistd.log.
The twistd utility has a fair number of options that might be useful, and
can be viewed with:
twistd --help
When the service starts, it will connect to the XMPP server at the local
machine using the component protocol, and assumes the JID 'pubsub'. This
assumes a couple of defaults which can be overridden by passing parameters to
the twistd plugin. You can get an overview of the parameters and their defaults
using:
twistd sat_pubsub --help
In particular, the following parameters will be of interest:
--jid: The Jabber ID the component will assume.
--rport: the port number of the XMPP server to connect to
--secret: the secret used to authenticate with the XMPP server.
For example:
twistd sat_pubsub --jid=sat-pubsub.<your_xmpp_domain> --secret=<password>
You may also want to provide the --verbose flag to see the traffic flow,
for example to debug the configuration. Below some specifics for the
Prosody XMPP server implementation.
Running sat_pubsub with Prosody
===============================
To enable the micro-blogging feature with Prosody XMPP server, you need
the mod_delegation and privileged_entity plugins.
Check if the mod_delegation and mod_privilege plugins are already
in your Prosody installation:
cd prosody/plugins
ls mod_delegation.lua
ls mod_privilege.lua
If you can't see it, download them from http://modules.prosody.im:
wget http://hg.prosody.im/prosody-modules/raw-file/tip/mod_delegation/mod_delegation.lua
wget http://hg.prosody.im/prosody-modules/raw-file/tip/mod_privilege/mod_privilege.lua
Edit the prosody.cfg.lua file to add this module:
modules_enabled = {
[...]
"delegation";
"privilege";
[...]
}
In your VirtualHost, add this lines:
VirtualHost "<your_xmpp_domain>"
privileged_entities = {
["sat-pubsub.<your_xmpp_domain>"] = {
roster = "get";
message = "outgoing";
},
}
delegations = {
["urn:xmpp:mam:1"] = {
filtering = {"node"};
jid = "sat-pubsub.<your_xmpp_domain>";
},
["http://jabber.org/protocol/pubsub"] = {
jid = "sat-pubsub.<your_xmpp_domain>";
},
}
Also add these two lines at the end of the file, adapting them to your XMPP server
domain (virtual host) and selecting a password of your choice:
Component "sat-pubsub.<your_xmpp_domain>"
component_secret = "<password>"
modules_enabled = {"delegation", "privilege"}
For a more complete installation and configuration of Prosody to be used with
sat_pubsub, please report yourself to the Salut à Toi wiki:
http://wiki.goffi.org/wiki/Libervia/en#XMPP_server
include INSTALL
include COPYING
include CHANGELOG
include db/*
graft twisted
SàT PubSub component v0.1.1
This program is heavily based on Idavoll (0.9.1), which was written by Ralph Meijer
Copyright (c) 2012-2018 Jérôme Poisson
Copyright (c) 2014-2016 Adrien Cossa
Copyright (c) 2003-2011 Ralph Meijer
Sàt PubSub is a PubSub component service for XMPP
** LICENSE **
Sàt PubSub 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
(at your option) any later version.
Sàt PubSub 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 Sàt PubSub. If not, see <http://www.gnu.org/licenses/>.
** ABOUT **
SàT PubSub is a XMPP PubSub service component (XEP-0060)
It's based on Ralph Meijer's Idavoll, but provide special features necessary for the « Salut à Toi » project ( http://sat.goffi.org ), but it can also be used for any other XMPP project.
The use of a standard external component allow to use this features with most XMPP servers.
One of the main addition is fine access tuning for PubSub, which allow the publication of items for only some groups, even if the entire node is open. The protocol is explained on http://www.goffi.org/post/2012/06/24/Fine-access-tuning-for-PubSub for the moment, and a protoxep should be proposed to the XSF in the future...
** INSTALLATION **
Instructions for installation are the same as for Idavoll, so follow what is written in INSTALL and UPGRADING files.
** CREDIT **
The base project (Idavoll) was made by Ralph Meijer and can be found on http://idavoll.ik.nu/
** CONTACT **
Goffi (Jérôme Poisson): goffi@goffi.org (e-mail) or goffi@jabber.fr (jid)
Souliane (Adrien Cossa): souliane@mailoo.org (e-mail) or souliane@libervia.org (jid)
XMPP MUC: sat@chat.jabberfr.org
create table callbacks (
service text not null,
node text not null,
uri text not null,
PRIMARY KEY (service, node, uri)
);
CREATE TABLE entities (
entity_id serial PRIMARY KEY,
jid text NOT NULL UNIQUE
);
CREATE TABLE nodes (
node_id serial PRIMARY KEY,
node text NOT NULL,
pep text,
node_type text NOT NULL DEFAULT 'leaf'
CHECK (node_type IN ('leaf', 'collection')),
access_model text NOT NULL DEFAULT 'open'
CHECK (access_model IN ('open', 'presence', 'publisher-roster', 'whitelist', 'publish-only', 'self-publisher')),
persist_items boolean,
deliver_payloads boolean NOT NULL DEFAULT TRUE,
serial_ids boolean NOT NULL DEFAULT FALSE,
send_last_published_item text NOT NULL DEFAULT 'on_sub'
CHECK (send_last_published_item IN ('never', 'on_sub')),
publish_model text NOT NULL DEFAULT 'publishers'
CHECK (publish_model IN ('publishers', 'subscribers', 'open')),
schema xml
);
/* we need 2 partial indexes to manage NULL value for PEP */
CREATE UNIQUE INDEX nodes_node_pep_key_not_null ON nodes(node, pep) WHERE pep IS NOT NULL;
CREATE UNIQUE INDEX nodes_node_pep_key_null ON nodes(node) WHERE pep IS NULL;
INSERT INTO nodes (node, node_type) values ('', 'collection');
CREATE TABLE affiliations (
affiliation_id serial PRIMARY KEY,
entity_id integer NOT NULL REFERENCES entities ON DELETE CASCADE,
node_id integer NOT NULL references nodes ON DELETE CASCADE,
affiliation text NOT NULL
CHECK (affiliation IN ('outcast', 'member', 'publisher', 'owner')),
UNIQUE (entity_id, node_id)
);
CREATE TABLE node_groups_authorized (
node_groups_authorized_id serial PRIMARY KEY,
node_id integer NOT NULL references nodes ON DELETE CASCADE,
groupname text NOT NULL,
UNIQUE (node_id,groupname)
);
CREATE TABLE subscriptions (
subscription_id serial PRIMARY KEY,
entity_id integer NOT NULL REFERENCES entities ON DELETE CASCADE,
resource text,
node_id integer NOT NULL REFERENCES nodes ON delete CASCADE,
state text NOT NULL DEFAULT 'subscribed'
CHECK (state IN ('subscribed', 'pending', 'unconfigured')),
subscription_type text
CHECK (subscription_type IN (NULL, 'items', 'nodes')),
subscription_depth text
CHECK (subscription_depth IN (NULL, '1', 'all')),
UNIQUE (entity_id, resource, node_id));
CREATE TABLE items (
item_id serial PRIMARY KEY,
node_id integer NOT NULL REFERENCES nodes ON DELETE CASCADE,
item text NOT NULL,
publisher text NOT NULL,
data xml,
access_model text NOT NULL DEFAULT 'open'
CHECK (access_model IN ('open', 'publisher-roster', 'whitelist')),
created timestamp with time zone NOT NULL DEFAULT now(),
updated timestamp with time zone NOT NULL DEFAULT now(),
UNIQUE (node_id, item)
);
CREATE TABLE item_groups_authorized (
item_groups_authorized_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
groupname text NOT NULL,
UNIQUE (item_id,groupname)
);
CREATE TABLE item_jids_authorized (
item_jids_authorized_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
jid text NOT NULL,
UNIQUE (item_id,jid)
);
CREATE TABLE item_languages (
item_languages_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
language text NOT NULL,
UNIQUE (item_id,language)
);
CREATE TABLE item_categories (
item_categories_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
category text NOT NULL,
UNIQUE (item_id,category)
);
CREATE TABLE metadata (
key text PRIMARY KEY,
value text
);
INSERT INTO metadata VALUES ('version', '4');
-- we check version of the database before doing anything
-- and stop execution if not good
\set ON_ERROR_STOP
DO $$
DECLARE ver text;
BEGIN
SELECT value INTO ver FROM metadata WHERE key='version';
IF FOUND THEN
RAISE EXCEPTION 'This update file need to be applied on older database, you don''t have to use it';
END IF;
END$$;
\unset ON_ERROR_STOP
-- end of version check
ALTER TABLE nodes ADD COLUMN pep text;
ALTER TABLE nodes DROP CONSTRAINT nodes_node_key;
/* we need 2 partial indexes to manage NULL value for PEP */
CREATE UNIQUE INDEX nodes_node_pep_key_not_null ON nodes(node, pep) WHERE pep IS NOT NULL;
CREATE UNIQUE INDEX nodes_node_pep_key_null ON nodes(node) WHERE pep IS NULL;
CREATE TABLE metadata (
key text PRIMARY KEY,
value text
);
INSERT INTO metadata VALUES ('version', '1');
CREATE TABLE item_categories (
item_categories_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
category text NOT NULL,
UNIQUE (item_id,category)
);
UPDATE nodes SET node='urn:xmpp:microblog:0', pep=substring(node from 20) WHERE node LIKE 'urn:xmpp:groupblog:_%';
/* This is to update namespaces, SàT was buggy before 0.6 and didn't set the atom namespace in <entry/> */
/* But yeah, this is a crazy query */
UPDATE items SET data = xmlelement(name item, xmlattributes((xpath('/item/@id', data::xml))[1] as id),
XMLPARSE(CONTENT NULLIF(array_to_string(xpath('/item/entry/preceding-sibling::*', data::xml)::text[],''),'')),
xmlelement(name entry, xmlattributes('http://www.w3.org/2005/Atom' as xmlns), array_to_string(xpath('/item/entry/*', data::xml)::text[], '')::xml),
XMLPARSE(CONTENT NULLIF(array_to_string(xpath('/item/entry/following-sibling::*', data::xml)::text[],''),'')))
FROM nodes WHERE nodes.node_id = items.node_id
AND (node = 'urn:xmpp:microblog:0' or node LIKE 'urn:xmpp:comments:%')
AND XMLEXISTS('/item/entry' PASSING (data::xml));
-- we check version of the database before doing anything
-- and stop execution if not good
\set ON_ERROR_STOP
DO $$
DECLARE ver smallint;
BEGIN
SELECT value INTO ver FROM metadata WHERE key='version';
IF NOT FOUND OR ver!='1' THEN
RAISE EXCEPTION 'This update file need to be applied on database schema version 1, you use version %',ver;
END IF;
END$$;
\unset ON_ERROR_STOP
-- end of version check
/* roster access model was badly used, we rename it to publisher-roster */
ALTER TABLE nodes DROP CONSTRAINT nodes_access_model_check;
UPDATE nodes SET access_model = 'publisher-roster' WHERE access_model = 'roster';
ALTER TABLE nodes ADD CHECK (access_model IN ('open', 'publisher-roster', 'whitelist', 'publish-only', 'self-publisher'));
ALTER TABLE items DROP CONSTRAINT items_access_model_check;
UPDATE items SET access_model = 'publisher-roster' WHERE access_model = 'roster';
ALTER TABLE items ADD CHECK (access_model IN ('open', 'publisher-roster', 'whitelist'));
ALTER TABLE affiliations DROP CONSTRAINT affiliations_affiliation_check;
ALTER TABLE affiliations ADD CHECK (affiliation IN ('outcast', 'member', 'publisher', 'owner'));
CREATE TABLE item_jids_authorized (
item_jids_authorized_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
jid text NOT NULL,
UNIQUE (item_id,jid)
);
CREATE TABLE item_languages (
item_languages_id serial PRIMARY KEY,
item_id integer NOT NULL references items ON DELETE CASCADE,
language text NOT NULL,
UNIQUE (item_id,language)
);
UPDATE metadata SET value='2' WHERE key='version';
-- we check version of the database before doing anything
-- and stop execution if not good
\set ON_ERROR_STOP
DO $$
DECLARE ver text;
BEGIN
SELECT value INTO ver FROM metadata WHERE key='version';
IF NOT FOUND OR ver!='2' THEN
RAISE EXCEPTION 'This update file need to be applied on database schema version 2, you use version %',ver;
END IF;
END$$;
\unset ON_ERROR_STOP
-- end of version check
/* we add "presence" access model */
ALTER TABLE nodes DROP CONSTRAINT nodes_access_model_check;
ALTER TABLE nodes ADD CHECK (access_model IN ('open', 'presence', 'publisher-roster', 'whitelist', 'publish-only', 'self-publisher'));
/* and schema column */
ALTER TABLE nodes ADD COLUMN schema xml;
/* we want xml types for items data too */
ALTER TABLE items ALTER data TYPE xml using data::xml;
UPDATE metadata SET value='3' WHERE key='version';
-- we check version of the database before doing anything
-- and stop execution if not good
\set ON_ERROR_STOP
DO $$
DECLARE ver text;
BEGIN
SELECT value INTO ver FROM metadata WHERE key='version';
IF NOT FOUND OR ver!='3' THEN
RAISE EXCEPTION 'This update file need to be applied on database schema version 3, you use version %',ver;
END IF;
END$$;
\unset ON_ERROR_STOP
-- end of version check
/* new "serial ids" option */
ALTER TABLE nodes ADD COLUMN serial_ids boolean NOT NULL DEFAULT FALSE;
/* we want to keep creation and update times */
ALTER TABLE items RENAME COLUMN date TO created;
ALTER TABLE items ADD COLUMN updated timestamp with time zone NOT NULL DEFAULT now();
UPDATE metadata SET value='4' WHERE key='version';
#!/usr/bin/python
#-*- coding: utf-8 -*-
"""
Copyright (c) 2003-2011 Ralph Meijer
Copyright (c) 2012, 2013 Jérôme Poisson
This program 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
(at your option) any later version.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
--
This program is based on Idavoll (http://idavoll.ik.nu/),
originaly written by Ralph Meijer (http://ralphm.net/blog/)
It is sublicensed under AGPL v3 (or any later version) as allowed by the original
license.
--
Here is a copy of the original license:
Copyright (c) 2003-2011 Ralph Meijer
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
"""
Example TAC for Salut à Toi Pubsub.
"""
from twisted.application import service
from twisted.words.protocols.jabber.jid import JID
from sat_pubsub import tap
application = service.Application(u"SàT Pubsub")
config = {
'jid': JID('pubsub.example.org'),
'secret': 'secret',
'rhost': '127.0.0.1',
'rport': 5347,
'backend': 'memory',
'verbose': True,
'hide-nodes': False,
}
satPubsubService = tap.makeService(config)
satPubsubService.setServiceParent(application)
# Set the maximum delay until trying to reconnect.
componentService = satPubsubService.getServiceNamed('component')
componentService.factory.maxdelay = 300
#!/usr/bin/python
#-*- coding: utf-8 -*-
# Copyright (c) 2003-2008 Ralph Meijer
# See LICENSE for details.
"""
Example TAC for SàT Pubsub.
"""
from twisted.application import service
from twisted.words.protocols.jabber.jid import JID
from sat_pubsub import tap
application = service.Application("sat_pubsub")
config = {
'jid': JID('sat-pubsub.necton3.int'),
'secret': 'pass',
'rhost': '127.0.0.1',
'rport': 5347,
'backend': 'pgsql',
'dbuser': 'goffi',
'dbpass': 'toto',
'dbname': "pubsub",
'dbhost': "localhost",
'dbport': None,
'verbose': True,
'hide-nodes': False,
}
idavollService = tap.makeService(config)
idavollService.setServiceParent(application)
# Set the maximum delay until trying to reconnect.
componentService = idavollService.getServiceNamed('component')
componentService.factory.maxdelay = 300
#!/usr/bin/python
#-*- coding: utf-8 -*-
# Copyright (c) 2012-2018 Jérôme Poisson
# Copyright (c) 2013-2016 Adrien Cossa
# Copyright (c) 2003-2011 Ralph Meijer
#
#
# This program 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
# (at your option) any later version.
#
# This program 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 program. If not, see <http://www.gnu.org/licenses/>.
# --
#
# This program is based on Idavoll (http://idavoll.ik.nu/),
# originaly written by Ralph Meijer (http://ralphm.net/blog/)
# It is sublicensed under AGPL v3 (or any later version) as allowed by the original
# license.
#
# --
#
# Here is a copy of the original license:
#
# Copyright (c) 2003-2011 Ralph Meijer
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
SàT PubSub, a generic XMPP publish-subscribe service.
"""
__version__ = '0.2.0'
# TODO: remove this when RSM and MAM are in wokkel
import wokkel
from sat_tmp.wokkel import pubsub as tmp_pubsub, rsm as tmp_rsm, mam as tmp_mam
wokkel.pubsub = tmp_pubsub
wokkel.rsm = tmp_rsm
wokkel.mam = tmp_mam
This diff is collapsed.
#!/usr/bin/python
#-*- coding: utf-8 -*-
# Copyright (c) 2012-2018 Jérôme Poisson
# Copyright (c) 2013-2016 Adrien Cossa
# Copyright (c) 2003-2011 Ralph Meijer
# This program 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
# (at your option) any later version.
# This program 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 program. If not, see <http://www.gnu.org/licenses/>.
# --
# This program is based on Idavoll (http://idavoll.ik.nu/),
# originaly written by Ralph Meijer (http://ralphm.net/blog/)
# It is sublicensed under AGPL v3 (or any later version) as allowed by the original
# license.
# --
# Here is a copy of the original license:
# Copyright (c) 2003-2011 Ralph Meijer
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
NS_CLIENT = 'jabber:client'
NS_GROUPBLOG_PREFIX = 'urn:xmpp:groupblog:'
NS_ITEM_CONFIG = "http://jabber.org/protocol/pubsub#item-config"
NS_ATOM = "http://www.w3.org/2005/Atom"
NS_FORWARD = 'urn:xmpp:forward:0'
NS_SCHEMA = 'https://salut-a-toi/protocol/schema:0'
NS_SCHEMA_RESTRICT = 'https://salut-a-toi/protocol/schema#restrict:0'
OPT_ACCESS_MODEL = 'pubsub#access_model'
OPT_ROSTER_GROUPS_ALLOWED = 'pubsub#roster_groups_allowed'
OPT_PERSIST_ITEMS = "pubsub#persist_items"
OPT_DELIVER_PAYLOADS = "pubsub#deliver_payloads"
OPT_SEND_LAST_PUBLISHED_ITEM = "pubsub#send_last_published_item"
OPT_PUBLISH_MODEL = 'pubsub#publish_model'
OPT_SERIAL_IDS = 'pubsub#serial_ids'
VAL_AMODEL_OPEN = 'open'
VAL_AMODEL_PRESENCE = 'presence'
VAL_AMODEL_PUBLISHER_ROSTER = 'publisher-roster'
VAL_AMODEL_WHITELIST = 'whitelist'
VAL_AMODEL_PUBLISH_ONLY = 'publish-only'
VAL_AMODEL_SELF_PUBLISHER = 'self-publisher'
VAL_AMODEL_DEFAULT = VAL_AMODEL_OPEN
VAL_AMODEL_ALL = (VAL_AMODEL_OPEN, VAL_AMODEL_PUBLISHER_ROSTER, VAL_AMODEL_WHITELIST, VAL_AMODEL_PUBLISH_ONLY, VAL_AMODEL_SELF_PUBLISHER)
VAL_PMODEL_PUBLISHERS = 'publishers'