diff options
Diffstat (limited to 'spec/scansion')
-rw-r--r-- | spec/scansion/basic_message.scs | 6 | ||||
-rw-r--r-- | spec/scansion/blocking.scs | 8 | ||||
-rw-r--r-- | spec/scansion/keep_full_sub_req.scs | 58 | ||||
-rw-r--r-- | spec/scansion/lastactivity.scs | 45 | ||||
-rw-r--r-- | spec/scansion/muc_create_destroy.scs | 317 | ||||
-rw-r--r-- | spec/scansion/muc_members_only_change.scs | 2 | ||||
-rw-r--r-- | spec/scansion/muc_nickname_change.scs | 127 | ||||
-rw-r--r-- | spec/scansion/muc_password.scs | 2 | ||||
-rw-r--r-- | spec/scansion/muc_register.scs | 14 | ||||
-rw-r--r-- | spec/scansion/muc_show_offline.scs | 544 | ||||
-rw-r--r-- | spec/scansion/muc_subject_issue_667.scs | 129 | ||||
-rw-r--r-- | spec/scansion/presence_preapproval.scs | 74 | ||||
-rw-r--r-- | spec/scansion/prosody.cfg.lua | 43 | ||||
-rw-r--r-- | spec/scansion/pubsub_basic.scs | 2 | ||||
-rw-r--r-- | spec/scansion/pubsub_preconditions.scs | 234 | ||||
-rw-r--r-- | spec/scansion/server_contact_info.scs | 53 | ||||
-rw-r--r-- | spec/scansion/uptime.scs | 21 | ||||
-rw-r--r-- | spec/scansion/version.scs | 27 |
18 files changed, 1685 insertions, 21 deletions
diff --git a/spec/scansion/basic_message.scs b/spec/scansion/basic_message.scs index fb21c465..1258dbf5 100644 --- a/spec/scansion/basic_message.scs +++ b/spec/scansion/basic_message.scs @@ -79,7 +79,7 @@ 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> + </message> # Romeo sends another bare-JID message, it should be delivered # instantly to Juliet's phone @@ -92,7 +92,7 @@ Romeo sends: Juliet's phone receives: <message from="${Romeo's full JID}" type="chat"> <body>Oh, hi!</body> - </message> + </message> # Juliet's laptop goes online, but with a negative priority @@ -122,7 +122,7 @@ Romeo sends: Juliet's phone receives: <message from="${Romeo's full JID}" type="chat"> <body>How are you?</body> - </message> + </message> # Romeo sends direct to Juliet's full JID, and she should receive it diff --git a/spec/scansion/blocking.scs b/spec/scansion/blocking.scs index 6a9f199e..5bb5a41b 100644 --- a/spec/scansion/blocking.scs +++ b/spec/scansion/blocking.scs @@ -145,16 +145,16 @@ Juliet receives: </message> # Bye -Juliet disconnects - Juliet sends: <presence type="unavailable"/> +Juliet disconnects + Romeo receives: <presence from="${Juliet's full JID}" to="${Romeo's JID}" type="unavailable"/> -Romeo disconnects - Romeo sends: <presence type="unavailable"/> +Romeo disconnects + diff --git a/spec/scansion/keep_full_sub_req.scs b/spec/scansion/keep_full_sub_req.scs new file mode 100644 index 00000000..41ffec0d --- /dev/null +++ b/spec/scansion/keep_full_sub_req.scs @@ -0,0 +1,58 @@ +# server MUST keep a record of the complete presence stanza comprising the subscription request (#689) + +[Client] Alice + jid: pars-a@localhost + password: password + +[Client] Bob + jid: pars-b@localhost + password: password + +[Client] Bob's phone + jid: pars-b@localhost/phone + password: password + +--------- + +Alice connects + +Alice sends: + <presence to="${Bob's JID}" type="subscribe"> + <preauth xmlns="urn:xmpp:pars:0" token="1tMFqYDdKhfe2pwp" /> + </presence> + +Alice disconnects + +Bob connects + +Bob sends: + <presence/> + +Bob receives: + <presence from="${Bob's full JID}"/> + +Bob receives: + <presence from="${Alice's JID}" type="subscribe"> + <preauth xmlns="urn:xmpp:pars:0" token="1tMFqYDdKhfe2pwp" /> + </presence> + +Bob disconnects + +# Works if they reconnect too + +Bob's phone connects + +Bob's phone sends: + <presence/> + +Bob's phone receives: + <presence from="${Bob's phone's full JID}"/> + + +Bob's phone receives: + <presence from="${Alice's JID}" type="subscribe"> + <preauth xmlns="urn:xmpp:pars:0" token="1tMFqYDdKhfe2pwp" /> + </presence> + +Bob's phone disconnects + diff --git a/spec/scansion/lastactivity.scs b/spec/scansion/lastactivity.scs new file mode 100644 index 00000000..44f4e516 --- /dev/null +++ b/spec/scansion/lastactivity.scs @@ -0,0 +1,45 @@ +# XEP-0012: Last Activity / mod_lastactivity + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <presence> + <status>Hello</status> + </presence> + +Romeo receives: + <presence from="${Romeo's full JID}"> + <status>Hello</status> + </presence> + +Romeo sends: + <presence type="unavailable"> + <status>Goodbye</status> + </presence> + +Romeo receives: + <presence from="${Romeo's full JID}" type="unavailable"> + <status>Goodbye</status> + </presence> + +# mod_lastlog saves time + status message from the last unavailable presence + +Romeo sends: + <iq id='a' type='get'> + <query xmlns='jabber:iq:last'/> + </iq> + +Romeo receives: + <iq type='result' id='a'> + <query xmlns='jabber:iq:last' seconds='0'>Goodbye</query> + </iq> + +Romeo disconnects + +# recording ended on 2020-04-20T14:39:47Z diff --git a/spec/scansion/muc_create_destroy.scs b/spec/scansion/muc_create_destroy.scs new file mode 100644 index 00000000..195200bb --- /dev/null +++ b/spec/scansion/muc_create_destroy.scs @@ -0,0 +1,317 @@ +# MUC creation, basic messages and destruction + +[Client] Romeo + jid: romeo@localhost/mK0dD6Ha + password: password + +[Client] Juliet + jid: juliet@localhost/lVwkim_k + password: password + +[Client] Admin + jid: admin@localhost/DfNgg9VE + password: password + +----- + +Romeo connects + +Romeo sends: + <presence to="garden@conference.localhost/romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from="garden@conference.localhost/romeo"> + <x xmlns="vcard-temp:x:update"> + <photo/> + </x> + <x xmlns="http://jabber.org/protocol/muc#user"> + <status code="201"/> + <item affiliation="owner" jid="${Romeo's full JID}" role="moderator"/> + <status code="110"/> + </x> + </presence> + +Romeo receives: + <message from="garden@conference.localhost" type="groupchat"> + <subject/> + </message> + +Romeo sends: + <iq to="garden@conference.localhost" id="lx3" type="set"> + <query xmlns="http://jabber.org/protocol/muc#owner"> + <x type="submit" xmlns="jabber:x:data"/> + </query> + </iq> + +Romeo receives: + <iq id="lx3" type="result" from="garden@conference.localhost"/> + +Juliet connects + +Romeo sends: + <message to="garden@conference.localhost" type="groupchat" id="rm1"> + <body>Where are thou my Juliet?</body> + </message> + +Romeo receives: + <message type="groupchat" from="garden@conference.localhost/romeo" id="rm1"> + <body>Where are thou my Juliet?</body> + </message> + +Juliet sends: + <presence to="garden@conference.localhost/juliet"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Juliet receives: + <presence from="garden@conference.localhost/romeo"> + <x xmlns="vcard-temp:x:update"> + <photo/> + </x> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item affiliation="owner" role="moderator"/> + </x> + </presence> + +Juliet receives: + <presence from="garden@conference.localhost/juliet"> + <x xmlns="vcard-temp:x:update"> + <photo/> + </x> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item affiliation="none" jid="${Juliet's full JID}" role="participant"/> + <status code="110"/> + </x> + </presence> + +Juliet receives: + <message from="garden@conference.localhost/romeo" id="rm1" type="groupchat"> + <body>Where are thou my Juliet?</body> + <delay stamp="{scansion:any}" xmlns="urn:xmpp:delay" from="garden@conference.localhost"/> + <x stamp="{scansion:any}" xmlns="jabber:x:delay" from="garden@conference.localhost"/> + </message> + +Juliet receives: + <message from="garden@conference.localhost" type="groupchat"> + <subject/> + </message> + +Romeo receives: + <presence from="garden@conference.localhost/juliet"> + <x xmlns="vcard-temp:x:update"> + <photo/> + </x> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item affiliation="none" jid="${Juliet's full JID}" role="participant"/> + </x> + </presence> + +Juliet sends: + <message to="garden@conference.localhost" type="groupchat" id="jm1"> + <body>/me jumps out from behind a tree</body> + </message> + +Romeo receives: + <message type="groupchat" id="jm1" from="garden@conference.localhost/juliet"> + <body>/me jumps out from behind a tree</body> + </message> + +Juliet receives: + <message type="groupchat" id="jm1" from="garden@conference.localhost/juliet"> + <body>/me jumps out from behind a tree</body> + </message> + +Juliet sends: + <message to="garden@conference.localhost" type="groupchat" id="jm2"> + <body>Here I am!</body> + </message> + +Romeo receives: + <message type="groupchat" id="jm2" from="garden@conference.localhost/juliet"> + <body>Here I am!</body> + </message> + +Juliet receives: + <message type="groupchat" id="jm2" from="garden@conference.localhost/juliet"> + <body>Here I am!</body> + </message> + +Romeo sends: + <message to="garden@conference.localhost" type="groupchat" id="rm2"> + <body>What is this place?</body> + </message> + +Romeo receives: + <message type="groupchat" id="rm2" from="garden@conference.localhost/romeo"> + <body>What is this place?</body> + </message> + +Juliet receives: + <message type="groupchat" id="rm2" from="garden@conference.localhost/romeo"> + <body>What is this place?</body> + </message> + +Juliet sends: + <message to="garden@conference.localhost" type="groupchat" id="jm3"> + <body>I think we're in a script!</body> + </message> + +Romeo receives: + <message type="groupchat" id="jm3" from="garden@conference.localhost/juliet"> + <body>I think we're in a script!</body> + </message> + +Juliet receives: + <message type="groupchat" id="jm3" from="garden@conference.localhost/juliet"> + <body>I think we're in a script!</body> + </message> + +Romeo sends: + <message to="garden@conference.localhost" type="groupchat" id="rm3"> + <body>Oh no! Does that mean our love is not real?!</body> + </message> + +Romeo receives: + <message type="groupchat" id="rm3" from="garden@conference.localhost/romeo"> + <body>Oh no! Does that mean our love is not real?!</body> + </message> + +Juliet receives: + <message type="groupchat" id="rm3" from="garden@conference.localhost/romeo"> + <body>Oh no! Does that mean our love is not real?!</body> + </message> + +Juliet sends: + <message to="garden@conference.localhost" type="groupchat" id="jm4"> + <body>I refuse to accept this! Let's burn this place to the ground!</body> + </message> + +Romeo receives: + <message type="groupchat" id="jm4" from="garden@conference.localhost/juliet"> + <body>I refuse to accept this! Let's burn this place to the ground!</body> + </message> + +Juliet receives: + <message type="groupchat" id="jm4" from="garden@conference.localhost/juliet"> + <body>I refuse to accept this! Let's burn this place to the ground!</body> + </message> + +Romeo sends: + <message to="garden@conference.localhost" type="groupchat" id="rm4"> + <body>Yes!</body> + </message> + +Romeo receives: + <message type="groupchat" id="rm4" from="garden@conference.localhost/romeo"> + <body>Yes!</body> + </message> + +Juliet receives: + <message type="groupchat" id="rm4" from="garden@conference.localhost/romeo"> + <body>Yes!</body> + </message> + +Romeo sends: + <iq to="garden@conference.localhost" id="lx4" type="set"> + <query xmlns="http://jabber.org/protocol/muc#owner"> + <destroy> + <reason>We refuse to live in this fantasy!</reason> + </destroy> + </query> + </iq> + +Juliet receives: + <presence from="garden@conference.localhost/juliet" type="unavailable"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <destroy> + <reason>We refuse to live in this fantasy!</reason> + </destroy> + <item affiliation="none" jid="${Juliet's full JID}" role="none"/> + <status code="110"/> + </x> + </presence> + +Romeo receives: + <presence from="garden@conference.localhost/romeo" type="unavailable"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <destroy> + <reason>We refuse to live in this fantasy!</reason> + </destroy> + <item affiliation="owner" jid="${Romeo's full JID}" role="none"/> + <status code="110"/> + </x> + </presence> + +Romeo receives: + <iq id="lx4" type="result" from="garden@conference.localhost"/> + +Juliet disconnects + +Romeo sends: + <presence to="elsewhere@conference.localhost/romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from="elsewhere@conference.localhost/romeo"> + <x xmlns="vcard-temp:x:update"> + <photo/> + </x> + <x xmlns="http://jabber.org/protocol/muc#user"> + <status code="201"/> + <item affiliation="owner" jid="${Romeo's full JID}" role="moderator"/> + <status code="110"/> + </x> + </presence> + +Romeo receives: + <message from="elsewhere@conference.localhost" type="groupchat"> + <subject/> + </message> + +Romeo sends: + <iq to="elsewhere@conference.localhost" id="lx5" type="set"> + <query xmlns="http://jabber.org/protocol/muc#owner"> + <x type="submit" xmlns="jabber:x:data"/> + </query> + </iq> + +Romeo receives: + <iq id="lx5" type="result" from="elsewhere@conference.localhost"/> + +Admin connects + +Admin sends: + <iq id="destroy" type="set" to="conference.localhost"> + <command xmlns="http://jabber.org/protocol/commands" node="http://prosody.im/protocol/muc#destroy"> + <x xmlns="jabber:x:data"> + <field var="rooms"> + <value>elsewhere@conference.localhost</value> + </field> + </x> + </command> + </iq> + +Romeo receives: + <presence from="elsewhere@conference.localhost/romeo" type="unavailable"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <destroy/> + <item affiliation="owner" jid="${Romeo's full JID}" role="none"/> + <status code="110"/> + </x> + </presence> + +Romeo disconnects + +Admin receives: + <iq id="destroy" type="result" from="conference.localhost"> + <command xmlns="http://jabber.org/protocol/commands" node="http://prosody.im/protocol/muc#destroy" status="completed" sessionid="{scansion:any}"> + <note type="info">The following rooms were destroyed: elsewhere@conference.localhost</note> + </command> + </iq> + +Admin disconnects + +# recording ended on 2019-08-31T13:45:32Z diff --git a/spec/scansion/muc_members_only_change.scs b/spec/scansion/muc_members_only_change.scs index dc40b5a0..a708dbfb 100644 --- a/spec/scansion/muc_members_only_change.scs +++ b/spec/scansion/muc_members_only_change.scs @@ -94,7 +94,7 @@ Romeo sends: <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'> diff --git a/spec/scansion/muc_nickname_change.scs b/spec/scansion/muc_nickname_change.scs new file mode 100644 index 00000000..73f81203 --- /dev/null +++ b/spec/scansion/muc_nickname_change.scs @@ -0,0 +1,127 @@ +# MUC: Change nickname +# Make sure a role is not reset, see #1466 + +[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> + +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_moderatedroom'> + <value>1</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"/> + +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'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='owner'/> + </x> + </presence> + +Juliet receives: + <presence from='room@conference.localhost/Juliet'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's full JID}" affiliation='none' role='visitor'/> + <status code='110'/> + </x> + </presence> + + +Juliet 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'> + <item affiliation="none" role="visitor" jid="${Juliet's full JID}"/> + </x> + </presence> + +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_moderatedroom'> + <value>0</value> + </field> + </x> + </query> + </iq> + +Romeo receives: + <iq id="config1" from="room@conference.localhost" type="result"/> + +Juliet receives: + <message type='groupchat' from='room@conference.localhost'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status xmlns='http://jabber.org/protocol/muc#user' code='104'/> + </x> + </message> + +Juliet sends: + <presence to="room@conference.localhost/Juliet2"> + </presence> + +Juliet receives: + <presence from='room@conference.localhost/Juliet' type='unavailable'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <status code='303'/> + <item nick='Juliet2' jid="${Juliet's full JID}" affiliation='none' role='visitor'/> + <status code='110'/> + </x> + </presence> + +Juliet receives: + <presence from='room@conference.localhost/Juliet2'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item jid="${Juliet's full JID}" affiliation='none' role='visitor'/> + <status code='110'/> + </x> + </presence> + diff --git a/spec/scansion/muc_password.scs b/spec/scansion/muc_password.scs index 82611183..63c821e0 100644 --- a/spec/scansion/muc_password.scs +++ b/spec/scansion/muc_password.scs @@ -58,7 +58,7 @@ Juliet sends: Juliet receives: <presence from="room@conference.localhost/Juliet" type="error"> - <error type="auth" code="401"> + <error type="auth" code="401" by="room@conference.localhost"> <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence> diff --git a/spec/scansion/muc_register.scs b/spec/scansion/muc_register.scs index a7e57177..9fcce688 100644 --- a/spec/scansion/muc_register.scs +++ b/spec/scansion/muc_register.scs @@ -100,7 +100,9 @@ Juliet receives: <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'/> + <field type='text-single' label='Nickname' var='muc#register_roomnick'> + <required/> + </field> </x> </query> </iq> @@ -175,7 +177,7 @@ Rosaline sends: Rosaline receives: <presence type='error' from='room@conference.localhost/Juliet'> - <error type='cancel'> + <error type='cancel' by='room@conference.localhost'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> <x xmlns='http://jabber.org/protocol/muc'/> @@ -286,7 +288,7 @@ Rosaline sends: Rosaline receives: <presence type='error' from='room@conference.localhost/Juliet'> - <error type='cancel'> + <error type='cancel' by='room@conference.localhost'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> <x xmlns='http://jabber.org/protocol/muc'/> @@ -326,7 +328,7 @@ Romeo receives: </iq> # Romeo updates his own registration - + Romeo sends: <iq id='jw81b36f' to='room@conference.localhost' type='get'> <query xmlns='jabber:iq:register'/> @@ -339,7 +341,9 @@ Romeo receives: <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'/> + <field type='text-single' label='Nickname' var='muc#register_roomnick'> + <required/> + </field> </x> </query> </iq> diff --git a/spec/scansion/muc_show_offline.scs b/spec/scansion/muc_show_offline.scs new file mode 100644 index 00000000..57b75ec7 --- /dev/null +++ b/spec/scansion/muc_show_offline.scs @@ -0,0 +1,544 @@ +# MUC: Room registration and presence broadcast of unavailable members + +[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> + <field var='muc#roomconfig_presencebroadcast'> + <value>none</value> + <value>participant</value> + <value>moderator</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'> + <required/> + </field> + </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' by='room@conference.localhost'> + <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}" affiliation='none' /> + </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' by='room@conference.localhost'> + <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'> + <required/> + </field> + </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/Juliet' type='unavailable'> + <x xmlns='http://jabber.org/protocol/muc#user'> + <item affiliation='member' role='none' nick='Juliet' xmlns='http://jabber.org/protocol/muc#user'/> + </x> + </presence> + +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_subject_issue_667.scs b/spec/scansion/muc_subject_issue_667.scs new file mode 100644 index 00000000..74980073 --- /dev/null +++ b/spec/scansion/muc_subject_issue_667.scs @@ -0,0 +1,129 @@ +# #667 MUC message with subject and body SHALL NOT be interpreted as a subject change + +[Client] Romeo + password: password + jid: romeo@localhost + +----- + +Romeo connects + +# and creates a room +Romeo sends: + <presence to="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +Romeo receives: + <presence from="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <status code="201"/> + <item affiliation="owner" role="moderator" jid="${Romeo's full JID}"/> + <status code="110"/> + </x> + </presence> + +# the default (empty) subject +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost"> + <subject/> + </message> + +# this should be treated as a normal message +Romeo sends: + <message to="issue667@conference.localhost" type="groupchat"> + <subject>Greetings</subject> + <body>Hello everyone</body> + </message> + +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <subject>Greetings</subject> + <body>Hello everyone</body> + </message> + +# Resync +Romeo sends: + <presence to="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +# Presences +Romeo receives: + <presence from="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item affiliation="owner" role="moderator" jid="${Romeo's full JID}"/> + <status code="110"/> + </x> + </presence> + +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <subject>Greetings</subject> + <body>Hello everyone</body> + </message> + +# the still empty subject +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost"> + <subject/> + </message> + +# this is a subject change +Romeo sends: + <message to="issue667@conference.localhost" type="groupchat"> + <subject>Something to talk about</subject> + </message> + +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <subject>Something to talk about</subject> + </message> + +# a message without <subject> +Romeo sends: + <message to="issue667@conference.localhost" type="groupchat"> + <body>Lorem ipsum dolor sit amet</body> + </message> + +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <body>Lorem ipsum dolor sit amet</body> + </message> + +# Resync +Romeo sends: + <presence to="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc"/> + </presence> + +# Presences +Romeo receives: + <presence from="issue667@conference.localhost/Romeo"> + <x xmlns="http://jabber.org/protocol/muc#user"> + <item affiliation="owner" role="moderator" jid="${Romeo's full JID}"/> + <status code="110"/> + </x> + </presence> + +# History +# These have delay tags but we ignore those for now +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <subject>Greetings</subject> + <body>Hello everyone</body> + </message> + +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <body>Lorem ipsum dolor sit amet</body> + </message> + +# Finally, the topic +Romeo receives: + <message type="groupchat" from="issue667@conference.localhost/Romeo"> + <subject>Something to talk about</subject> + </message> + +Romeo disconnects + diff --git a/spec/scansion/presence_preapproval.scs b/spec/scansion/presence_preapproval.scs new file mode 100644 index 00000000..e34ac7cf --- /dev/null +++ b/spec/scansion/presence_preapproval.scs @@ -0,0 +1,74 @@ +# server supports contact subscription pre-approval (RFC 6121 3.4) + +[Client] Alice + jid: preappove-a@localhost + password: password + +[Client] Bob + jid: preapprove-b@localhost + password: password + +--------- + +Alice connects + +Alice sends: + <presence/> + +Alice receives: + <presence/> + +Alice sends: + <presence to="${Bob's JID}" type="subscribed"/> + +Bob connects + +Bob sends: + <iq type="get" id="roster1"> + <query xmlns="jabber:iq:roster"/> + </iq> + +Bob receives: + <iq type="result" id="roster1"> + <query xmlns="jabber:iq:roster" ver="{scansion:any}"> + </query> + </iq> + +Bob sends: + <presence/> + +Bob receives: + <presence from="${Bob's full JID}"/> + +Bob sends: + <presence to="${Alice's JID}" type="subscribe" /> + +Bob receives: + <iq type='set' id='{scansion:any}'> + <query ver='1' xmlns='jabber:iq:roster'> + <item jid="${Alice's JID}" subscription='none' ask='subscribe' /> + </query> + </iq> + + + +Bob receives: + <presence from="${Alice's JID}" type="subscribed" /> + +Bob disconnects + +Alice sends: + <iq type="get" id="roster1"> + <query xmlns="jabber:iq:roster"/> + </iq> + +Alice receives: + <iq type="result" id="roster1"> + <query xmlns="jabber:iq:roster" ver="{scansion:any}"> + <item jid="${Bob's JID}" subscription="from" /> + </query> + </iq> + +Alice disconnects + +Bob disconnects diff --git a/spec/scansion/prosody.cfg.lua b/spec/scansion/prosody.cfg.lua index f95ea31b..4cf03de8 100644 --- a/spec/scansion/prosody.cfg.lua +++ b/spec/scansion/prosody.cfg.lua @@ -1,5 +1,16 @@ --luacheck: ignore +-- Mock time functions to simplify tests +function _G.os.time() + return 1219439344; +end +package.preload["util.time"] = function () + return { + now = function () return 1219439344.1; end; + monotonic = function () return 0.1; end; + } +end + admins = { "admin@localhost" } use_libevent = true @@ -8,16 +19,17 @@ 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 + --"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 + "pep"; -- Enables users to publish their avatar, 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 + "vcard4"; -- User profiles (stored in PEP) + "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard -- Nice to have "version"; -- Replies to server version requests @@ -26,6 +38,11 @@ modules_enabled = { "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 + --"csi_simple"; -- Simple Mobile optimizations + + -- Admin interfaces + --"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + --"admin_telnet"; -- Opens telnet console interface on localhost port 5582 -- HTTP modules --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" @@ -35,18 +52,31 @@ modules_enabled = { -- Other specific functionality --"limits"; -- Enable bandwidth limiting for XMPP connections --"groups"; -- Shared roster support - --"server_contact_info"; -- Publish contact information for this service + "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 + "lastactivity"; -- Useful for testing --"scansion_record"; -- Records things that happen in scansion test case format } +contact_info = { + abuse = { "mailto:abuse@localhost", "xmpp:abuse@localhost" }; + admin = { "mailto:admin@localhost", "xmpp:admin@localhost" }; + feedback = { "http://localhost/feedback.html", "mailto:feedback@localhost", "xmpp:feedback@localhost" }; + sales = { "xmpp:sales@localhost" }; + security = { "xmpp:security@localhost" }; + support = { "https://localhost/support.html", "xmpp:support@localhost" }; +} + +modules_disabled = { + "s2s"; +} certificate = "certs" allow_registration = false @@ -71,11 +101,12 @@ mam_smart_enable = true -- For advanced logging see https://prosody.im/doc/logging log = "*console" -daemonize = true pidfile = "prosody.pid" VirtualHost "localhost" +hide_os_type = true -- absense tested for in version.scs + Component "conference.localhost" "muc" storage = "memory" diff --git a/spec/scansion/pubsub_basic.scs b/spec/scansion/pubsub_basic.scs index d983ff66..0adf6857 100644 --- a/spec/scansion/pubsub_basic.scs +++ b/spec/scansion/pubsub_basic.scs @@ -32,7 +32,7 @@ Juliet connects -- <subscribe node="princely_musings" jid="${Romeo's full JID}"/> -- </pubsub> -- </iq> --- +-- -- Juliet receives: -- <iq type="error"/> diff --git a/spec/scansion/pubsub_preconditions.scs b/spec/scansion/pubsub_preconditions.scs new file mode 100644 index 00000000..25afaa8d --- /dev/null +++ b/spec/scansion/pubsub_preconditions.scs @@ -0,0 +1,234 @@ +# Pubsub preconditions are enforced + +[Client] Romeo + password: password + jid: jqpcrbq2@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 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> + <publish-options> + <x xmlns="jabber:x:data"> + <field var="FORM_TYPE" type="hidden"> + <value>http://jabber.org/protocol/pubsub#publish-options</value> + </field> + <field var="pubsub#access_model"> + <value>whitelist</value> + </field> + </x> + </publish-options> + </pubsub> + </iq> + +Romeo receives: + <iq type='error' id='67eb1f47-1e69-4cb3-91e2-4d5943e72d4c'> + <error type='cancel'> + <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> + <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Field does not match: access_model</text> + <precondition-not-met xmlns='http://jabber.org/protocol/pubsub#errors'/> + </error> + </iq> + +Romeo disconnects + diff --git a/spec/scansion/server_contact_info.scs b/spec/scansion/server_contact_info.scs new file mode 100644 index 00000000..15537e11 --- /dev/null +++ b/spec/scansion/server_contact_info.scs @@ -0,0 +1,53 @@ +# XEP-0157: Contact Addresses for XMPP Services +# mod_server_contact_info + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <iq type='get' id='lx2' to='localhost'> + <query xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + +# Ignore other disco#info features, identities etc + +Romeo receives: + <iq from='localhost' id='lx2' type='result'> + <query xmlns='http://jabber.org/protocol/disco#info' scansion:strict='false'> + <x xmlns='jabber:x:data' type='result'> + <field type='hidden' var='FORM_TYPE'> + <value>http://jabber.org/network/serverinfo</value> + </field> + <field type='list-multi' var='abuse-addresses'> + <value>mailto:abuse@localhost</value> + <value>xmpp:abuse@localhost</value> + </field> + <field type='list-multi' var='admin-addresses'> + <value>mailto:admin@localhost</value> + <value>xmpp:admin@localhost</value> + </field> + <field type='list-multi' var='feedback-addresses'> + <value>http://localhost/feedback.html</value> + <value>mailto:feedback@localhost</value> + <value>xmpp:feedback@localhost</value> + </field> + <field type='list-multi' var='sales-addresses'> + <value>xmpp:sales@localhost</value> + </field> + <field type='list-multi' var='security-addresses'> + <value>xmpp:security@localhost</value> + </field> + <field type='list-multi' var='support-addresses'> + <value>https://localhost/support.html</value> + <value>xmpp:support@localhost</value> + </field> + </x> + </query> + </iq> + +Romeo disconnects diff --git a/spec/scansion/uptime.scs b/spec/scansion/uptime.scs new file mode 100644 index 00000000..188b9eb5 --- /dev/null +++ b/spec/scansion/uptime.scs @@ -0,0 +1,21 @@ +# XEP-0012: Last Activity / mod_uptime + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + <iq id='a' type='get' to='localhost'> + <query xmlns='jabber:iq:last'/> + </iq> + +Romeo receives: + <iq type='result' id='a' from='localhost'> + <query xmlns='jabber:iq:last' seconds='0'/> + </iq> + +Romeo disconnects diff --git a/spec/scansion/version.scs b/spec/scansion/version.scs new file mode 100644 index 00000000..6c841dd9 --- /dev/null +++ b/spec/scansion/version.scs @@ -0,0 +1,27 @@ +# XEP-0092: Software Version / mod_version + +[Client] Romeo + password: password + jid: romeo@localhost/dfaZpuxV + +----- + +Romeo connects + +Romeo sends: + <iq id='lx2' to='localhost' type='get'> + <query xmlns='jabber:iq:version'/> + </iq> + +# Version string would vary so we can't do an exact match atm +# Inclusion of <os/> is disabled in the config, it should be absent +Romeo receives: + <iq id='lx2' from='localhost' type='result'> + <query xmlns='jabber:iq:version' scansion:strict='true'> + <name>Prosody</name> + <version scansion:strict='false'/> + </query> + </iq> + + +Romeo disconnects |