[Tkabber-dev] r741 - trunk/tkabber

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Sun Oct 1 22:08:42 MSD 2006


Author: sergei
Date: 2006-10-01 22:08:20 +0400 (Sun, 01 Oct 2006)
New Revision: 741

Modified:
   trunk/tkabber/ChangeLog
   trunk/tkabber/balloon.tcl
   trunk/tkabber/pubsub.tcl
   trunk/tkabber/tkabber.tcl
Log:
	* balloon.tcl: Wokarounded a bug when balloon shows up in wrong
	  screen if multiple monitor configuration is used in Windows
	  (thanks to Pat Thoyts).

	* pubsub.tcl: Made pubsub implementation closer to JEP-0060
	  v. 1.9. (It is still untested and unusable though.)

	* tkabber.tcl: Source pubsub.tcl.


Modified: trunk/tkabber/ChangeLog
===================================================================
--- trunk/tkabber/ChangeLog	2006-09-30 17:03:08 UTC (rev 740)
+++ trunk/tkabber/ChangeLog	2006-10-01 18:08:20 UTC (rev 741)
@@ -1,3 +1,14 @@
+2006-10-01  Sergei Golovan  <sgolovan at nes.ru>
+
+	* balloon.tcl: Wokarounded a bug when balloon shows up in wrong
+	  screen if multiple monitor configuration is used in Windows
+	  (thanks to Pat Thoyts).
+
+	* pubsub.tcl: Made pubsub implementation closer to JEP-0060
+	  v. 1.9. (It is still untested and unusable though.)
+
+	* tkabber.tcl: Source pubsub.tcl.
+
 2006-09-30  Sergei Golovan  <sgolovan at nes.ru>
 
 	* balloon.tcl: Added function balloon::setup, which is useful

Modified: trunk/tkabber/balloon.tcl
===================================================================
--- trunk/tkabber/balloon.tcl	2006-09-30 17:03:08 UTC (rev 740)
+++ trunk/tkabber/balloon.tcl	2006-10-01 18:08:20 UTC (rev 741)
@@ -31,8 +31,6 @@
 wm withdraw .balloon
 
 namespace eval balloon {
-    variable screenheight [winfo screenheight .]
-    variable screenwidth [winfo screenwidth .]
     variable _id ""
     variable _delay 600
     variable _cur ""
@@ -62,8 +60,6 @@
     variable balloon_showed 
     variable balloon_remove 
     variable max_bx 
-    variable screenwidth
-    variable screenheight
 
     if {[.balloon.text cget -text] == ""} {
 	balloon::destroy
@@ -76,27 +72,31 @@
     set b_w [winfo reqwidth .balloon]
     set b_h [winfo reqheight .balloon]
 
-    set max_bx [expr {$screenwidth - $b_w}]
-    set max_by [expr {$screenheight - $b_h}]
+    if {$::tcl_platform(platform) == "windows" && \
+	    ($mx >= [winfo screenwidth .] || $my >= [winfo screenheight .])} {
+	set b_x [expr {$mx + 1}]
+	set b_y [expr {$my + 1}]
+    } else {
+	set max_bx [expr {[winfo screenwidth .] - $b_w}]
+	set max_by [expr {[winfo screenheight .] - $b_h}]
 
-    set b_x [expr {$mx + 12}]
-    set b_y [expr {$my + 15}]
+	set b_x [expr {$mx + 12}]
+	set b_y [expr {$my + 15}]
 
-    set b_x [max [min $b_x $max_bx] 0]
-    set b_y [max [min $b_y $max_by] 0]
+	set b_x [max [min $b_x $max_bx] 0]
+	set b_y [max [min $b_y $max_by] 0]
 
-    if {($mx >= $b_x) && ($mx <= $b_x+$b_w)} {
-	if {($my >= $b_y) && ($my <= $b_y+$b_h)} {
-	    set b_y1 [expr {$my - 5 - $b_h}]
-	    if {$b_y1 >= 0} {
-		set b_y $b_y1
+	if {($mx >= $b_x) && ($mx <= $b_x+$b_w)} {
+	    if {($my >= $b_y) && ($my <= $b_y+$b_h)} {
+		set b_y1 [expr {$my - 5 - $b_h}]
+		if {$b_y1 >= 0} {
+		    set b_y $b_y1
+		}
 	    }
 	}
     }
 
     wm geometry .balloon +$b_x+$b_y
-    
-
     wm deiconify .balloon
 
     # need the raise in case we're ballooning over a detached menu (emoticons)

Modified: trunk/tkabber/pubsub.tcl
===================================================================
--- trunk/tkabber/pubsub.tcl	2006-09-30 17:03:08 UTC (rev 740)
+++ trunk/tkabber/pubsub.tcl	2006-10-01 18:08:20 UTC (rev 741)
@@ -1,23 +1,56 @@
 # $Id$
 #
 # Publish-Subscribe Support (JEP-0060)
-# Personal Eventing Protocol Support (JEP-0163)
+# Personal Eventing via Pubsub Support (JEP-0163)
 #
 
+##########################################################################
+#
+# Publish-subscribe JEP-0060
+#
+
 namespace eval pubsub {
-    variable ns(get-pending) \
-	"http://jabber.org/protocol/pubsub#get-pending"
-    variable ns(subscribe_authorization) \
-	"http://jabber.org/protocol/pubsub#subscribe_authorization"
-    variable ns(node_config) \
-	"http://jabber.org/protocol/pubsub#node_config"
+    variable ns
+    array set ns [list \
+	collections                "http://jabber.org/protocol/pubsub#collections" \
+	config-node                "http://jabber.org/protocol/pubsub#config-node" \
+	create-and-configure       "http://jabber.org/protocol/pubsub#create-and-configure" \
+	create-nodes               "http://jabber.org/protocol/pubsub#create-nodes" \
+	delete-any                 "http://jabber.org/protocol/pubsub#delete-any" \
+	delete-nodes               "http://jabber.org/protocol/pubsub#delete-nodes" \
+	get-pending                "http://jabber.org/protocol/pubsub#get-pending" \
+	instant-nodes              "http://jabber.org/protocol/pubsub#instant-nodes" \
+	item-ids                   "http://jabber.org/protocol/pubsub#item-ids" \
+	leased-subscription        "http://jabber.org/protocol/pubsub#leased-subscription" \
+	meta-data                  "http://jabber.org/protocol/pubsub#meta-data" \
+	manage-subscription        "http://jabber.org/protocol/pubsub#manage-subscription" \
+	modify-affiliations        "http://jabber.org/protocol/pubsub#modify-affiliations" \
+	multi-collection           "http://jabber.org/protocol/pubsub#multi-collection" \
+	multi-subscribe            "http://jabber.org/protocol/pubsub#multi-subscribe" \
+	outcast-affiliation        "http://jabber.org/protocol/pubsub#outcast-affiliation" \
+	persistent-items           "http://jabber.org/protocol/pubsub#persistent-items" \
+	presence-notifications     "http://jabber.org/protocol/pubsub#presence-notifications" \
+	publish                    "http://jabber.org/protocol/pubsub#publish" \
+	publisher-affiliation      "http://jabber.org/protocol/pubsub#publisher-affiliation" \
+	purge-nodes                "http://jabber.org/protocol/pubsub#purge-nodes" \
+	retract-items              "http://jabber.org/protocol/pubsub#retract-items" \
+	retrieve-affiliations      "http://jabber.org/protocol/pubsub#retrieve-affiliations" \
+	retrieve-default           "http://jabber.org/protocol/pubsub#retrieve-default" \
+	retrieve-items             "http://jabber.org/protocol/pubsub#retrieve-items" \
+	retrieve-subscriptions     "http://jabber.org/protocol/pubsub#retrieve-subscriptions" \
+	subscribe                  "http://jabber.org/protocol/pubsub#subscribe" \
+	subscription-options       "http://jabber.org/protocol/pubsub#subscription-options" \
+	subscription-notifications "http://jabber.org/protocol/pubsub#subscription-notifications" \
+	subscribe_authorization    "http://jabber.org/protocol/pubsub#subscribe_authorization" \
+	subscribe_options          "http://jabber.org/protocol/pubsub#subscribe_options" \
+	node_config                "http://jabber.org/protocol/pubsub#node_config"]
 
     variable m2a
     variable a2m
     set aff_list [list [::msgcat::mc "Owner"] owner \
-		       [::msgcat::mc "Publisher" publisher \
-		       [::msgcat::mc "None" none \
-		       [::msgcat::mc "Outcast" outcast]]]
+		       [::msgcat::mc "Publisher"] publisher \
+		       [::msgcat::mc "None"] none \
+		       [::msgcat::mc "Outcast"] outcast]
     foreach {m a} $aff_list {
 	set m2a($m) $a
 	set a2m($a) $m
@@ -37,11 +70,32 @@
 
 ##########################################################################
 #
-# Create pubsub node "node" at service "service" (8.1.2)
+# Entity use cases (5)
 #
 
-proc pubsub::create_node {service node args} {
+##########################################################################
+#
+# Discover features (5.1) is implemented in disco.tcl
+# Discover nodes (5.2) is implemented in disco.tcl
+# Discover node information (5.3) is implemented in disco.tcl
+# Discover node meta-data (5.4) is implemented in disco.tcl
+#
 
+##########################################################################
+#
+# Discover items for a node (5.5) is NOT implemented in disco.tcl
+# TODO
+#
+
+##########################################################################
+#
+# Retrieve subscriptions (5.6)
+#
+# Evaluates command for attribute lists
+#
+
+proc pubsub::retrieve_subscriptions {service args} {
+
     debugmsg pubsub [info level 0]
 
     set command ""
@@ -53,166 +107,141 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error \
+	       "pubsub::retrieve_subscriptions: -connection is mandatory"
     }
 
     if {$node == ""} {
-	set vars {}
-    } else {
-	set vars [list node $node]
+	return -code error "pubsub::retrieve_subscriptions: Node is empty"
     }
 
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
 	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag create \
-				 -vars $vars] \
-			    [jlib::wrapper:createtag configure]]] \
+	     -subtags [list [jlib::wrapper:createtag subscriptions]]] \
 	-to $service \
 	-connection $connid \
-	-command [list [namespace current]::create_node_result \
-		       $node $command]
+	-command [list [namespace current]::retrieve_subscriptions_result $command]
 }
 
-proc pubsub::create_node_result {node command res child} {
+proc pubsub::retrieve_subscriptions_result {command res child} {
 
     debugmsg pubsub [info level 0]
 
-    if {$res == "OK" && $node == ""} {
-	# Instant node: get node name from the answer
+    if {$res != "OK"} {
+	if {$command != ""} {
+	    eval $command [list $res $child]
+	}
+	return
+    }
 
-	jlib::wrapper:splitxml $child tag vars isempty chdata children
+    set items {}
 
-	if {[jlib::wrapper:getattr $vars xmlns] == $::NS(pubsub)} {
-	    foreach child1 $children {
-		jlib::wrapper:splitxml \
-		    $child1 tag1 vars1 isempty1 chdata1 children1
-		if {$tag == "create"} {
-		    set node [jlib::wrapper:getattr $vars1 node]
-		}
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
+
+	if {$tag1 != "subscriptions"} continue
+
+	foreach item $children1 {
+	    jlib::wrapper:splitxml \
+		$item tag2 vars2 isempty2 chdata2 children2
+
+	    if {$tag2 == "subscription"} {
+		lappend items $vars2
 	    }
 	}
     }
 
     if {$command != ""} {
-	eval $command [list $node $res $child]
+	eval $command [list $res $items]
     }
 }
 
 ##########################################################################
 #
-# Publish item "itemid" to pubsub node "node" at service "service" (8.1.3)
-# payload is a list of xml tags
-# node must not be empty
+# Retrieve affiliations (5.6)
+#
+# Evaluates command for attribute lists
+#
 
-proc pubsub::publish_item {service node itemid args} {
+proc pubsub::retrieve_affiliations {service args} {
 
     debugmsg pubsub [info level 0]
 
     set command ""
-    set payload {}
     foreach {key val} $args {
 	switch -- $key {
-	    -payload { set payload $val }
 	    -connection { set connid $val}
 	    -command { set command $val }
 	}
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error \
+	       "pubsub::retrieve_affiliations: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pubsub::publish_item error: Node is empty"
+	return -code error "pubsub::retrieve_affiliations: Node is empty"
     }
 
-    if {$itemid == ""} {
-	set vars {}
-    } else {
-	set vars [list id $itemid]
-    }
-
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
 	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags \
-		 [list [jlib::wrapper:createtag publish \
-			    -vars [list node $node] \
-			    -subtags [list [jlib::wrapper:createtag item \
-						-vars $vars \
-						-subtags $payload]]]]] \
+	     -subtags [list [jlib::wrapper:createtag affiliations]]] \
 	-to $service \
 	-connection $connid \
-	-command [list [namespace current]::publish_item_result $command]
+	-command [list [namespace current]::retrieve_affiliations_result $command]
 }
 
-proc pubsub::publish_item_result {command res child} {
+proc pubsub::retrieve_affiliations_result {command res child} {
 
     debugmsg pubsub [info level 0]
 
-    if {$command != ""} {
-	eval $command [list $res $child]
+    if {$res != "OK"} {
+	if {$command != ""} {
+	    eval $command [list $res $child]
+	}
+	return
     }
-}
 
-##########################################################################
-#
-# Delete item "itemid" from pubsub node "node" at service "service" (8.1.4)
-# node and itemid must not be empty
+    set items {}
 
-proc pubsub::delete_item {service node itemid args} {
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
 
-    debugmsg pubsub [info level 0]
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
 
-    set command ""
-    foreach {key val} $args {
-	switch -- $key {
-	    -connection { set connid $val}
-	    -command { set command $val }
-	}
-    }
+	if {$tag1 != "affiliations"} continue
 
-    if {![info exists connid]} {
-	set connid [jlib::route $service]
-    }
+	foreach item $children1 {
+	    jlib::wrapper:splitxml \
+		$item tag2 vars2 isempty2 chdata2 children2
 
-    if {$node == ""} {
-	return -code error "pubsub::delete_item error: Node is empty"
+	    if {$tag2 == "affiliation"} {
+		lappend items $vars2
+	    }
+	}
     }
 
-    if {$itemid == ""} {
-	return -code error "pubsub::delete_item error: Item ID is empty"
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags \
-		 [list [jlib::wrapper:createtag retract \
-			    -vars [list node $node] \
-			    -subtags \
-				[list [jlib::wrapper:createtag item \
-					   -vars [list id $itemid]]]]]] \
-	-to $service \
-	-connection $connid \
-	-command [list [namespace current]::delete_item_result $command]
-}
-
-proc pubsub::delete_item_result {command res child} {
-
-    debugmsg pubsub [info level 0]
-
     if {$command != ""} {
-	eval $command [list $res $child]
+	eval $command [list $res $items]
     }
 }
 
 ##########################################################################
 #
-# Subscribe to pubsub node "node" at service "service" (8.1.5)
-# node must not be empty
+# Subscriber use cases (6)
 #
+
+##########################################################################
+#
+# Subscribe to pubsub node "node" at service "service" (6.1)
+#
+# if node is empty then it's a subscription to root collection node (9.2)
+#
 # -jid "jid" is optional (when it's present it's included to sub request)
 #
 # -resource "res" is optional (when it's present bare_jid/res is included
@@ -221,41 +250,76 @@
 # if both options are absent then user's bare JID is included to sub
 # request
 #
+# Optional pubsub#subscribe_options parameters
+# -deliver
+# -digest
+# -expire
+# -include_body
+# -show-values
+# -subscription_type
+# -subscription_depth
+#
 
 proc pubsub::subscribe {service node args} {
+    variable ns
 
     debugmsg pubsub [info level 0]
 
     set command ""
+    set options {}
     foreach {key val} $args {
 	switch -- $key {
 	    -jid { set jid $val }
 	    -resource { set resource $val }
 	    -connection { set connid $val}
 	    -command { set command $val }
+	    -deliver -
+	    -digest -
+	    -expire -
+	    -include_body -
+	    -show-values -
+	    -subscription_type -
+	    -subscription_depth {
+		lappend options [field "pubsub#[string range $opt 1 end]" $val]
+	    }
 	}
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error "pubsub::subscribe: -connection is mandatory"
     }
 
     if {![info exists jid]} {
 	set jid [jlib::connection_bare_jid $connid]
-	if {[info exists resource]} {
-	    append jid "/$resource"
-	}
     }
 
+    if {[info exists resource]} {
+	append jid "/$resource"
+    }
+
+    set vars [list jid $jid]
     if {$node == ""} {
-	return -code error "pubsub::subscribe error: Node is empty"
+	lappend vars node $node
     }
 
+    if {![lempty $options]} {
+	set options \
+	    [list [jlib::wrapper:createtag options \
+		       -subtags \
+			   [list [jlib::wrapper:createtag x \
+				      -vars [list xmlns $::NS(data) \
+						  type submit] \
+				      -subtags \
+					  [linsert $options 0 \
+						   [form_type $ns(subscribe_options)]]]]]]
+    }
+
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
 	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag subscribe \
-				 -vars [list node $node jid $jid]]]] \
+	     -subtags [concat [list [jlib::wrapper:createtag subscribe \
+					 -vars $vars]] \
+			      $options]] \
 	-to $service \
 	-connection $connid \
 	-command [list [namespace current]::subscribe_result $command]
@@ -272,24 +336,25 @@
 	    foreach child1 $children {
 		jlib::wrapper:splitxml \
 		    $child1 tag1 vars1 isempty1 chdata1 children1
-		if {$tag == "entity"} {
+		if {$tag == "subscription"} {
 		    set node [jlib::wrapper:getattr $vars1 node]
 		    set jid [jlib::wrapper:getattr $vars1 jid]
-		    set affiliation \
-			[jlib::wrapper:getattr $vars1 affiliation]
 		    set subid [jlib::wrapper:getattr $vars1 subid]
 		    set subscription \
 			[jlib::wrapper:getattr $vars1 subscription]
+		    # TODO: subscription-options
 		    if {$command != ""} {
-			eval $command [list $res $node $jid $affiliation \
-					    $subid $subscription]
+			eval $command [list $res \
+					    [list $node $jid \
+						  $subid $subscription]]
 			return
 		    }
 		}
 	    }
 	    if {$command != ""} {
 		# Something strange: OK without subscription details
-		eval $command [list $res]
+		eval $command [list $res {}]
+		return
 	    }
 	}
     }
@@ -301,101 +366,10 @@
 
 ##########################################################################
 #
-# Approving subscription (8.1.6)
+# Unsubscribe from pubsub node "node" at service "service" (6.2)
 #
-
-proc pubsub::request_pending_subscription {service args} {
-    variable ns
-
-    debugmsg pubsub [info level 0]
-
-    foreach {key val} $args {
-	switch -- $key {
-	    -connection { set connid $val}
-	}
-    }
-    if {![info exists connid]} {
-	set connid [jlib::route $jid]
-    }
-
-    # Let xcommands.tcl do the job
-    xcommands::execute $service $ns(get-pending) -connection $connid
-}
-
-##########################################################################
+# if node is empty then it's a unsubscription from root collection node (9.2)
 #
-# Processing messages with authorization requests
-# is done in messages.tcl
-#
-
-##########################################################################
-#
-# Retrieve current affiliations (8.1.7)
-# Evaluates command with list of entity attributes lists
-#
-
-proc pubsub::request_affiliations {service args} {
-
-    debugmsg pubsub [info level 0]
-
-    foreach {key val} $args {
-	switch -- $key {
-	    -connection { set connid $val}
-	}
-    }
-    if {![info exists connid]} {
-	set connid [jlib::route $jid]
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag affiliations]]]
-	-to $service \
-	-connection $connid \
-	-command [list [namespace current]::affiliations_result $command]
-}
-
-proc pubsub::affiliations_result {command res child} {
-
-    debugmsg pubsub [info level 0]
-
-    if {$res != "OK"} {
-	if {$command != ""} {
-	    eval $command [list $res $child]
-	}
-	return
-    }
-
-    set entities {}
-
-    jlib::wrapper:splitxml $child tag vars isempty chdata children
-
-    foreach ch $children {
-	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
-
-	if {$tag1 != "affiliations"} continue
-
-	foreach entity $children1 {
-	    jlib::wrapper:splitxml \
-		$entity tag2 vars2 isempty2 chdata2 children2
-
-	    if {$tag2 == "entity"} {
-		lappend entities $vars2
-	    }
-	}
-    }
-
-    if {$command != ""} {
-	eval $command [list $res $entities]
-    }
-}
-
-##########################################################################
-#
-# Unsubscribe from pubsub node "node" at service "service" (8.1.8)
-# node must not be empty
-#
 # -jid "jid" is optional (when it's present it's included to sub request)
 #
 # -resource "res" is optional (when it's present bare_jid/res is included
@@ -405,7 +379,7 @@
 # request
 #
 
-proc pubsub::unsubscribe {service node subid args} {
+proc pubsub::unsubscribe {service node args} {
 
     debugmsg pubsub [info level 0]
 
@@ -413,6 +387,7 @@
     foreach {key val} $args {
 	switch -- $key {
 	    -jid { set jid $val }
+	    -subid { set subid $val }
 	    -resource { set resource $val }
 	    -connection { set connid $val}
 	    -command { set command $val }
@@ -420,27 +395,30 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error "pubsub::unsubscribe: -connection is mandatory"
     }
 
     if {![info exists jid]} {
 	set jid [jlib::connection_bare_jid $connid]
-	if {[info exists resource]} {
-	    append jid "/$resource"
-	}
     }
 
-    if {$node == ""} {
-	return -code error "pubsub::unsubscribe error: Node is empty"
+    if {[info exists resource]} {
+	append jid "/$resource"
     }
 
+    set vars [list jid $jid]
+    if {$node != ""} {
+	lappend vars node $node
+    }
+    if {[info exists subid]} {
+	lappend vars subid $subid
+    }
+
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
 	     -vars [list xmlns $::NS(pubsub)] \
 	     -subtags [list [jlib::wrapper:createtag unsubscribe \
-				 -vars [list node $node \
-					     subid $subid \
-					     jid $jid]]]] \
+				 -vars $vars]]] \
 	-to $service \
 	-connection $connid \
 	-command [list [namespace current]::unsubscribe_result $command]
@@ -457,10 +435,10 @@
 
 ##########################################################################
 #
-# Request and send subscription options form (8.1.9)
+# Configure subscription options (6.3)
 #
 
-proc pubsub::request_subscription_options {service node subid args} {
+proc pubsub::request_subscription_options {service node args} {
 
     debugmsg pubsub [info level 0]
 
@@ -468,6 +446,7 @@
     foreach {key val} $args {
 	switch -- $key {
 	    -jid { set jid $val }
+	    -subid { set subid $val }
 	    -resource { set resource $val }
 	    -connection { set connid $val}
 	    -command { set command $val }
@@ -475,28 +454,34 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error \
+	       "pubsub::request_subscription_options: -connection is mandatory"
     }
 
+    if {$node == ""} {
+	return -code error \
+	    "pubsub::request_subscription_options: Node is empty"
+    }
+
     if {![info exists jid]} {
 	set jid [jlib::connection_bare_jid $connid]
-	if {[info exists resource]} {
-	    append jid "/$resource"
-	}
     }
 
-    if {$node == ""} {
-	return -code error \
-	    "pubsub::request_subscription_options error: Node is empty"
+    if {[info exists resource]} {
+	append jid "/$resource"
     }
 
+    if {[info exists subid]} {
+	set vars [list node $node subid $subid jid $jid]
+    } else {
+	set vars [list node $node jid $jid]
+    }
+
     jlib::send_iq get \
 	[jlib::wrapper:createtag pubsub \
 	     -vars [list xmlns $::NS(pubsub)] \
 	     -subtags [list [jlib::wrapper:createtag options \
-				 -vars [list node $node \
-					     subid $subid \
-					     jid $jid]]]] \
+				 -vars $vars]]] \
 	-to $service \
 	-connection $connid \
 	-command [list [namespace current]::subscription_options_result \
@@ -521,7 +506,7 @@
 
 	if {$tag1 == "options"} {
 	    jlib::wrapper:splitxml \
-		$entity tag2 vars2 isempty2 chdata2 children2
+		[lindex $children1 0] tag2 vars2 isempty2 chdata2 children2
 	    set node [jlib::wrapper:getattr $vars2 node]
 	    set jid [jlib::wrapper:getattr $vars2 jid]
 	    set subid [jlib::wrapper:getattr $vars2 subid]
@@ -541,12 +526,16 @@
     destroy $w.error.msg
     $w.bbox itemconfigure 0 -state disabled
 
+    if {$subid != ""} {
+	set vars [list node $node subid $subid jid $jid]
+    } else {
+	set vars [list node $node jid $jid]
+    }
+
     jlib::send_iq set [jlib::wrapper:createtag pubsub \
 			   -vars [list xmlns $::NS(pubsub)] \
 			   -subtags [jlib::wrapper:createtag options \
-					 -vars [list node  $node \
-						     jid   $jid \
-						     subid $subid] \
+					 -vars $vars \
 					 -subtags $restags]] \
 	-to $service \
 	-connection $connid \
@@ -555,14 +544,14 @@
 
 ##########################################################################
 #
-# Get items for a node (8.1.10)
+# Retrieve items for a node (6.4)
 # Node must not be empty
 # Evaluates command with list of items
 #
-# -max_items $number (request $number last items, see example 58)
-# -items $item_id_list (request specific items, see example 60)
+# -max_items $number (request $number last items)
+# -items $item_id_list (request specific items)
 
-proc pubsub::get_items {service node subid args} {
+proc pubsub::retrieve_items {service node args} {
 
     debugmsg pubsub [info level 0]
 
@@ -570,26 +559,34 @@
     set items {}
     foreach {key val} $args {
 	switch -- $key {
-	    -connection { set connid $val}
+	    -connection { set connid $val }
 	    -command { set command $val }
+	    -subid { set subid $val }
 	    -max_items { set max_items $val }
 	    -items {
 		foreach id $val {
-		lappend items [jlib::wrapper:createtag item
-				   -vars [list id $id]]
+		    lappend items [jlib::wrapper:createtag item
+				       -vars [list id $id]]
+		}
 	    }
 	}
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error \
+	       "pubsub::retrieve_items: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pubsub::get_items error: Node is empty"
+	return -code error "pubsub::retrieve_items: Node is empty"
     }
 
-    set vars [list node $node subid $subid]
+    if {[info exists subid]} {
+	set vars [list node $node subid $subid]
+    } else {
+	set vars [list node $node]
+    }
+
     if {[info exists max_items]} {
 	lappend vars max_items $max_items
     }
@@ -627,7 +624,7 @@
 
 	foreach item $children1 {
 	    jlib::wrapper:splitxml \
-		$entity tag2 vars2 isempty2 chdata2 children2
+		$item tag2 vars2 isempty2 chdata2 children2
 
 	    if {$tag2 == "item"} {
 		lappend items $item
@@ -642,18 +639,79 @@
 
 ##########################################################################
 #
-# Discover nodes (8.1.11) implemented in disco.tcl
-# Discover node information (8.1.12) implemented in disco.tcl
-# Discover items for a node (8.1.13) implemented in disco.tcl
+# Publisher use cases (7)
 #
 
 ##########################################################################
 #
-# Configure pubsub node "node" at service "service" (8.2.1)
+# Publish item "itemid" to pubsub node "node" at service "service" (7.1)
+# payload is a LIST of xml tags
 # node must not be empty
+
+proc pubsub::publish_item {service node itemid args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    set payload {}
+    set transient 0
+    foreach {key val} $args {
+	switch -- $key {
+	    -transient { set transient $val }
+	    -payload { set payload $val }
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error "pubsub::publish_item: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error "pubsub::publish_item: Node is empty"
+    }
+
+    if {$itemid == ""} {
+	set vars {}
+    } else {
+	set vars [list id $itemid]
+    }
+
+    if {$transient} {
+	set item {}
+    } else {
+	set item [list [jlib::wrapper:createtag item \
+			    -vars $vars \
+			    -subtags $payload]]
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub)] \
+	     -subtags [list [jlib::wrapper:createtag publish \
+				 -vars [list node $node] \
+				 -subtags $item]]]
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::publish_item_result $command]
+}
+
+proc pubsub::publish_item_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$command != ""} {
+	eval $command [list $res $child]
+    }
+}
+
+##########################################################################
 #
+# Delete item "itemid" from pubsub node "node" at service "service" (7.2)
+# node and itemid must not be empty
 
-proc pubsub::configure {service node args} {
+proc pubsub::delete_item {service node itemid args} {
 
     debugmsg pubsub [info level 0]
 
@@ -666,26 +724,244 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error "pubsub::delete_item: -connection is mandatory"
     }
 
     if {$node == ""} {
+	return -code error "pubsub::delete_item: Node is empty"
+    }
+
+    if {$itemid == ""} {
+	return -code error "pubsub::delete_item: Item ID is empty"
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub)] \
+	     -subtags \
+		 [list [jlib::wrapper:createtag retract \
+			    -vars [list node $node] \
+			    -subtags \
+				[list [jlib::wrapper:createtag item \
+					   -vars [list id $itemid]]]]]] \
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::delete_item_result $command]
+}
+
+proc pubsub::delete_item_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$command != ""} {
+	eval $command [list $res $child]
+    }
+}
+
+##########################################################################
+#
+# Owner use cases (8)
+#
+
+##########################################################################
+#
+# Create pubsub node "node" at service "service" (8.1)
+#
+# 8.1.2 create_node service node -connection connid -command callback
+# or    create_node service node -access_model model -connection connid \
+#				 -command callback
+#
+# 8.1.3 create_node service node -connection connid -command callback \
+#				 -title title \
+#				  ........... \
+#				 -body_xslt xslt
+#
+# Optional pubsub#node_config parameters
+# -access_model
+# -body_xslt
+# -collection
+# -dataform_xslt
+# -deliver_notifications
+# -deliver_payloads
+# -itemreply
+# -children_association_policy
+# -children_association_whitelist
+# -children
+# -children_max
+# -max_items
+# -max_payload_size
+# -node_type
+# -notify_config
+# -notify_delete
+# -notify_retract
+# -persist_items
+# -presence_based_delivery
+# -publish_model
+# -replyroom
+# -replyto
+# -roster_groups_allowed
+# -send_last_published_item
+# -subscribe
+# -title
+# -type
+
+proc pubsub::create_node {service node args} {
+    variable ns
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    set options {}
+    set fields {}
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	    -access_model -
+	    -body_xslt -
+	    -collection -
+	    -dataform_xslt -
+	    -deliver_notifications -
+	    -deliver_payloads -
+	    -itemreply -
+	    -children_association_policy -
+	    -children_association_whitelist -
+	    -children -
+	    -children_max -
+	    -max_items -
+	    -max_payload_size -
+	    -node_type -
+	    -notify_config -
+	    -notify_delete -
+	    -notify_retract -
+	    -persist_items -
+	    -presence_based_delivery -
+	    -publish_model -
+	    -replyroom -
+	    -replyto -
+	    -roster_groups_allowed -
+	    -send_last_published_item -
+	    -subscribe -
+	    -title -
+	    -type {
+		lappend fields [field "pubsub#[string range $opt 1 end]" $val]
+	    }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error "pubsub::create_node: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	set vars {}
+    } else {
+	set vars [list node $node]
+    }
+
+    if {![lempty $fields]} {
+	set fields [linsert $fields 0 [form_type $ns(node_config)]]
+	set fields \
+	    [list [jlib::wrapper:createtag x \
+		       -vars [list xmlns $::NS(data) \
+				   type submit] \
+		       -subtags \
+			   [linsert $fields 0 \
+				    [form_type $ns(node_config)]]]]
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub)] \
+	     -subtags [list [jlib::wrapper:createtag create \
+				 -vars $vars] \
+			    [jlib::wrapper:createtag configure \
+				 -subtags $fields]]] \
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::create_node_result \
+		       $node $command]
+}
+
+proc pubsub::form_type {value} {
+    return [jlib::wrapper:createtag field \
+		-vars [list var FORM_TYPE \
+			    type hidden]
+		-subtags [list [jlib::wrapper:createtag value \
+				    -chdata $value]]]
+}
+
+proc pubsub::field {var value} {
+    return [jlib::wrapper:createtag field \
+		-vars [list var $var] \
+		-subtags [list [jlib::wrapper:createtag value \
+				    -chdata $value]]]
+}
+
+proc pubsub::create_node_result {node command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$res == "OK" && $node == ""} {
+	# Instant node: get node name from the answer
+
+	jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+	if {[jlib::wrapper:getattr $vars xmlns] == $::NS(pubsub)} {
+	    foreach child1 $children {
+		jlib::wrapper:splitxml \
+		    $child1 tag1 vars1 isempty1 chdata1 children1
+		if {$tag == "create"} {
+		    set node [jlib::wrapper:getattr $vars1 node]
+		}
+	    }
+	}
+    }
+
+    if {$command != ""} {
+	eval $command [list $node $res $child]
+    }
+}
+
+##########################################################################
+#
+# Configure pubsub node "node" at service "service" (8.2)
+# node must not be empty
+#
+
+proc pubsub::configure_node {service node args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error "pubsub::configure_node: -connection is mandatory"
+    }
+
+    if {$node == ""} {
 	return -code error \
-	    "pubsub::configure error: Node is empty"
+	    "pubsub::configure_node: Node is empty"
     }
 
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
 	     -subtags [list [jlib::wrapper:createtag configure \
 				 -vars [list node $node]]] \
 	-to $service \
 	-connection $connid \
-	-command [list [namespace current]::configure_result \
+	-command [list [namespace current]::configure_node_result \
 		       $connid $service $command]
 }
 
-proc pubsub::configure_result {connid service command res child} {
+proc pubsub::configure_node_result {connid service command res child} {
 
     debugmsg pubsub [info level 0]
 
@@ -702,19 +978,19 @@
 	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
 
 	if {$tag1 == "configure"} {
+	    set node [jlib::wrapper:getattr $vars1 node]
 	    jlib::wrapper:splitxml \
-		$entity tag2 vars2 isempty2 chdata2 children2
-	    set node [jlib::wrapper:getattr $vars2 node]
+		[lindex $children1 0] tag2 vars2 isempty2 chdata2 children2
 	    break
 	}
     }
 
     data::draw_window $children2 \
-	[list [namespace current]::send_configure
+	[list [namespace current]::send_configure_node
 	      $connid $service $node $command]
 }
 
-proc pubsub::send_configure {connid service node command w restags} {
+proc pubsub::send_configure_node {connid service node command w restags} {
 
     debugmsg pubsub [info level 0]
 
@@ -722,9 +998,9 @@
     $w.bbox itemconfigure 0 -state disabled
 
     jlib::send_iq set [jlib::wrapper:createtag pubsub \
-			   -vars [list xmlns $::NS(pubsub)] \
+			   -vars [list xmlns $::NS(pubsub#owner)] \
 			   -subtags [jlib::wrapper:createtag configure \
-					 -vars [list node  $node] \
+					 -vars [list node $node] \
 					 -subtags $restags]] \
 	-to $service \
 	-connection $connid \
@@ -733,13 +1009,99 @@
 
 ##########################################################################
 #
-# Request default configuration options (8.2.2)
-# TODO
+# Request default configuration options (8.3)
 #
 
+proc pubsub::request_default {service args} {
+    variable ns
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    set form [jlib::wrapper:createtag default]
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	    -node_type {
+		set form \
+		    [jlib::wrapper:createtag default \
+			 -subtags [list [jlib::wrapper:createtag x \
+					     -vars [list xmlns $::NS(data) \
+							 type submit] \
+					     -subtags [list [form_type $ns(node_config)] \
+							    [field pubsub#node_type $val]]]]]
+	    }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error "pubsub::request_default: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error \
+	    "pubsub::request_default: Node is empty"
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list $form] \
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::request_default_result \
+		       $connid $service $command]
+}
+
+proc pubsub::request_default_result {connid service command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$res != "OK"} {
+	if {$command != ""} {
+	    eval $command [list $res $child]
+	}
+	return
+    }
+
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
+
+	if {$tag1 == "default"} {
+	    jlib::wrapper:splitxml \
+		[lindex $children1 0] tag2 vars2 isempty2 chdata2 children2
+	    break
+	}
+    }
+
+    # TODO: Don't send the form
+    data::draw_window $children2 \
+	[list [namespace current]::send_request_results
+	      $connid $service $node $command]
+}
+
+proc pubsub::send_request_results {connid service node command w restags} {
+
+    debugmsg pubsub [info level 0]
+
+    destroy $w.error.msg
+    $w.bbox itemconfigure 0 -state disabled
+
+    jlib::send_iq set [jlib::wrapper:createtag pubsub \
+			   -vars [list xmlns $::NS(pubsub#owner)] \
+			   -subtags [jlib::wrapper:createtag default \
+					 -subtags $restags]] \
+	-to $service \
+	-connection $connid \
+	-command [list data::test_error_res $w]
+}
+
 ##########################################################################
 #
-# Delete a node (8.2.3)
+# Delete a node (8.4)
 # node must not be empty
 #
 
@@ -756,19 +1118,18 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error "pubsub::delete_node: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pubsub::delete_node error: Node is empty"
+	return -code error "pubsub::delete_node: Node is empty"
     }
 
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags \
-		 [list [jlib::wrapper:createtag delete \
-			    -vars [list node $node]]]
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag delete \
+				 -vars [list node $node]]]
 	-to $service \
 	-connection $connid \
 	-command [list [namespace current]::delete_node_result $command]
@@ -785,7 +1146,7 @@
 
 ##########################################################################
 #
-# Purge all node items (8.2.4)
+# Purge all node items (8.5)
 # node must not be empty
 #
 
@@ -802,19 +1163,18 @@
     }
 
     if {![info exists connid]} {
-	set connid [jlib::route $service]
+	return -code error "pubsub::purge_items: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pubsub::purge_items error: Node is empty"
+	return -code error "pubsub::purge_items: Node is empty"
     }
 
     jlib::send_iq set \
 	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags \
-		 [list [jlib::wrapper:createtag purge \
-			    -vars [list node $node]]]
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag purge \
+				 -vars [list node $node]]]
 	-to $service \
 	-connection $connid \
 	-command [list [namespace current]::purge_items_result $command]
@@ -831,8 +1191,283 @@
 
 ##########################################################################
 #
-# Modifying entity affiliations (8.2.5)
+# Manage subscription requests (8.6)
+# is done in messages.tcl
+#
+
+##########################################################################
+#
+# Request all pending subscription requests (8.6.1)
+#
+
+proc pubsub::request_pending_subscription {service args} {
+    variable ns
+
+    debugmsg pubsub [info level 0]
+
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error \
+	       "pubsub::request_pending_subscription: -connection is mandatory"
+    }
+
+    # Let xcommands.tcl do the job
+    xcommands::execute $service $ns(get-pending) -connection $connid
+}
+
+##########################################################################
+#
+# Manage subscriptions (8.7)
+#
+# Callback is called with list of entities:
+# {jid JID subscription SUB subid ID}
+#
+
+proc pubsub::request_subscriptions {service node args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error \
+	       "pubsub::request_subscriptions: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error "pubsub::request_subscriptions: Node is empty"
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag subscriptions \
+				 -vars [list node $node]]]]
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::subscriptions_result $command]
+}
+
+proc pubsub::subscriptions_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$res != "OK"} {
+	if {$command != ""} {
+	    eval $command [list $res $child]
+	}
+	return
+    }
+
+    set entities {}
+
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
+
+	if {$tag1 != "subscriptions"} continue
+
+	foreach entity $children1 {
+	    jlib::wrapper:splitxml \
+		$entity tag2 vars2 isempty2 chdata2 children2
+
+	    if {$tag2 == "subscription"} {
+		lappend entities $vars2
+	    }
+	}
+    }
+
+    if {$command != ""} {
+	eval $command [list $res $entities]
+    }
+}
+
+##########################################################################
+
+proc pubsub::modify_subscriptions {service node entities args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error \
+	       "pubsub::modify_subscriptions: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error "pubsub::modify_subscriptions: Node is empty"
+    }
+
+    set subscriptions {}
+    foreach entity $entities {
+	lappend subscriptions [jlib::wrapper:createtag subscription \
+				   -vars $entity]
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag subscriptions \
+				 -vars [list node $node] \
+				 -subtags $subscriptions]]]
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::modify_subscriptions_result $command]
+}
+
+proc pubsub::modify_subscriptions_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$command != ""} {
+	eval $command [list $res $child]
+    }
+}
+
+##########################################################################
+#
+# Retrieve current affiliations (8.8)
+# Evaluates command with list of entity attributes lists
+#
+
+proc pubsub::request_affiliations {service node args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error \
+	       "pubsub::request_affiliations: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error "pubsub::request_affiliations: Node is empty"
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag affiliations]]]
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::affiliations_result $command]
+}
+
+proc pubsub::affiliations_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$res != "OK"} {
+	if {$command != ""} {
+	    eval $command [list $res $child]
+	}
+	return
+    }
+
+    set entities {}
+
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
+
+	if {$tag1 != "affiliations"} continue
+
+	foreach entity $children1 {
+	    jlib::wrapper:splitxml \
+		$entity tag2 vars2 isempty2 chdata2 children2
+
+	    if {$tag2 == "affiliation"} {
+		lappend entities $vars2
+	    }
+	}
+    }
+
+    if {$command != ""} {
+	eval $command [list $res $entities]
+    }
+}
+
+##########################################################################
+
+proc pubsub::modify_affiliations {service node entities args} {
+
+    debugmsg pubsub [info level 0]
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -connection { set connid $val}
+	    -command { set command $val }
+	}
+    }
+
+    if {![info exists connid]} {
+	return -code error \
+	       "pubsub::modify_subscriptions: -connection is mandatory"
+    }
+
+    if {$node == ""} {
+	return -code error "pubsub::modify_subscriptions: Node is empty"
+    }
+
+    set affiliations {}
+    foreach entity $entities {
+	lappend affiliations [jlib::wrapper:createtag affiliation \
+				   -vars $entity]
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag pubsub \
+	     -vars [list xmlns $::NS(pubsub#owner)] \
+	     -subtags [list [jlib::wrapper:createtag affiliations \
+				 -vars [list node $node] \
+				 -subtags $affiliations]]]
+	-to $service \
+	-connection $connid \
+	-command [list [namespace current]::modify_affiliations_result $command]
+}
+
+proc pubsub::modify_affiliations_result {command res child} {
+
+    debugmsg pubsub [info level 0]
+
+    if {$command != ""} {
+	eval $command [list $res $child]
+    }
+}
+
+##########################################################################
+#
+# Modifying entity affiliations
 # node must not be empty
+# TODO
 #
 
 proc pubsub::request_entities {service node args} {
@@ -1153,23 +1788,64 @@
 
 ##########################################################################
 #
-# Collection nodes
-# TODO
+# Collection nodes (9)
 #
 
 ##########################################################################
 #
-# PEP JEP-0163
+# Subscribe to a collection node (9.1)
+# Implemented in
+# pubsub::subscribe service node id -connection connid \
+#		    -subscription_type {nodes|items} \
+#		    -subscription_depth {1|all}
 #
 
+##########################################################################
+#
+# Root collection node (9.2)
+# Implemented in pubsub::subscribe and pubsub::unsubscribe with empty node
+#
+
+##########################################################################
+#
+# Create collection node (9.3)
+# Implemented in
+# pubsub::create_node service node -connection connid \
+#		      -node_type collection
+#
+
+##########################################################################
+#
+# Create a node associated with a collection (9.4)
+# Implemented in
+# pubsub::create_node service node -connection connid \
+#		      -collection collection
+#
+
+##########################################################################
+#
+# Associate an existing node with a collection (9.5)
+# Implemented in TODO
+
+##########################################################################
+#
+# Diassociate an node from a collection (9.6)
+# Implemented in TODO
+
+##########################################################################
+##########################################################################
+#
+# Personal eventing via pubsub JEP-0163
+#
+
 namespace eval pep {}
 
 ##########################################################################
 #
-# PEP Creating a node (4.1)
-# -access mode (mode: open, presence, roster)
-# -groups groups (roster group list if access is roster)
+# PEP Creating a node (5)
 # -connection is mandatory
+# -access_model (open, presence (default), roster, whitelist)
+# -roster_groups_allowed (roster group list if access is roster)
 #
 
 proc pep::create_node {node args} {
@@ -1182,69 +1858,26 @@
     set groups {}
     foreach {key val} $args {
 	switch -- $key {
-	    -access { set access $val }
-	    -groups { set groups $val }
 	    -connection { set connid $val}
-	    -command { set command $val }
 	}
     }
 
     if {![info exists connid]} {
-	return -code error "pep::create_node error: -connection is mandatory"
+	return -code error "pep::create_node: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pep::create_node error: node must not be empty"
+	return -code error "pep::create_node: node must not be empty"
     }
 
-    if {$access == "roster" && $groups != {}} {
-	set form_type [jlib::wrapper:createtag field \
-			   -vars [list var FORM_TYPE \
-				       type hidden] \
-			   -subtags [list [jlib::wrapper:createtag value \
-					       -chdata $ns(pubsub#node_config)]]]
+    set service [jlib::connection_bare_jid $connid]
 
-	set gvalues {}
-	foreach group $groups {
-	    lappend gvalues [jlib::wrapper:createtag value -chdata $group]
-	}
-	set gfield [jlib::wrapper:createtag field \
-			-vars [list var pubsub#roster_groups_allowed] \
-			-subtags $gvalues]
-
-	set subtags [list [jlib::wrapper:createtag x
-			       -vars [list xmlns $::NS(data) \
-					   type  form] \
-			       -subtags [list $form_type $gfield]]]
-    } else {
-	set subtags {}
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag create \
-				 -vars [list node $node]] \
-			    [jlib::wrapper:createtag configure \
-				 -vars [list access $access] \
-				 -subtags $subtags]]] \
-	-connection $connid \
-	-command [list [namespace current]::create_node_result \
-		       $node $command]
+    eval [list pubsub::create_node $service $node] $args
 }
 
-proc pep::create_node_result {node command res child} {
-
-    debugmsg pep [info level 0]
-
-    if {$command != ""} {
-	eval $command [list $node $res $child]
-    }
-}
-
 ##########################################################################
 #
-# Publish item to PEP node "node" (4.2)
+# Publish item to PEP node "node" (8)
 # payload is a list of xml tags
 # node must not be empty
 # -connection is mandatory
@@ -1255,42 +1888,23 @@
     debugmsg pep [info level 0]
 
     set command ""
-    set payload {}
     foreach {key val} $args {
 	switch -- $key {
-	    -payload { set payload $val }
 	    -connection { set connid $val}
-	    -command { set command $val }
 	}
     }
 
     if {![info exists connid]} {
-	return -code error "pep::publish_item error: -connection is mandatory"
+	return -code error "pep::publish_item: -connection is mandatory"
     }
 
     if {$node == ""} {
-	return -code error "pep::publish_item error: node must not be empty"
+	return -code error "pep::publish_item: node must not be empty"
     }
 
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags \
-		 [list [jlib::wrapper:createtag publish \
-			    -vars [list node $node] \
-			    -subtags [list [jlib::wrapper:createtag item \
-						-subtags $payload]]]]] \
-	-connection $connid \
-	-command [list [namespace current]::publish_item_result $command]
-}
+    set service [jlib::connection_bare_jid $connid]
 
-proc pep::publish_item_result {command res child} {
-
-    debugmsg pep [info level 0]
-
-    if {$command != ""} {
-	eval $command [list $res $child]
-    }
+    eval [pubsub::publish_item $service $node ""] $args
 }
 
 ##########################################################################
@@ -1311,13 +1925,9 @@
 
     debugmsg pep [info level 0]
 
-    set command ""
     foreach {key val} $args {
 	switch -- $key {
-	    -jid { set jid $val }
-	    -resource { set resource $val }
 	    -connection { set connid $val}
-	    -command { set command $val }
 	}
     }
 
@@ -1329,32 +1939,9 @@
 	return -code error "pep::subscribe error: node must not be empty"
     }
 
-    if {![info exists jid]} {
-	set jid [jlib::connection_bare_jid $connid]
-	if {[info exists resource]} {
-	    append jid "/$resource"
-	}
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag subscribe \
-				 -vars [list node $node jid $jid]]]] \
-	-to $to \
-	-connection $connid \
-	-command [list [namespace current]::subscribe_result $command]
+    eval [list pubsub::subscribe $to $node] $args
 }
 
-proc pep::subscribe_result {command res child} {
-
-    debugmsg pep [info level 0]
-
-    if {$command != ""} {
-	eval $command [list $res $child]
-    }
-}
-
 ##########################################################################
 #
 # Unsubscribe from PEP node "node" at bare JID "to" (undocumented?!)
@@ -1376,10 +1963,7 @@
     set command ""
     foreach {key val} $args {
 	switch -- $key {
-	    -jid { set jid $val }
-	    -resource { set resource $val }
 	    -connection { set connid $val}
-	    -command { set command $val }
 	}
     }
 
@@ -1391,31 +1975,8 @@
 	return -code error "pep::unsubscribe error: node must not be empty"
     }
 
-    if {![info exists jid]} {
-	set jid [jlib::connection_bare_jid $connid]
-	if {[info exists resource]} {
-	    append jid "/$resource"
-	}
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag pubsub \
-	     -vars [list xmlns $::NS(pubsub)] \
-	     -subtags [list [jlib::wrapper:createtag unsubscribe \
-				 -vars [list node $node jid $jid]]]] \
-	-to $to \
-	-connection $connid \
-	-command [list [namespace current]::unsubscribe_result $command]
+    eval [list pubsub::unsubscribe $to $node] $args
 }
 
-proc pep::unsubscribe_result {command res child} {
-
-    debugmsg pep [info level 0]
-
-    if {$command != ""} {
-	eval $command [list $res $child]
-    }
-}
-
 ##########################################################################
 

Modified: trunk/tkabber/tkabber.tcl
===================================================================
--- trunk/tkabber/tkabber.tcl	2006-09-30 17:03:08 UTC (rev 740)
+++ trunk/tkabber/tkabber.tcl	2006-10-01 18:08:20 UTC (rev 741)
@@ -250,6 +250,7 @@
 load_source filters.tcl
 load_source privacy.tcl
 load_source gpgme.tcl
+load_source pubsub.tcl
 
 load_source ifacetk bwidget_workarounds.tcl
 load_source ifacetk iface.tcl



More information about the Tkabber-dev mailing list