diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2013-10-08 19:04:50 -0400 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2013-10-16 11:51:17 -0400 |
commit | 31f94287d72f8c76d0f619c43b4269a07d595a83 (patch) | |
tree | fbba479edbd20a655aa11c70bc22b10c6d8ced00 | |
parent | 373e0890806a623851625fc5a609be55dd2f5406 (diff) |
remove OLPC specific code
Its API should be redesigned to advertise room ID with their handle as we
can't inspect room handles any more. Also, it may be better to use
plugins/sidecars.
31 files changed, 3 insertions, 5831 deletions
diff --git a/docs/Makefile.am b/docs/Makefile.am index 485c2d8b0..027e56e67 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -5,7 +5,6 @@ htmldir = $(if $(filter-out @%@,@htmldir@),@htmldir@,$(datadir)/doc/$(PACKAGE)) man_MANS = telepathy-gabble.8 html_DATA = \ - olpc.html \ muc-bytestream.html \ si-multiple.html \ tubes.html diff --git a/docs/olpc.xml b/docs/olpc.xml deleted file mode 100644 index 515b30358..000000000 --- a/docs/olpc.xml +++ /dev/null @@ -1,797 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<!DOCTYPE xep [ - <!ENTITY NS_OLPC_ACTIVITIES "http://laptop.org/xmpp/activities"> - <!ENTITY NS_OLPC_ACTIVITY_PROPS "http://laptop.org/xmpp/activity-properties"> - <!ENTITY NS_OLPC_BUDDY_PROPS "http://laptop.org/xmpp/buddy-properties"> - <!ENTITY NS_OLPC_CURRENT_ACTIVITY "http://laptop.org/xmpp/current-activity"> -]> -<?xml-stylesheet type='text/xsl' href='xep.xsl'?> -<xep> -<header> - <title>OLPC-specific properties, version 1.0</title> - <abstract>Properties for the Activity and Buddy abstractions used in the - One Laptop per Child's Sugar environment.</abstract> - <legal>Copyright (c) 2007 Collabora Limited. This document may be - distributed under the same terms as the Telepathy specification.</legal> - <number>proto-olpc1.0</number> - <status>ProtoXEP</status> - <type>Extension</type> - <sig>Standards</sig> - <approver>Telepathy project</approver> - <dependencies> - <spec>XMPP Core</spec> - <spec>XEP-0045</spec> - <spec>XEP-proto-clique</spec> - </dependencies> - <supersedes/> - <supersededby/> - <shortname>NOT YET ASSIGNED</shortname> - <author> - <firstname>Simon</firstname> - <surname>McVittie</surname> - <email>simon.mcvittie@collabora.co.uk</email> - <jid>simon.mcvittie@collabora.co.uk</jid> - </author> - <revision> - <version>0.0.1</version> - <date>2007-10-01</date> - <initials>smcv</initials> - <remark><p>First draft.</p></remark> - </revision> -</header> -<section1 topic='Introduction' anchor='intro'> - <p>This document describes the protocol used to transfer OLPC-specific - buddy (contact) and activity (chat room) information.</p> -</section1> -<section1 topic='Requirements' anchor='reqs'> - <p>The OLPC Sugar environment has the abstractions of a Buddy (corresponding - to a child and/or their laptop (XO), represented in XMPP by a JID and in - link-local XMPP by a _presence._tcp record) and an Activity (corresponding to - a shared activity, represented in XMPP by a MUC and in link-local XMPP by a - llmuc chatroom). The API requires that various properties can be browsed for - (without joining any activities or chatrooms).</p> -</section1> - -<section1 topic='Use Cases' anchor='usecases'> - <section2 topic='Buddy properties'> - - <p>Buddy properties are published in PEP. As currently implemented, - all XOs subscribe to the presence and buddy properties of all other - XOs on the same server.</p> - - <p>The buddy properties currently supported are ip4-address, key and - color.</p> - - <example caption='Publishing buddy properties'> - <![CDATA[ - <iq type="set" id="345265478350" - from='1111111111111111111111111111111111111111@jabber.laptop.org'> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/buddy-properties"> - <item> - <properties xmlns="http://laptop.org/xmpp/buddy-properties"> - <property type="str" name="ip4-address">10.0.0.123</property> - <property type="bytes" name="key">Base64Base64...</property> - <property type="str" name="color">#005FE4,#00A0FF</property> - </properties> - </item> - </publish> - </pubsub> - </iq> - ]]> - </example> - - <p>Subscribers receive the change notification, as usual for PEP. - (For all the other PEP nodes described in this document, the process - is the same, and has been omitted from this document for - conciseness.)</p> - - <example caption='Subscriber receives buddy properties notification'> - <![CDATA[ - <message - from='1111111111111111111111111111111111111111@jabber.laptop.org' - to='2222222222222222222222222222222222222222@jabber.laptop.org/Telepathy'> - <event xmlns='http://jabber.org/protocol/pubsub#event'> - <items node='http://laptop.org/xmpp/current-activity'> - <item> - <properties xmlns="http://laptop.org/xmpp/buddy-properties"> - <property type="str" name="ip4-address">10.0.0.123</property> - <property type="bytes" name="key">Base64Base64...</property> - <property type="str" name="color">#005FE4,#00A0FF</property> - </properties> - </item> - </items> - </event> - </message> - ]]> - </example> - - <section3 topic='Buddy properties in link-local XMPP'> - <p>In link-local XMPP, none of this happens. Instead, the ip4-address - property is implicitly available, and the key and color properties - are encoded in the _presence._tcp TXT record.</p> - - <p>The 'color' property is mapped to the 'olpc-color' TXT record key:</p> - - <code> - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-color=#005FE4,#00A0FF" - </code> - - <p>The 'key' property is mapped to the 'olpc-key-part0', - 'olpc-key-part1', ... properties, split as necessary to fit in - the 255-byte limit for TXT records. Because mDNS TXT records - are 8-bit-clean, the segments contain raw binary rather than - the Base64 binary used in XMPP:</p> - - <code> - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part0=binarybinary..." - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part1=binarybinary..." - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part2=binarybinary..." - </code> - - <p>(As currently implemented, the "raw binary" is in fact *also* - Base64, so the data seen in XMPP is doubly Base64'd. However, this - is not guaranteed to remain the case, so the protocols need to - assume the underlying byte array for the key can contain - anything.)</p> - - <p>Implementors must be careful to ensure that there is no key - in the TXT record for the key segment 1 greater than the last one - they need (in this case, olpc-key-part3 must be removed if - present).</p> - </section3> - - </section2> - - <section2 topic='Current activity'> - - <p>The Neighbourhood view on the OLPC groups XO icons by their - current activity, so XOs must notify each other of current-activity - changes.</p> - - <p>As currently implemented, this is done for both public and private - activities, which represents an information leak. (FIXME)</p> - - <p>Note that the 'type' attribute is in fact the activity ID; the name is - for historical reasons.</p> - - <example caption='Publishing current activity'> - <![CDATA[ - <iq type="set" id="364923889843" - from='1111111111111111111111111111111111111111@jabber.laptop.org'> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/current-activity"> - <item> - <activity xmlns="http://laptop.org/xmpp/current-activity"> - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org" - type="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"/> - </item> - </publish> - </pubsub> - </iq> - ]]> - </example> - - <section3 topic='Current activity in link-local XMPP'> - <p>In link-local XMPP, the current activity is mapped to a pair of - keys in the TXT record: olpc-current-activity (the activity ID) - and olpc-current-activity-room (the Salut rMulticast chat room - name).</p> - - <code> - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-current-activity=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-current-activity-room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - </code> - </section3> - - </section2> - - <section2 topic='Public activity properties'> - - <p>For activities to be handled by the Sugar environment, certain - properties are needed. Because there is no server-side storage - corresponding to a chat room and accessible by all participants, - participants each publish the properties of all their activities.</p> - - <p>To keep participants' idea of the activity properties in sync, - when the properties change, the participant making the change MUST - send a broadcast message to the chatroom, notifying other participants - of the new properties.</p> - - <p>This <message/> MUST be sent before updating the PEP node - with the activity properties.</p> - - <example caption='Notifying the chatroom of a properties change'> - <![CDATA[ - <message type="groupchat" - from='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org/1111111111111111111111111111111111111111'> - to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> - <properties xmlns="http://laptop.org/xmpp/activity-properties" - activity="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org"> - <property type="str" name="type">org.laptop.Connect</property> - <property type="str" name="name">Connect Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">0</property> - </properties> - </message> - ]]> - </example> - - <p>For public activities, the participants all announce all their - activities and their properties in a PEP node.</p> - - <p>When an activity becomes private, the participants all delete it - from their activity-properties PEP nodes.</p> - - <example caption='Publishing activity properties'> - <![CDATA[ - <iq type="set" id="275828931562" - from='1111111111111111111111111111111111111111@jabber.laptop.org'> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activity-properties"> - <item> - <activities xmlns="http://laptop.org/xmpp/activity-properties"> - <properties - xmlns="http://laptop.org/xmpp/activity-properties" - activity="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org"> - <property type="str" name="type">org.laptop.Connect</property> - <property type="str" name="name">Connect Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">0</property> - </properties> - <properties - xmlns="http://laptop.org/xmpp/activity-properties" - activity="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - room="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@conference.jabber.laptop.org"> - <property type="str" name="type">org.laptop.HelloMesh</property> - <property type="str" name="name">Example Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">0</property> - </properties> - </activities> - </item> - </publish> - </pubsub> - </iq> - ]]> - </example> - - <p>The participants all announce all their list of activities in yet - another PEP node, for backwards compatibility. This mechanism - will be removed in a future version of this protocol.</p> - - <p>Note that again, the 'type' attribute is in fact the activity ID; - the name is for historical reasons.</p> - - <example caption='Publishing public activity list'> - <![CDATA[ - <iq type="set" id="116108118099"> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activities"> - <item> - <activities xmlns="http://laptop.org/xmpp/activities"> - <activity - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org" - type="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"/> - <activity - room="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@conference.jabber.laptop.org" - type="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"/> - </activities> - </item> - </publish> - </pubsub> - </iq> - ]]> - </example> - - <section3 topic='Activity properties in link-local XMPP'> - <p>In link-local XMPP, the activity properties are mapped to - the _olpc-activity1._udp record. Each participant in each public - activity publishes an mDNS service named - <em>chatroomname</em>:<em>publishedname</em>@<em>hostname</em>, - like so:</p> - - <code> - ; Advertised by 11111... - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local. IN SRV 0 xo-12-34-56.local. - _olpc-activity1._udp.local. IN PTR aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local. - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "txtvers=0" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "activity-id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "name=Connect Activity" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "type=org.laptop.ConnectActivity" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "tags=" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local. IN SRV 0 xo-12-34-56.local. - _olpc-activity1._udp.local. IN PTR bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local. - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "txtvers=0" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "room=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "activity-id=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "name=Example Activity" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "type=org.laptop.HelloMesh" - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "tags=" - - ; Advertised by 22222... - suppose here that 22222... is in the activity - ; aaaaa... but not in bbbbb... - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local. IN SRV 0 xo-22-22-22.local. - _olpc_activity._udp.local. IN PTR aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local. - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "txtvers=0" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "activity-id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "name=Connect Activity" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "type=org.laptop.ConnectActivity" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "tags=" - </code> - - <p>The <message/> sent to the chat room with the updated - properties is much the same as for XMPP:</p> - - <example caption='Notifying the chatroom of a properties change (link-local)'> - <![CDATA[ - <!-- Sent via chatroom aaaaa... using rMulticast --> - <message type="groupchat" - from='11111@xo-12-34-56' - to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'> - <properties xmlns="http://laptop.org/xmpp/activity-properties" - activity="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"> - <property type="str" name="type">org.laptop.Connect</property> - <property type="str" name="name">Connect Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">0</property> - </properties> - </message> - ]]> - </example> - - </section3> - - </section2> - - <section2 topic='Private activities'> - - <p>When an activity becomes private, the participants all delete it - from their activity-properties and activities PEP nodes. In - this example, the XO whose JID starts with 11111 makes the activity - whose ID starts with aaaaa private, and removes it from their PEP nodes; - the XO whose JID starts with 22222 responds by removing it from - their PEP nodes too.</p> - - <p>To a third XO observing the PEP nodes, this is indistinguishable from - both XOs leaving the activity simultaneously, which is what we want.</p> - - <example caption='Making an activity private'> - <![CDATA[ - <message type="groupchat" - from='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org/1111111111111111111111111111111111111111'> - to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> - <properties xmlns="http://laptop.org/xmpp/activity-properties" - activity="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org"> - <property type="str" name="type">org.laptop.Connect</property> - <property type="str" name="name">Connect Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">1</property> - </properties> - </message> - - <iq type="set" id="275828931562" - from='1111111111111111111111111111111111111111@jabber.laptop.org'> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activity-properties"> - <item> - <activities xmlns="http://laptop.org/xmpp/activity-properties"> - <properties - xmlns="http://laptop.org/xmpp/activity-properties" - activity="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - room="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@conference.jabber.laptop.org"> - <property type="str" name="type">org.laptop.HelloMesh</property> - <property type="str" name="name">Example Activity</property> - <property type="str" name="tags"></property> - <property type="str" name="color">#005FE4,#00A0FF</property> - <property type="bool" name="private">0</property> - </properties> - </activities> - </item> - </publish> - </pubsub> - </iq> - - <iq type="set" id="116108118099"> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activities"> - <item> - <activities xmlns="http://laptop.org/xmpp/activities"> - <activity - room="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@conference.jabber.laptop.org" - type="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"/> - </activities> - </item> - </publish> - </pubsub> - </iq> - - <!-- 22222... receives the above <message/>, and responds by deleting - activity aaaaa... from their PEP records. We assume here that 22222 - is not in any other public activity. --> - - <iq type="set" id="103874931562" - from='2222222222222222222222222222222222222222@jabber.laptop.org'> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activity-properties"> - <item> - <activities xmlns="http://laptop.org/xmpp/activity-properties"> - </activities> - </item> - </publish> - </pubsub> - </iq> - - <iq type="set" id="116108239899"> - <pubsub xmlns="http://jabber.org/protocol/pubsub"> - <publish node="http://laptop.org/xmpp/activities"> - <item> - <activities xmlns="http://laptop.org/xmpp/activities"> - </activities> - </item> - </publish> - </pubsub> - </iq> - ]]> - </example> - - <section3 topic='Private activities in link-local XMPP'> - <p>Instead of deleting activities from their PEP records, - link-local peers delete them from their mDNS records.</p> - - <p>The <message/> sent to the chat room with the updated - properties is, again, much the same as for XMPP.</p> - </section3> - - </section2> - - <section2 topic='Invitations'> - - <p>Before inviting a buddy to an activity, OLPC users are expected to - send them the activity properties. These are sent in a <message/> - stanza referred to as a "pseudo-invitation". If the activity - is private, then this is the only opportunity the invitee has to - get the activity properties.</p> - - <example caption='Inviting a buddy to an activity'> - <![CDATA[ - <!-- 11111 sends pseudo-invitation directly to 33333 --> - <message - from='1111111111111111111111111111111111111111@jabber.laptop.org/Telepathy' - to='3333333333333333333333333333333333333333@jabber.laptop.org'> - <properties xmlns='http://laptop.org/xmpp/activity-properties' - activity='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> - <property type='str' name='type'>org.laptop.Connect</property> - <property type='str' name='name'>Connect Activity</property> - <property type='str' name='tags'/> - <property type='str' name='color'>#0d1c38,#49bce4</property> - <property type='bool' name='private'>1</property> - </properties> - </message> - - <!-- 11111 sends invitation to 33333 via MUC service --> - <message - to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> - <x xmlns="http://jabber.org/protocol/muc#user"> - <invite to="3333333333333333333333333333333333333333@jabber.laptop.org"/> - </x> - </message> - - <!-- MUC service relays invitation to 33333 --> - <message type='normal' - from='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org' - to='3333333333333333333333333333333333333333@jabber.laptop.org'> - <x xmlns='http://jabber.org/protocol/muc#user'> - <invite from='1111111111111111111111111111111111111111@jabber.laptop.org/Telepathy'> - <reason/> - </invite> - </x> - <x xmlns='jabber:x:conference' jid='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'/> - </message> - ]]> - </example> - - <p>If the activity properties change before the invitee joins the - activity, the inviter must notify the invitee by re-sending the - pseudo-invitation (only).</p> - - <example caption='Updating a buddy on activity properties'> - <![CDATA[ - <message - from='1111111111111111111111111111111111111111@jabber.laptop.org/Telepathy' - to='3333333333333333333333333333333333333333@jabber.laptop.org'> - <properties xmlns='http://laptop.org/xmpp/activity-properties' - activity='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> - <property type='str' name='type'>org.laptop.Connect</property> - <property type='str' name='name'>this name changed</property> - <property type='str' name='tags'/> - <property type='str' name='color'>#0d1c38,#49bce4</property> - <property type='bool' name='private'>1</property> - </properties> - </message> - ]]> - </example> - - <p>If the inviter leaves the activity before the invitee joins, the - invitee can no longer rely on being notified about any changes; - if the activity was private, the invitee can't even rely on being - able to see whether it exists. Accordingly, the inviter should cancel - their invitation; if all invitations to a private activity have been - cancelled, the invitee should assume that the activity has - disappeared.</p> - - <example caption='Cancelling an invitation'> - <![CDATA[ - <message - from='1111111111111111111111111111111111111111@jabber.laptop.org/Telepathy' - to='3333333333333333333333333333333333333333@jabber.laptop.org'> - <uninvite xmlns='http://laptop.org/xmpp/activity-properties' - id='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'/> - </message> - ]]> - </example> - </section2> - - <section3 topic='Invitations in link-local XMPP'> - <p>There isn't the concept of sending an invitation via the MUC service - in link-local XMPP, so the process can be made somewhat simpler.</p> - - <example caption='Inviting a buddy to an activity (link-local)'> - <![CDATA[ - <!-- Sent over unicast TCP connection between xo-12-34-56.local. - and xo-33-33-33.local. --> - <message from='11111@xo-12-34-56' to='33333@xo-33-33-33'> - <x xmlns='http://collabora.co.uk/protocol/llmuc'> - <invite protocol='rmulticast'> - <roomname>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</roomname> - <address>224.0.0.1</address> - <port>23453</port> - <properties xmlns='http://laptop.org/xmpp/activity-properties' - activity='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'> - <property type='str' name='type'>org.laptop.Connect</property> - <property type='str' name='name'>Connect Activity</property> - <property type='str' name='tags'/> - <property type='str' name='color'>#0d1c38,#49bce4</property> - <property type='bool' name='private'>1</property> - </properties> - </invite> - </x> - </message> - ]]> - </example> - - <example caption='Updating a buddy on activity properties (link-local)'> - <![CDATA[ - <!-- Sent over unicast TCP connection between xo-12-34-56.local. - and xo-33-33-33.local. We just re-send the invitation. --> - - <message from='11111@xo-12-34-56' to='33333@xo-33-33-33'> - <x xmlns='http://collabora.co.uk/protocol/llmuc'> - <invite protocol='rmulticast'> - <roomname>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</roomname> - <address>224.0.0.1</address> - <port>23453</port> - <properties xmlns='http://laptop.org/xmpp/activity-properties' - activity='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'> - <property type='str' name='type'>org.laptop.Connect</property> - <property type='str' name='name'>The name changed</property> - <property type='str' name='tags'/> - <property type='str' name='color'>#0d1c38,#49bce4</property> - <property type='bool' name='private'>1</property> - </properties> - </invite> - </x> - </message> - ]]> - </example> - - <example caption='Cancelling an invitation (link-local)'> - <![CDATA[ - <!-- Sent over unicast TCP connection between xo-12-34-56.local. - and xo-33-33-33.local. --> - <message from='11111@xo-12-34-56' to='33333@xo-33-33-33'> - <uninvite xmlns='http://laptop.org/xmpp/activity-properties' - id='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - room='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'/> - </message> - ]]> - </example> - - </section3> - -</section1> -<section1 topic='Business Rules' anchor='rules'> - <p>Properties have the same syntax and semantics as the "parameters" in - XEP-proto-tubes.</p> -</section1> -<section1 topic='Security Considerations' anchor='security'> - <p>Putting the current activity in a PEP node, even if it's private, - leaks the room name.</p> -</section1> -<section1 topic='IANA Considerations' anchor='iana'> - <p>None.</p> -</section1> -<section1 topic='XMPP Registrar Considerations' anchor='registrar'> - <p>None.</p> -</section1> -<section1 topic='XML Schema' anchor='schema'> - <code> - <![CDATA[ - <!-- Buddy properties --> - <xs:schema - xmlns:xs='http://www.w3.org/2001/XMLSchema' - targetNamespace='http://laptop.org/xmpp/buddy-properties' - xmlns='http://laptop.org/xmpp/buddy-properties' - elementFormDefault='qualified'> - - <!-- Published in the PEP node of the same namespace --> - <xs:element name='properties'> - <xs:complexType> - <xs:sequence> - <xs:element name='property' minOccurs='0' maxOccurs='unbounded' - type='name-value-pair'/> - </xs:sequence> - </xs:complexType> - </xs:element> - - <!-- A name-value pair (the same format as Tubes parameters, as it - happens) --> - <xs:complexType name='name-value-pair'> - <xs:simpleContent> - <xs:extension base='xs:string'> - <xs:attribute name='name' type='xs:string'/> - <xs:attribute name='type'> - <xs:simpleType> - <xs:restriction base='xs:NCName'> - <xs:enumeration value='bool'/> - <xs:enumeration value='str'/> - <xs:enumeration value='bytes'/> - <xs:enumeration value='int'/> - <xs:enumeration value='uint'/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - </xs:schema> - ]]> - <![CDATA[ - <!-- Activity properties --> - <xs:schema - xmlns:xs='http://www.w3.org/2001/XMLSchema' - targetNamespace='http://laptop.org/xmpp/activity-properties' - xmlns='http://laptop.org/xmpp/activity-properties' - elementFormDefault='qualified'> - - <!-- Sent in pseudo-invitations, published in the PEP node - of the same namespace, and sent in chatrooms --> - <xs:element name='properties'> - <xs:complexType> - <!-- XMPP MUC's (bare) JID --> - <xs:attribute name='room' use='required' type='xs:string'/> - <!-- OLPC Activity ID (a 40-character hex string, as of Trial-3) --> - <xs:attribute name='activity' use='required' type='xs:string'/> - - <xs:element name='property' minOccurs='0' maxOccurs='unbounded' - type='name-value-pair'/> - </xs:complexType> - </xs:element> - - <!-- Sent to cancel invitations --> - <xs:element name='uninvite'> - <xs:complexType> - <xs:attribute name='room' use='required' type='xs:string'/> - <xs:attribute name='id' use='required' type='xs:string'/> - </xs:complexType> - </xs:element> - - <!-- A name-value pair (the same format as Tubes parameters, as it - happens) --> - <xs:complexType name='name-value-pair'> - <xs:simpleContent> - <xs:extension base='xs:string'> - <xs:attribute name='name' type='xs:string'/> - <xs:attribute name='type'> - <xs:simpleType> - <xs:restriction base='xs:NCName'> - <xs:enumeration value='bool'/> - <xs:enumeration value='str'/> - <xs:enumeration value='bytes'/> - <xs:enumeration value='int'/> - <xs:enumeration value='uint'/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - - <xs:simpleType name='empty'> - <xs:restriction base='xs:string'> - <xs:enumeration value=''/> - </xs:restriction> - </xs:simpleType> - </xs:schema> - ]]> - <![CDATA[ - <!-- Buddy's Activities list --> - <xs:schema - xmlns:xs='http://www.w3.org/2001/XMLSchema' - targetNamespace='http://laptop.org/xmpp/activities' - xmlns='http://laptop.org/xmpp/activities' - elementFormDefault='qualified'> - - <!-- Published in the PEP node of the same namespace --> - <xs:element name='activities'> - <xs:complexType> - <xs:sequence> - <xs:element name='activity'> - <xs:complexType> - <!-- Despite its name, this attribute is actually the - OLPC activity ID! Historical reasons... --> - <xs:attribute name='type' type='xs:string'/> - <!-- XMPP MUC (bare) JID --> - <xs:attribute name='room' type='xs:string'/> - </xs:complexType> - </xs:element> - </xs:sequence> - </xs:complexType> - </xs:element> - - <xs:simpleType name='empty'> - <xs:restriction base='xs:string'> - <xs:enumeration value=''/> - </xs:restriction> - </xs:simpleType> - </xs:schema> - ]]> - <![CDATA[ - <!-- Buddy's current activity --> - <xs:schema - xmlns:xs='http://www.w3.org/2001/XMLSchema' - targetNamespace='http://laptop.org/xmpp/current-activity' - xmlns='http://laptop.org/xmpp/current-activity' - elementFormDefault='qualified'> - - <!-- Published in the PEP node of the same namespace --> - <xs:element name='activity'> - <xs:complexType> - <!-- Despite its name, this attribute is actually the - OLPC activity ID! Historical reasons... - Empty if no current activity. --> - <xs:attribute name='type' type='xs:string'/> - <!-- XMPP MUC (bare) JID, or empty if no current activity --> - <xs:attribute name='room' type='xs:string'/> - </xs:complexType> - </xs:element> - - <xs:simpleType name='empty'> - <xs:restriction base='xs:string'> - <xs:enumeration value=''/> - </xs:restriction> - </xs:simpleType> - </xs:schema> - ]]> - </code> -</section1> -</xep> diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 2e4ac3690..b32c3208b 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -8,8 +8,6 @@ EXTRA_DIST = \ Gabble_Plugin_Console.xml \ Gabble_Plugin_Gateways.xml \ Gabble_Plugin_Test.xml \ - OLPC_Activity_Properties.xml \ - OLPC_Buddy_Info.xml \ $(NULL) noinst_LTLIBRARIES = libgabble-extensions.la diff --git a/extensions/OLPC_Activity_Properties.xml b/extensions/OLPC_Activity_Properties.xml deleted file mode 100644 index d1ea2afa5..000000000 --- a/extensions/OLPC_Activity_Properties.xml +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0" ?> -<node name="/OLPC_Activity_Properties" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <tp:copyright> Copyright (C) 2007 Collabora Limited </tp:copyright> - <tp:license xmlns="http://www.w3.org/1999/xhtml"> - <p>This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version.</p> - -<p>This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details.</p> - -<p>You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> - </tp:license> - <interface name="org.laptop.Telepathy.ActivityProperties"> - <tp:requires interface="org.freedesktop.Telepathy.Connection"/> - - <method name="SetProperties" tp:name-for-bindings="Set_Properties"> - <arg direction="in" name="room" type="u"> - <tp:docstring> - An integer handle representing the room of the activity - </tp:docstring> - </arg> - <arg direction="in" name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping properties names to the desired values - </tp:docstring> - </arg> - <tp:docstring> - Set the properties of the activity associated to the given room for this connection. - You have to be the owner of this activity. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - <tp:error name="org.freedesktop.Telepathy.Error.PermissionDenied"/> - </tp:possible-errors> - </method> - - <method name="GetProperties" tp:name-for-bindings="Get_Properties"> - <arg direction="in" name="room" type="u"> - <tp:docstring> - An integer handle for the activity's room to request his properties for - </tp:docstring> - </arg> - <arg direction="out" name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping properties names to their values - </tp:docstring> - </arg> - <tp:docstring> - Get the properties of a particular activity. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <method name="GetActivity" tp:name-for-bindings="Get_Activity"> - <arg direction="in" name="activity_id" type="s"> - <tp:docstring> - An activity id - </tp:docstring> - </arg> - <arg direction="out" name="room" type="u"> - <tp:docstring> - A room handle - </tp:docstring> - </arg> - <tp:docstring> - Returns the handle of the room associated with this activity - <tp:rationale> - <p>When an activity starts up, it knows its activity_id but doesn't - know yet if it's shared or not, much less the room.</p> - </tp:rationale> - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <signal name="ActivityPropertiesChanged" - tp:name-for-bindings="Activity_Properties_Changed"> - <arg name="room" type="u"> - <tp:docstring> - An integer handle representing the room of the activity - </tp:docstring> - </arg> - <arg name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping properties names to their new values - </tp:docstring> - </arg> - <tp:docstring> - Signal emitted when the properties of an activity are changed. - </tp:docstring> - </signal> - - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>An interface on connections to associate OLPC activity properties - with rooms.</p> - - <p>The following types and names are used to request and set properties:</p> - <dl> - <dt>s:color</dt> - <dd>The color of the activity. Format used is #RRGGBB,#RRGGBB (stroke,fill).</dd> - - <dt>s:name</dt> - <dd>The name of the activity.</dd> - - <dt>s:type</dt> - <dd>The type of the activity.</dd> - </dl> - - </tp:docstring> - </interface> -</node> -<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/extensions/OLPC_Buddy_Info.xml b/extensions/OLPC_Buddy_Info.xml deleted file mode 100644 index 7caf35c01..000000000 --- a/extensions/OLPC_Buddy_Info.xml +++ /dev/null @@ -1,285 +0,0 @@ -<?xml version="1.0" ?> -<node name="/OLPC_Buddy_Info" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <tp:copyright> Copyright (C) 2007 Collabora Limited </tp:copyright> - <tp:license xmlns="http://www.w3.org/1999/xhtml"> - <p>This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version.</p> - -<p>This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details.</p> - -<p>You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> - </tp:license> - <interface name="org.laptop.Telepathy.BuddyInfo"> - <tp:requires interface="org.freedesktop.Telepathy.Connection"/> - - <method name="SetProperties" tp:name-for-bindings="Set_Properties"> - <arg direction="in" name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping information names to the desired values. - This replaces any existing buddy properties completely: any keys - which were previously present, but are not present in this dictionary, - are deleted. - </tp:docstring> - </arg> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>Set the information of the local user for this connection.</p> - <p>This method may be called before Connect(), in which case the given - properties will be advertised as soon as possible after connection - (possibly immediately).</p> - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <method name="GetProperties" tp:name-for-bindings="Get_Properties"> - <arg direction="in" name="contact" type="u"> - <tp:docstring> - An integer handle for the contact to request his properties for - </tp:docstring> - </arg> - <arg direction="out" name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping information names to their values - </tp:docstring> - </arg> - <tp:docstring> - Get the properties of a particular contact. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <signal name="PropertiesChanged" tp:name-for-bindings="Properties_Changed"> - <arg name="contact" type="u"> - <tp:docstring> - An integer handle representing the contact - </tp:docstring> - </arg> - <arg name="properties" type="a{sv}"> - <tp:docstring> - A dictionary mapping property names to their new values. All - properties are included, not just those that have changed. - </tp:docstring> - </arg> - <tp:docstring> - Signal emitted when the properties of a contact from your 'subscribe' - contact list are changed. - </tp:docstring> - </signal> - - - <tp:struct name="Activity" array-name="Activity_List"> - <tp:docstring>A struct containing: - <ul> - <li>the identifier of the activity</li> - <li>the room handle of the activity channel</li> - </ul> - </tp:docstring> - <tp:member type="s" name="id"/> - <tp:member type="u" tp:type="Room_Handle" name="room"/> - </tp:struct> - - <method name="SetActivities" tp:name-for-bindings="Set_Activities"> - <arg direction="in" name="activities" type="a(su)" tp:type="Activity[]"> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - An array of structs containing: - <ul> - <li>the identifier of the activity</li> - <li>the room handle of the activity channel</li> - </ul> - </tp:docstring> - </arg> - <tp:docstring> - Set the activities of the local user for this connection. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <method name="AddActivity" tp:name-for-bindings="Add_Activity"> - <arg direction="in" name="id" type="s"> - <tp:docstring> - An activity id - </tp:docstring> - </arg> - <arg direction="in" name="handle" type="u"> - <tp:docstring> - A room handle - </tp:docstring> - </arg> - <tp:docstring> - Advertise an activity associated to a muc room - <tp:rationale> - <p>Once an activity shares itself, needs to be advertised if it's not - private. SetActivities could be used for this but it would mean that - the activity would need to call GetActivities then add itself.</p> - </tp:rationale> - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <method name="GetActivities" tp:name-for-bindings="Get_Activities"> - <arg direction="in" name="contact" type="u"> - <tp:docstring> - An integer handle for the contact whose activities are to be returned - </tp:docstring> - </arg> - <arg direction="out" name="activities" type="a(su)" tp:type="Activity[]"> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - An array of structs containing: - <ul> - <li>the identifier of the activity</li> - <li>the room handle of the activity channel</li> - </ul> - </tp:docstring> - </arg> - <tp:docstring> - Get the activities of a particular contact. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <signal name="ActivitiesChanged" tp:name-for-bindings="Activities_Changed"> - <arg name="contact" type="u"> - <tp:docstring> - An integer handle representing the contact - </tp:docstring> - </arg> - <arg name="activities" type="a(su)" tp:type="Activity[]"> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - An array of structs containing: - <ul> - <li>the identifier of the activity</li> - <li>the handle of the activity channel</li> - </ul> - </tp:docstring> - </arg> - <tp:docstring> - Signal emitted when the activities of a contact from your 'subscribe' - contact list are changed. - </tp:docstring> - </signal> - - <method name="SetCurrentActivity" - tp:name-for-bindings="Set_Current_Activity"> - <arg direction="in" name="activity" type="s"> - <tp:docstring> - The identifier of the activity, or the empty string if there is no - current activity - </tp:docstring> - </arg> - <arg direction="in" name="channel" type="u"> - <tp:docstring> - The room handle of the activity channel, or 0 if there is no current - activity - </tp:docstring> - </arg> - <tp:docstring> - Set the current activity of the local user for this connection. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <method name="GetCurrentActivity" - tp:name-for-bindings="Get_Current_Activity"> - <arg direction="in" name="contact" type="u"> - <tp:docstring> - An integer handle for the contact whose current activity is to be - returned - </tp:docstring> - </arg> - <arg direction="out" name="activity" type="s"> - <tp:docstring> - The identifier of the activity, or "" if there is no current activity - </tp:docstring> - </arg> - <arg direction="out" name="channel" type="u"> - <tp:docstring> - The room handle of the activity, or 0 if there is no current activity - </tp:docstring> - </arg> - <tp:docstring> - Get the current activity of a particular contact. - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - </tp:possible-errors> - </method> - - <signal name="CurrentActivityChanged" - tp:name-for-bindings="Current_Activity_Changed"> - <arg name="contact" type="u"> - <tp:docstring> - An integer handle representing the contact - </tp:docstring> - </arg> - <arg name="activity" type="s"> - <tp:docstring> - The identifier of the activity, or "" if there is no current activity - </tp:docstring> - </arg> - <arg name="channel" type="u"> - <tp:docstring> - The room handle of the activity channel, or 0 if there is no current - activity - </tp:docstring> - </arg> - <tp:docstring> - Signal emitted when the current activity of a contact from your 'subscribe' - contact list is changed. - </tp:docstring> - </signal> - - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>An interface on connections to associate OLPC buddy information - with contacts, providing methods for the user to set their own - information and retrieve information of contacts. - The user is automatically notified when information of contacts that - are in his 'subscribe' contact list change.</p> - - <p>The following types and names are used to request and set information - (except for activities):</p> - <dl> - <dt>s:color</dt> - <dd>The color name of the buddy. Format used is #RRGGBB,#RRGGBB - (stroke,fill). - </dd> - - <dt>ay:key</dt> - <dd>The public key of the buddy.</dd> - - <dt>s:jid</dt> - <dd>For link-local connections, the JID of the buddy's server account.</dd> - </dl> - - <p>Activities are represented by a struct containing:</p> - <ul> - <li>the identifier of the activity</li> - <li>the handle of the activity channel</li> - </ul> - </tp:docstring> - </interface> -</node> -<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/extensions/all.xml b/extensions/all.xml index 8b2205f09..0a32c7d40 100644 --- a/extensions/all.xml +++ b/extensions/all.xml @@ -33,9 +33,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> from="Telepathy specification"/> </tp:generic-types> -<xi:include href="OLPC_Buddy_Info.xml"/> -<xi:include href="OLPC_Activity_Properties.xml"/> - <xi:include href="Channel_Type_FileTransfer_Future.xml"/> <xi:include href="Connection_Interface_Gabble_Decloak.xml"/> <xi:include href="Connection_Future.xml"/> diff --git a/gabble/capabilities.h b/gabble/capabilities.h index dd0a0c901..8cc91aeea 100644 --- a/gabble/capabilities.h +++ b/gabble/capabilities.h @@ -45,7 +45,6 @@ const GabbleCapabilitySet *gabble_capabilities_get_any_google_av (void); const GabbleCapabilitySet *gabble_capabilities_get_any_jingle_av (void); const GabbleCapabilitySet *gabble_capabilities_get_any_transport (void); const GabbleCapabilitySet *gabble_capabilities_get_geoloc_notify (void); -const GabbleCapabilitySet *gabble_capabilities_get_olpc_notify (void); /* XEP-0115 version 1.3: * diff --git a/src/Makefile.am b/src/Makefile.am index 6f5b47c71..28ff3506b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,8 +45,6 @@ libgabble_convenience_la_SOURCES = \ conn-contact-info.c \ conn-location.h \ conn-location.c \ - conn-olpc.h \ - conn-olpc.c \ conn-power-saving.h \ conn-power-saving.c \ conn-presence.h \ @@ -84,8 +82,6 @@ libgabble_convenience_la_SOURCES = \ muc-tube-stream.h \ muc-tube-stream.c \ namespaces.h \ - olpc-activity.h \ - olpc-activity.c \ plugin-loader.h \ plugin-loader.c \ presence.h \ diff --git a/src/capabilities.c b/src/capabilities.c index 1c4801fd8..03de7b3a9 100644 --- a/src/capabilities.c +++ b/src/capabilities.c @@ -38,7 +38,6 @@ struct _Feature enum { FEATURE_FIXED, FEATURE_OPTIONAL, - FEATURE_OLPC } feature_type; gchar *ns; }; @@ -84,11 +83,6 @@ static const Feature self_advertised_features[] = { FEATURE_OPTIONAL, NS_JINGLE_RTP_VIDEO }, #endif - { FEATURE_OLPC, NS_OLPC_BUDDY_PROPS "+notify" }, - { FEATURE_OLPC, NS_OLPC_ACTIVITIES "+notify" }, - { FEATURE_OLPC, NS_OLPC_CURRENT_ACTIVITY "+notify" }, - { FEATURE_OLPC, NS_OLPC_ACTIVITY_PROPS "+notify" }, - { FEATURE_OPTIONAL, NS_GEOLOC "+notify" }, { 0, NULL } @@ -112,7 +106,6 @@ static GabbleCapabilitySet *any_jingle_av_caps = NULL; static GabbleCapabilitySet *any_transport_caps = NULL; static GabbleCapabilitySet *fixed_caps = NULL; static GabbleCapabilitySet *geoloc_caps = NULL; -static GabbleCapabilitySet *olpc_caps = NULL; const GabbleCapabilitySet * gabble_capabilities_get_legacy (void) @@ -192,12 +185,6 @@ gabble_capabilities_get_geoloc_notify (void) return geoloc_caps; } -const GabbleCapabilitySet * -gabble_capabilities_get_olpc_notify (void) -{ - return olpc_caps; -} - static gboolean omits_content_creators (WockyNode *identity) { @@ -318,14 +305,6 @@ gabble_capabilities_init (gpointer conn) geoloc_caps = gabble_capability_set_new (); gabble_capability_set_add (geoloc_caps, NS_GEOLOC "+notify"); - - olpc_caps = gabble_capability_set_new (); - - for (feat = self_advertised_features; feat->ns != NULL; feat++) - { - if (feat->feature_type == FEATURE_OLPC) - gabble_capability_set_add (olpc_caps, feat->ns); - } } g_assert (feature_handles != NULL); @@ -355,7 +334,6 @@ gabble_capabilities_finalize (gpointer conn) #endif gabble_capability_set_free (fixed_caps); gabble_capability_set_free (geoloc_caps); - gabble_capability_set_free (olpc_caps); legacy_caps = NULL; share_v1_caps = NULL; @@ -370,7 +348,6 @@ gabble_capabilities_finalize (gpointer conn) any_transport_caps = NULL; fixed_caps = NULL; geoloc_caps = NULL; - olpc_caps = NULL; tp_clear_object (&feature_handles); } diff --git a/src/conn-olpc.c b/src/conn-olpc.c deleted file mode 100644 index 46fef4b0d..000000000 --- a/src/conn-olpc.c +++ /dev/null @@ -1,3081 +0,0 @@ -/* - * conn-olpc.c - Gabble OLPC BuddyInfo and ActivityProperties interfaces - * Copyright (C) 2007 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "conn-olpc.h" - -#include <string.h> -#include <stdlib.h> - -#include <telepathy-glib/telepathy-glib.h> - -#define DEBUG_FLAG GABBLE_DEBUG_OLPC - -#include <gabble/error.h> - -#include "debug.h" -#include "connection.h" -#include "muc-channel.h" -#include "presence-cache.h" -#include "namespaces.h" -#include "disco.h" -#include "util.h" -#include "olpc-activity.h" - -/* FIXME: At some point we should audit this code to check which assumptions - * it does about buddy and activity and if they are still relevant. - * For example, we currently allow the creation of activity objects which - * don't have an ID. I'm not sure that really make sense. - * Or at some place in the code, we allow user to change the ID of an existing - * activity object which is probably bong too. */ - -static gboolean -update_activities_properties (GabbleConnection *conn, const gchar *contact, - WockyStanza *msg); - -/* - * This function performs a depth-first search on @node to find any element - * named @name in namespace @ns. This is usually not what you want because you - * don't want a depth-first search of the entire hierarchy: you know at what - * level of nesting you expect to find an element. Using this function rather - * than wocky_node_get_child_ns() a couple of times opens you up to accepting - * wildly misconstructed stanzas. Please think of the kittens. - */ -static WockyNode * -search_for_child ( - WockyNode *node, - const gchar *name, - const gchar *ns) -{ - WockyNode *found, *child; - WockyNodeIter i; - - found = wocky_node_get_child_ns (node, name, ns); - if (found != NULL) - return found; - - wocky_node_iter_init (&i, node, NULL, NULL); - while (wocky_node_iter_next (&i, &child)) - { - found = search_for_child (child, name, ns); - if (found != NULL) - return found; - } - - return NULL; -} - -/* Returns TRUE if it actually contributed something, else FALSE. - */ -static gboolean -activity_info_contribute_properties (GabbleOlpcActivity *activity, - WockyNode *parent, - gboolean only_public) -{ - WockyNode *props_node; - - if (activity->id == NULL || activity->properties == NULL) - return FALSE; - - if (only_public && !gabble_olpc_activity_is_visible (activity)) - return FALSE; - - props_node = wocky_node_add_child_ns (parent, - "properties", NS_OLPC_ACTIVITY_PROPS); - wocky_node_set_attributes (props_node, - "room", gabble_olpc_activity_get_room (activity), - "activity", activity->id, - NULL); - - lm_message_node_add_children_from_properties (props_node, - activity->properties, "property"); - return TRUE; -} - -static void -decrement_contacts_activities_set_foreach (TpHandleSet *set, - TpHandle handle, - gpointer data) -{ - GabbleConnection *conn = data; - GabbleOlpcActivity *activity = g_hash_table_lookup ( - conn->olpc_activities_info, GUINT_TO_POINTER (handle)); - - g_object_unref (activity); -} - -/* context may be NULL. */ -static gboolean -check_pep (GabbleConnection *conn, - DBusGMethodInvocation *context) -{ - if (!(conn->features & GABBLE_CONNECTION_FEATURES_PEP)) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Server does not support PEP" }; - - DEBUG ("%s", error.message); - if (context != NULL) - dbus_g_method_return_error (context, &error); - return FALSE; - } - - return TRUE; -} - -static const gchar * -inspect_handle (TpBaseConnection *base, - DBusGMethodInvocation *context, - guint handle, - TpHandleRepoIface *handle_repo) -{ - GError *error = NULL; - - if (!tp_handle_is_valid (handle_repo, handle, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return NULL; - } - - return tp_handle_inspect (handle_repo, handle); -} - -static const gchar * -inspect_contact (TpBaseConnection *base, - DBusGMethodInvocation *context, - guint contact) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - base, TP_HANDLE_TYPE_CONTACT); - - return inspect_handle (base, context, contact, contact_repo); -} - -static const gchar * -inspect_room (TpBaseConnection *base, - DBusGMethodInvocation *context, - guint room) -{ - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - base, TP_HANDLE_TYPE_ROOM); - - return inspect_handle (base, context, room, room_repo); -} - -/* context may be NULL, since this may be called in response to becoming - * connected. - */ -static gboolean -check_publish_reply_msg (WockyStanza *reply_msg, - DBusGMethodInvocation *context) -{ - GError *error = NULL; - - if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) - { - GError *tp_error = NULL; - - gabble_set_tp_error_from_wocky (error, &tp_error); - g_prefix_error (&tp_error, "Failed to publish to the PEP node: "); - DEBUG ("%s", tp_error->message); - - if (context != NULL) - dbus_g_method_return_error (context, tp_error); - - g_error_free (tp_error); - g_error_free (error); - return FALSE; - } - else - { - return TRUE; - } -} - -static gboolean -check_query_reply_msg (WockyStanza *reply_msg, - DBusGMethodInvocation *context) -{ - GError *error = NULL; - - if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) - { - GError *tp_error = NULL; - - gabble_set_tp_error_from_wocky (error, &tp_error); - g_prefix_error (&tp_error, "Failed to query the PEP node: "); - DEBUG ("%s", tp_error->message); - - if (context != NULL) - dbus_g_method_return_error (context, tp_error); - - g_error_free (tp_error); - g_error_free (error); - return FALSE; - } - else - { - return TRUE; - } -} - -typedef struct -{ - GabbleConnection *conn; - DBusGMethodInvocation *context; -} pubsub_query_ctx; - -static pubsub_query_ctx * -pubsub_query_ctx_new (GabbleConnection *conn, - DBusGMethodInvocation *context) -{ - pubsub_query_ctx *ctx = g_slice_new (pubsub_query_ctx); - - ctx->conn = conn; - ctx->context = context; - return ctx; -} - -static void -pubsub_query_ctx_free (pubsub_query_ctx *ctx) -{ - g_slice_free (pubsub_query_ctx, ctx); -} - -static void -get_properties_reply_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; - WockyStanza *reply_msg; - GError *error = NULL; - GHashTable *properties; - WockyNode *node; - - /* FIXME: can we just pass &node in here to get the <properties/>? */ - reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, - NULL, &error); - if (reply_msg == NULL) - { - GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property request to server" }; - - DEBUG ("Query failed: %s", error->message); - - dbus_g_method_return_error (ctx->context, &err); - g_error_free (error); - goto out; - } - - if (!check_query_reply_msg (reply_msg, ctx->context)) - goto out; - - node = search_for_child ( - wocky_stanza_get_top_node (reply_msg), "properties", NULL); - properties = lm_message_node_extract_properties (node, "property"); - - gabble_svc_olpc_buddy_info_return_from_get_properties (ctx->context, - properties); - g_hash_table_unref (properties); - -out: - pubsub_query_ctx_free (ctx); - if (reply_msg != NULL) - g_object_unref (reply_msg); -} - -static void -olpc_buddy_info_get_properties (GabbleSvcOLPCBuddyInfo *iface, - guint handle, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - const gchar *jid; - pubsub_query_ctx *ctx; - WockyBareContact *contact; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - jid = inspect_contact (base, context, handle); - if (jid == NULL) - return; - - ctx = pubsub_query_ctx_new (conn, context); - contact = ensure_bare_contact_from_jid (conn, jid); - - wocky_pep_service_get_async (conn->pep_olpc_buddy_props, contact, NULL, - get_properties_reply_cb, ctx); - - g_object_unref (contact); -} - -/* context may be NULL. */ -static void -set_properties_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - DBusGMethodInvocation *context = user_data; - - if (!check_publish_reply_msg (reply_msg, context)) - return; - - if (context != NULL) - gabble_svc_olpc_buddy_info_return_from_set_properties (context); -} - -/* context may be NULL, in which case it will be NULL in the reply_cb. */ -static void -transmit_properties (GabbleConnection *conn, - GHashTable *properties, - DBusGMethodInvocation *context) -{ - WockyStanza *msg; - WockyNode *item, *props_node; - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_buddy_props, - &item); - props_node = wocky_node_add_child_ns (item, "properties", - NS_OLPC_BUDDY_PROPS); - - lm_message_node_add_children_from_properties (props_node, properties, - "property"); - - if (!_gabble_connection_send_with_reply (conn, msg, - set_properties_reply_cb, NULL, context, NULL)) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property change request to server" }; - - DEBUG ("%s", error.message); - if (context != NULL) - dbus_g_method_return_error (context, &error); - } - - g_object_unref (msg); -} - -static GQuark -preload_buddy_properties_quark (void) -{ - static GQuark q = 0; - if (q == 0) - { - q = g_quark_from_static_string - ("GabbleConnection.preload_buddy_properties_quark"); - } - return q; -} - -static GQuark -invitees_quark (void) -{ - static GQuark q = 0; - if (q == 0) - { - q = g_quark_from_static_string - ("GabbleConnection.conn_olpc_invitees_quark"); - } - return q; -} - -static void -gabble_connection_connected_olpc (GabbleConnection *conn) -{ - GHashTable *preload = g_object_steal_qdata ((GObject *) conn, - preload_buddy_properties_quark ()); - - if (preload != NULL) - { - transmit_properties (conn, preload, NULL); - g_hash_table_unref (preload); - } -} - -static void -olpc_buddy_info_set_properties (GabbleSvcOLPCBuddyInfo *iface, - GHashTable *properties, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - DEBUG ("called"); - - if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED) - { - transmit_properties (conn, properties, context); - } - else - { - GHashTable *preload; - GQuark preload_quark = preload_buddy_properties_quark (); - - DEBUG ("Not connected: will perform OLPC buddy property update later"); - - preload = g_object_get_qdata ((GObject *) conn, preload_quark); - if (preload != NULL) - { - /* throw away any already-preloaded properties - SetProperties - * is an overwrite, not an update */ - g_hash_table_remove_all (preload); - } - else - { - preload = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) tp_g_value_slice_free); - g_object_set_qdata_full ((GObject *) conn, preload_quark, preload, - (GDestroyNotify) g_hash_table_unref); - } - - tp_g_hash_table_update (preload, properties, - (GBoxedCopyFunc) g_strdup, - (GBoxedCopyFunc) tp_g_value_slice_dup); - - gabble_svc_olpc_buddy_info_return_from_set_properties (context); - } -} - -static void -olpc_buddy_props_pep_node_changed (WockyPepService *pep, - WockyBareContact *contact, - WockyStanza *stanza, - WockyNode *item, - GabbleConnection *conn) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - GHashTable *properties; - WockyNode *node; - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandle handle; - const gchar *jid; - - jid = wocky_bare_contact_get_jid (contact); - handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); - if (handle == 0) - { - DEBUG ("Invalid from: %s", jid); - return; - } - - if (handle == tp_base_connection_get_self_handle (base)) - /* Ignore echoed pubsub notifications */ - return; - - node = search_for_child ( - wocky_stanza_get_top_node (stanza), "properties", NULL); - properties = lm_message_node_extract_properties (node, "property"); - gabble_svc_olpc_buddy_info_emit_properties_changed (conn, handle, - properties); - g_hash_table_unref (properties); -} - -static void -get_activity_properties_reply_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) - -{ - GabbleConnection *conn = GABBLE_CONNECTION (user_data); - const gchar *from; - WockyStanza *reply_msg; - GError *error = NULL; - - reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, - NULL, &error); - if (reply_msg == NULL) - { - DEBUG ("Failed to send activity properties request to server: %s", - error->message); - g_error_free (error); - return; - } - - from = wocky_node_get_attribute ( - wocky_stanza_get_top_node (reply_msg), "from"); - update_activities_properties (conn, from, reply_msg); - g_object_unref (reply_msg); -} - -static gboolean -remove_activity (gpointer key, - gpointer value, - gpointer activity) -{ - return activity == value; -} - -static void -activity_disposed_cb (gpointer _conn, - GObject *activity) -{ - GabbleConnection *conn = GABBLE_CONNECTION (_conn); - - if (conn->olpc_activities_info == NULL) - /* We are disposing */ - return; - - g_hash_table_foreach_remove (conn->olpc_activities_info, - remove_activity, activity); -} - -static GabbleOlpcActivity * -add_activity_info (GabbleConnection *conn, - TpHandle handle) -{ - GabbleOlpcActivity *activity; - - activity = gabble_olpc_activity_new (conn, handle); - - g_hash_table_insert (conn->olpc_activities_info, - GUINT_TO_POINTER (handle), activity); - g_object_weak_ref (G_OBJECT (activity), activity_disposed_cb, conn); - - return activity; -} - -static GPtrArray * -get_buddy_activities (GabbleConnection *conn, - TpHandle buddy) -{ - TpIntset *all; - gboolean free_all = FALSE; - GPtrArray *activities = g_ptr_array_new (); - TpHandleSet *invited_activities, *pep_activities; - - invited_activities = g_hash_table_lookup (conn->olpc_invited_activities, - GUINT_TO_POINTER (buddy)); - pep_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (buddy)); - - if (invited_activities == NULL) - { - if (pep_activities == NULL) - { - all = NULL; - } - else - { - all = tp_handle_set_peek (pep_activities); - } - } - else - { - if (pep_activities == NULL) - { - all = tp_handle_set_peek (invited_activities); - } - else - { - all = tp_intset_union (tp_handle_set_peek (invited_activities), - tp_handle_set_peek (pep_activities)); - free_all = TRUE; - } - } - - if (all != NULL) - { - TpIntsetFastIter iter; - guint element; - - tp_intset_fast_iter_init (&iter, all); - - while (tp_intset_fast_iter_next (&iter, &element)) - { - GabbleOlpcActivity *activity = g_hash_table_lookup ( - conn->olpc_activities_info, GUINT_TO_POINTER (element)); - GValue gvalue = { 0 }; - - g_assert (activity != NULL); - if (activity->id == NULL) - { - DEBUG ("... activity #%u has no ID, skipping", element); - continue; - } - - g_value_init (&gvalue, GABBLE_STRUCT_TYPE_ACTIVITY); - g_value_take_boxed (&gvalue, dbus_g_type_specialized_construct - (GABBLE_STRUCT_TYPE_ACTIVITY)); - dbus_g_type_struct_set (&gvalue, - 0, activity->id, - 1, activity->room, - G_MAXUINT); - DEBUG ("... activity #%u (ID %s)", - activity->room, activity->id); - g_ptr_array_add (activities, g_value_get_boxed (&gvalue)); - } - } - - if (free_all) - tp_intset_destroy (all); - - return activities; -} - -static void -extract_activities (GabbleConnection *conn, - WockyStanza *msg, - TpHandle sender) -{ - WockyNode *activities_node; - TpHandleSet *activities_set, *old_activities; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - WockyNodeIter i; - - activities_node = search_for_child ( - wocky_stanza_get_top_node (msg), "activities", NULL); - - activities_set = tp_handle_set_new (room_repo); - - if (activities_node != NULL) - { - WockyNode *node; - wocky_node_iter_init (&i, activities_node, "activity", NULL); - while (wocky_node_iter_next (&i, &node)) - { - const gchar *act_id; - const gchar *room; - GabbleOlpcActivity *activity; - TpHandle room_handle; - - act_id = wocky_node_get_attribute (node, "type"); - if (act_id == NULL) - { - NODE_DEBUG (node, "No activity ID, skipping"); - continue; - } - - room = wocky_node_get_attribute (node, "room"); - if (room == NULL) - { - NODE_DEBUG (node, "No room name, skipping"); - continue; - } - - room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); - if (room_handle == 0) - { - DEBUG ("Invalid room name <%s>, skipping", room); - continue; - } - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (activity == NULL) - { - activity = add_activity_info (conn, room_handle); - g_assert (!tp_handle_set_is_member (activities_set, room_handle)); - } - else - { - if (tp_handle_set_is_member (activities_set, room_handle)) - { - NODE_DEBUG (node, "Room advertised twice, skipping"); - continue; - } - - g_object_ref (activity); - - DEBUG ("ref: %s (%d) refcount: %d\n", - gabble_olpc_activity_get_room (activity), - activity->room, G_OBJECT (activity)->ref_count); - } - /* pass ownership to the activities_set */ - tp_handle_set_add (activities_set, room_handle); - - if (tp_strdiff (activity->id, act_id)) - { - DEBUG ("Assigning new ID <%s> to room #%u <%s>", act_id, room_handle, - room); - g_object_set (activity, "id", act_id, NULL); - } - } - } - - old_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (sender)); - - if (old_activities != NULL) - { - /* We decrement the refcount (and free if needed) all the - * activities previously announced by this contact. */ - tp_handle_set_foreach (old_activities, - decrement_contacts_activities_set_foreach, conn); - } - - /* Update the list of activities associated with this contact. */ - g_hash_table_insert (conn->olpc_pep_activities, - GUINT_TO_POINTER (sender), activities_set); -} - -static void -free_activities (GPtrArray *activities) -{ - guint i; - - for (i = 0; i < activities->len; i++) - g_boxed_free (GABBLE_STRUCT_TYPE_ACTIVITY, activities->pdata[i]); - - g_ptr_array_unref (activities); -} - -static void -check_activity_properties (GabbleConnection *conn, - GPtrArray *activities, - const gchar *from) -{ - /* XXX: dirty hack! - * We use PEP instead of pubsub until we have MEP. - * When we request activities from a remote contact we need to check - * if we already "know" his activities (we have its properties). - * If not, we need to explicitely ask to the user to send them to us. - * When we'll have MEP we will be able to request activities - * propreties from muc's pubsub node and so avoid all this crack. - */ - gboolean query_needed = FALSE; - guint i; - - for (i = 0; i < activities->len && !query_needed; i++) - { - GValue pair = {0,}; - guint channel; - GabbleOlpcActivity *activity; - - g_value_init (&pair, GABBLE_STRUCT_TYPE_ACTIVITY); - g_value_set_static_boxed (&pair, g_ptr_array_index (activities, i)); - dbus_g_type_struct_get (&pair, - 1, &channel, - G_MAXUINT); - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (channel)); - if (activity == NULL || activity->properties == NULL) - { - query_needed = TRUE; - } - } - - if (query_needed) - { - WockyBareContact *contact = ensure_bare_contact_from_jid (conn, from); - - wocky_pep_service_get_async (conn->pep_olpc_act_props, contact, - NULL, get_activity_properties_reply_cb, conn); - - g_object_unref (contact); - } -} - -static void -get_activities_reply_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) - -{ - pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; - WockyStanza *reply_msg; - GError *err = NULL; - GPtrArray *activities; - const gchar *from; - TpHandle from_handle; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) ctx->conn, TP_HANDLE_TYPE_CONTACT); - GError *stanza_error = NULL; - - reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, - NULL, &err); - if (reply_msg == NULL) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property request to server" }; - - DEBUG ("Query failed: %s", err->message); - - dbus_g_method_return_error (ctx->context, &error); - g_error_free (err); - goto out; - } - - from = wocky_node_get_attribute ( - wocky_stanza_get_top_node (reply_msg), "from"); - if (from == NULL) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Error in pubsub reply: no sender" }; - - dbus_g_method_return_error (ctx->context, &error); - goto out; - } - - from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); - if (from_handle == 0) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Error in pubsub reply: unknown sender" }; - - dbus_g_method_return_error (ctx->context, &error); - goto out; - } - - if (wocky_stanza_extract_errors (reply_msg, NULL, &stanza_error, NULL, NULL)) - { - GError *tp_error = NULL; - - gabble_set_tp_error_from_wocky (stanza_error, &tp_error); - g_prefix_error (&tp_error, "Error in pubsub reply: "); - dbus_g_method_return_error (ctx->context, tp_error); - g_clear_error (&tp_error); - g_clear_error (&stanza_error); - goto out; - } - - extract_activities (ctx->conn, reply_msg, from_handle); - - activities = get_buddy_activities (ctx->conn, from_handle); - - /* FIXME: race between client and PEP */ - check_activity_properties (ctx->conn, activities, from); - - gabble_svc_olpc_buddy_info_return_from_get_activities (ctx->context, - activities); - - free_activities (activities); -out: - pubsub_query_ctx_free (ctx); - if (reply_msg != NULL) - g_object_unref (reply_msg); -} - -static void -olpc_buddy_info_get_activities (GabbleSvcOLPCBuddyInfo *iface, - guint handle, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - const gchar *jid; - pubsub_query_ctx *ctx; - WockyBareContact *contact; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - jid = inspect_contact (base, context, handle); - if (jid == NULL) - return; - - ctx = pubsub_query_ctx_new (conn, context); - contact = ensure_bare_contact_from_jid (conn, jid); - - wocky_pep_service_get_async (conn->pep_olpc_activities, contact, NULL, - get_activities_reply_cb, ctx); - - g_object_unref (contact); -} - -/* FIXME: API could be improved */ -static gboolean -upload_activities_pep (GabbleConnection *conn, - GabbleConnectionMsgReplyFunc callback, - gpointer user_data, - GError **error) -{ - TpBaseConnection *base = (TpBaseConnection *) conn; - WockyNode *item, *activities; - WockyStanza *msg; - TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - GError *e = NULL; - gboolean ret; - - msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_activities, - &item); - activities = wocky_node_add_child_ns (item, "activities", - NS_OLPC_ACTIVITIES); - - if (my_activities != NULL) - { - TpIntsetFastIter iter; - guint element; - - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities)); - - while (tp_intset_fast_iter_next (&iter, &element)) - { - GabbleOlpcActivity *activity = g_hash_table_lookup ( - conn->olpc_activities_info, GUINT_TO_POINTER (element)); - WockyNode *activity_node; - - g_assert (activity != NULL); - if (!gabble_olpc_activity_is_visible (activity)) - continue; - - activity_node = wocky_node_add_child_with_content (activities, - "activity", ""); - wocky_node_set_attributes (activity_node, - "type", activity->id, - "room", gabble_olpc_activity_get_room (activity), - NULL); - } - } - - ret = _gabble_connection_send_with_reply (conn, msg, callback, NULL, - user_data, &e); - - if (!ret) - { - g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property change request to server: %s", e->message); - g_error_free (e); - } - - g_object_unref (msg); - return ret; -} - -static void -set_activities_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - DBusGMethodInvocation *context = user_data; - - if (!check_publish_reply_msg (reply_msg, context)) - return; - - /* FIXME: emit ActivitiesChanged? */ - - gabble_svc_olpc_buddy_info_return_from_set_activities (context); -} - -static gboolean -add_activity (GabbleConnection *self, - const gchar *id, - guint channel, - GError **error) -{ - TpBaseConnection *base = (TpBaseConnection *) self; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - base, TP_HANDLE_TYPE_ROOM); - TpHandleSet *old_activities = g_hash_table_lookup (self->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - GabbleOlpcActivity *activity; - - if (!tp_handle_is_valid (room_repo, channel, error)) - { - DEBUG ("Invalid room handle %d", channel); - return FALSE; - } - - if (old_activities != NULL && tp_handle_set_is_member (old_activities, channel)) - { - *error = g_error_new (TP_ERROR, - TP_ERROR_INVALID_ARGUMENT, - "Can't set twice the same activity: %s", id); - - DEBUG ("activity already added: %s", id); - return FALSE; - } - - activity = g_hash_table_lookup (self->olpc_activities_info, - GUINT_TO_POINTER (channel)); - - if (activity == NULL) - { - activity = add_activity_info (self, channel); - } - - g_object_ref (activity); - - DEBUG ("ref: %s (%d) refcount: %d\n", - gabble_olpc_activity_get_room (activity), - activity->room, G_OBJECT (activity)->ref_count); - - g_object_set (activity, "id", id, NULL); - - return TRUE; -} - -static void -olpc_buddy_info_set_activities (GabbleSvcOLPCBuddyInfo *iface, - const GPtrArray *activities, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - base, TP_HANDLE_TYPE_ROOM); - guint i; - TpHandleSet *activities_set, *old_activities; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - activities_set = tp_handle_set_new (room_repo); - - for (i = 0; i < activities->len; i++) - { - GValue pair = {0,}; - gchar *id; - guint channel; - const gchar *room = NULL; - GabbleOlpcActivity *activity; - GError *error = NULL; - - g_value_init (&pair, GABBLE_STRUCT_TYPE_ACTIVITY); - g_value_set_static_boxed (&pair, g_ptr_array_index (activities, i)); - dbus_g_type_struct_get (&pair, - 0, &id, - 1, &channel, - G_MAXUINT); - - if (!tp_handle_is_valid (room_repo, channel, &error)) - { - DEBUG ("Invalid room handle"); - dbus_g_method_return_error (context, error); - - /* We have to unref information previously - * refed in this loop */ - tp_handle_set_foreach (activities_set, - decrement_contacts_activities_set_foreach, conn); - - /* set_activities failed so we don't unref old activities - * of the local user */ - - tp_handle_set_destroy (activities_set); - g_error_free (error); - g_free (id); - return; - } - - room = tp_handle_inspect (room_repo, channel); - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (channel)); - - if (activity == NULL) - { - activity = add_activity_info (conn, channel); - } - else - { - if (tp_handle_set_is_member (activities_set, channel)) - { - error = g_error_new (TP_ERROR, - TP_ERROR_INVALID_ARGUMENT, - "Can't set twice the same activity: %s", room); - - DEBUG ("activity already added: %s", room); - dbus_g_method_return_error (context, error); - - /* We have to unref information previously - * refed in this loop */ - tp_handle_set_foreach (activities_set, - decrement_contacts_activities_set_foreach, conn); - - /* set_activities failed so we don't unref old activities - * of the local user */ - - tp_handle_set_destroy (activities_set); - g_error_free (error); - g_free (activity); - g_free (id); - return; - } - - g_object_ref (activity); - - DEBUG ("ref: %s (%d) refcount: %d\n", - gabble_olpc_activity_get_room (activity), - activity->room, G_OBJECT (activity)->ref_count); - } - - g_object_set (activity, "id", id, NULL); - g_free (id); - - tp_handle_set_add (activities_set, channel); - } - - old_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - - if (old_activities != NULL) - { - /* We decrement the refcount (and free if needed) all the - * activities previously announced by our own contact. */ - tp_handle_set_foreach (old_activities, - decrement_contacts_activities_set_foreach, conn); - } - - /* Update the list of activities associated with our own contact. */ - g_hash_table_insert (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)), - activities_set); - - if (!upload_activities_pep (conn, set_activities_reply_cb, context, NULL)) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property request to server" }; - - dbus_g_method_return_error (context, &error); - } - - /* FIXME: what if we were advertising properties for things that - * we've declared are no longer in our activities list? Strictly speaking - * we should probably re-upload our activity properties PEP if that's - * the case */ -} - -static void -olpc_activities_pep_node_changed (WockyPepService *pep, - WockyBareContact *contact, - WockyStanza *stanza, - WockyNode *item, - GabbleConnection *conn) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - GPtrArray *activities; - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandle handle; - const gchar *jid; - - jid = wocky_bare_contact_get_jid (contact); - handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); - if (handle == 0) - { - DEBUG ("Invalid from: %s", jid); - return; - } - - if (handle != tp_base_connection_get_self_handle (base)) - extract_activities (conn, stanza, handle); - - activities = get_buddy_activities (conn, handle); - gabble_svc_olpc_buddy_info_emit_activities_changed (conn, handle, - activities); - free_activities (activities); -} - -static GabbleOlpcActivity * -add_activity_info_in_set (GabbleConnection *conn, - TpHandle room_handle, - const gchar *from, - GHashTable *table) -{ - GabbleOlpcActivity *activity; - TpHandle from_handle; - TpHandleSet *activities_set; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - - from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); - - if (from_handle == 0) - { - DEBUG ("unknown sender"); - return NULL; - } - - activity = add_activity_info (conn, room_handle); - - /* Add activity information in the list of the contact */ - activities_set = g_hash_table_lookup (table, GUINT_TO_POINTER ( - from_handle)); - if (activities_set == NULL) - { - activities_set = tp_handle_set_new (room_repo); - g_hash_table_insert (table, GUINT_TO_POINTER (from_handle), - activities_set); - } - - /* add_activity_info_in_set isn't meant to be called if the - * activity already existed */ - g_assert (!tp_handle_set_is_member (activities_set, room_handle)); - - /* the set owns the ref of the newly created activity */ - tp_handle_set_add (activities_set, room_handle); - - return activity; -} - -static GabbleOlpcActivity * -extract_current_activity (GabbleConnection *conn, - WockyNode *node, - const gchar *contact, - gboolean create_activity) -{ - const gchar *room, *id; - GabbleOlpcActivity *activity; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpHandle room_handle, contact_handle; - - if (node == NULL) - return NULL; - - /* For some weird reasons, the PEP protocol use "type" for the activity ID. - * We can't change that without breaking compatibility but if there is no - * "type" attribute then we can use the "id" one. */ - id = wocky_node_get_attribute (node, "type"); - if (id == NULL) - { - id = wocky_node_get_attribute (node, "id"); - } - - room = wocky_node_get_attribute (node, "room"); - if (room == NULL || room[0] == '\0') - return NULL; - - room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); - if (room_handle == 0) - return NULL; - - contact_handle = tp_handle_lookup (contact_repo, contact, NULL, NULL); - if (contact_handle == 0) - return NULL; - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (activity == NULL && create_activity) - { - /* Humm we received as current activity an activity we don't know yet. - * If the remote user doesn't announce this activity - * in his next activities list, information about - * it will be freed */ - - DEBUG ("unknown current activity %s", room); - - activity = add_activity_info_in_set (conn, room_handle, contact, - conn->olpc_pep_activities); - } - - /* update current-activity cache */ - if (activity != NULL) - { - g_object_set (activity, "id", id, NULL); - g_hash_table_insert (conn->olpc_current_act, - GUINT_TO_POINTER (contact_handle), g_object_ref (activity)); - } - else - { - g_hash_table_remove (conn->olpc_current_act, - GUINT_TO_POINTER (contact_handle)); - } - - return activity; -} - -static void -get_current_activity_reply_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; - WockyStanza *reply_msg; - GError *error = NULL; - WockyNode *node; - const gchar *from; - GabbleOlpcActivity *activity; - - reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, - NULL, &error); - if (reply_msg == NULL) - { - GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property request to server" }; - - DEBUG ("Query failed: %s", error->message); - - dbus_g_method_return_error (ctx->context, &err); - g_error_free (error); - goto out; - } - - if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL)) - { - DEBUG ("Failed to query PEP node. No current activity"); - - gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, - "", 0); - - goto out; - } - - from = wocky_node_get_attribute ( - wocky_stanza_get_top_node (reply_msg), "from"); - node = search_for_child ( - wocky_stanza_get_top_node (reply_msg), "activity", NULL); - activity = extract_current_activity (ctx->conn, node, from, TRUE); - if (activity == NULL) - { - DEBUG ("GetCurrentActivity returns no activity"); - - gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, - "", 0); - } - else - { - DEBUG ("GetCurrentActivity returns (\"%s\", room#%u)", activity->id, - activity->room); - - gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, - activity->id, activity->room); - } - -out: - pubsub_query_ctx_free (ctx); - if (reply_msg != NULL) - g_object_unref (reply_msg); -} - -static void -olpc_buddy_info_get_current_activity (GabbleSvcOLPCBuddyInfo *iface, - guint handle, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - const gchar *jid; - GabbleOlpcActivity *activity; - pubsub_query_ctx *ctx; - WockyBareContact *contact; - - DEBUG ("called for contact#%u", handle); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - jid = inspect_contact (base, context, handle); - if (jid == NULL) - return; - - activity = g_hash_table_lookup (conn->olpc_current_act, - GUINT_TO_POINTER (handle)); - if (activity != NULL) - { - DEBUG ("found current activity in cache: %s (%u)", activity->id, - activity->room); - - gabble_svc_olpc_buddy_info_return_from_get_current_activity (context, - activity->id, activity->room); - return; - } - - DEBUG ("current activity not in cache, query PEP node"); - - ctx = pubsub_query_ctx_new (conn, context); - contact = ensure_bare_contact_from_jid (conn, jid); - - wocky_pep_service_get_async (conn->pep_olpc_current_act, contact, - NULL, get_current_activity_reply_cb, ctx); - - g_object_unref (contact); -} - -static void -set_current_activity_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - DBusGMethodInvocation *context = user_data; - - if (!check_publish_reply_msg (reply_msg, context)) - return; - - gabble_svc_olpc_buddy_info_return_from_set_current_activity (context); -} - -/* Check if this activity is in our own activities list */ -static gboolean -activity_in_own_set (GabbleConnection *conn, - const gchar *room) -{ - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandleSet *activities_set; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - TpHandle room_handle; - - room_handle = tp_handle_lookup (room_repo, room, NULL, NULL); - if (room_handle == 0) - /* If activity's information was in the list, we would - * have found the handle as Activity keep a ref on it */ - return FALSE; - - activities_set = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - - if (activities_set == NULL || - !tp_handle_set_is_member (activities_set, room_handle)) - return FALSE; - - return TRUE; -} - -static void -olpc_buddy_info_set_current_activity (GabbleSvcOLPCBuddyInfo *iface, - const gchar *activity, - guint channel, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - WockyStanza *msg; - WockyNode *item, *publish; - const gchar *room = ""; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - /* if activity == "" there is no current activity */ - if (activity[0] != '\0') - { - room = inspect_room (base, context, channel); - if (room == NULL) - return; - - if (!activity_in_own_set (conn, room)) - { - GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, - "Can't set an activity as current if you're not announcing it" }; - - dbus_g_method_return_error (context, &error); - return; - } - } - - msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_current_act, - &item); - publish = wocky_node_add_child_ns (item, "activity", - NS_OLPC_CURRENT_ACTIVITY); - - wocky_node_set_attributes (publish, - "type", activity, - "room", room, - NULL); - - if (!_gabble_connection_send_with_reply (conn, msg, - set_current_activity_reply_cb, NULL, context, NULL)) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property change request to server" }; - - dbus_g_method_return_error (context, &error); - } - - g_object_unref (msg); -} - -static void -olpc_current_act_pep_node_changed (WockyPepService *pep, - WockyBareContact *contact, - WockyStanza *stanza, - WockyNode *item, - GabbleConnection *conn) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpBaseConnection *base = (TpBaseConnection *) conn; - WockyNode *node; - GabbleOlpcActivity *activity; - TpHandle handle; - const gchar *jid; - - jid = wocky_bare_contact_get_jid (contact); - handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); - if (handle == 0) - { - DEBUG ("Invalid from: %s", jid); - return; - } - - if (handle == tp_base_connection_get_self_handle (base)) - /* Ignore echoed pubsub notifications */ - return; - - node = search_for_child (wocky_stanza_get_top_node (stanza), - "activity", NULL); - - activity = extract_current_activity (conn, node, jid, TRUE); - if (activity != NULL) - { - DEBUG ("emitting CurrentActivityChanged(contact#%u, ID \"%s\", room#%u)", - handle, activity->id, activity->room); - gabble_svc_olpc_buddy_info_emit_current_activity_changed (conn, handle, - activity->id, activity->room); - } - else - { - DEBUG ("emitting CurrentActivityChanged(contact#%u, \"\", 0)", - handle); - gabble_svc_olpc_buddy_info_emit_current_activity_changed (conn, handle, - "", 0); - } -} - -static void -add_activity_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - DBusGMethodInvocation *context = user_data; - - if (!check_publish_reply_msg (reply_msg, context)) - return; - - /* FIXME: emit ActivitiesChanged? */ - - gabble_svc_olpc_buddy_info_return_from_add_activity (context); -} - -static void -olpc_buddy_info_add_activity (GabbleSvcOLPCBuddyInfo *iface, - const gchar *id, - guint channel, - DBusGMethodInvocation *context) -{ - GabbleConnection *self = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; - TpHandleSet *activities_set = g_hash_table_lookup (self->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_ROOM); - GError *error = NULL; - - gabble_connection_ensure_capabilities (self, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (self, context)) - return; - - if (!add_activity (self, id, channel, &error)) - { - dbus_g_method_return_error (context, error); - return; - } - - if (activities_set == NULL) { - activities_set = tp_handle_set_new (room_repo); - g_hash_table_insert (self->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)), - activities_set); - } - - tp_handle_set_add (activities_set, channel); - - if (!upload_activities_pep (self, add_activity_reply_cb, context, NULL)) - { - error = g_error_new (TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property request to server"); - - dbus_g_method_return_error (context, error); - } -} - -void -olpc_buddy_info_iface_init (gpointer g_iface, - gpointer iface_data) -{ - GabbleSvcOLPCBuddyInfoClass *klass = g_iface; - -#define IMPLEMENT(x) gabble_svc_olpc_buddy_info_implement_##x (\ - klass, olpc_buddy_info_##x) - IMPLEMENT(get_activities); - IMPLEMENT(set_activities); - IMPLEMENT(get_properties); - IMPLEMENT(set_properties); - IMPLEMENT(get_current_activity); - IMPLEMENT(set_current_activity); - IMPLEMENT(add_activity); -#undef IMPLEMENT -} - -/* FIXME: API could be improved */ -static gboolean -upload_activity_properties_pep (GabbleConnection *conn, - GabbleConnectionMsgReplyFunc callback, - gpointer user_data, - GError **error) -{ - TpBaseConnection *base = (TpBaseConnection *) conn; - WockyNode *publish, *item; - WockyStanza *msg; - GError *e = NULL; - gboolean ret; - TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - - msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_act_props, &item); - publish = wocky_node_add_child_ns (item, "activities", - NS_OLPC_ACTIVITY_PROPS); - - if (my_activities != NULL) - { - TpIntsetFastIter iter; - guint element; - - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities)); - - while (tp_intset_fast_iter_next (&iter, &element)) - { - GabbleOlpcActivity *activity = g_hash_table_lookup ( - conn->olpc_activities_info, GUINT_TO_POINTER (element)); - - activity_info_contribute_properties (activity, publish, TRUE); - } - } - - ret = _gabble_connection_send_with_reply (conn, msg, callback, NULL, - user_data, &e); - - if (!ret) - { - g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property change request to server: %s", e->message); - g_error_free (e); - } - - g_object_unref (msg); - return ret; -} - -typedef struct { - DBusGMethodInvocation *context; - gboolean visibility_changed; - GabbleOlpcActivity *activity; -} set_properties_ctx; - -static void -set_activity_properties_activities_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - set_properties_ctx *context = user_data; - - /* if the SetProperties() call was skipped, both messages are NULL */ - g_assert ((sent_msg == NULL) == (reply_msg == NULL)); - - if (reply_msg != NULL && - !check_publish_reply_msg (reply_msg, context->context)) - { - g_slice_free (set_properties_ctx, context); - return; - } - - gabble_svc_olpc_activity_properties_emit_activity_properties_changed ( - conn, context->activity->room, context->activity->properties); - - gabble_svc_olpc_activity_properties_return_from_set_properties ( - context->context); - - g_slice_free (set_properties_ctx, context); - return; -} - -static void -set_activity_properties_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - set_properties_ctx *context = user_data; - - /* if the SetProperties() call was skipped, both messages are NULL */ - g_assert ((sent_msg == NULL) == (reply_msg == NULL)); - - if (reply_msg != NULL && - !check_publish_reply_msg (reply_msg, context->context)) - { - g_slice_free (set_properties_ctx, context); - return; - } - - if (context->visibility_changed) - { - GError *err = NULL; - - if (!upload_activities_pep (conn, - set_activity_properties_activities_reply_cb, - context, &err)) - { - dbus_g_method_return_error (context->context, err); - g_error_free (err); - } - } - else - { - /* nothing to do, so just "succeed" */ - set_activity_properties_activities_reply_cb (conn, NULL, NULL, NULL, - context); - } -} - -static gboolean -refresh_invitations (GabbleConnection *conn, - GabbleMucChannel *chan, - GabbleOlpcActivity *activity, - GError **error) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpHandleSet *invitees = g_object_get_qdata ((GObject *) chan, - invitees_quark ()); - - if (invitees != NULL && tp_handle_set_size (invitees) > 0) - { - TpIntsetFastIter iter; - guint element; - - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees)); - - while (tp_intset_fast_iter_next (&iter, &element)) - { - const gchar *to = tp_handle_inspect (contact_repo, element); - WockyStanza *msg = wocky_stanza_build ( - WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, to, NULL); - - activity_info_contribute_properties (activity, - wocky_stanza_get_top_node (msg), FALSE); - - if (!_gabble_connection_send (conn, msg, error)) - { - DEBUG ("Unable to re-send activity properties to invitee %s", - to); - g_object_unref (msg); - return FALSE; - } - - g_object_unref (msg); - } - } - - return TRUE; -} - -static void -olpc_activity_properties_set_properties (GabbleSvcOLPCActivityProperties *iface, - guint room, - GHashTable *properties, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) conn; - WockyStanza *msg; - const gchar *jid; - GHashTable *properties_copied; - GabbleOlpcActivity *activity; - GabbleMucChannel *muc_channel; - guint state; - gboolean was_visible, is_visible; - set_properties_ctx *ctx; - GError *err = NULL; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - jid = inspect_room (base, context, room); - if (jid == NULL) - return; - - if (!activity_in_own_set (conn, jid)) - { - GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, - "Can't set properties on an activity if you're not announcing it" }; - - dbus_g_method_return_error (context, &error); - return; - } - - muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, - room); - if (muc_channel != NULL) - { - g_object_get (muc_channel, - "state", &state, - NULL); - } - if (muc_channel == NULL || state != MUC_STATE_JOINED) - { - GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, - "Can't set properties on an activity if you're not in it" }; - - dbus_g_method_return_error (context, &error); - return; - } - - properties_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) tp_g_value_slice_free); - tp_g_hash_table_update (properties_copied, properties, - (GBoxedCopyFunc) g_strdup, (GBoxedCopyFunc) tp_g_value_slice_dup); - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room)); - - was_visible = gabble_olpc_activity_is_visible (activity); - - g_object_set (activity, "properties", properties_copied, NULL); - - is_visible = gabble_olpc_activity_is_visible (activity); - - msg = wocky_stanza_build ( - WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_GROUPCHAT, - NULL, jid, NULL); - activity_info_contribute_properties (activity, - wocky_stanza_get_top_node (msg), FALSE); - if (!_gabble_connection_send (conn, msg, NULL)) - { - GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, - "Failed to send property change notification to chatroom" }; - - g_object_unref (msg); - dbus_g_method_return_error (context, &error); - return; - } - g_object_unref (msg); - - if (!refresh_invitations (conn, muc_channel, activity, &err)) - { - dbus_g_method_return_error (context, err); - g_error_free (err); - return; - } - - ctx = g_slice_new (set_properties_ctx); - ctx->context = context; - ctx->visibility_changed = (was_visible != is_visible); - ctx->activity = activity; - - if (was_visible || is_visible) - { - if (!upload_activity_properties_pep (conn, - set_activity_properties_reply_cb, ctx, &err)) - { - g_slice_free (set_properties_ctx, ctx); - dbus_g_method_return_error (context, err); - g_error_free (err); - return; - } - } - else - { - /* chain straight to the reply callback, which changes our Activities - * list */ - set_activity_properties_reply_cb (conn, NULL, NULL, NULL, ctx); - } -} - -static void -olpc_activity_properties_get_properties (GabbleSvcOLPCActivityProperties *iface, - guint room, - DBusGMethodInvocation *context) -{ - GabbleConnection *conn = GABBLE_CONNECTION (iface); - gboolean not_prop = FALSE; - GHashTable *properties; - GabbleOlpcActivity *activity; - - DEBUG ("called"); - - gabble_connection_ensure_capabilities (conn, - gabble_capabilities_get_olpc_notify ()); - - if (!check_pep (conn, context)) - return; - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room)); - - if (activity == NULL || activity->properties == NULL) - { - /* no properties */ - properties = g_hash_table_new (g_str_hash, g_str_equal); - not_prop = TRUE; - } - else - { - properties = activity->properties; - } - - gabble_svc_olpc_activity_properties_return_from_get_properties (context, - properties); - - if (not_prop) - g_hash_table_unref (properties); -} - -struct _i_hate_g_hash_table_foreach -{ - GHashTable *old_properties; - gboolean new_infos; -}; - -static void -check_prop_in_old_properties (gpointer key, - gpointer value, - gpointer user_data) -{ - const gchar *prop = key; - GValue *gvalue = value, *old_gvalue; - struct _i_hate_g_hash_table_foreach *data = - (struct _i_hate_g_hash_table_foreach *) user_data; - - old_gvalue = g_hash_table_lookup (data->old_properties, prop); - - if (old_gvalue == NULL) - { - data->new_infos = TRUE; - } - else if (G_VALUE_TYPE (gvalue) != G_VALUE_TYPE (old_gvalue)) - { - data->new_infos = TRUE; - } - else - { - if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) - { - const gchar *str1, *str2; - - str1 = g_value_get_string (gvalue); - str2 = g_value_get_string (old_gvalue); - - if (tp_strdiff (str1, str2)) - { - data->new_infos = TRUE; - } - } - else if (G_VALUE_TYPE (gvalue) == G_TYPE_BOOLEAN) - { - gboolean bool1, bool2; - - bool1 = g_value_get_boolean (gvalue); - bool2 = g_value_get_boolean (old_gvalue); - - if (bool1 != bool2) - { - data->new_infos = TRUE; - } - } - else - { - /* if in doubt, emit the signal */ - data->new_infos = TRUE; - } - } -} - -static gboolean -properties_contains_new_infos (GHashTable *old_properties, - GHashTable *new_properties) -{ - struct _i_hate_g_hash_table_foreach data; - - if (g_hash_table_size (new_properties) > g_hash_table_size (old_properties)) - /* New key/value pair(s) */ - return TRUE; - - data.old_properties = old_properties; - data.new_infos = FALSE; - - g_hash_table_foreach (new_properties, check_prop_in_old_properties, - &data); - - return data.new_infos; -} - -static void -update_activity_properties (GabbleConnection *conn, - const gchar *room, - const gchar *contact, - WockyNode *properties_node) -{ - GHashTable *new_properties, *old_properties; - gboolean new_infos = FALSE; - GabbleOlpcActivity *activity; - TpHandle room_handle; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - - room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (activity == NULL) - { - DEBUG ("unknown activity: %s", room); - if (contact != NULL) - { - /* Humm we received properties for an activity we don't - * know yet. - * If the remote user doesn't announce this activity - * in his next activities list, information about - * it will be freed */ - activity = add_activity_info_in_set (conn, room_handle, contact, - conn->olpc_pep_activities); - } - else - { - activity = add_activity_info (conn, room_handle); - } - } - - if (activity == NULL) - return; - - old_properties = activity->properties; - - new_properties = lm_message_node_extract_properties (properties_node, - "property"); - - if (g_hash_table_size (new_properties) == 0) - { - g_hash_table_unref (new_properties); - return; - } - - if (old_properties == NULL || - properties_contains_new_infos (old_properties, - new_properties)) - { - new_infos = TRUE; - } - - g_object_set (activity, "properties", new_properties, NULL); - - if (new_infos) - { - /* Only emit the signal if we add new values */ - - gabble_svc_olpc_activity_properties_emit_activity_properties_changed ( - conn, activity->room, new_properties); - } -} - -static gboolean -update_activities_properties (GabbleConnection *conn, - const gchar *contact, - WockyStanza *msg) -{ - const gchar *room; - WockyNode *node; - WockyNodeIter i; - WockyNode *properties_node; - - node = search_for_child ( - wocky_stanza_get_top_node (msg), "activities", NULL); - if (node == NULL) - return FALSE; - - wocky_node_iter_init (&i, node, "properties", NULL); - while (wocky_node_iter_next (&i, &properties_node)) - { - room = wocky_node_get_attribute (properties_node, "room"); - if (room == NULL) - continue; - - update_activity_properties (conn, room, contact, properties_node); - } - return TRUE; -} - -static void -olpc_act_props_pep_node_changed (WockyPepService *pep, - WockyBareContact *contact, - WockyStanza *stanza, - WockyNode *item, - GabbleConnection *conn) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandle handle; - const gchar *jid; - - jid = wocky_bare_contact_get_jid (contact); - handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); - if (handle == 0) - { - DEBUG ("Invalid from: %s", jid); - return; - } - - if (handle == tp_base_connection_get_self_handle (base)) - /* Ignore echoed pubsub notifications */ - return; - - update_activities_properties (conn, jid, stanza); -} - -static void -connection_status_changed_cb (GabbleConnection *conn, - TpConnectionStatus status, - TpConnectionStatusReason reason, - gpointer user_data) -{ - if (status == TP_CONNECTION_STATUS_CONNECTED) - { - /* Well, let's do another crack. - * We have to cleanup PEP node to avoid to confuse - * remote contacts with old properties from a previous session. - */ - if (!upload_activities_pep (conn, NULL, NULL, NULL)) - { - DEBUG ("Failed to send PEP activities reset in response to " - "initial connection"); - } - if (!upload_activity_properties_pep (conn, NULL, NULL, - NULL)) - { - DEBUG ("Failed to send PEP activity props reset in response to " - "initial connection"); - } - - gabble_connection_connected_olpc (conn); - } -} - -static void -pseudo_invite_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - if (!check_publish_reply_msg (reply_msg, NULL)) - { - STANZA_DEBUG (reply_msg, "Failed to make PEP change in " - "response to pseudo-invitation message"); - STANZA_DEBUG (sent_msg, "The failed request was"); - } -} - -gboolean -conn_olpc_process_activity_properties_message (GabbleConnection *conn, - WockyStanza *msg, - const gchar *from) -{ - TpBaseConnection *base = (TpBaseConnection *) conn; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_ROOM); - WockyNode *node = search_for_child ( - wocky_stanza_get_top_node (msg), "properties", NS_OLPC_ACTIVITY_PROPS); - const gchar *id; - TpHandle room_handle, contact_handle = 0; - GabbleOlpcActivity *activity; - TpHandleSet *their_invites, *our_activities; - GHashTable *old_properties, *new_properties; - gboolean properties_changed, pep_properties_changed, activities_changed; - gboolean was_visible, is_visible; - GabbleMucChannel *muc_channel = NULL; - - /* if no <properties xmlns=...>, then not for us */ - if (node == NULL) - return FALSE; - - DEBUG ("Found <properties> node in <message>"); - - id = wocky_node_get_attribute (node, "activity"); - if (id == NULL) - { - NODE_DEBUG (node, "... activity ID missing - ignoring"); - return TRUE; - } - - room_handle = gabble_get_room_handle_from_jid (room_repo, from); - - if (room_handle != 0) - { - muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, - room_handle); - } - - if (muc_channel == NULL) - { - const gchar *room; - - DEBUG ("Activity properties message was a pseudo-invitation"); - - /* FIXME: This is stupid. We should ref the handles in a TpHandleSet - * per activity, then we could _ensure this handle */ - contact_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); - if (contact_handle == 0) - { - DEBUG ("... contact <%s> unknown - ignoring (FIX THIS)", from); - return TRUE; - } - - room = wocky_node_get_attribute (node, "room"); - if (room == NULL) - { - NODE_DEBUG (node, "... room name missing - ignoring"); - return TRUE; - } - DEBUG ("... room <%s>", room); - room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); - if (room_handle == 0) - { - DEBUG ("... room <%s> invalid - ignoring", room); - return TRUE; - } - - muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, - room_handle); - if (muc_channel != NULL) - { - guint state; - - g_object_get (muc_channel, - "state", &state, - NULL); - if (state == MUC_STATE_JOINED) - { - DEBUG ("Ignoring pseudo-invitation to <%s> - we're already " - "there", room); - return TRUE; - } - } - } - else - { - TpHandle self_handle; - - DEBUG ("Activity properties message was in a chatroom"); - - tp_group_mixin_get_self_handle ((GObject *) muc_channel, &self_handle, - NULL); - - if (tp_handle_lookup (contact_repo, from, NULL, NULL) == self_handle) - { - DEBUG ("Ignoring echoed activity properties message from myself"); - return TRUE; - } - } - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (contact_handle != 0) - { - their_invites = g_hash_table_lookup (conn->olpc_invited_activities, - GUINT_TO_POINTER (contact_handle)); - if (their_invites == NULL) - { - activities_changed = TRUE; - their_invites = tp_handle_set_new (room_repo); - g_hash_table_insert (conn->olpc_invited_activities, - GUINT_TO_POINTER (contact_handle), their_invites); - } - else - { - activities_changed = !tp_handle_set_is_member (their_invites, - room_handle); - } - - if (activity == NULL) - { - DEBUG ("... creating new Activity"); - activity = add_activity_info (conn, room_handle); - tp_handle_set_add (their_invites, room_handle); - } - else if (!tp_handle_set_is_member (their_invites, room_handle)) - { - DEBUG ("... it's the first time that contact invited me, " - "referencing Activity on their behalf"); - g_object_ref (activity); - tp_handle_set_add (their_invites, room_handle); - } - } - else - { - activities_changed = FALSE; - /* we're in the room, so it ought to have an Activity ref'd */ - g_assert (activity != NULL); - } - - new_properties = lm_message_node_extract_properties (node, - "property"); - g_assert (new_properties); - - /* before applying the changes, gather enough information to work out - * whether anything changed */ - - old_properties = activity->properties; - - was_visible = gabble_olpc_activity_is_visible (activity); - - properties_changed = old_properties == NULL - || properties_contains_new_infos (old_properties, new_properties); - - /* apply the info we found */ - - if (tp_strdiff (activity->id, id)) - { - DEBUG ("... recording new activity ID %s", id); - g_object_set (activity, "id", id, NULL); - } - - g_object_set (activity, "properties", new_properties, NULL); - - /* emit signals and amend our PEP nodes, if necessary */ - - is_visible = gabble_olpc_activity_is_visible (activity); - - if (is_visible) - { - pep_properties_changed = properties_changed || !was_visible; - } - else - { - pep_properties_changed = was_visible; - } - - if (properties_changed) - gabble_svc_olpc_activity_properties_emit_activity_properties_changed (conn, - room_handle, new_properties); - - if (activities_changed) - { - GPtrArray *activities; - g_assert (contact_handle != 0); - - activities = get_buddy_activities (conn, contact_handle); - gabble_svc_olpc_buddy_info_emit_activities_changed (conn, contact_handle, - activities); - free_activities (activities); - } - - if (properties_changed && muc_channel != NULL) - refresh_invitations (conn, muc_channel, activity, NULL); - - /* If we're announcing this activity, we might need to change our PEP node */ - if (pep_properties_changed) - { - our_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - if (our_activities != NULL && - tp_handle_set_is_member (our_activities, room_handle)) - { - if (!upload_activity_properties_pep (conn, - pseudo_invite_reply_cb, NULL, NULL)) - { - DEBUG ("Failed to send PEP properties change in response to " - "properties change message"); - } - } - } - - if (is_visible != was_visible) - { - our_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - if (our_activities != NULL && - tp_handle_set_is_member (our_activities, room_handle)) - { - if (!upload_activities_pep (conn, - pseudo_invite_reply_cb, NULL, NULL)) - { - DEBUG ("Failed to send PEP activities change in response to " - "properties change message"); - } - } - } - - return TRUE; -} - -static void -closed_pep_reply_cb (GabbleConnection *conn, - WockyStanza *sent_msg, - WockyStanza *reply_msg, - GObject *object, - gpointer user_data) -{ - if (!check_publish_reply_msg (reply_msg, NULL)) - { - STANZA_DEBUG (reply_msg, "Failed to make PEP change in " - "response to channel closure"); - STANZA_DEBUG (sent_msg, "The failed request was"); - } -} - -static gboolean -revoke_invitations (GabbleConnection *conn, - GabbleMucChannel *chan, - GabbleOlpcActivity *activity, - GError **error) -{ - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - TpHandleSet *invitees = g_object_get_qdata ((GObject *) chan, - invitees_quark ()); - - if (activity->id == NULL) - /* this is not a real OLPC activity */ - return TRUE; - - if (invitees != NULL && tp_handle_set_size (invitees) > 0) - { - TpIntsetFastIter iter; - guint element; - - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees)); - - DEBUG ("revoke invitations for activity %s", activity->id); - while (tp_intset_fast_iter_next (&iter, &element)) - { - const gchar *to = tp_handle_inspect (contact_repo, element); - WockyStanza *msg = wocky_stanza_build ( - WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, to, - '(', "uninvite", ':', NS_OLPC_ACTIVITY_PROPS, - '@', "room", gabble_olpc_activity_get_room (activity), - '@', "id", activity->id, - ')', NULL); - - if (!_gabble_connection_send (conn, msg, error)) - { - DEBUG ("Unable to send activity invitee revocation %s", - to); - g_object_unref (msg); - return FALSE; - } - - g_object_unref (msg); - } - } - - return TRUE; -} - -gboolean -conn_olpc_process_activity_uninvite_message (GabbleConnection *conn, - WockyStanza *msg, - const gchar *from) -{ - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - WockyNode *node; - const gchar *id, *room; - TpHandle room_handle, from_handle; - TpHandleSet *rooms; - - node = search_for_child ( - wocky_stanza_get_top_node (msg), "uninvite", NS_OLPC_ACTIVITY_PROPS); - - /* if no <uninvite xmlns=...>, then not for us */ - if (node == NULL) - return FALSE; - - id = wocky_node_get_attribute (node, "id"); - if (id == NULL) - { - DEBUG ("no activity id. Skip"); - return TRUE; - } - - room = wocky_node_get_attribute (node, "room"); - if (room == NULL) - { - DEBUG ("no room. Skip"); - return TRUE; - } - - room_handle = tp_handle_lookup (room_repo, room, NULL, NULL); - if (room_handle == 0) - { - DEBUG ("room %s unknown", room); - return TRUE; - } - - from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); - if (from_handle == 0) - { - DEBUG ("sender %s unknown", from); - return TRUE; - } - - rooms = g_hash_table_lookup (conn->olpc_invited_activities, - GUINT_TO_POINTER (from_handle)); - - if (rooms == NULL) - { - DEBUG ("No invites associated with contact %d", from_handle); - return TRUE; - } - - if (tp_handle_set_remove (rooms, room_handle)) - { - GabbleOlpcActivity *activity; - GPtrArray *activities; - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (activity == NULL) - { - DEBUG ("No info about activity associated with room %s", room); - return TRUE; - } - - if (tp_strdiff (id, activity->id)) - { - DEBUG ("Uninvite's activity id (%s) doesn't match our " - "activity id (%s)", id, activity->id); - return TRUE; - } - - DEBUG ("remove invite from %s", from); - g_object_unref (activity); - - /* Emit BuddyInfo::ActivitiesChanged */ - activities = get_buddy_activities (conn, from_handle); - gabble_svc_olpc_buddy_info_emit_activities_changed (conn, from_handle, - activities); - free_activities (activities); - } - else - { - DEBUG ("No invite from %s for activity %s (room %s)", from, id, room); - return TRUE; - } - - return TRUE; -} - -static void -muc_channel_closed_cb (GabbleMucChannel *chan, - GabbleOlpcActivity *activity) -{ - GabbleConnection *conn; - TpBaseConnection *base; - TpHandleSet *my_activities; - gboolean was_in_our_pep = FALSE; - - /* is the muc channel /actually/ disappearing */ - if (!tp_base_channel_is_destroyed (TP_BASE_CHANNEL (chan))) - return; - - g_object_get (activity, "connection", &conn, NULL); - base = TP_BASE_CONNECTION (conn); - - /* Revoke invitations we sent for this activity */ - revoke_invitations (conn, chan, activity, NULL); - - /* remove it from our advertised activities list, unreffing it in the - * process if it was in fact advertised */ - my_activities = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); - if (my_activities != NULL) - { - if (tp_handle_set_remove (my_activities, activity->room)) - { - was_in_our_pep = gabble_olpc_activity_is_visible (activity); - g_object_unref (activity); - } - } - - /* unref it again (it was referenced on behalf of the channel) */ - g_object_unref (activity); - - if (was_in_our_pep) - { - if (!upload_activities_pep (conn, closed_pep_reply_cb, NULL, NULL)) - { - DEBUG ("Failed to send PEP activities change in response to " - "channel close"); - } - if (!upload_activity_properties_pep (conn, closed_pep_reply_cb, NULL, - NULL)) - { - DEBUG ("Failed to send PEP activity props change in response to " - "channel close"); - } - } - - g_object_unref (conn); -} - -static void -muc_channel_pre_invite_cb (GabbleMucChannel *chan, - const gchar *jid, - GabbleOlpcActivity *activity) -{ - GabbleConnection *conn; - TpHandleRepoIface *contact_repo; - GQuark quark = invitees_quark (); - TpHandleSet *invitees; - /* send them the properties */ - WockyStanza *msg; - TpHandle handle; - GError *error = NULL; - - g_object_get (activity, "connection", &conn, NULL); - contact_repo = tp_base_connection_get_handles - ((TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); - - msg = wocky_stanza_build ( - WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, jid, - NULL); - - if (activity_info_contribute_properties (activity, - wocky_stanza_get_top_node (msg), FALSE)) - { - /* not much we can do about errors - but if this fails, the invitation - * will too, unless something extremely strange is going on */ - if (!_gabble_connection_send (conn, msg, NULL)) - { - DEBUG ("Unable to send activity properties to invitee"); - } - } - g_object_unref (msg); - - handle = tp_handle_ensure (contact_repo, jid, NULL, &error); - if (handle == 0) - { - DEBUG ("can't add %s to invitees: %s", jid, error->message); - g_error_free (error); - g_object_unref (conn); - return; - } - - invitees = g_object_get_qdata ((GObject *) chan, quark); - if (invitees == NULL) - { - invitees = tp_handle_set_new (contact_repo); - g_object_set_qdata_full ((GObject *) chan, quark, invitees, - (GDestroyNotify) tp_handle_set_destroy); - } - - tp_handle_set_add (invitees, handle); - - g_object_unref (conn); -} - -typedef struct -{ - GabbleConnection *conn; - TpHandle room_handle; -} remove_invite_foreach_ctx; - -static void -remove_invite_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - TpHandle inviter = GPOINTER_TO_UINT (key); - TpHandleSet *rooms = (TpHandleSet *) value; - remove_invite_foreach_ctx *ctx = (remove_invite_foreach_ctx *) user_data; - - /* We are now in the activity and so the responsibilty to track - * buddies membership is delegated to the PS. At some point, maybe that - * should be done by CM's */ - if (tp_handle_set_remove (rooms, ctx->room_handle)) - { - GabbleOlpcActivity *activity; - GPtrArray *activities; - - activity = g_hash_table_lookup (ctx->conn->olpc_activities_info, - GUINT_TO_POINTER (ctx->room_handle)); - - activities = get_buddy_activities (ctx->conn, inviter); - gabble_svc_olpc_buddy_info_emit_activities_changed (ctx->conn, inviter, - activities); - free_activities (activities); - - g_assert (activity != NULL); - DEBUG ("forget invite for activity %s from contact %d", activity->id, - inviter); - g_object_unref (activity); - } -} - -static void -forget_activity_invites (GabbleConnection *conn, - TpHandle room_handle) -{ - remove_invite_foreach_ctx ctx; - - ctx.conn = conn; - ctx.room_handle = room_handle; - g_hash_table_foreach (conn->olpc_invited_activities, remove_invite_foreach, - &ctx); -} - -static void -muc_channel_contact_join_cb (GabbleMucChannel *chan, - TpHandle contact, - GabbleOlpcActivity *activity) -{ - GabbleConnection *conn; - TpBaseConnection *base; - - g_object_get (activity, "connection", &conn, NULL); - base = TP_BASE_CONNECTION (conn); - - if (contact == tp_base_connection_get_self_handle (base)) - { - /* We join the channel, forget about all invites we received about - * this activity */ - forget_activity_invites (conn, activity->room); - } - else - { - GQuark quark = invitees_quark (); - TpHandleSet *invitees; - - invitees = g_object_get_qdata ((GObject *) chan, quark); - if (invitees != NULL) - { - DEBUG ("contact %d joined the muc, remove the invite we sent to him", - contact); - tp_handle_set_remove (invitees, contact); - } - } - - g_object_unref (conn); -} - -static void -muc_factory_new_channel_cb (gpointer key, - gpointer value, - gpointer data) -{ - GabbleConnection *conn = GABBLE_CONNECTION (data); - TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (key); - GabbleOlpcActivity *activity; - TpHandle room_handle; - - if (!GABBLE_IS_MUC_CHANNEL (chan)) - return; - - g_object_get (chan, - "handle", &room_handle, - NULL); - - /* ref the activity as long as we have a channel open */ - - activity = g_hash_table_lookup (conn->olpc_activities_info, - GUINT_TO_POINTER (room_handle)); - - if (activity == NULL) - { - activity = add_activity_info (conn, room_handle); - } - else - { - g_object_ref (activity); - } - - g_signal_connect (chan, "closed", G_CALLBACK (muc_channel_closed_cb), - activity); - g_signal_connect (chan, "pre-invite", G_CALLBACK (muc_channel_pre_invite_cb), - activity); - g_signal_connect (chan, "contact-join", - G_CALLBACK (muc_channel_contact_join_cb), activity); -} - -static void -muc_factory_new_channels_cb (GabbleMucFactory *fac, - GHashTable *channels, - GabbleConnection *conn) -{ - g_hash_table_foreach (channels, muc_factory_new_channel_cb, conn); -} - -static void -connection_presence_do_update (GabblePresenceCache *cache, - TpHandle handle, - GabbleConnection *conn) -{ - GabblePresence *presence; - - presence = gabble_presence_cache_get (cache, handle); - - if (presence && presence->status <= GABBLE_PRESENCE_LAST_UNAVAILABLE) - { - /* Contact becomes unavailable. We have to unref all the information - * provided by him - */ - GPtrArray *empty = g_ptr_array_new (); - TpHandleSet *list; - - list = g_hash_table_lookup (conn->olpc_pep_activities, - GUINT_TO_POINTER (handle)); - - if (list != NULL) - tp_handle_set_foreach (list, - decrement_contacts_activities_set_foreach, conn); - - g_hash_table_remove (conn->olpc_pep_activities, - GUINT_TO_POINTER (handle)); - - list = g_hash_table_lookup (conn->olpc_invited_activities, - GUINT_TO_POINTER (handle)); - - if (list != NULL) - tp_handle_set_foreach (list, - decrement_contacts_activities_set_foreach, conn); - - g_hash_table_remove (conn->olpc_invited_activities, - GUINT_TO_POINTER (handle)); - - gabble_svc_olpc_buddy_info_emit_activities_changed (conn, handle, - empty); - g_ptr_array_unref (empty); - } -} - -static void -connection_presences_updated_cb (GabblePresenceCache *cache, - GArray *handles, - GabbleConnection *conn) -{ - guint i; - - for (i = 0; i < handles->len ; i++) - { - TpHandle handle; - - handle = g_array_index (handles, TpHandle, i); - connection_presence_do_update (cache, handle, conn); - } -} - -void -conn_olpc_activity_properties_init (GabbleConnection *conn) -{ - /* room TpHandle => borrowed Activity */ - conn->olpc_activities_info = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, NULL); - - /* Activity from PEP - * - * contact TpHandle => TpHandleSet of room handles, - * each representing a reference to an Activity - * - * Special case: the entry for self_handle is the complete list of - * activities, not just those from PEP - */ - conn->olpc_pep_activities = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, (GDestroyNotify) tp_handle_set_destroy); - - /* Activity from pseudo-invitations - * - * contact TpHandle => TpHandleSet of room handles, - * each representing a reference to an Activity - * - * Special case: there is never an entry for self_handle - */ - conn->olpc_invited_activities = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, (GDestroyNotify) tp_handle_set_destroy); - - /* Current activity - * - * contact TpHandle => reffed GabbleOlpcActivity - */ - conn->olpc_current_act = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, (GDestroyNotify) g_object_unref); - - g_signal_connect (conn, "status-changed", - G_CALLBACK (connection_status_changed_cb), NULL); - - g_signal_connect (TP_CHANNEL_MANAGER (conn->muc_factory), "new-channels", - G_CALLBACK (muc_factory_new_channels_cb), conn); - - g_signal_connect (conn->presence_cache, "presences-updated", - G_CALLBACK (connection_presences_updated_cb), conn); - - conn->pep_olpc_buddy_props = wocky_pep_service_new (NS_OLPC_BUDDY_PROPS, - TRUE); - g_signal_connect (conn->pep_olpc_buddy_props, "changed", - G_CALLBACK (olpc_buddy_props_pep_node_changed), conn); - - conn->pep_olpc_activities = wocky_pep_service_new (NS_OLPC_ACTIVITIES, - TRUE); - g_signal_connect (conn->pep_olpc_activities, "changed", - G_CALLBACK (olpc_activities_pep_node_changed), conn); - - conn->pep_olpc_current_act = wocky_pep_service_new (NS_OLPC_CURRENT_ACTIVITY, - TRUE); - g_signal_connect (conn->pep_olpc_current_act, "changed", - G_CALLBACK (olpc_current_act_pep_node_changed), conn); - - conn->pep_olpc_act_props = wocky_pep_service_new (NS_OLPC_ACTIVITY_PROPS, - TRUE); - g_signal_connect (conn->pep_olpc_act_props, "changed", - G_CALLBACK (olpc_act_props_pep_node_changed), conn); -} - -static void -unref_activities_in_each_set (TpHandle handle, - TpHandleSet *set, - GabbleConnection *conn) -{ - if (set != NULL) - { - tp_handle_set_foreach (set, - decrement_contacts_activities_set_foreach, conn); - } -} - -void -conn_olpc_activity_properties_dispose (GabbleConnection *self) -{ - g_hash_table_unref (self->olpc_current_act); - self->olpc_current_act = NULL; - - g_hash_table_foreach (self->olpc_pep_activities, - (GHFunc) unref_activities_in_each_set, self); - g_hash_table_unref (self->olpc_pep_activities); - self->olpc_pep_activities = NULL; - - g_hash_table_foreach (self->olpc_invited_activities, - (GHFunc) unref_activities_in_each_set, self); - g_hash_table_unref (self->olpc_invited_activities); - self->olpc_invited_activities = NULL; - - g_hash_table_unref (self->olpc_activities_info); - self->olpc_activities_info = NULL; -} - -static GabbleOlpcActivity * -find_activity_by_id (GabbleConnection *self, - const gchar *activity_id) -{ - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, self->olpc_activities_info); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - GabbleOlpcActivity *activity = GABBLE_OLPC_ACTIVITY (value); - if (!tp_strdiff (activity->id, activity_id)) - return activity; - } - - return NULL; -} - -static void -olpc_activity_properties_get_activity (GabbleSvcOLPCActivityProperties *iface, - const gchar *activity_id, - DBusGMethodInvocation *context) -{ - GabbleConnection *self = GABBLE_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; - GabbleOlpcActivity *activity; - GError *error = NULL; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - activity = find_activity_by_id (self, activity_id); - if (activity == NULL) - { - g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, - "Activity unknown: %s", activity_id); - goto error; - } - - gabble_svc_olpc_activity_properties_return_from_get_activity (context, - activity->room); - - return; - -error: - dbus_g_method_return_error (context, error); - g_error_free (error); -} - -void -olpc_activity_properties_iface_init (gpointer g_iface, - gpointer iface_data) -{ - GabbleSvcOLPCActivityPropertiesClass *klass = g_iface; - -#define IMPLEMENT(x) gabble_svc_olpc_activity_properties_implement_##x (\ - klass, olpc_activity_properties_##x) - IMPLEMENT(get_properties); - IMPLEMENT(set_properties); - IMPLEMENT(get_activity); -#undef IMPLEMENT -} - diff --git a/src/conn-olpc.h b/src/conn-olpc.h deleted file mode 100644 index cef23cbbd..000000000 --- a/src/conn-olpc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * conn-olpc.h - Header for Gabble OLPC BuddyInfo and ActivityProperties interfaces - * Copyright (C) 2007 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __CONN_OLPC_H__ -#define __CONN_OLPC_H__ - -#include <extensions/extensions.h> - -#include "connection.h" - -void -olpc_buddy_info_iface_init (gpointer g_iface, gpointer iface_data); - -void -olpc_activity_properties_iface_init (gpointer g_iface, gpointer iface_data); - -void conn_olpc_activity_properties_init (GabbleConnection *conn); - -void conn_olpc_activity_properties_dispose (GabbleConnection *conn); - -gboolean conn_olpc_process_activity_properties_message (GabbleConnection *conn, - WockyStanza *msg, const gchar *from); - -gboolean conn_olpc_process_activity_uninvite_message (GabbleConnection *conn, - WockyStanza *msg, const gchar *from); - -#endif /* __CONN_OLPC_H__ */ - diff --git a/src/connection.c b/src/connection.c index 25cf610af..5a563851c 100644 --- a/src/connection.c +++ b/src/connection.c @@ -52,7 +52,6 @@ #include "conn-presence.h" #include "conn-sidecars.h" #include "conn-mail-notif.h" -#include "conn-olpc.h" #include "conn-power-saving.h" #include "debug.h" #include "disco.h" @@ -118,10 +117,6 @@ G_DEFINE_TYPE_WITH_CODE(GabbleConnection, conn_decloak_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_LOCATION, location_iface_init); - G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_BUDDY_INFO, - olpc_buddy_info_iface_init); - G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_ACTIVITY_PROPERTIES, - olpc_activity_properties_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, gabble_conn_contact_caps_iface_init); @@ -440,7 +435,6 @@ gabble_connection_constructor (GType type, conn_avatars_init (self); conn_contact_info_init (self); conn_presence_init (self); - conn_olpc_activity_properties_init (self); conn_location_init (self); conn_sidecars_init (self); conn_mail_notif_init (self); @@ -868,8 +862,6 @@ _gabble_connection_create_handle_repos (TpBaseConnection *conn, static const gchar *implemented_interfaces[] = { /* conditionally present interfaces */ TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, - GABBLE_IFACE_OLPC_ACTIVITY_PROPERTIES, - GABBLE_IFACE_OLPC_BUDDY_INFO, /* always present interfaces */ TP_IFACE_CONNECTION_INTERFACE_POWER_SAVING, @@ -889,7 +881,7 @@ static const gchar *implemented_interfaces[] = { TP_IFACE_CONNECTION_INTERFACE_ADDRESSING, NULL }; -static const gchar **interfaces_always_present = implemented_interfaces + 3; +static const gchar **interfaces_always_present = implemented_interfaces + 1; const gchar ** gabble_connection_get_implemented_interfaces (void) @@ -1294,8 +1286,6 @@ gabble_connection_dispose (GObject *object) tp_clear_object (&self->self_presence); tp_clear_object (&self->presence_cache); - conn_olpc_activity_properties_dispose (self); - g_hash_table_unref (self->avatar_requests); g_hash_table_unref (self->vcard_requests); @@ -1328,10 +1318,6 @@ gabble_connection_dispose (GObject *object) tp_clear_object (&self->pep_location); tp_clear_object (&self->pep_nick); - tp_clear_object (&self->pep_olpc_buddy_props); - tp_clear_object (&self->pep_olpc_activities); - tp_clear_object (&self->pep_olpc_current_act); - tp_clear_object (&self->pep_olpc_act_props); conn_sidecars_dispose (self); @@ -1954,10 +1940,6 @@ connector_connected (GabbleConnection *self, wocky_pep_service_start (self->pep_location, self->session); wocky_pep_service_start (self->pep_nick, self->session); - wocky_pep_service_start (self->pep_olpc_buddy_props, self->session); - wocky_pep_service_start (self->pep_olpc_activities, self->session); - wocky_pep_service_start (self->pep_olpc_current_act, self->session); - wocky_pep_service_start (self->pep_olpc_act_props, self->session); /* Don't use wocky_session_start as we don't want to start all the * components (Roster, presence-manager, etc) for now */ @@ -2793,15 +2775,6 @@ set_status_to_connected (GabbleConnection *conn) return; } - if (conn->features & GABBLE_CONNECTION_FEATURES_PEP) - { - const gchar *ifaces[] = { GABBLE_IFACE_OLPC_BUDDY_INFO, - GABBLE_IFACE_OLPC_ACTIVITY_PROPERTIES, - NULL }; - - tp_base_connection_add_interfaces ((TpBaseConnection *) conn, ifaces); - } - if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY) { const gchar *ifaces[] = diff --git a/src/connection.h b/src/connection.h index 842f9e58f..a7886e7a1 100644 --- a/src/connection.h +++ b/src/connection.h @@ -204,12 +204,6 @@ struct _GabbleConnection { /* vCard lookup helper */ GabbleVCardManager *vcard_manager; - /* OLPC hash tables */ - GHashTable *olpc_activities_info; - GHashTable *olpc_pep_activities; - GHashTable *olpc_invited_activities; - GHashTable *olpc_current_act; - /* bytestream factory */ GabbleBytestreamFactory *bytestream_factory; @@ -231,10 +225,6 @@ struct _GabbleConnection { /* PEP */ WockyPepService *pep_nick; WockyPepService *pep_location; - WockyPepService *pep_olpc_buddy_props; - WockyPepService *pep_olpc_activities; - WockyPepService *pep_olpc_current_act; - WockyPepService *pep_olpc_act_props; /* Sidecars */ /* gchar *interface → GabbleSidecar */ diff --git a/src/debug.c b/src/debug.c index 8e3dd0c50..c656400f8 100644 --- a/src/debug.c +++ b/src/debug.c @@ -36,7 +36,6 @@ static GDebugKey keys[] = { { "vcard", GABBLE_DEBUG_VCARD }, { "pipeline", GABBLE_DEBUG_PIPELINE }, { "jid", GABBLE_DEBUG_JID }, - { "olpc", GABBLE_DEBUG_OLPC }, { "bytestream", GABBLE_DEBUG_BYTESTREAM }, { "tubes", GABBLE_DEBUG_TUBES }, { "location", GABBLE_DEBUG_LOCATION }, diff --git a/src/muc-factory.c b/src/muc-factory.c index 39f468509..6b61b7244 100644 --- a/src/muc-factory.c +++ b/src/muc-factory.c @@ -33,7 +33,6 @@ #include "gabble/caps-channel-manager.h" #include "connection.h" -#include "conn-olpc.h" #include "debug.h" #include "disco.h" #include "im-channel.h" @@ -772,7 +771,6 @@ muc_factory_message_cb ( gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); - GabbleMucFactoryPrivate *priv = fac->priv; const gchar *from, *body, *id; time_t stamp; @@ -785,14 +783,6 @@ muc_factory_message_cb ( &msgtype, &id, &body, &state, &send_error, &delivery_status)) return TRUE; - if (conn_olpc_process_activity_properties_message (priv->conn, message, - from)) - return TRUE; - - if (conn_olpc_process_activity_uninvite_message (priv->conn, message, - from)) - return TRUE; - if (process_muc_invite (fac, message, from, send_error)) return TRUE; diff --git a/src/namespaces.h b/src/namespaces.h index 2a2d8f91b..705a0b4c6 100644 --- a/src/namespaces.h +++ b/src/namespaces.h @@ -93,12 +93,6 @@ #define NS_MUC_OWNER "http://jabber.org/protocol/muc#owner" #define NS_NICK "http://jabber.org/protocol/nick" #define NS_OOB "jabber:iq:oob" -#define NS_OLPC_BUDDY_PROPS "http://laptop.org/xmpp/buddy-properties" -#define NS_OLPC_ACTIVITIES "http://laptop.org/xmpp/activities" -#define NS_OLPC_CURRENT_ACTIVITY "http://laptop.org/xmpp/current-activity" -#define NS_OLPC_ACTIVITY_PROPS "http://laptop.org/xmpp/activity-properties" -#define NS_OLPC_BUDDY "http://laptop.org/xmpp/buddy" -#define NS_OLPC_ACTIVITY "http://laptop.org/xmpp/activity" #define NS_PUBSUB "http://jabber.org/protocol/pubsub" #define NS_PRESENCE_INVISIBLE "presence-invisible" #define NS_PRIVACY "jabber:iq:privacy" diff --git a/src/olpc-activity.c b/src/olpc-activity.c deleted file mode 100644 index a5f34a581..000000000 --- a/src/olpc-activity.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * olpc-activity.c - Source for GabbleOlpcActivity - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include "olpc-activity.h" - -#include <stdlib.h> -#include <string.h> - -#include <glib.h> - -#define DEBUG_FLAG GABBLE_DEBUG_OLPC - -#include "debug.h" -#include "extensions/extensions.h" -#include "gabble-signals-marshal.h" -#include "namespaces.h" -#include "util.h" - -/* properties */ -enum -{ - PROP_CONNECTION = 1, - PROP_ROOM, - PROP_ID, - PROP_PROPERTIES, - LAST_PROPERTY -}; - -struct _GabbleOlpcActivityPrivate -{ - GabbleConnection *conn; - - gboolean dispose_has_run; -}; - -G_DEFINE_TYPE (GabbleOlpcActivity, gabble_olpc_activity, G_TYPE_OBJECT); - -static void -gabble_olpc_activity_init (GabbleOlpcActivity *self) -{ - GabbleOlpcActivityPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - GABBLE_TYPE_OLPC_ACTIVITY, GabbleOlpcActivityPrivate); - - self->priv = priv; - - priv->dispose_has_run = FALSE; -} - -static void -gabble_olpc_activity_finalize (GObject *object) -{ - GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); - - if (self->id != NULL) - { - g_free (self->id); - self->id = NULL; - } - - if (self->properties != NULL) - { - g_hash_table_unref (self->properties); - self->properties = NULL; - } - - G_OBJECT_CLASS (gabble_olpc_activity_parent_class)->finalize (object); -} - -static void -gabble_olpc_activity_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); - GabbleOlpcActivityPrivate *priv = self->priv; - - switch (property_id) - { - case PROP_CONNECTION: - g_value_set_object (value, priv->conn); - break; - case PROP_ROOM: - g_value_set_uint (value, self->room); - break; - case PROP_ID: - g_value_set_string (value, self->id); - break; - case PROP_PROPERTIES: - g_value_set_boxed (value, self->properties); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gabble_olpc_activity_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); - GabbleOlpcActivityPrivate *priv = self->priv; - - switch (property_id) - { - case PROP_CONNECTION: - priv->conn = g_value_get_object (value); - break; - case PROP_ROOM: - self->room = g_value_get_uint (value); - break; - case PROP_ID: - g_free (self->id); - self->id = g_value_dup_string (value); - break; - case PROP_PROPERTIES: - if (self->properties != NULL) - g_hash_table_unref (self->properties); - - self->properties = g_value_get_boxed (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static GObject * -gabble_olpc_activity_constructor (GType type, - guint n_props, - GObjectConstructParam *props) -{ - GObject *obj; - GabbleOlpcActivity *self; - - obj = G_OBJECT_CLASS (gabble_olpc_activity_parent_class)-> - constructor (type, n_props, props); - - self = GABBLE_OLPC_ACTIVITY (obj); - - g_assert (self->room != 0); - - DEBUG ("new activity %s (%d)", gabble_olpc_activity_get_room (self), - self->room); - - return obj; -} - -static void -gabble_olpc_activity_class_init ( - GabbleOlpcActivityClass *gabble_olpc_activity_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_activity_class); - GParamSpec *param_spec; - - object_class->get_property = gabble_olpc_activity_get_property; - object_class->set_property = gabble_olpc_activity_set_property; - object_class->constructor = gabble_olpc_activity_constructor; - - g_type_class_add_private (gabble_olpc_activity_class, - sizeof (GabbleOlpcActivityPrivate)); - - object_class->finalize = gabble_olpc_activity_finalize; - - param_spec = g_param_spec_object ( - "connection", - "GabbleConnection object", - "Gabble connection object that owns this activity object.", - GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); - - param_spec = g_param_spec_uint ( - "room", - "activity room", - "a TpHandle representing the activity room", - 0, G_MAXUINT, 0, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_ROOM, param_spec); - - param_spec = g_param_spec_string ( - "id", - "activity id", - "the activity ID", - NULL, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_ID, param_spec); - - param_spec = g_param_spec_boxed ( - "properties", - "activity properties", - "a GHashTable containing activity's properties", - G_TYPE_HASH_TABLE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_PROPERTIES, param_spec); -} - -GabbleOlpcActivity * -gabble_olpc_activity_new (GabbleConnection *conn, - TpHandle room) -{ - return g_object_new (GABBLE_TYPE_OLPC_ACTIVITY, - "connection", conn, - "room", room, - NULL); -} - -const gchar * -gabble_olpc_activity_get_room (GabbleOlpcActivity *self) -{ - TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) self->priv->conn, - TP_HANDLE_TYPE_ROOM); - - return tp_handle_inspect (room_repo, self->room); -} - -gboolean -gabble_olpc_activity_is_visible (GabbleOlpcActivity *self) -{ - GValue *gv; - - /* false if incomplete */ - if (self->id == NULL || self->properties == NULL) - return FALSE; - - gv = g_hash_table_lookup (self->properties, "private"); - if (gv == NULL) - { - return FALSE; - } - - /* if they put something non-boolean in it, err on the side of privacy */ - if (!G_VALUE_HOLDS_BOOLEAN (gv)) - return FALSE; - - /* if they specified a privacy level, go with it */ - return !g_value_get_boolean (gv); -} diff --git a/src/olpc-activity.h b/src/olpc-activity.h deleted file mode 100644 index 4c08df6cf..000000000 --- a/src/olpc-activity.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * olpc-activity.h - Header for GabbleOlpcActivity - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GABBLE_OLPC_ACTIVITY_H__ -#define __GABBLE_OLPC_ACTIVITY_H__ - -#include <glib-object.h> - -#include <telepathy-glib/telepathy-glib.h> - -#include "connection.h" - -G_BEGIN_DECLS - -typedef struct _GabbleOlpcActivity GabbleOlpcActivity; -typedef struct _GabbleOlpcActivityClass GabbleOlpcActivityClass; -typedef struct _GabbleOlpcActivityPrivate GabbleOlpcActivityPrivate; - -struct _GabbleOlpcActivityClass { - GObjectClass parent_class; -}; - -struct _GabbleOlpcActivity { - GObject parent; - - TpHandle room; - gchar *id; - GHashTable *properties; - - GabbleOlpcActivityPrivate *priv; -}; - -GType gabble_olpc_activity_get_type (void); - -/* TYPE MACROS */ -#define GABBLE_TYPE_OLPC_ACTIVITY \ - (gabble_olpc_activity_get_type ()) -#define GABBLE_OLPC_ACTIVITY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_ACTIVITY,\ - GabbleOlpcActivity)) -#define GABBLE_OLPC_ACTIVITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_ACTIVITY,\ - GabbleOlpcActivityClass)) -#define GABBLE_IS_OLPC_ACTIVITY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_ACTIVITY)) -#define GABBLE_IS_OLPC_ACTIVITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_ACTIVITY)) -#define GABBLE_OLPC_ACTIVITY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_ACTIVITY,\ - GabbleOlpcActivityClass)) - -GabbleOlpcActivity * gabble_olpc_activity_new (GabbleConnection *conn, - TpHandle room); - -const gchar * gabble_olpc_activity_get_room (GabbleOlpcActivity *activity); - -gboolean gabble_olpc_activity_is_visible (GabbleOlpcActivity *activity); - -G_END_DECLS - -#endif /* #ifndef __GABBLE_OLPC_ACTIVITY_H__ */ diff --git a/src/presence-cache.c b/src/presence-cache.c index f7d02eecf..92bc358db 100644 --- a/src/presence-cache.c +++ b/src/presence-cache.c @@ -2336,86 +2336,6 @@ gabble_presence_cache_really_remove ( tp_handle_set_remove (priv->presence_handles, handle); } -void -gabble_presence_cache_contacts_added_to_olpc_view (GabblePresenceCache *self, - TpHandleSet *handles) -{ - GArray *tmp, *changed; - guint i; - - tmp = tp_handle_set_to_array (handles); - - changed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); - - for (i = 0; i < tmp->len; i++) - { - TpHandle handle; - GabblePresence *presence; - - handle = g_array_index (tmp, TpHandle, i); - - presence = gabble_presence_cache_get (self, handle); - if (presence == NULL) - { - presence = _cache_insert (self, handle); - } - - if (gabble_presence_added_to_view (presence)) - { - g_array_append_val (changed, handle); - } - } - - if (changed->len > 0) - { - g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed); - } - - g_array_unref (tmp); - g_array_unref (changed); -} - -void -gabble_presence_cache_contacts_removed_from_olpc_view ( - GabblePresenceCache *self, - TpHandleSet *handles) -{ - GArray *tmp, *changed; - guint i; - - tmp = tp_handle_set_to_array (handles); - - changed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); - - for (i = 0; i < tmp->len; i++) - { - TpHandle handle; - GabblePresence *presence; - - handle = g_array_index (tmp, TpHandle, i); - - presence = gabble_presence_cache_get (self, handle); - if (presence == NULL) - { - presence = _cache_insert (self, handle); - } - - if (gabble_presence_removed_from_view (presence)) - { - g_array_append_val (changed, handle); - gabble_presence_cache_maybe_remove (self, handle); - } - } - - if (changed->len > 0) - { - g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed); - } - - g_array_unref (tmp); - g_array_unref (changed); -} - static gboolean gabble_presence_cache_caps_pending (GabblePresenceCache *cache, TpHandle handle) diff --git a/src/presence-cache.h b/src/presence-cache.h index 55023447f..ff177049f 100644 --- a/src/presence-cache.h +++ b/src/presence-cache.h @@ -127,12 +127,6 @@ gboolean gabble_presence_parse_presence_message ( const gchar *from, WockyStanza *message); -void gabble_presence_cache_contacts_added_to_olpc_view ( - GabblePresenceCache *cache, TpHandleSet *handles); - -void gabble_presence_cache_contacts_removed_from_olpc_view ( - GabblePresenceCache *cache, TpHandleSet *handles); - gboolean gabble_presence_cache_is_unsure (GabblePresenceCache *cache, TpHandle handle); diff --git a/src/presence.c b/src/presence.c index db9830c6e..f968f11a2 100644 --- a/src/presence.c +++ b/src/presence.c @@ -69,7 +69,6 @@ struct _GabblePresencePrivate { gchar *no_resource_status_message; GSList *resources; - guint olpc_views; gchar *active_resource; }; @@ -444,15 +443,6 @@ aggregate_resources (GabblePresence *presence) priv->active_resource = g_strdup (best->name); } - if (presence->status <= GABBLE_PRESENCE_HIDDEN && priv->olpc_views > 0) - { - /* Contact is in at least one view and we didn't receive a better - * presence from him so announce it as available */ - presence->status = GABBLE_PRESENCE_AVAILABLE; - g_free (presence->status_message); - presence->status_message = NULL; - } - return old_client_types != presence->client_types; } @@ -739,7 +729,6 @@ gabble_presence_dump (GabblePresence *presence) gboolean gabble_presence_added_to_view (GabblePresence *self) { - GabblePresencePrivate *priv = self->priv; GabblePresenceId old_status; gchar *old_status_message; gboolean ret = FALSE; @@ -748,7 +737,6 @@ gabble_presence_added_to_view (GabblePresence *self) old_status = self->status; old_status_message = g_strdup (self->status_message); - priv->olpc_views++; aggregate_resources (self); /* detect changes */ @@ -763,7 +751,6 @@ gabble_presence_added_to_view (GabblePresence *self) gboolean gabble_presence_removed_from_view (GabblePresence *self) { - GabblePresencePrivate *priv = self->priv; GabblePresenceId old_status; gchar *old_status_message; gboolean ret = FALSE; @@ -772,7 +759,6 @@ gabble_presence_removed_from_view (GabblePresence *self) old_status = self->status; old_status_message = g_strdup (self->status_message); - priv->olpc_views--; aggregate_resources (self); /* detect changes */ diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index 5865b14f5..399efdf10 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -55,12 +55,6 @@ TWISTED_TESTS = \ muc/test-muc-invitation.py \ muc/test-muc-ownership.py \ muc/test-muc.py \ - olpc/change-notifications.py \ - olpc/current-activity.py \ - olpc/olpc-muc-invitation.py \ - olpc/olpc-muc-prop-change.py \ - olpc/test-olpc-bundle.py \ - olpc/test-olpc-set-props-preload.py \ pep-support.py \ plugin-channel-managers.py \ power-save.py \ @@ -237,7 +231,6 @@ TWISTED_OTHER_FILES = \ jingle-share/jingleshareutils.py \ mucutil.py \ ns.py \ - olpc/util.py \ presence_helper.py \ presence/__init__.py \ presence/invisible_helper.py \ diff --git a/tests/twisted/ns.py b/tests/twisted/ns.py index 30f9a8114..f5f60ab77 100644 --- a/tests/twisted/ns.py +++ b/tests/twisted/ns.py @@ -45,16 +45,6 @@ NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl' NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind' NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls' NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session' -OLPC_ACTIVITIES = "http://laptop.org/xmpp/activities" -OLPC_ACTIVITIES_NOTIFY = "%s+notify" % OLPC_ACTIVITIES -OLPC_ACTIVITY = "http://laptop.org/xmpp/activity" -OLPC_ACTIVITY_PROPS = "http://laptop.org/xmpp/activity-properties" -OLPC_ACTIVITY_PROPS_NOTIFY = "%s+notify" % OLPC_ACTIVITY_PROPS -OLPC_BUDDY = "http://laptop.org/xmpp/buddy" -OLPC_BUDDY_PROPS = "http://laptop.org/xmpp/buddy-properties" -OLPC_BUDDY_PROPS_NOTIFY = "%s+notify" % OLPC_BUDDY_PROPS -OLPC_CURRENT_ACTIVITY = "http://laptop.org/xmpp/current-activity" -OLPC_CURRENT_ACTIVITY_NOTIFY = "%s+notify" % OLPC_CURRENT_ACTIVITY PUBSUB = "http://jabber.org/protocol/pubsub" PUBSUB_EVENT = "%s#event" % PUBSUB RECEIPTS = "urn:xmpp:receipts" diff --git a/tests/twisted/olpc/change-notifications.py b/tests/twisted/olpc/change-notifications.py deleted file mode 100644 index 3b637dffa..000000000 --- a/tests/twisted/olpc/change-notifications.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -test OLPC Buddy properties change notifications -""" -# FIXME: merge this file to other tests ? - -from servicetest import EventPattern -from gabbletest import exec_test, acknowledge_iq -import constants as cs -from util import send_buddy_changed_properties_msg -import ns - -def test(q, bus, conn, stream): - iq_event, disco_event = q.expect_many( - EventPattern('stream-iq', to=None, query_ns='vcard-temp', - query_name='vCard'), - EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) - - acknowledge_iq(stream, iq_event.stanza) - - handles = {} - - handles['alice'] = conn.get_contact_handle_sync('alice@localhost') - - # Alice, one our friends changed her properties - send_buddy_changed_properties_msg(stream, 'alice@localhost', - {'color': ('str', '#005FE4,#00A0FF')}) - - event = q.expect('dbus-signal', signal='PropertiesChanged', - args=[handles['alice'], {'color' : '#005FE4,#00A0FF'}]) - -if __name__ == '__main__': - exec_test(test) diff --git a/tests/twisted/olpc/current-activity.py b/tests/twisted/olpc/current-activity.py deleted file mode 100644 index 382110217..000000000 --- a/tests/twisted/olpc/current-activity.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -test OLPC Buddy properties current activity -""" - -import dbus - -from servicetest import call_async, EventPattern -from gabbletest import exec_test, acknowledge_iq -import constants as cs -from util import (send_buddy_changed_current_act_msg, - answer_to_current_act_pubsub_request, answer_error_to_pubsub_request) -import ns - -def test(q, bus, conn, stream): - iq_event, disco_event = q.expect_many( - EventPattern('stream-iq', to=None, query_ns='vcard-temp', - query_name='vCard'), - EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) - - acknowledge_iq(stream, iq_event.stanza) - - buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - - handles = {} - - # Alice is one of our friend so we receive her PEP notifications - handles['alice'] = conn.get_contact_handle_sync('alice@localhost') - - # Try to get Alice's currrent-activity - call_async(q, buddy_info_iface, "GetCurrentActivity", handles['alice']) - - # Alice's current-activity is not in the cache so Gabble sends a PEP query - event = q.expect('stream-iq', iq_type='get', query_name='pubsub') - answer_to_current_act_pubsub_request(stream, event.stanza, 'activity1', - 'room1@conference.localhost') - - event = q.expect('dbus-return', method='GetCurrentActivity') - id, handles['room1'] = event.value - assert id == 'activity1' - assert conn.InspectHandles(2, [handles['room1']]) == \ - ['room1@conference.localhost'] - - # Retry to get Alice's current-activity - # Alice's current-activity is now in the cache so Gabble doesn't - # send PEP query - assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ - ('activity1', handles['room1']) - - # Alice changed her current-activity - send_buddy_changed_current_act_msg(stream, 'alice@localhost', 'activity2', - 'room2@conference.localhost') - - event = q.expect('dbus-signal', signal='CurrentActivityChanged') - contact, id, handles['room2'] = event.args - assert contact == handles['alice'] - assert id == 'activity2' - assert conn.InspectHandles(2, [handles['room2']]) == \ - ['room2@conference.localhost'] - - # Get Alice's current-activity as the cache have to be updated - assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ - ('activity2', handles['room2']) - -if __name__ == '__main__': - exec_test(test) diff --git a/tests/twisted/olpc/olpc-muc-invitation.py b/tests/twisted/olpc/olpc-muc-invitation.py deleted file mode 100644 index 8307e2972..000000000 --- a/tests/twisted/olpc/olpc-muc-invitation.py +++ /dev/null @@ -1,234 +0,0 @@ -""" -Test OLPC extensions to MUC invitations. -""" - -import dbus - -from twisted.words.xish import domish, xpath - -from gabbletest import exec_test, make_muc_presence -from servicetest import call_async, EventPattern, wrap_channel -import constants as cs -import ns - -def test(q, bus, conn, stream): - handles = {} - handles['bob'] = conn.get_contact_handle_sync('bob@localhost') - - buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') - call_async(q, buddy_iface, 'GetActivities', handles['bob']) - - event = q.expect('stream-iq', iq_type='get', to='bob@localhost') - # Bob has no activities - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'bob@localhost' - stream.send(event.stanza) - - event = q.expect('dbus-return', method='GetActivities') - # initially, Bob has no activities - assert event.value == ([],) - - # Bob sends an activity properties message - message = domish.Element(('jabber:client', 'message')) - message['from'] = 'bob@localhost' - message['to'] = 'test@localhost' - properties = message.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties')) - properties['room'] = 'chat@conf.localhost' - properties['activity'] = 'foo_id' - property = properties.addElement((None, 'property')) - property['type'] = 'str' - property['name'] = 'color' - property.addContent('#ffff00,#00ffff') - property = properties.addElement((None, 'property')) - property['type'] = 'bool' - property['name'] = 'private' - property.addContent('1') - - stream.send(message) - - event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') - handles['chat'], props = event.args - assert props == {'color': '#ffff00,#00ffff', 'private' : True} - - event = q.expect('dbus-signal', signal='ActivitiesChanged') - assert event.args[0] == handles['bob'] - acts = event.args[1] - assert len(acts) == 1 - assert acts[0] == ('foo_id', handles['chat']) - - props = act_prop_iface.GetProperties(handles['chat']) - assert props == {'color': '#ffff00,#00ffff', 'private' : True} - - # Bobs invites us to the activity - message = domish.Element((None, 'message')) - message['from'] = 'chat@conf.localhost' - message['to'] = 'test@localhost' - x = message.addElement((ns.MUC_USER, 'x')) - invite = x.addElement((None, 'invite')) - invite['from'] = 'bob@localhost' - reason = invite.addElement((None, 'reason')) - reason.addContent('No good reason') - - stream.send(message) - - event = q.expect('dbus-signal', signal='NewChannel') - assert event.args[1] == cs.CHANNEL_TYPE_TEXT - - assert event.args[2] == 2 # handle type - assert event.args[3] == handles['chat'] # handle - - text_chan = wrap_channel(bus.get_object(conn.bus_name, event.args[0]), - 'Text') - group_iface = text_chan.Group - - members = group_iface.GetAllMembers()[0] - local_pending = group_iface.GetAllMembers()[1] - remote_pending = group_iface.GetAllMembers()[2] - - assert len(members) == 1 - assert conn.inspect_contact_sync(members[0]) == 'bob@localhost' - assert len(local_pending) == 1 - # FIXME: the username-part-is-nickname assumption - assert conn.inspect_contact_sync(local_pending[0]) == \ - 'chat@conf.localhost/test' - assert len(remote_pending) == 0 - - handles['chat_self'] = text_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, - "SelfHandle") - assert handles['chat_self'] == local_pending[0] - - # by now, we should have picked up the extra activity properties - call_async(q, buddy_iface, 'GetActivities', handles['bob']) - - event = q.expect('stream-iq', iq_type='get', to='bob@localhost') - # Bob still has no (public) activities - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'bob@localhost' - stream.send(event.stanza) - - event = q.expect('dbus-return', method='GetActivities') - - assert event.value == ([('foo_id', handles['chat'])],) - - # OK, now accept the invitation - call_async(q, group_iface, 'AddMembers', [handles['chat_self']], 'Oh, OK then') - - _, event, _ = q.expect_many( - EventPattern('stream-presence', to='chat@conf.localhost/test'), - EventPattern('dbus-signal', signal='MembersChanged'), - EventPattern('dbus-return', method='AddMembers') - ) - - assert event.args == ['', [], [handles['bob']], [], - [handles['chat_self']], 0, cs.GC_REASON_INVITED] - - # Send presence for own membership of room. - stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) - - event = q.expect('dbus-signal', signal='MembersChanged') - assert event.args == ['', [handles['chat_self']], [], [], [], 0, 0] - - call_async(q, buddy_iface, 'SetActivities', [('foo_id', handles['chat'])]) - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - q.expect('dbus-return', method='SetActivities') - call_async(q, act_prop_iface, 'SetProperties', - handles['chat'], {'color': '#ffff00,#00ffff', 'private': True}) - - event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') - chat_handle, props = event.args - assert chat_handle == handles['chat'] - assert props == {'color': '#ffff00,#00ffff', 'private' : True} - - q.expect('dbus-return', method='SetProperties') - # Test sending an invitation - handles['alice'] = conn.get_contact_handle_sync('alice@localhost') - call_async(q, group_iface, 'AddMembers', [handles['alice']], - 'I want to test invitations') - - event = q.expect('stream-message', to='alice@localhost') - message = event.stanza - - properties = xpath.queryForNodes('/message/properties', message) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'color': - assert p['type'] == 'str' - assert str(p) == '#ffff00,#00ffff' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '1' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'color' in seen, seen - assert 'private' in seen, seen - - event = q.expect('stream-message', to='chat@conf.localhost') - message = event.stanza - - x = xpath.queryForNodes('/message/x', message) - assert (x is not None and len(x) == 1), repr(x) - assert x[0].uri == ns.MUC_USER - - invites = xpath.queryForNodes('/x/invite', x[0]) - assert (invites is not None and len(invites) == 1), repr(invites) - assert invites[0]['to'] == 'alice@localhost' - - reasons = xpath.queryForNodes('/invite/reason', invites[0]) - assert (reasons is not None and len(reasons) == 1), repr(reasons) - assert str(reasons[0]) == 'I want to test invitations' - - call_async(q, act_prop_iface, 'SetProperties', - handles['chat'], {'color': '#f00baa,#f00baa', 'private': True}) - - event, apc_event, _ = q.expect_many( - EventPattern('stream-message', to='alice@localhost'), - EventPattern('dbus-signal', signal='ActivityPropertiesChanged'), - EventPattern('dbus-return', method='SetProperties'), - ) - message = event.stanza - - properties = xpath.queryForNodes('/message/properties', message) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'color': - assert p['type'] == 'str' - assert str(p) == '#f00baa,#f00baa' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '1' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'color' in seen, seen - assert 'private' in seen, seen - - chat_handle, props = apc_event.args - assert chat_handle == handles['chat'] - assert props == {'color': '#f00baa,#f00baa', 'private' : True} - -if __name__ == '__main__': - exec_test(test) diff --git a/tests/twisted/olpc/olpc-muc-prop-change.py b/tests/twisted/olpc/olpc-muc-prop-change.py deleted file mode 100644 index d18788ccd..000000000 --- a/tests/twisted/olpc/olpc-muc-prop-change.py +++ /dev/null @@ -1,403 +0,0 @@ -""" -Test OLPC MUC properties. -""" - -import dbus - -from twisted.words.xish import domish, xpath - -from gabbletest import exec_test, acknowledge_iq, make_muc_presence -from servicetest import call_async, EventPattern, wrap_channel -import constants as cs -import ns - -from mucutil import echo_muc_presence - -def test(q, bus, conn, stream): - iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', - query_name='vCard') - - acknowledge_iq(stream, iq_event.stanza) - - buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') - bob_handle = conn.get_contact_handle_sync('bob@localhost') - - # Bob invites us to a chatroom, pre-seeding properties - message = domish.Element(('jabber:client', 'message')) - message['from'] = 'bob@localhost' - message['to'] = 'test@localhost' - properties = message.addElement( - (ns.OLPC_ACTIVITY_PROPS, 'properties')) - properties['room'] = 'chat@conf.localhost' - properties['activity'] = 'foo_id' - property = properties.addElement((None, 'property')) - property['type'] = 'str' - property['name'] = 'title' - property.addContent('From the invitation') - property = properties.addElement((None, 'property')) - property['type'] = 'bool' - property['name'] = 'private' - property.addContent('1') - - stream.send(message) - - message = domish.Element((None, 'message')) - message['from'] = 'chat@conf.localhost' - message['to'] = 'test@localhost' - x = message.addElement((ns.MUC_USER, 'x')) - invite = x.addElement((None, 'invite')) - invite['from'] = 'bob@localhost' - reason = invite.addElement((None, 'reason')) - reason.addContent('No good reason') - - stream.send(message) - - event = q.expect('dbus-signal', signal='NewChannel') - - assert event.args[1] == cs.CHANNEL_TYPE_TEXT - - assert event.args[2] == 2 # handle type - assert event.args[3] == 1 # handle - room_handle = 1 - - text_chan = wrap_channel(bus.get_object(conn.bus_name, event.args[0]), - 'Text') - group_iface = text_chan.Group - - members = group_iface.GetAllMembers()[0] - local_pending = group_iface.GetAllMembers()[1] - remote_pending = group_iface.GetAllMembers()[2] - - assert len(members) == 1 - assert conn.inspect_contact_sync(members[0]) == 'bob@localhost' - bob_handle = members[0] - assert len(local_pending) == 1 - # FIXME: the username-part-is-nickname assumption - assert conn.inspect_contact_sync(local_pending[0]) == \ - 'chat@conf.localhost/test' - assert len(remote_pending) == 0 - - room_self_handle = text_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, - "SelfHandle") - assert room_self_handle == local_pending[0] - - # by now, we should have picked up the extra activity properties - buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - call_async(q, buddy_iface, 'GetActivities', bob_handle) - - event = q.expect('stream-iq', iq_type='get', to='bob@localhost') - # Bob still has no (public) activities - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'bob@localhost' - stream.send(event.stanza) - - event = q.expect('dbus-return', method='GetActivities') - - assert event.value == ([('foo_id', room_handle)],) - - props = act_prop_iface.GetProperties(room_handle) - assert len(props) == 2 - assert props['title'] == 'From the invitation' - assert props['private'] == True - - # Now Bob changes the properties - message = domish.Element(('jabber:client', 'message')) - message['from'] = 'bob@localhost' - message['to'] = 'test@localhost' - properties = message.addElement( - (ns.OLPC_ACTIVITY_PROPS, 'properties')) - properties['room'] = 'chat@conf.localhost' - properties['activity'] = 'foo_id' - property = properties.addElement((None, 'property')) - property['type'] = 'str' - property['name'] = 'title' - property.addContent('Mushroom, mushroom') - property = properties.addElement((None, 'property')) - property['type'] = 'bool' - property['name'] = 'private' - property.addContent('0') - - stream.send(message) - - event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') - - assert event.args == [room_handle, {'title': 'Mushroom, mushroom', - 'private': False }] - assert act_prop_iface.GetProperties(room_handle) == \ - event.args[1] - - # OK, now accept the invitation - call_async(q, group_iface, 'AddMembers', [room_self_handle], 'Oh, OK then') - - q.expect_many( - EventPattern('stream-presence', to='chat@conf.localhost/test'), - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [], [bob_handle], [], [room_self_handle], - 0, cs.GC_REASON_INVITED]), - EventPattern('dbus-return', method='AddMembers'), - ) - - # Send presence for own membership of room. - stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) - - event = q.expect('dbus-signal', signal='MembersChanged') - assert event.args == ['', [room_self_handle], [], [], [], 0, 0] - - call_async(q, buddy_iface, 'SetActivities', [('foo_id', room_handle)]) - - event = q.expect('stream-iq', iq_type='set') - # Now that it's not private, it'll go in my PEP - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - q.expect('dbus-return', method='SetActivities') - - # Bob changes the properties and tells the room he's done so - message = domish.Element(('jabber:client', 'message')) - message['from'] = 'chat@conf.localhost/bob' - message['to'] = 'chat@conf.localhost' - properties = message.addElement( - (ns.OLPC_ACTIVITY_PROPS, 'properties')) - properties['activity'] = 'foo_id' - property = properties.addElement((None, 'property')) - property['type'] = 'str' - property['name'] = 'title' - property.addContent('Badger badger badger') - property = properties.addElement((None, 'property')) - property['type'] = 'bool' - property['name'] = 'private' - property.addContent('0') - - stream.send(message) - - event = q.expect('stream-iq', iq_type='set') - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS - - properties = xpath.queryForNodes('/activities/properties', activities[0]) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'title': - assert p['type'] == 'str' - assert str(p) == 'Badger badger badger' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '0' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'title' in seen, seen - assert 'private' in seen, seen - - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') - - # test sets the title and sets private back to True - call_async(q, act_prop_iface, 'SetProperties', - room_handle, {'title': 'I can set the properties too', 'private': True}) - - event = q.expect('stream-message', to='chat@conf.localhost') - message = event.stanza - - properties = xpath.queryForNodes('/message/properties', message) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'title': - assert p['type'] == 'str' - assert str(p) == 'I can set the properties too' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '1' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'title' in seen, seen - assert 'private' in seen, seen - - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS - - properties = xpath.queryForNodes('/activities/properties', activities[0]) - assert properties is None, repr(properties) - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITIES - - activity = xpath.queryForNodes('/activities/activity', activities[0]) - assert activity is None, repr(activity) - - q.expect('dbus-return', method='SetProperties') - - # test sets the title and sets private back to True - call_async(q, act_prop_iface, 'SetProperties', - room_handle, {'title': 'I can set the properties too', - 'private': False}) - - event = q.expect('stream-message', to='chat@conf.localhost') - message = event.stanza - - properties = xpath.queryForNodes('/message/properties', message) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'title': - assert p['type'] == 'str' - assert str(p) == 'I can set the properties too' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '0' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'title' in seen, seen - assert 'private' in seen, seen - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS - - properties = xpath.queryForNodes('/activities/properties', activities[0]) - assert (properties is not None and len(properties) == 1), repr(properties) - assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS - assert properties[0]['room'] == 'chat@conf.localhost' - assert properties[0]['activity'] == 'foo_id' - - property = xpath.queryForNodes('/properties/property', properties[0]) - assert (property is not None and len(property) == 2), repr(property) - seen = set() - for p in property: - seen.add(p['name']) - if p['name'] == 'title': - assert p['type'] == 'str' - assert str(p) == 'I can set the properties too' - elif p['name'] == 'private': - assert p['type'] == 'bool' - assert str(p) == '0' - else: - assert False, 'Unexpected property %s' % p['name'] - assert 'title' in seen, seen - assert 'private' in seen, seen - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITIES - - activity = xpath.queryForNodes('/activities/activity', activities[0]) - assert (activity is not None and len(activity) == 1), repr(activity) - assert activity[0]['room'] == 'chat@conf.localhost' - assert activity[0]['type'] == 'foo_id' # sic - - q.expect('dbus-return', method='SetProperties') - - text_chan.Close() - - # we must echo the MUC presence so the room will actually close - event = q.expect('stream-presence', to='chat@conf.localhost/test', - presence_type='unavailable') - echo_muc_presence(q, stream, event.stanza, 'none', 'participant') - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITIES - - activity = xpath.queryForNodes('/activities/activity', activities[0]) - assert activity is None, repr(activity) - - event = q.expect('stream-iq', iq_type='set') - event.stanza['type'] = 'result' - event.stanza['to'] = 'test@localhost' - event.stanza['from'] = 'test@localhost' - stream.send(event.stanza) - - message = event.stanza - - activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', - message) - assert (activities is not None and len(activities) == 1), repr(activities) - assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS - - properties = xpath.queryForNodes('/activities/properties', activities[0]) - assert properties is None, repr(properties) - -if __name__ == '__main__': - exec_test(test) diff --git a/tests/twisted/olpc/test-olpc-bundle.py b/tests/twisted/olpc/test-olpc-bundle.py deleted file mode 100644 index 647777757..000000000 --- a/tests/twisted/olpc/test-olpc-bundle.py +++ /dev/null @@ -1,74 +0,0 @@ -"""test OLPC bundle. We shouldn't announce OLPC features until we use the OLPC -interface""" -import dbus - -from servicetest import call_async, EventPattern -from gabbletest import exec_test, acknowledge_iq - -from twisted.words.xish import domish, xpath -import ns -import constants as cs - -olpc_features = set([ns.OLPC_BUDDY_PROPS_NOTIFY, ns.OLPC_ACTIVITIES_NOTIFY, - ns.OLPC_CURRENT_ACTIVITY_NOTIFY, ns.OLPC_ACTIVITY_PROPS_NOTIFY]) - -def test(q, bus, conn, stream): - iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', - query_name='vCard') - - acknowledge_iq(stream, iq_event.stanza) - - # send diso request - m = domish.Element((None, 'iq')) - m['from'] = 'alice@jabber.laptop.org' - m['id'] = '1' - m['type'] = 'get' - query = m.addElement('query') - query['xmlns'] = ns.DISCO_INFO - stream.send(m) - - # wait for disco response - event = q.expect('stream-iq', iq_type='result', - query_ns=ns.DISCO_INFO, - to='alice@jabber.laptop.org') - - features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', - event.stanza)]) - - # OLPC NS aren't announced - assert len(olpc_features.intersection(features)) == 0 - - # Use OLPC interface - buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - call_async(q, buddy_info_iface, 'SetProperties', - {'color': '#ff0000,#0000ff'}) - - # wait for <presence> stanza - event = q.expect('stream-presence') - c_nodes = xpath.queryForNodes('/presence/c', event.stanza) - assert c_nodes is not None - assert len(c_nodes) == 1 - - # send diso request - m = domish.Element((None, 'iq')) - m['from'] = 'alice@jabber.laptop.org' - m['id'] = '2' - m['type'] = 'get' - query = m.addElement('query') - query['xmlns'] = ns.DISCO_INFO - stream.send(m) - - # wait for disco response - event = q.expect('stream-iq', iq_type='result', - query_ns=ns.DISCO_INFO, - to='alice@jabber.laptop.org') - assert event.stanza['id'] == '2' - - # OLPC NS are now announced - features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', - event.stanza)]) - - assert olpc_features.issubset(features) - -if __name__ == '__main__': - exec_test(test) diff --git a/tests/twisted/olpc/test-olpc-set-props-preload.py b/tests/twisted/olpc/test-olpc-set-props-preload.py deleted file mode 100644 index 91b8cd3f7..000000000 --- a/tests/twisted/olpc/test-olpc-set-props-preload.py +++ /dev/null @@ -1,54 +0,0 @@ - -""" -Test connecting to a server. -""" - -import dbus -from twisted.words.xish import xpath - -from gabbletest import exec_test -import ns - -def test(q, bus, conn, stream): - buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') - buddy_info_iface.SetProperties({'color': '#ff0000,#0000ff'}) - - conn.Connect() - - # buddy activities - event = q.expect('stream-iq', iq_type='set', query_name='pubsub') - assert xpath.queryForNodes( - "/iq[@type='set']/pubsub[@xmlns='%s']" - "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_ACTIVITIES), event.stanza) - - # activity properties - event = q.expect('stream-iq', iq_type='set', query_name='pubsub') - assert xpath.queryForNodes( - "/iq[@type='set']/pubsub[@xmlns='%s']" - "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_ACTIVITY_PROPS), - event.stanza) - - # buddy properties - event = q.expect('stream-iq', iq_type='set', query_name='pubsub') - iq = event.stanza - nodes = xpath.queryForNodes( - "/iq[@type='set']/pubsub[@xmlns='%s']" - "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_BUDDY_PROPS), iq) - assert nodes - - nodes = xpath.queryForNodes( - "/publish/item" - "/properties[@xmlns='%s']" - "/property" % (ns.OLPC_BUDDY_PROPS), - nodes[0]) - assert len(nodes) == 1 - assert nodes[0]['type'] == 'str' - assert nodes[0]['name'] == 'color' - text = str(nodes[0]) - assert text == '#ff0000,#0000ff', text - - iq['type'] = 'result' - stream.send(iq) - -if __name__ == '__main__': - exec_test(test, do_connect=False) diff --git a/tests/twisted/olpc/util.py b/tests/twisted/olpc/util.py deleted file mode 100644 index 2822a7f20..000000000 --- a/tests/twisted/olpc/util.py +++ /dev/null @@ -1,88 +0,0 @@ -import dbus - -from servicetest import call_async, EventPattern -from gabbletest import make_result_iq, elem, elem_iq -from twisted.words.xish import domish, xpath -from twisted.words.protocols.jabber.client import IQ -import constants as cs -import ns - -def properties_to_xml(properties): - result = [] - - for key, (type, value) in properties.iteritems(): - property = domish.Element((None, 'property')) - property['type'] = type - property['name'] = key - property.addContent(value) - result.append(property) - - return result - -def _make_pubsub_event_msg(from_, node): - # manually create the item node as we need a ref on it - item = domish.Element((None, 'item')) - - message = elem('message', from_=from_, to='test@localhost')( - elem(ns.PUBSUB_EVENT, 'event')( - elem('items', node=node)(item))) - - return message, item - -def send_buddy_changed_properties_msg(stream, from_, props): - message, item = _make_pubsub_event_msg(from_, - ns.OLPC_BUDDY_PROPS) - - properties = item.addElement((ns.OLPC_BUDDY_PROPS, 'properties')) - - for child in properties_to_xml(props): - properties.addChild(child) - - stream.send(message) - -def send_buddy_changed_current_act_msg(stream, from_, id, room): - message, item = _make_pubsub_event_msg(from_, - ns.OLPC_CURRENT_ACTIVITY) - - activity = item.addElement((ns.OLPC_CURRENT_ACTIVITY, 'activity')) - activity['room'] = room - activity['type'] = id - - stream.send(message) - -def answer_to_current_act_pubsub_request(stream, request, id, room): - # check request structure - assert request['type'] == 'get' - items = xpath.queryForNodes( - '/iq/pubsub[@xmlns="%s"]/items' % ns.PUBSUB, request)[0] - assert items['node'] == ns.OLPC_CURRENT_ACTIVITY - - reply = make_result_iq(stream, request) - reply['from'] = request['to'] - pubsub = reply.firstChildElement() - items = pubsub.addElement((None, 'items')) - items['node'] = ns.OLPC_CURRENT_ACTIVITY - item = items.addElement((None, 'item')) - item['id'] = 'itemID' - activity = item.addElement((ns.OLPC_CURRENT_ACTIVITY, 'activity')) - activity['room'] = room - activity['type'] = id - reply.send() - -def answer_error_to_pubsub_request(stream, request): - # look for node's name in the request - items = xpath.queryForNodes('/iq/pubsub/items', request)[0] - node = items['node'] - - reply = IQ(stream, "error") - reply['id'] = request['id'] - reply['from'] = request['to'] - pubsub = reply.addElement((ns.PUBSUB, 'pubsub')) - items = pubsub.addElement((None, 'items')) - items['node'] = node - error = reply.addElement((None, 'error')) - error['type'] = 'auth' - error.addElement((ns.STANZA, 'not-authorized')) - error.addElement(("%s#errors" % ns.PUBSUB, 'presence-subscription-required')) - stream.send(reply) - diff --git a/tests/twisted/test-location.py b/tests/twisted/test-location.py index 2a29700ab..40fab225b 100644 --- a/tests/twisted/test-location.py +++ b/tests/twisted/test-location.py @@ -28,13 +28,8 @@ def test(q, bus, conn, stream): conn.Connect() - # discard activities request and status change - q.expect_many( - EventPattern('stream-iq', iq_type='set', - query_ns=ns.PUBSUB), - EventPattern('dbus-signal', signal='StatusChanged', - args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), - ) + q.expect('dbus-signal', signal='StatusChanged', + args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # we now know we have PEP assertEquals(cs.LOCATION_FEATURE_CAN_SET, conn.Get(cs.CONN_IFACE_LOCATION, |