diff options
Diffstat (limited to 'spec/scansion')
23 files changed, 2896 insertions, 0 deletions
diff --git a/spec/scansion/basic.scs b/spec/scansion/basic.scs new file mode 100644 index 00000000..43c9831a --- /dev/null +++ b/spec/scansion/basic.scs @@ -0,0 +1,18 @@ +# Basic login and initial presence + +[Client] Romeo + jid: user@localhost + password: password + +--------- + +Romeo connects + +Romeo sends: + <presence/> + +Romeo receives: + <presence/> + +Romeo disconnects + diff --git a/spec/scansion/basic_message.scs b/spec/scansion/basic_message.scs new file mode 100644 index 00000000..fb21c465 --- /dev/null +++ b/spec/scansion/basic_message.scs @@ -0,0 +1,174 @@ +# Basic message routing and delivery + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: juliet@localhost + password: password + +[Client] Juliet's phone + jid: juliet@localhost + password: password + resource: mobile + +--------- + +# Act 1, scene 1 +# The clients connect + +Romeo connects + +Juliet connects + +Juliet's phone connects + +# Romeo publishes his presence. Juliet has not, and so does not receive presence. + +Romeo sends: + <presence/> + +Romeo receives: + <presence from="${Romeo's full JID}" /> + +# Romeo sends a message to Juliet's full JID + +Romeo sends: + <message to="${Juliet's full JID}" type="chat"> + <body>Hello Juliet!</body> + </message> + +Juliet receives: + <message to="${Juliet's full JID}" from="${Romeo's full JID}" type="chat"> + <body>Hello Juliet!</body> + </message> + +# Romeo sends a message to Juliet's phone + +Romeo sends: + <message to="${Juliet's phone's full JID}" type="chat"> + <body>Hello Juliet, on your phone.</body> + </message> + +Juliet's phone receives: + <message to="${Juliet's phone's full JID}" from="${Romeo's full JID}" type="chat"> + <body>Hello Juliet, on your phone.</body> + </message> + +# Scene 2 +# This requires the server to support offline messages (which is optional). + +# Romeo sends a message to Juliet's bare JID. This is not immediately delivered, as she +# has not published presence on either of her resources. + +Romeo sends: + <message to="juliet@localhost" type="chat"> + <body>Hello Juliet, are you there?</body> + </message> + +# Juliet sends presence on her phone, and should receive the message there + +Juliet's phone sends: + <presence/> + +Juliet's phone receives: + <presence/> + +Juliet's phone receives: + <message from="${Romeo's full JID}" type="chat"> + <body>Hello Juliet, are you there?</body> + <delay xmlns='urn:xmpp:delay' from='localhost' stamp='{scansion:any}' /> + </message> + +# Romeo sends another bare-JID message, it should be delivered +# instantly to Juliet's phone + +Romeo sends: + <message to="juliet@localhost" type="chat"> + <body>Oh, hi!</body> + </message> + +Juliet's phone receives: + <message from="${Romeo's full JID}" type="chat"> + <body>Oh, hi!</body> + </message> + +# Juliet's laptop goes online, but with a negative priority + +Juliet sends: + <presence> + <priority>-1</priority> + </presence> + +Juliet receives: + <presence from="${Juliet's full JID}"> + <priority>-1</priority> + </presence> + +Juliet's phone receives: + <presence from="${Juliet's full JID}"> + <priority>-1</priority> + </presence> + +# Again, Romeo sends a message to her bare JID, but it should +# only get delivered to her phone: + +Romeo sends: + <message to="juliet@localhost" type="chat"> + <body>How are you?</body> + </message> + +Juliet's phone receives: + <message from="${Romeo's full JID}" type="chat"> + <body>How are you?</body> + </message> + +# Romeo sends direct to Juliet's full JID, and she should receive it + +Romeo sends: + <message to="${Juliet's full JID}" type="chat"> + <body>Are you hiding?</body> + </message> + +Juliet receives: + <message from="${Romeo's full JID}" type="chat"> + <body>Are you hiding?</body> + </message> + +# Juliet publishes non-negative presence + +Juliet sends: + <presence/> + +Juliet receives: + <presence from="${Juliet's full JID}"/> + +Juliet's phone receives: + <presence from="${Juliet's full JID}"/> + +# And now Romeo's bare JID messages get delivered to both resources +# (server behaviour may vary here) + +Romeo sends: + <message to="juliet@localhost" type="chat"> + <body>There!</body> + </message> + +Juliet receives: + <message from="${Romeo's full JID}" type="chat"> + <body>There!</body> + </message> + +Juliet's phone receives: + <message from="${Romeo's full JID}" type="chat"> + <body>There!</body> + </message> + +# The End + +Romeo disconnects + +Juliet disconnects + +Juliet's phone disconnects diff --git a/spec/scansion/basic_roster.scs b/spec/scansion/basic_roster.scs new file mode 100644 index 00000000..2e292083 --- /dev/null +++ b/spec/scansion/basic_roster.scs @@ -0,0 +1,73 @@ +# Basic roster test + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: juliet@localhost + password: password + +--------- + +Romeo connects + +Juliet connects + +Romeo sends: + <presence/> + +Romeo receives: + <presence from="${Romeo's full JID}" /> + +Romeo sends: + <iq type="get" id="roster1"> + <query xmlns='jabber:iq:roster'/> + </iq> + +Romeo receives: + <iq type="result" id="roster1"> + <query ver='{scansion:any}' xmlns="jabber:iq:roster"/> + </iq> + +# Add nurse to roster + +Romeo sends: + <iq type="set" id="roster2"> + <query xmlns="jabber:iq:roster"> + <item jid='nurse@localhost'/> + </query> + </iq> + +# Receive the roster add result + +Romeo receives: + <iq type="result" id="roster2"/> + +# Receive the roster push + +Romeo receives: + <iq type="set" id="{scansion:any}"> + <query xmlns='jabber:iq:roster' ver='{scansion:any}'> + <item jid='nurse@localhost' subscription='none'/> + </query> + </iq> + +Romeo sends: + <iq type="result" id="fixme"/> + +# Fetch the roster, it should include nurse now + +Romeo sends: + <iq type="get" id="roster3"> + <query xmlns='jabber:iq:roster'/> + </iq> + +Romeo receives: + <iq type="result" id="roster3"> + <query xmlns='jabber:iq:roster' ver="{scansion:any}"> + <item subscription='none' jid='nurse@localhost'/> + </query> + </iq> + +Romeo disconnects diff --git a/spec/scansion/issue1224.scs b/spec/scansion/issue1224.scs new file mode 100644 index 00000000..b75cfbd1 --- /dev/null +++ b/spec/scansion/issue1224.scs @@ -0,0 +1,115 @@ +# MUC: Handle affiliation changes from buggy clients + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' xmlns='http://jabber.org/protocol/muc#user'/> + </x> + </message> + +Romeo receives: + <iq from='room@conference.localhost' id='member1' type='result'/> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# Romeo makes Juliet a member of the room, however his client is buggy and only +# specifies her nickname + +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' nick='Juliet' /> + </query> + </iq> + +Romeo receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' role='participant' jid="${Juliet's full JID}"> + <actor jid="${Romeo's full JID}" nick='Romeo'/> + </item> + </x> + </presence> + +Romeo receives: + <iq type='result' id='member1' from='room@conference.localhost' /> + +Juliet receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' role='participant' jid="${Juliet's full JID}"> + <actor nick='Romeo' /> + </item> + <status xmlns='http://jabber.org/protocol/muc#user' code='110'/> + </x> + </presence> diff --git a/spec/scansion/issue505.scs b/spec/scansion/issue505.scs new file mode 100644 index 00000000..24fbeb72 --- /dev/null +++ b/spec/scansion/issue505.scs @@ -0,0 +1,79 @@ +# Issue 505: mod_muc doesn’t forward part statuses + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet sends: + <presence type='unavailable' to='room@conference.localhost'> + <status>Farewell</status> + </presence> + +Romeo receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <status>Farewell</status> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's full JID}" affiliation='none' role='none'/> + </x> + </presence> diff --git a/spec/scansion/issue978-multi.scs b/spec/scansion/issue978-multi.scs new file mode 100644 index 00000000..d8f99228 --- /dev/null +++ b/spec/scansion/issue978-multi.scs @@ -0,0 +1,111 @@ +# Issue 978: MUC does not carry error into occupant leave status (multiple clients) + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +[Client] Juliet's phone + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user' scansion:strict='false'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# Juliet's phone connects, and joins the room +Juliet's phone connects + +Juliet's phone sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet's phone receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet's phone receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet's phone receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user' scansion:strict='false'> + <item affiliation='none' jid="${Juliet's phone's full JID}" role='participant'/> + <item affiliation='none' jid="${Juliet's full JID}" role='participant'/> + </x> + </presence> + +# Juliet leaves with an error +Juliet sends: + <presence type='error' to='room@conference.localhost'> + <error type='cancel'> + <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Test error</text> + </error> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's phone's full JID}" affiliation='none' role='participant'/> + </x> + </presence> diff --git a/spec/scansion/issue978.scs b/spec/scansion/issue978.scs new file mode 100644 index 00000000..59db8335 --- /dev/null +++ b/spec/scansion/issue978.scs @@ -0,0 +1,85 @@ +# Issue 978: MUC does not carry error into occupant leave status (single client) +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_whois'> + <value>anyone</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet sends: + <presence type='error' to='room@conference.localhost'> + <error type='cancel'> + <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Test error</text> + </error> + </presence> + +Romeo receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <status>Kicked: service unavailable: Test error</status> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='333'/> + <item jid="${Juliet's full JID}" affiliation='none' role='none'/> + </x> + </presence> diff --git a/spec/scansion/mam_prefs_prep.scs b/spec/scansion/mam_prefs_prep.scs new file mode 100644 index 00000000..9589ec65 --- /dev/null +++ b/spec/scansion/mam_prefs_prep.scs @@ -0,0 +1,36 @@ +# mod_mam shold apply JIDprep in prefs + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <iq id="lx2" type="set"> + <prefs xmlns="urn:xmpp:mam:2" default="roster"> + <always> + <jid>JULIET@MONTAGUE.LIT</jid> + </always> + <never> + <jid>MONTAGUE@MONTAGUE.LIT</jid> + </never> + </prefs> + </iq> + +Romeo receives: + <iq id="lx2" type="result"> + <prefs xmlns="urn:xmpp:mam:2" default="roster"> + <always> + <jid>juliet@montague.lit</jid> + </always> + <never> + <jid>montague@montague.lit</jid> + </never> + </prefs> + </iq> + +Romeo disconnects + diff --git a/spec/scansion/muc_affiliation_notify.scs b/spec/scansion/muc_affiliation_notify.scs new file mode 100644 index 00000000..e7d21fcd --- /dev/null +++ b/spec/scansion/muc_affiliation_notify.scs @@ -0,0 +1,137 @@ +# MUC: Notification of affiliation changes of non-occupants + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +[Client] Rosaline + jid: user3@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Promote Juliet to member +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +# Juliet is not in the room, so an affiliation change message is received + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' xmlns='http://jabber.org/protocol/muc#user'/> + </x> + </message> + +# The affiliation change succeeded + +Romeo receives: + <iq from='room@conference.localhost' id='member1' type='result'/> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# To check the status of the room is as expected, Romeo requests the member list + +Romeo sends: + <iq id='member3' to='room@conference.localhost' type='get'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member'/> + </query> + </iq> + +Romeo receives: + <iq from='room@conference.localhost' type='result' id='member3'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +# Romeo grants membership to Rosaline, who is not in the room + +Romeo sends: + <iq id='member2' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Rosaline's JID}" /> + </query> + </iq> + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Rosaline's JID}" affiliation='member' xmlns='http://jabber.org/protocol/muc#user'/> + </x> + </message> + +Romeo receives: + <iq type='result' id='member2' from='room@conference.localhost' /> + +Romeo sends: + <message type="groupchat" to="room@conference.localhost"> + <body>Finished!</body> + </message> + +Juliet receives: + <message type="groupchat" from="room@conference.localhost/Romeo"> + <body>Finished!</body> + </message> diff --git a/spec/scansion/muc_mediated_invite.scs b/spec/scansion/muc_mediated_invite.scs new file mode 100644 index 00000000..340aefc7 --- /dev/null +++ b/spec/scansion/muc_mediated_invite.scs @@ -0,0 +1,76 @@ +# MUC: Mediated invites + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Juliet connects +Juliet connects + +Juliet sends: + <presence/> + +Juliet receives: + <presence/> + + +# Romeo invites Juliet to join the room + +Romeo sends: + <message to="room@conference.localhost" id="invite1"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <invite to="${Juliet's JID}" /> + </x> + </message> + +Juliet receives: + <message from="room@conference.localhost" id="invite1"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <invite from="room@conference.localhost/Romeo"> + <reason/> + </invite> + </x> + <body>room@conference.localhost/Romeo invited you to the room room@conference.localhost</body> + <x xmlns="jabber:x:conference" jid="room@conference.localhost"/> + </message> diff --git a/spec/scansion/muc_members_only_change.scs b/spec/scansion/muc_members_only_change.scs new file mode 100644 index 00000000..dc40b5a0 --- /dev/null +++ b/spec/scansion/muc_members_only_change.scs @@ -0,0 +1,114 @@ +# MUC: Members-only rooms kick members who lose affiliation + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form, set the room to members-only +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_membersonly'> + <value>1</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Romeo adds Juliet to the member list +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' /> + </x> + </message> + +Romeo receives: + <iq from='room@conference.localhost' id='member1' type='result'/> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + + +# Romeo removes Juliet's membership status +Romeo sends: + <iq id='member2' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='none' jid="${Juliet's JID}" /> + </query> + </iq> + +# As a non-member, Juliet must now be removed from the room +Romeo receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='321'/> + <item role='none' jid="${Juliet's full JID}" affiliation='none'> + <actor nick='Romeo' jid="${Romeo's full JID}"/> + </item> + </x> + </presence> + +Romeo receives: + <iq id='member2' type='result'/> + +Romeo disconnects + +Juliet disconnects diff --git a/spec/scansion/muc_members_only_deregister.scs b/spec/scansion/muc_members_only_deregister.scs new file mode 100644 index 00000000..dcc84146 --- /dev/null +++ b/spec/scansion/muc_members_only_deregister.scs @@ -0,0 +1,122 @@ +# MUC: Members-only rooms kick members who deregister + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form, set the room to members-only +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_membersonly'> + <value>1</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Romeo adds Juliet to the member list +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' /> + </x> + </message> + +Romeo receives: + <iq from='room@conference.localhost' id='member1' type='result'/> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + + +# Tired of Romeo's company, Juliet unregisters from the room + +Juliet sends: + <iq type='set' to='room@conference.localhost' id='unreg1'> + <query xmlns='jabber:iq:register'> + <remove/> + </query> + </iq> + +Juliet receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='321'/> + <item affiliation='none' role='none' jid="${Juliet's full JID}" /> + <status code='110'/> + </x> + </presence> + +Juliet receives: + <iq type='result' from='room@conference.localhost' id='unreg1'/> + +Romeo receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='321'/> + <item affiliation='none' role='none' jid="${Juliet's full JID}" /> + </x> + </presence> + + +Romeo disconnects + +Juliet disconnects diff --git a/spec/scansion/muc_password.scs b/spec/scansion/muc_password.scs new file mode 100644 index 00000000..82611183 --- /dev/null +++ b/spec/scansion/muc_password.scs @@ -0,0 +1,143 @@ +# MUC: Password-protected rooms + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_roomsecret'> + <value>cauldronburn</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +# Juliet connects, and tries to join the room (password-protected) +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" type="error"> + <error type="auth" code="401"> + <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + </presence> + +# Retry with the correct password +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"> + <password>cauldronburn</password> + </x> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# Ok, now Juliet leaves, and Romeo unsets the password + +Juliet sends: + <presence type="unavailable" to="room@conference.localhost"/> + +Romeo receives: + <presence type="unavailable" from="room@conference.localhost/Juliet"/> + +Juliet receives: + <presence type="unavailable" from="room@conference.localhost/Juliet"/> + +# Remove room password +Romeo sends: + <iq id='config2' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_roomsecret'> + </field> + </x> + </query> + </iq> + +# Config change success +Romeo receives: + <iq id="config2" from="room@conference.localhost" type="result"> + </iq> + +# Notification of room configuration update +Romeo receives: + <message type='groupchat' from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='104'/> + </x> + </message> + +# Juliet tries to join (should succeed) +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +# Notification of Romeo's presence in the room +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +# Room topic +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + diff --git a/spec/scansion/muc_register.scs b/spec/scansion/muc_register.scs new file mode 100644 index 00000000..e1eaf4e0 --- /dev/null +++ b/spec/scansion/muc_register.scs @@ -0,0 +1,528 @@ +# MUC: Room registration and reserved nicknames + +[Client] Romeo + jid: user@localhost + password: password + +[Client] Juliet + jid: user2@localhost + password: password + +[Client] Rosaline + jid: user3@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +# Submit config form +Romeo sends: + <iq id='config1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"> + </iq> + +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" /> + </query> + </iq> + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' /> + </x> + </message> + +Romeo receives: + <iq from='room@conference.localhost' id='member1' type='result'/> + +# Juliet connects, and joins the room +Juliet connects + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# Juliet retrieves the registration form + +Juliet sends: + <iq id='jw81b36f' to='room@conference.localhost' type='get'> + <query xmlns='jabber:iq:register'/> + </iq> + +Juliet receives: + <iq type='result' from='room@conference.localhost' id='jw81b36f'> + <query xmlns='jabber:iq:register'> + <x type='form' xmlns='jabber:x:data'> + <field type='hidden' var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#register</value> + </field> + <field type='text-single' label='Nickname' var='muc#register_roomnick'/> + </x> + </query> + </iq> + +Juliet sends: + <iq id='nv71va54' to='room@conference.localhost' type='set'> + <query xmlns='jabber:iq:register'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#register</value> + </field> + <field var='muc#register_roomnick'> + <value>Juliet</value> + </field> + </x> + </query> + </iq> + +Juliet receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' jid="${Juliet's full JID}" role='participant'/> + <status code='110'/> + </x> + </presence> + +Juliet receives: + <iq type='result' from='room@conference.localhost' id='nv71va54'/> + +# Juliet discovers her reserved nick + +Juliet sends: + <iq id='getnick1' to='room@conference.localhost' type='get'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/> + </iq> + +Juliet receives: + <iq type='result' from='room@conference.localhost' id='getnick1'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'> + <identity category='conference' name='Juliet' type='text'/> + </query> + </iq> + +# Juliet leaves the room: + +Juliet sends: + <presence type="unavailable" to="room@conference.localhost/Juliet" /> + +Juliet receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's full JID}" affiliation='member' role='none'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's full JID}" affiliation='member' role='participant'/> + </x> + </presence> + +# Rosaline connect and tries to join the room as Juliet + +Rosaline connects + +Rosaline sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Rosaline receives: + <presence type='error' from='room@conference.localhost/Juliet'> + <error type='cancel'> + <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + <x xmlns='http://jabber.org/protocol/muc'/> + </presence> + +# In a heated moment, Juliet unregisters from the room + +Juliet sends: + <iq type='set' to='room@conference.localhost' id='unreg1'> + <query xmlns='jabber:iq:register'> + <remove/> + </query> + </iq> + +Juliet receives: + <iq type='result' from='room@conference.localhost' id='unreg1'/> + +# Romeo is notified of Juliet's sad decision + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user' scansion:strict='true'> + <item jid="${Juliet's JID}" /> + </x> + </message> + +# Rosaline attempts once more to sneak into the room, disguised as Juliet + +Rosaline sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Rosaline receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='owner' role='moderator'/> + </x> + </presence> + +Rosaline receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='none' jid="${Rosaline's full JID}" role='participant'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='none' jid="${Rosaline's full JID}" role='participant'/> + </x> + </presence> + +# On discovering the ruse, Romeo restores Juliet's nick and status within the room + +Romeo sends: + <iq id='member1' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Juliet's JID}" nick='Juliet' /> + </query> + </iq> + +# Rosaline is evicted from the room + +Romeo receives: + <presence from='room@conference.localhost/Juliet' type='unavailable'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='307'/> + <item affiliation='none' role='none' jid="${Rosaline's full JID}"> + <reason>This nickname is reserved</reason> + </item> + </x> + </presence> + +# An out-of-room affiliation change is received for Juliet + +Romeo receives: + <message from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's JID}" affiliation='member' /> + </x> + </message> + +Romeo receives: + <iq type='result' id='member1' from='room@conference.localhost' /> + +Rosaline receives: + <presence type='unavailable' from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='307'/> + <item affiliation='none' jid="${Rosaline's full JID}" role='none'> + <reason>This nickname is reserved</reason> + </item> + <status code='110'/> + </x> + </presence> + +# Rosaline, frustrated, attempts to get back into the room... + +Rosaline sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +# ...but once again, is denied + +Rosaline receives: + <presence type='error' from='room@conference.localhost/Juliet'> + <error type='cancel'> + <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + <x xmlns='http://jabber.org/protocol/muc'/> + </presence> + +# Juliet, however, quietly joins the room with success + +Juliet sends: + <presence to="room@conference.localhost/Juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="room@conference.localhost/Romeo" /> + +Juliet receives: + <presence from="room@conference.localhost/Juliet" /> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from="room@conference.localhost/Juliet" /> + +# Romeo checks whether he has reserved his own nick yet + +Romeo sends: + <iq id='getnick1' to='room@conference.localhost' type='get'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/> + </iq> + +# But no nick is returned, as he hasn't registered yet! + +Romeo receives: + <iq type='result' from='room@conference.localhost' id='getnick1'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item' scansion:strict='true' /> + </iq> + +# Romeo updates his own registration + +Romeo sends: + <iq id='jw81b36f' to='room@conference.localhost' type='get'> + <query xmlns='jabber:iq:register'/> + </iq> + +Romeo receives: + <iq type='result' from='room@conference.localhost' id='jw81b36f'> + <query xmlns='jabber:iq:register'> + <x type='form' xmlns='jabber:x:data'> + <field type='hidden' var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#register</value> + </field> + <field type='text-single' label='Nickname' var='muc#register_roomnick'/> + </x> + </query> + </iq> + +Romeo sends: + <iq id='nv71va54' to='room@conference.localhost' type='set'> + <query xmlns='jabber:iq:register'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#register</value> + </field> + <field var='muc#register_roomnick'> + <value>Romeo</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='owner' jid="${Romeo's full JID}" role='moderator'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <iq type='result' from='room@conference.localhost' id='nv71va54'/> + +Juliet receives: + <presence from='room@conference.localhost/Romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='owner'/> + </x> + </presence> + +# Romeo discovers his reserved nick + +Romeo sends: + <iq id='getnick1' to='room@conference.localhost' type='get'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/> + </iq> + +Romeo receives: + <iq type='result' from='room@conference.localhost' id='getnick1'> + <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'> + <identity category='conference' name='Romeo' type='text'/> + </query> + </iq> + +# To check the status of the room is as expected, Romeo requests the member list + +Romeo sends: + <iq id='member3' to='room@conference.localhost' type='get'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member'/> + </query> + </iq> + +Romeo receives: + <iq from='room@conference.localhost' type='result' id='member3'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item jid="${Juliet's JID}" affiliation='member' nick='Juliet'/> + </query> + </iq> + +Juliet sends: + <presence type="unavailable" to="room@conference.localhost/Juliet" /> + +Juliet receives: + <presence from='room@conference.localhost/Juliet' type='unavailable' /> + +Romeo receives: + <presence type='unavailable' from='room@conference.localhost/Juliet' /> + +# Rosaline joins as herself + +Rosaline sends: + <presence to="room@conference.localhost/Rosaline"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Rosaline receives: + <presence from="room@conference.localhost/Romeo" /> + +Rosaline receives: + <presence from="room@conference.localhost/Rosaline" /> + +Rosaline receives: + <message type='groupchat' from='room@conference.localhost'><subject/></message> + +Romeo receives: + <presence from='room@conference.localhost/Rosaline'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Rosaline's full JID}" affiliation='none' role='participant'/> + </x> + </presence> + +# Rosaline tries to register her own nickname, but unaffiliated +# registration is disabled by default + +Rosaline sends: + <iq id='reg990' to='room@conference.localhost' type='get'> + <query xmlns='jabber:iq:register'/> + </iq> + +Rosaline receives: + <iq type='error' from='room@conference.localhost' id='reg990'> + <error type='auth'> + <registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + </iq> + +Rosaline sends: + <iq id='reg991' to='room@conference.localhost' type='set'> + <query xmlns='jabber:iq:register'> + <x xmlns='jabber:x:data' type='submit'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#register</value> + </field> + <field var='muc#register_roomnick'> + <value>Romeo</value> + </field> + </x> + </query> + </iq> + +Rosaline receives: + <iq id='reg991' type='error'> + <error type='auth'> + <registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + </iq> + +# Romeo reserves her nickname for her + +Romeo sends: + <iq id='member2' to='room@conference.localhost' type='set'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member' jid="${Rosaline's JID}" nick='Rosaline' /> + </query> + </iq> + +Romeo receives: + <presence from='room@conference.localhost/Rosaline'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' role='participant' jid="${Rosaline's full JID}"> + <actor jid="${Romeo's full JID}" nick='Romeo'/> + </item> + </x> + </presence> + +Romeo receives: + <iq type='result' id='member2' from='room@conference.localhost' /> + +Rosaline receives: + <presence from='room@conference.localhost/Rosaline'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' role='participant' jid="${Rosaline's full JID}"> + <actor nick='Romeo' /> + </item> + <status xmlns='http://jabber.org/protocol/muc#user' code='110'/> + </x> + </presence> + +# Romeo sets their their own nickname via admin query (see #1273) +Romeo sends: + <iq to="room@conference.localhost" id="reserve" type="set"> + <query xmlns="http://jabber.org/protocol/muc#admin"> + <item nick="Romeo" affiliation="owner" jid="${Romeo's JID}"/> + </query> + </iq> + +Romeo receives: + <presence from="room@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item xmlns="http://jabber.org/protocol/muc#user" role="moderator" jid="${Romeo's full JID}" affiliation="owner"> + <actor xmlns="http://jabber.org/protocol/muc#user" nick="Romeo"/> + </item> + <status xmlns="http://jabber.org/protocol/muc#user" code="110"/> + </x> + </presence> + +Romeo receives: + <iq from="room@conference.localhost" id="reserve" type="result"/> + diff --git a/spec/scansion/muc_whois_anyone_member.scs b/spec/scansion/muc_whois_anyone_member.scs new file mode 100644 index 00000000..9a6f7e15 --- /dev/null +++ b/spec/scansion/muc_whois_anyone_member.scs @@ -0,0 +1,101 @@ +# MUC: Allow members to fetch the affiliation lists in open non-anonymous rooms + +[Client] Romeo + jid: romeo@localhost/MsliYo9C + password: password + +[Client] Juliet + jid: juliet@localhost/vJrUtY4Z + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to='issue1230@conference.localhost/romeo'> + <x xmlns='http://jabber.org/protocol/muc'/> + </presence> + +Romeo receives: + <presence from='issue1230@conference.localhost/romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='201'/> + <item jid="${Romeo's JID}" role='moderator' affiliation='owner'/> + <status code='110'/> + </x> + </presence> + +Romeo receives: + <message from='issue1230@conference.localhost' type='groupchat'> + <subject/> + </message> + +Romeo sends: + <iq id='lx3' type='set' to='issue1230@conference.localhost'> + <query xmlns='http://jabber.org/protocol/muc#owner'> + <x type='submit' xmlns='jabber:x:data'> + <field var='FORM_TYPE'> + <value>http://jabber.org/protocol/muc#roomconfig</value> + </field> + <field var='muc#roomconfig_whois'> + <value>anyone</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq from='issue1230@conference.localhost' type='result' id='lx3'/> + +Romeo receives: + <message from='issue1230@conference.localhost' type='groupchat'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='172'/> + </x> + </message> + +Juliet connects + +Juliet sends: + <presence to='issue1230@conference.localhost/juliet'> + <x xmlns='http://jabber.org/protocol/muc'/> + </presence> + +Juliet receives: + <presence from='issue1230@conference.localhost/romeo'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Romeo's JID}" role='moderator' affiliation='owner'/> + </x> + </presence> + +Juliet receives: + <presence from='issue1230@conference.localhost/juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='100'/> + <item jid="${Juliet's JID}" role='participant' affiliation='none'/> + <status code='110'/> + </x> + </presence> + +Juliet receives: + <message from='issue1230@conference.localhost' type='groupchat'> + <subject/> + </message> + +Juliet sends: + <iq id='lx2' type='get' to='issue1230@conference.localhost'> + <query xmlns='http://jabber.org/protocol/muc#admin'> + <item affiliation='member'/> + </query> + </iq> + +Juliet receives: + <iq from='issue1230@conference.localhost' type='result' id='lx2'> + <query xmlns='http://jabber.org/protocol/muc#admin'/> + </iq> + +Juliet disconnects + +Romeo disconnects + diff --git a/spec/scansion/pep_nickname.scs b/spec/scansion/pep_nickname.scs new file mode 100644 index 00000000..f958ec75 --- /dev/null +++ b/spec/scansion/pep_nickname.scs @@ -0,0 +1,72 @@ +# Publishing a nickname in PEP and receiving a notification + +[Client] Romeo + jid: romeo@localhost/nJi7BeTR + password: password + +----- + +Romeo connects + +Romeo sends: + <iq id="4" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="http://jabber.org/protocol/nick"> + <item id="current"> + <nickname xmlns="http://jabber.org/protocol/nick"/> + </item> + </publish> + </pubsub> + </iq> + +Romeo receives: + <iq id="4" to="romeo@localhost/nJi7BeTR" type="result"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="http://jabber.org/protocol/nick"> + <item id="current"/> + </publish> + </pubsub> + </iq> + +Romeo sends: + <presence> + <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://code.matthewwild.co.uk/clix/" ver="jC32N+FhQoLrZ7nNQtZK3aqR0Fk="/> + </presence> + +Romeo receives: + <iq id="disco" to="romeo@localhost/nJi7BeTR" from="romeo@localhost" type="get"> + <query xmlns="http://jabber.org/protocol/disco#info" node="http://code.matthewwild.co.uk/clix/#jC32N+FhQoLrZ7nNQtZK3aqR0Fk="/> + </iq> + +Romeo receives: + <presence from="romeo@localhost/nJi7BeTR"> + <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://code.matthewwild.co.uk/clix/" ver="jC32N+FhQoLrZ7nNQtZK3aqR0Fk="/> + </presence> + +Romeo sends: + <iq id="disco" type="result" to="romeo@localhost"> + <query xmlns="http://jabber.org/protocol/disco#info" node="http://code.matthewwild.co.uk/clix/#jC32N+FhQoLrZ7nNQtZK3aqR0Fk="> + <identity type="console" name="clix" category="client"/> + <feature var="http://jabber.org/protocol/disco#items"/> + <feature var="http://jabber.org/protocol/disco#info"/> + <feature var="http://jabber.org/protocol/caps"/> + <feature var="http://jabber.org/protocol/nick+notify"/> + </query> + </iq> + +Romeo receives: + <message type="headline" from="romeo@localhost" to="romeo@localhost/nJi7BeTR"> + <event xmlns="http://jabber.org/protocol/pubsub#event"> + <items node="http://jabber.org/protocol/nick"> + <item id="current"> + <nickname xmlns="http://jabber.org/protocol/nick"/> + </item> + </items> + </event> + </message> + +Romeo sends: + <presence type="unavailable"/> + +Romeo disconnects + diff --git a/spec/scansion/pep_publish_subscribe.scs b/spec/scansion/pep_publish_subscribe.scs new file mode 100644 index 00000000..e8080134 --- /dev/null +++ b/spec/scansion/pep_publish_subscribe.scs @@ -0,0 +1,210 @@ +# PEP publish, subscribe and publish-options + +[Client] Romeo + jid: pep-test-wjebo4kg@localhost + password: password + +[Client] Juliet + jid: pep-test-tqvqu_pv@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence> + <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/> + </presence> + +Romeo receives: + <iq type='get' id='disco' from="${Romeo's JID}"> + <query node='http://code.matthewwild.co.uk/verse/#PDH7CGVPRERS2WUqBD18PHGEzaY=' xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + +Romeo receives: + <presence from="${Romeo's full JID}"> + <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/> + </presence> + +Romeo sends: + <iq type='get' id='6'> + <query ver='' xmlns='jabber:iq:roster'/> + </iq> + +Romeo receives: + <iq type='result' id='6'> + <query ver='1' xmlns='jabber:iq:roster'/> + </iq> + +Juliet connects + +Juliet sends: + <presence> + <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/> + </presence> + +Juliet receives: + <iq type='get' id='disco' from="${Juliet's JID}"> + <query node='http://code.matthewwild.co.uk/verse/#PDH7CGVPRERS2WUqBD18PHGEzaY=' xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + +Juliet receives: + <presence from="${Juliet's full JID}"> + <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/> + </presence> + +Juliet sends: + <iq type='get' id='6'> + <query ver='' xmlns='jabber:iq:roster'/> + </iq> + +Juliet receives: + <iq type='result' id='6'> + <query ver='1' xmlns='jabber:iq:roster'/> + </iq> + +Romeo sends: + <iq type='result' id='disco' to='pep-test-wjebo4kg@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#PDH7CGVPRERS2WUqBD18PHGEzaY='><identity type='pc' name='Verse' category='client'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/caps'/></query></iq> + +Romeo sends: + <presence type='subscribe' to="${Juliet's JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='set' id='{scansion:any}'><query ver='1' xmlns='jabber:iq:roster'><item ask='subscribe' jid='pep-test-tqvqu_pv@localhost' subscription='none'/></query></iq> + +Romeo receives: + <presence type='unavailable' to='pep-test-wjebo4kg@localhost' from='pep-test-tqvqu_pv@localhost'/> + +Juliet receives: + <presence type='subscribe' from='pep-test-wjebo4kg@localhost' to='pep-test-tqvqu_pv@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Juliet sends: + <iq type='result' id='disco' to='pep-test-tqvqu_pv@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#PDH7CGVPRERS2WUqBD18PHGEzaY='><identity type='pc' name='Verse' category='client'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/caps'/></query></iq> + +Juliet sends: + <presence type='subscribe' to="${Romeo's JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Juliet receives: + <iq type='set' id='{scansion:any}'><query ver='2' xmlns='jabber:iq:roster'><item ask='subscribe' jid='pep-test-wjebo4kg@localhost' subscription='none'/></query></iq> + +Juliet receives: + <presence type='unavailable' to='pep-test-tqvqu_pv@localhost' from='pep-test-wjebo4kg@localhost'/> + +Romeo receives: + <presence type='subscribe' from='pep-test-tqvqu_pv@localhost' to='pep-test-wjebo4kg@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo sends: + <iq type='result' id='fixme'/> + +Romeo sends: + <presence type='subscribed' to='pep-test-tqvqu_pv@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='set' id='{scansion:any}'><query ver='3' xmlns='jabber:iq:roster'><item ask='subscribe' jid='pep-test-tqvqu_pv@localhost' subscription='from'/></query></iq> + +Juliet receives: + <presence type='subscribed' from='pep-test-wjebo4kg@localhost' to='pep-test-tqvqu_pv@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Juliet receives: + <iq type='set' id='{scansion:any}'><query ver='3' xmlns='jabber:iq:roster'><item jid='pep-test-wjebo4kg@localhost' subscription='to'/></query></iq> + +Juliet receives: + <presence to='pep-test-tqvqu_pv@localhost' from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/><delay xmlns='urn:xmpp:delay' stamp='{scansion:any}' from='localhost'/></presence> + +Juliet sends: + <presence type='subscribed' to='pep-test-wjebo4kg@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Juliet receives: + <iq type='set' id='{scansion:any}'><query ver='4' xmlns='jabber:iq:roster'><item jid='pep-test-wjebo4kg@localhost' subscription='both'/></query></iq> + +Juliet receives: + <presence to='pep-test-tqvqu_pv@localhost' from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/><delay xmlns='urn:xmpp:delay' stamp='{scansion:any}' from='localhost'/></presence> + +Romeo receives: + <presence type='subscribed' from='pep-test-tqvqu_pv@localhost' to='pep-test-wjebo4kg@localhost'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='set' id='{scansion:any}'><query ver='4' xmlns='jabber:iq:roster'><item jid='pep-test-tqvqu_pv@localhost' subscription='both'/></query></iq> + +Romeo receives: + <presence to='pep-test-wjebo4kg@localhost' from="${Juliet's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='PDH7CGVPRERS2WUqBD18PHGEzaY=' node='http://code.matthewwild.co.uk/verse/'/><delay xmlns='urn:xmpp:delay' stamp='{scansion:any}' from='localhost'/></presence> + +Juliet sends: + <iq type='result' id='fixme'/> + +Romeo sends: + <iq type='result' id='fixme'/> + +Romeo sends: + <iq type='result' id='fixme'/> + +Romeo sends: + <presence><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='m/sIsyfzKk8X1okZMtStR43nQQg=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='get' id='disco' from='pep-test-wjebo4kg@localhost'><query node='http://code.matthewwild.co.uk/verse/#m/sIsyfzKk8X1okZMtStR43nQQg=' xmlns='http://jabber.org/protocol/disco#info'/></iq> + +Romeo receives: + <presence from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='m/sIsyfzKk8X1okZMtStR43nQQg=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='get' id='disco' from='pep-test-tqvqu_pv@localhost'><query node='http://code.matthewwild.co.uk/verse/#m/sIsyfzKk8X1okZMtStR43nQQg=' xmlns='http://jabber.org/protocol/disco#info'/></iq> + +Juliet receives: + <presence from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='m/sIsyfzKk8X1okZMtStR43nQQg=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo sends: + <presence><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='IfQwbaaDB4LEP5tkGArEaB/3Y+s=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='get' id='disco' from='pep-test-wjebo4kg@localhost'><query node='http://code.matthewwild.co.uk/verse/#IfQwbaaDB4LEP5tkGArEaB/3Y+s=' xmlns='http://jabber.org/protocol/disco#info'/></iq> + +Romeo receives: + <presence from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='IfQwbaaDB4LEP5tkGArEaB/3Y+s=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Romeo receives: + <iq type='get' id='disco' from='pep-test-tqvqu_pv@localhost'><query node='http://code.matthewwild.co.uk/verse/#IfQwbaaDB4LEP5tkGArEaB/3Y+s=' xmlns='http://jabber.org/protocol/disco#info'/></iq> + +Romeo sends: + <iq type='result' id='disco' to='pep-test-wjebo4kg@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#m/sIsyfzKk8X1okZMtStR43nQQg='/></iq> + +Romeo sends: + <iq type='result' id='disco' to='pep-test-tqvqu_pv@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#m/sIsyfzKk8X1okZMtStR43nQQg='/></iq> + +Romeo sends: + <iq type='result' id='disco' to='pep-test-wjebo4kg@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#IfQwbaaDB4LEP5tkGArEaB/3Y+s='><identity type='pc' name='Verse' category='client'/><feature var='http://jabber.org/protocol/tune+notify'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/caps'/><feature var='http://jabber.org/protocol/mood+notify'/></query></iq> + +Juliet receives: + <presence from="${Romeo's full JID}"><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' ver='IfQwbaaDB4LEP5tkGArEaB/3Y+s=' node='http://code.matthewwild.co.uk/verse/'/></presence> + +Juliet sends: + <iq type='result' id='fixme'/> + +Juliet sends: + <iq type='set' id='7'><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='http://jabber.org/protocol/tune'><item id='current'><tune xmlns='http://jabber.org/protocol/tune'><title>Beautiful Cedars</title><artist>The Spinners</artist><source>Not Quite Folk</source><track>4</track></tune></item></publish></pubsub></iq> + +Juliet receives: + <iq type='result' id='7' ><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='http://jabber.org/protocol/tune'><item id='current'/></publish></pubsub></iq> + +Juliet sends: + <iq type='set' id='8'><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='http://jabber.org/protocol/mood'><item><mood xmlns='http://jabber.org/protocol/mood'><happy/></mood></item></publish><publish-options><x type='submit' xmlns='jabber:x:data'><field type='hidden' var='FORM_TYPE'><value>http://jabber.org/protocol/pubsub#publish-options</value></field><field var='pubsub#persist_items'><value>true</value></field><field var='pubsub#access_model'><value>whitelist</value></field></x></publish-options></pubsub></iq> + +Juliet receives: + <iq type='result' id='8'><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='http://jabber.org/protocol/mood'><item id='{scansion:any}'/></publish></pubsub></iq> + +Juliet sends: + <iq type='result' id='{scansion:any}'/> + +Romeo receives: + <message type='headline' from='pep-test-tqvqu_pv@localhost'><event xmlns='http://jabber.org/protocol/pubsub#event'><items node='http://jabber.org/protocol/tune'><item id='current'><tune xmlns='http://jabber.org/protocol/tune'><title>Beautiful Cedars</title><artist>The Spinners</artist><source>Not Quite Folk</source><track>4</track></tune></item></items></event></message> + +Romeo sends: + <iq type='result' id='disco' to='pep-test-tqvqu_pv@localhost'><query xmlns='http://jabber.org/protocol/disco#info' node='http://code.matthewwild.co.uk/verse/#IfQwbaaDB4LEP5tkGArEaB/3Y+s='><identity type='pc' name='Verse' category='client'/><feature var='http://jabber.org/protocol/tune+notify'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/caps'/><feature var='http://jabber.org/protocol/mood+notify'/></query></iq> + +Romeo receives: + <message type='headline' from='pep-test-tqvqu_pv@localhost'><event xmlns='http://jabber.org/protocol/pubsub#event'><items node='http://jabber.org/protocol/tune'><item id='current'><tune xmlns='http://jabber.org/protocol/tune'><title>Beautiful Cedars</title><artist>The Spinners</artist><source>Not Quite Folk</source><track>4</track></tune></item></items></event></message> + +Juliet disconnects + +Romeo disconnects diff --git a/spec/scansion/prosody.cfg.lua b/spec/scansion/prosody.cfg.lua new file mode 100644 index 00000000..f95ea31b --- /dev/null +++ b/spec/scansion/prosody.cfg.lua @@ -0,0 +1,83 @@ +--luacheck: ignore + +admins = { "admin@localhost" } + +use_libevent = true + +modules_enabled = { + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "carbons"; -- Keep multiple clients in sync + "pep"; -- Enables users to publish their mood, activity, playing music and more + "private"; -- Private XML storage (for room bookmarks, etc.) + "blocklist"; -- Allow users to block communications with other users + "vcard"; -- Allow users to set vCards + + -- Nice to have + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "register"; -- Allow users to register on this server using a client and change passwords + "mam"; -- Store messages in an archive and allow users to access it + + -- HTTP modules + --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"websocket"; -- XMPP over WebSockets + --"http_files"; -- Serve static files from a directory over HTTP + + -- Other specific functionality + --"limits"; -- Enable bandwidth limiting for XMPP connections + --"groups"; -- Shared roster support + --"server_contact_info"; -- Publish contact information for this service + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + --"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use + + -- Useful for testing + --"scansion_record"; -- Records things that happen in scansion test case format +} + +certificate = "certs" + +allow_registration = false + +c2s_require_encryption = false +allow_unencrypted_plain_auth = true + +authentication = "insecure" +insecure_open_authentication = "Yes please, I know what I'm doing!" + +storage = "memory" + +mam_smart_enable = true + +-- For the "sql" backend, you can uncomment *one* of the below to configure: +--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename. +--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } +--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } + + +-- Logging configuration +-- For advanced logging see https://prosody.im/doc/logging +log = "*console" + +daemonize = true +pidfile = "prosody.pid" + +VirtualHost "localhost" + +Component "conference.localhost" "muc" + storage = "memory" + +Component "pubsub.localhost" "pubsub" + storage = "memory" diff --git a/spec/scansion/pubsub_advanced.scs b/spec/scansion/pubsub_advanced.scs new file mode 100644 index 00000000..c873486e --- /dev/null +++ b/spec/scansion/pubsub_advanced.scs @@ -0,0 +1,167 @@ +# Pubsub: Node creation, publish, subscribe, affiliations and delete + +[Client] Balthasar + jid: admin@localhost + password: password + +[Client] Romeo + jid: romeo@localhost + password: password + +[Client] Juliet + jid: juliet@localhost + password: password + +--------- + +Romeo connects + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='create1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="error" id='create1'> + <error type="auth"> + <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + </error> + </iq> + +Balthasar connects + +Balthasar sends: + <iq type='set' to='pubsub.localhost' id='create2'> + <pubsub xmlns='http://jabber.org/protocol/pubsub'> + <create node='princely_musings'/> + </pubsub> + </iq> + +Balthasar receives: + <iq type="result" id='create2'/> + +Balthasar sends: + <iq type="set" to="pubsub.localhost" id='create3'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="princely_musings"/> + </pubsub> + </iq> + +Balthasar receives: + <iq type="error" id='create3'> + <error type="cancel"> + <conflict xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> + </error> + </iq> + +Juliet connects + +Juliet sends: + <iq type="set" to="pubsub.localhost" id='sub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <subscribe node="princely_musings" jid="${Romeo's full JID}"/> + </pubsub> + </iq> + +Juliet receives: + <iq type="error" id='sub1'/> + +Juliet sends: + <iq type="set" to="pubsub.localhost" id='sub2'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <subscribe node="princely_musings" jid="${Juliet's full JID}"/> + </pubsub> + </iq> + +Juliet receives: + <iq type="result" id='sub2'> + <pubsub xmlns='http://jabber.org/protocol/pubsub'> + <subscription jid="${Juliet's full JID}" node='princely_musings' subscription='subscribed'/> + </pubsub> + </iq> + +Balthasar sends: + <iq type="get" id='aff1' to='pubsub.localhost'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <affiliations node="princely_musings"/> + </pubsub> + </iq> + +Balthasar receives: + <iq type="result" id='aff1' from='pubsub.localhost'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <affiliations node="princely_musings"> + <affiliation affiliation='owner' jid='admin@localhost' xmlns='http://jabber.org/protocol/pubsub#owner'/> + </affiliations> + </pubsub> + </iq> + +Balthasar sends: + <iq type="set" id='aff2' to='pubsub.localhost'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <affiliations node="princely_musings"> + <affiliation affiliation='owner' jid='admin@localhost' xmlns='http://jabber.org/protocol/pubsub#owner'/> + <affiliation jid="${Romeo's JID}" affiliation="publisher"/> + </affiliations> + </pubsub> + </iq> + +Balthasar receives: + <iq type="result" id='aff2' from='pubsub.localhost'/> + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='pub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="princely_musings"> + <item id="current"> + <entry xmlns="http://www.w3.org/2005/Atom"> + <title>Soliloquy</title> + <summary>Lorem ipsum dolor sit amet</summary> + </entry> + </item> + </publish> + </pubsub> + </iq> + +Juliet receives: + <message type="headline" from="pubsub.localhost"> + <event xmlns="http://jabber.org/protocol/pubsub#event"> + <items node="princely_musings"> + <item id="current"> + <entry xmlns="http://www.w3.org/2005/Atom"> + <title>Soliloquy</title> + <summary>Lorem ipsum dolor sit amet</summary> + </entry> + </item> + </items> + </event> + </message> + +Romeo receives: + <iq type="result" id='pub1'/> + +Juliet sends: + <iq type="set" to="pubsub.localhost" id='unsub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <unsubscribe node="princely_musings" jid="${Juliet's full JID}"/> + </pubsub> + </iq> + +Juliet receives: + <iq type="result" id='unsub1'/> + +Balthasar sends: + <iq type="set" to="pubsub.localhost" id='del1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <delete node="princely_musings"/> + </pubsub> + </iq> + +Balthasar receives: + <iq type="result" from='pubsub.localhost' id='del1'/> + +Romeo disconnects + +// vim: syntax=xml: diff --git a/spec/scansion/pubsub_basic.scs b/spec/scansion/pubsub_basic.scs new file mode 100644 index 00000000..d983ff66 --- /dev/null +++ b/spec/scansion/pubsub_basic.scs @@ -0,0 +1,104 @@ +# Pubsub: Basic support + +[Client] Romeo + jid: admin@localhost + password: password + +// admin@localhost is assumed to have node creation privileges + +[Client] Juliet + jid: juliet@localhost + password: password + +--------- + +Romeo connects + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='create1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="result" id='create1'/> + +Juliet connects + +-- Juliet sends: +-- <iq type="set" to="pubsub.localhost"> +-- <pubsub xmlns="http://jabber.org/protocol/pubsub"> +-- <subscribe node="princely_musings" jid="${Romeo's full JID}"/> +-- </pubsub> +-- </iq> +-- +-- Juliet receives: +-- <iq type="error"/> + +Juliet sends: + <iq type="set" to="pubsub.localhost" id='sub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <subscribe node="princely_musings" jid="${Juliet's full JID}"/> + </pubsub> + </iq> + +Juliet receives: + <iq type="result" id='sub1'/> + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='pub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="princely_musings"> + <item id="current"> + <entry xmlns="http://www.w3.org/2005/Atom"> + <title>Soliloquy</title> + <summary>Lorem ipsum dolor sit amet</summary> + </entry> + </item> + </publish> + </pubsub> + </iq> + +Romeo receives: + <iq type="result" id='pub1'/> + +Juliet receives: + <message type="headline" from="pubsub.localhost"> + <event xmlns="http://jabber.org/protocol/pubsub#event"> + <items node="princely_musings"> + <item id="current"> + <entry xmlns="http://www.w3.org/2005/Atom"> + <title>Soliloquy</title> + <summary>Lorem ipsum dolor sit amet</summary> + </entry> + </item> + </items> + </event> + </message> + +Juliet sends: + <iq type="set" to="pubsub.localhost" id='unsub1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <unsubscribe node="princely_musings" jid="${Juliet's full JID}"/> + </pubsub> + </iq> + +Juliet receives: + <iq type="result" id='unsub1'/> + +Juliet disconnects + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='del1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <delete node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="result" id='del1'/> + +Romeo disconnects + +// vim: syntax=xml: diff --git a/spec/scansion/pubsub_config.scs b/spec/scansion/pubsub_config.scs new file mode 100644 index 00000000..d979aca5 --- /dev/null +++ b/spec/scansion/pubsub_config.scs @@ -0,0 +1,205 @@ +# pubsub#title as name attribute in disco#items +# Issue 1226 + +[Client] Romeo + password: password + jid: jqpcrbq@localhost + +----- + +Romeo connects + +Romeo sends: + <iq id="67eb1f47-1e69-4cb3-91e2-4d5943e72d4c" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="http://jabber.org/protocol/tune"> + <item id="current"> + <tune xmlns="http://jabber.org/protocol/tune"/> + </item> + </publish> + </pubsub> + </iq> + +Romeo receives: + <iq id="67eb1f47-1e69-4cb3-91e2-4d5943e72d4c" type="result"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="http://jabber.org/protocol/tune"> + <item id="current"/> + </publish> + </pubsub> + </iq> + +Romeo sends: + <iq id="52d74a36-afb0-4028-87ed-b25b988b049e" type="get"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <configure node="http://jabber.org/protocol/tune"/> + </pubsub> + </iq> + +Romeo receives: + <iq id="52d74a36-afb0-4028-87ed-b25b988b049e" type="result"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <configure node="http://jabber.org/protocol/tune"> + <x xmlns="jabber:x:data" type="form"> + <field var="FORM_TYPE" type="hidden"> + <value>http://jabber.org/protocol/pubsub#node_config</value> + </field> + <field var="pubsub#title" label="Title" type="text-single"/> + <field var="pubsub#description" label="Description" type="text-single"/> + <field var="pubsub#type" label="The type of node data, usually specified by the namespace of the payload (if any)" type="text-single"/> + <field var="pubsub#max_items" label="Max # of items to persist" type="text-single"> + <validate xmlns="http://jabber.org/protocol/xdata-validate" datatype="xs:integer"/> + <value>1</value> + </field> + <field var="pubsub#persist_items" label="Persist items to storage" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#access_model" label="Specify the subscriber model" type="list-single"> + <option label="authorize"> + <value>authorize</value> + </option> + <option label="open"> + <value>open</value> + </option> + <option label="presence"> + <value>presence</value> + </option> + <option label="roster"> + <value>roster</value> + </option> + <option label="whitelist"> + <value>whitelist</value> + </option> + <value>presence</value> + </field> + <field var="pubsub#publish_model" label="Specify the publisher model" type="list-single"> + <option label="publishers"> + <value>publishers</value> + </option> + <option label="subscribers"> + <value>subscribers</value> + </option> + <option label="open"> + <value>open</value> + </option> + <value>publishers</value> + </field> + <field var="pubsub#deliver_notifications" label="Whether to deliver event notifications" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#deliver_payloads" label="Whether to deliver payloads with event notifications" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#notification_type" label="Specify the delivery style for notifications" type="list-single"> + <option label="Messages of type normal"> + <value>normal</value> + </option> + <option label="Messages of type headline"> + <value>headline</value> + </option> + <value>headline</value> + </field> + <field var="pubsub#notify_delete" label="Whether to notify subscribers when the node is deleted" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#notify_retract" label="Whether to notify subscribers when items are removed from the node" type="boolean"> + <value>1</value> + </field> + </x> + </configure> + </pubsub> + </iq> + +Romeo sends: + <iq id="a73aac09-74be-4ee2-97e5-571bbdbcd956" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <configure node="http://jabber.org/protocol/tune"> + <x xmlns="jabber:x:data" type="submit"> + <field var="FORM_TYPE" type="hidden"> + <value>http://jabber.org/protocol/pubsub#node_config</value> + </field> + <field var="pubsub#title" type="text-single" label="Title"> + <value>Nice tunes</value> + </field> + <field var="pubsub#description" type="text-single" label="Description"/> + <field var="pubsub#type" type="text-single" label="The type of node data, usually specified by the namespace of the payload (if any)"/> + <field var="pubsub#max_items" type="text-single" label="Max # of items to persist"> + <validate xmlns="http://jabber.org/protocol/xdata-validate" datatype="xs:integer"/> + <value>1</value> + </field> + <field var="pubsub#persist_items" type="boolean" label="Persist items to storage"> + <value>1</value> + </field> + <field var="pubsub#access_model" type="list-single" label="Specify the subscriber model"> + <option label="authorize"> + <value>authorize</value> + </option> + <option label="open"> + <value>open</value> + </option> + <option label="presence"> + <value>presence</value> + </option> + <option label="roster"> + <value>roster</value> + </option> + <option label="whitelist"> + <value>whitelist</value> + </option> + <value>presence</value> + </field> + <field var="pubsub#publish_model" type="list-single" label="Specify the publisher model"> + <option label="publishers"> + <value>publishers</value> + </option> + <option label="subscribers"> + <value>subscribers</value> + </option> + <option label="open"> + <value>open</value> + </option> + <value>publishers</value> + </field> + <field var="pubsub#deliver_notifications" type="boolean" label="Whether to deliver event notifications"> + <value>1</value> + </field> + <field var="pubsub#deliver_payloads" type="boolean" label="Whether to deliver payloads with event notifications"> + <value>1</value> + </field> + <field var="pubsub#notification_type" type="list-single" label="Specify the delivery style for notifications"> + <option label="Messages of type normal"> + <value>normal</value> + </option> + <option label="Messages of type headline"> + <value>headline</value> + </option> + <value>headline</value> + </field> + <field var="pubsub#notify_delete" type="boolean" label="Whether to notify subscribers when the node is deleted"> + <value>1</value> + </field> + <field var="pubsub#notify_retract" type="boolean" label="Whether to notify subscribers when items are removed from the node"> + <value>1</value> + </field> + </x> + </configure> + </pubsub> + </iq> + +Romeo receives: + <iq id="a73aac09-74be-4ee2-97e5-571bbdbcd956" type="result"/> + +Romeo sends: + <iq id="ab0e92d2-c06b-4987-9d45-f9f9e7721709" type="get"> + <query xmlns="http://jabber.org/protocol/disco#items"/> + </iq> + +Romeo receives: + <iq id="ab0e92d2-c06b-4987-9d45-f9f9e7721709" type="result"> + <query xmlns="http://jabber.org/protocol/disco#items"> + <item name="Nice tunes" node="http://jabber.org/protocol/tune" jid="${Romeo's JID}"/> + </query> + </iq> + +Romeo disconnects + diff --git a/spec/scansion/pubsub_createdelete.scs b/spec/scansion/pubsub_createdelete.scs new file mode 100644 index 00000000..a44695e7 --- /dev/null +++ b/spec/scansion/pubsub_createdelete.scs @@ -0,0 +1,63 @@ +# Pubsub: Create and delete + +[Client] Romeo + jid: admin@localhost + password: password + +// admin@localhost is assumed to have node creation privileges + +--------- + +Romeo connects + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='create1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="result" id='create1'/> + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='create2'> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="error" id='create2'> + <error type="cancel"> + <conflict xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> + </error> + </iq> + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='delete1'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <delete node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="result" id='delete1'/> + +Romeo sends: + <iq type="set" to="pubsub.localhost" id='delete2'> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <delete node="princely_musings"/> + </pubsub> + </iq> + +Romeo receives: + <iq type="error" id='delete2'> + <error type="cancel"> + <item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> + </error> + </iq> + +Romeo disconnects + +// vim: syntax=xml: diff --git a/spec/scansion/vcard_temp.scs b/spec/scansion/vcard_temp.scs new file mode 100644 index 00000000..38c6f755 --- /dev/null +++ b/spec/scansion/vcard_temp.scs @@ -0,0 +1,80 @@ +# XEP-0054 vCard-temp writable and readable by anyone +# mod_scansion_record on host 'localhost' recording started 2018-10-20T15:00:12Z + +[Client] Romeo + jid: romeo@localhost + password: password + +[Client] Juliet + jid: juliet@localhost + password: password + +----- + +Romeo connects + +# Romeo sets his vCard +# FN and N are required by the schema and mod_vcard_legacy will always inject them +Romeo sends: + <iq id="lx3" type="set"> + <vCard xmlns="vcard-temp"> + <FN>Romeo Montague</FN> + <N> + <FAMILY>Montague</FAMILY> + <GIVEN>Romeo</GIVEN> + <MIDDLE/> + <PREFIX/> + <SUFFIX/> + </N> + </vCard> + </iq> + +Romeo receives: + <iq type="result" id="lx3" to="${Romeo's full JID}"/> + +Romeo sends: + <iq id="lx4" type="get"> + <vCard xmlns="vcard-temp"/> + </iq> + +Romeo receives: + <iq type="result" id="lx4" to="${Romeo's full JID}"> + <vCard xmlns="vcard-temp"> + <FN>Romeo Montague</FN> + <N> + <FAMILY>Montague</FAMILY> + <GIVEN>Romeo</GIVEN> + <MIDDLE/> + <PREFIX/> + <SUFFIX/> + </N> + </vCard> + </iq> + +Romeo disconnects + +Juliet connects + +Juliet sends: + <iq type="get" id="lx3" to="romeo@localhost"> + <vCard xmlns="vcard-temp"/> + </iq> + +# Juliet can see Romeo's vCard since it's public +Juliet receives: + <iq type="result" from="romeo@localhost" id="lx3" to="${Juliet's full JID}"> + <vCard xmlns="vcard-temp"> + <FN>Romeo Montague</FN> + <N> + <FAMILY>Montague</FAMILY> + <GIVEN>Romeo</GIVEN> + <MIDDLE/> + <PREFIX/> + <SUFFIX/> + </N> + </vCard> + </iq> + +Juliet disconnects + +# recording ended on 2018-10-20T15:02:14Z |