<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;action=history&amp;feed=atom</id>
		<title>JabChapter 8 - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;action=history&amp;feed=atom"/>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;action=history"/>
		<updated>2013-06-20T00:16:25Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.11.0</generator>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=25881&amp;oldid=prev</id>
		<title>Newacct at 08:08, 10 December 2009</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=25881&amp;oldid=prev"/>
				<updated>2009-12-10T08:08:20Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 08:08, 10 December 2009&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,094:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,094:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;''The cvsmsg-s script''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;''The cvsmsg-s script''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;import jabber import sys &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;from string import split&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;import jabber import sys&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,103:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,103:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;def presenceCB(con, prs):&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;def presenceCB(con, prs):&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    type = prs.getType() parts = &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;split(&lt;/del&gt;prs.getFrom()&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;, &lt;/del&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    type = prs.getType() parts = prs.getFrom()&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.split(&lt;/ins&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    parts[0]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    parts[0]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,133:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,133:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    elif type == 'unavailable': print &amp;quot;%s is unavailable&amp;quot; % (who)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    elif type == 'unavailable': print &amp;quot;%s is unavailable&amp;quot; % (who)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;for line in sys.stdin&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.readlines()&lt;/del&gt;: message = &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;message + &lt;/del&gt;line&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;for line in sys.stdin: message &lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;+&lt;/ins&gt;= line&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;con = jabber.Client(host=Server)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;con = jabber.Client(host=Server)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,158:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,158:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;the original ''cvsmsg'' script.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;the original ''cvsmsg'' script.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;We bring in a string function that we'll be needing later in the script&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;to chop up JIDs into their component parts (''username'', ''hostname'',&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;and ''resource''):&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;import jabber import sys&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;import jabber import sys &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;tt&amp;gt;from string import split&amp;lt;/tt&amp;gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,181:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,177:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;(&amp;quot;presence callback&amp;quot;). Callbacks, in relation to programming with&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;(&amp;quot;presence callback&amp;quot;). Callbacks, in relation to programming with&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Jabber, are explained in Section 8.3.4.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Jabber, are explained in Section 8.3.4.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;We use a string method, &amp;lt;tt&amp;gt;split&amp;lt;/tt&amp;gt;,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;to chop up JIDs into their component parts (''username'', ''hostname'',&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;and ''resource'').&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;This is what the callback for handling &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;This is what the callback for handling &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,188:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,188:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;def presenceCB(con, prs):&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;def presenceCB(con, prs):&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    type = prs.getType() parts = &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;split(&lt;/del&gt;prs.getFrom()&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;, &lt;/del&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    type = prs.getType() parts = prs.getFrom()&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.split(&lt;/ins&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    parts[0]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;    parts[0]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,261:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,261:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;    type = prs.getType() parts = &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;split(&lt;/del&gt;prs.getFrom()&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;, &lt;/del&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;    type = prs.getType() parts = prs.getFrom()&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.split(&lt;/ins&gt;'/') who =&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;parts[0]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;parts[0]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,551:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1,551:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;for line in sys.stdin&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.readlines()&lt;/del&gt;: message = &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;message + &lt;/del&gt;line&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;for line in sys.stdin: message &lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;+&lt;/ins&gt;= line&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;con = jabber.Client(host=Server)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;con = jabber.Client(host=Server)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key wikicontent:diff:version:1.11a:oldid:25621:newid:25881 --&gt;
&lt;/table&gt;</summary>
		<author><name>Newacct</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=25621&amp;oldid=prev</id>
		<title>Uncopy: content navi added</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=25621&amp;oldid=prev"/>
				<updated>2009-09-18T14:22:23Z</updated>
		
		<summary type="html">&lt;p&gt;content navi added&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 14:22, 18 September 2009&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Content Programming Jabber}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;=Using Messages and Presence=&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;=Using Messages and Presence=&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Now that we have a decent grounding in the&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Now that we have a decent grounding in the&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key wikicontent:diff:version:1.11a:oldid:1748:newid:25621 --&gt;
&lt;/table&gt;</summary>
		<author><name>Uncopy</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=1748&amp;oldid=prev</id>
		<title>Mikeh at 03:02, 16 September 2006</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=JabChapter_8&amp;diff=1748&amp;oldid=prev"/>
				<updated>2006-09-16T03:02:30Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Using Messages and Presence=&lt;br /&gt;
&amp;lt;br&amp;gt;Now that we have a decent grounding in the&lt;br /&gt;
Jabber protocol and technology, let's put it to work for us. This&lt;br /&gt;
chapter fits Jabber into solutions for  two or three common problems and&lt;br /&gt;
shows how the technology and features  lend themselves very well to&lt;br /&gt;
application-to-person (A2P) scenarios.&lt;br /&gt;
&lt;br /&gt;
By way of introduction, we'll have a look at constructing and sending&lt;br /&gt;
simple Jabber messages, to effect an &amp;quot;in-your-face&amp;quot; notification&lt;br /&gt;
mechanism for a version control system.  We'll also introduce a usage of&lt;br /&gt;
the  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element as an availability indicator for&lt;br /&gt;
connecting systems. Finally we'll combine the two features&lt;br /&gt;
(&amp;lt;tt&amp;gt;&amp;amp;lt;message/&amp;amp;gt;&amp;lt;/tt&amp;gt; and the concept of  ''availability'') to make&lt;br /&gt;
the notification mechanism  &amp;quot;sensitive&amp;quot; to the presence of the person&lt;br /&gt;
being notified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CVS Notification via Jabber == &lt;br /&gt;
&amp;lt;br&amp;gt;CVS—the Concurrent Versions&lt;br /&gt;
System—allows you to comfortably create and manage versions of the&lt;br /&gt;
sources of your project. The most common use for CVS is to create and&lt;br /&gt;
manage versions of program source code, but it can be readily used for&lt;br /&gt;
any text files. For example, this book was written using DocBook SGML&lt;br /&gt;
(http://www.docbook.org), and a CVS ''repository'' was used to manage&lt;br /&gt;
different versions of the manuscript throughout the writing and editing&lt;br /&gt;
process. CVS allowed us to maintain the original source files for the&lt;br /&gt;
chapters, to compare those versions against edited files, and served as&lt;br /&gt;
a place from which older versions could be retrieved.  You can find out&lt;br /&gt;
more about CVS at http://www.cvshome.org.&lt;br /&gt;
&lt;br /&gt;
That's the &amp;quot;Versions System&amp;quot; part of CVS's  name. The &amp;quot;Concurrent&amp;quot; part&lt;br /&gt;
means that this  facility is given an extra dimension in the form of&lt;br /&gt;
group collaboration. With CVS,  more than one person can share work on a&lt;br /&gt;
project, and the various chunks of work carried out by each participant&lt;br /&gt;
are coordinated—automatically, to a large extent—by CVS. Multiple&lt;br /&gt;
changes by different people to the same file can be merged by CVS; any&lt;br /&gt;
unresolvable conflicts (which may  for example arise when more than one&lt;br /&gt;
person changes exactly the same line of source code) are flagged and&lt;br /&gt;
must be resolved by the participants  involved.&lt;br /&gt;
&lt;br /&gt;
The general idea is that you can create a project containing files and&lt;br /&gt;
directories and have it stored centrally in a CVS repository. Depending&lt;br /&gt;
on what sort of access is granted to this repository, other project&lt;br /&gt;
participants can pull down a copy of the project—those files and&lt;br /&gt;
directories—and work on it  independently. In this way, each&lt;br /&gt;
participant's work is isolated (in time and space) from the others. When&lt;br /&gt;
the work is done, the work can be sent back to the repository and the&lt;br /&gt;
changes will be merged into the central copy. After that, those merged&lt;br /&gt;
changes are available to the rest of the  participants.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CVS Watches and Notification === &lt;br /&gt;
&amp;lt;br&amp;gt;While CVS automatically handles&lt;br /&gt;
most of the tedious merging process that comes about when more than one&lt;br /&gt;
person works on a project, it also offers a facility that allows you to&lt;br /&gt;
set a &amp;quot;watch&amp;quot; on one or more  files in the project and be alerted when&lt;br /&gt;
someone else starts to work on those watched files. This is useful if&lt;br /&gt;
you wish to preempt any automatic merging process by contacting the&lt;br /&gt;
other participant and coordinating your editing efforts with him.&lt;br /&gt;
&lt;br /&gt;
There are two CVS commands involved in setting up watches and&lt;br /&gt;
notifications. There are also a couple of CVS administrative files that&lt;br /&gt;
determine how the notifications are carried out. Let's look at these&lt;br /&gt;
commands and files in turn.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== CVS commands ==== &lt;br /&gt;
&amp;lt;br&amp;gt;The CVS commands cvs watch and cvs notify are&lt;br /&gt;
used, usually in combination, by project participants to set up the&lt;br /&gt;
notification mechanism:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; cvs watch on|off&lt;br /&gt;
: Assuming we have a CVS-controlled project called ''proj1'' and we're&lt;br /&gt;
: currently inside a local checked-out copy of the project's files, we&lt;br /&gt;
: first use cvs watch to tell CVS to watch a file (&amp;quot;turn a watch&lt;br /&gt;
: ''on''&amp;quot;) that we're  interested in, which is file4 in this example: : &lt;br /&gt;
&amp;lt;code&amp;gt;yak:~/projects/proj1$ &amp;lt;tt&amp;gt;cvs watch on file4&amp;lt;/tt&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
: This causes CVS to mark file4 as &amp;quot;watched,&amp;quot; which  means any time a&lt;br /&gt;
: project participant checks out the file from the central repository,&lt;br /&gt;
: the checked-out working copy is created with read-only  attributes.&lt;br /&gt;
: This means the participant is (initially) prevented from saving any&lt;br /&gt;
: changes to that working copy. It is, in effect, a reminder to that&lt;br /&gt;
: participant to use the CVS command cvs edit, specifying file4, before&lt;br /&gt;
: commencing the edit session. Using cvs edit causes CVS to: # Remove&lt;br /&gt;
: the read-only attribute for the file &lt;br /&gt;
# Send out notifications (to those who have requested them with the cvs&lt;br /&gt;
# watch add) that the participant has  commenced editing it &lt;br /&gt;
&lt;br /&gt;
; cvs watch add|remove&lt;br /&gt;
: While running cvs watch on against a file will set a marker causing&lt;br /&gt;
: the file to be replicated with the read-only attribute when checked&lt;br /&gt;
: out (which has the effect of &amp;quot;suggesting&amp;quot; to the participant editing&lt;br /&gt;
: the file that he  use the cvs edit command to signal that he's to&lt;br /&gt;
: start editing), the actual determination of the notification&lt;br /&gt;
: recipients is  set up using the cvs watch add  command.  : Running the&lt;br /&gt;
: command: : &lt;br /&gt;
&amp;lt;code&amp;gt;yak:~/projects/proj1$ &amp;lt;tt&amp;gt;cvs watch add file4&amp;lt;/tt&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
: will arrange for the CVS notification to be sent to ''us'' when&lt;br /&gt;
: someone else signals their intention (via cvs edit) to edit file4. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== CVS administrative files ==== &lt;br /&gt;
&amp;lt;br&amp;gt;A number of administrative files used&lt;br /&gt;
to control how CVS works are kept in the central CVS repository. Two of&lt;br /&gt;
these files,  notify and users, are used to  manage the watch-based&lt;br /&gt;
notification process:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; notify&lt;br /&gt;
: The standard notify file contains a line like this: : &lt;br /&gt;
&amp;lt;code&amp;gt; ALL mail %s -s &amp;quot;CVS notification&amp;quot; &amp;lt;/code&amp;gt;&lt;br /&gt;
: The &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt; causes the formula described here to be used for any&lt;br /&gt;
: notification requirements (an alternative to  &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt; is a&lt;br /&gt;
: regular expression to match the directory name in which the edit&lt;br /&gt;
: causing the notification is being carried out). : The rest of the line&lt;br /&gt;
: is the formula to use to send the notification.  It is a simple&lt;br /&gt;
: invocation of the mail command,  specifying a subject line (&amp;lt;tt&amp;gt;-s&lt;br /&gt;
: &amp;quot;CVS notification&amp;quot;&amp;lt;/tt&amp;gt;). The &amp;lt;tt&amp;gt;%s&amp;lt;/tt&amp;gt; is a placeholder that CVS&lt;br /&gt;
: replaces with the address of the notification's intended recipient.&lt;br /&gt;
: The actual notification text, generated by CVS, is piped into the mail&lt;br /&gt;
: command via STDIN. &lt;br /&gt;
; users&lt;br /&gt;
: The users file contains a list of notification recipient addresses: : &lt;br /&gt;
&amp;lt;code&amp;gt; dj:dj.adams@pobox.com piers:pxharding@ompa.net&lt;br /&gt;
robert:robert@shiels.com ...&amp;lt;/code&amp;gt;&lt;br /&gt;
: This is a mapping from the user IDs (&amp;lt;tt&amp;gt;dj&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;piers&amp;lt;/tt&amp;gt;, and&lt;br /&gt;
: &amp;lt;tt&amp;gt;robert&amp;lt;/tt&amp;gt;) of the  CVS participants, local to the host where the&lt;br /&gt;
: CVS repository is stored, to the addresses (''dj.adams@pobox.com'',&lt;br /&gt;
: ''pxharding@ompa.net'',and ''robert@shiels.com'') that are used to&lt;br /&gt;
: replace the &amp;lt;tt&amp;gt;%s&amp;lt;/tt&amp;gt; in the formula described in the notify file. &lt;br /&gt;
&lt;br /&gt;
==== The notification ==== If the contents of the notify and users files&lt;br /&gt;
have been set up correctly,  a typical notification, set up by DJ using&lt;br /&gt;
the cvs watch on file4 and cvs watch add file4 commands, and triggered&lt;br /&gt;
by Piers using the cvs edit file4 command, will be received in DJ's&lt;br /&gt;
inbox looking like the one shown in Example 8-1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''A typical email CVS notification''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; Date: Fri, 8 Jun 2001 13:10:55 +0100 From: piers@ompa.net To:&lt;br /&gt;
dj.adams@pobox.com Subject: CVS notification&lt;br /&gt;
&lt;br /&gt;
testproject file4 --- Triggered edit watch on&lt;br /&gt;
/usr/local/cvsroot/testproject By piers&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CVS Notifications via Jabber === &lt;br /&gt;
&amp;lt;br&amp;gt;While email-based notifications are&lt;br /&gt;
useful, we can add value to this process by using a more immediate (and&lt;br /&gt;
penetrating) form of communication: Jabber. Although mail clients can be&lt;br /&gt;
configured to check for mail automatically on a regular basis, using an&lt;br /&gt;
IM-style client has a number of immediately obvious advantages:&lt;br /&gt;
&lt;br /&gt;
* It's likely to take up less screen real estate. * No amount of&lt;br /&gt;
tweaking of the mail client's autocheck frequency (which, if available,&lt;br /&gt;
will log in, check for, and ''pull'' emails from the mail server) will&lt;br /&gt;
match the immediacy of IM-style message ''push''. * In extreme cases,&lt;br /&gt;
the higher the autocheck frequency of the mail client, the higher the&lt;br /&gt;
effect on overall system performance. * Depending on the configuration,&lt;br /&gt;
an incoming Jabber message can be made to pop up, with greater effect. *&lt;br /&gt;
A Jabber user is more likely to have a Jabber client running permanently&lt;br /&gt;
than an email client. * It's more fun! The design of CVS's notification&lt;br /&gt;
mechanism is simple and abstract enough for us to put an alternative&lt;br /&gt;
notification system in place. If we substitute the formula in the notify&lt;br /&gt;
configuration file with something that will call a Jabber script,  we&lt;br /&gt;
might end up with something like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; ALL python cvsmsg %s   &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like the previous formula, it will be invoked by CVS to send the&lt;br /&gt;
notification, and the &amp;lt;tt&amp;gt;%s&amp;lt;/tt&amp;gt; will be substituted by the recipient's&lt;br /&gt;
address determined from the users file. In this case, the  Python script&lt;br /&gt;
''cvsmsg'' is called.  However, now that we're sending a notification&lt;br /&gt;
via Jabber, we need a Jabber  address—a JID—instead of an email address.&lt;br /&gt;
No problem, just edit the users file to reflect the new addresses. &lt;br /&gt;
Example 8-2 shows what the users file might contain if we were to use&lt;br /&gt;
JIDs instead of email addresses.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Matching users to JIDs in the notify file''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; dj:dj@gnu.pipetree.com piers:piers@jabber.org&lt;br /&gt;
robert:shiels@jabber.org&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As Jabber user JIDs in their most basic form (i.e., without a &lt;br /&gt;
''resource'' suffix) resemble email IDs, there doesn't appear to be that&lt;br /&gt;
much difference. In any case, CVS doesn't really care, and it takes the&lt;br /&gt;
portion following the colon separator and simply passes it to the&lt;br /&gt;
formula in the notify file.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The cvsmsg Script === &lt;br /&gt;
&amp;lt;br&amp;gt;Let's now have a look at the script, called&lt;br /&gt;
''cvsmsg''. It has to send a notification message, which it receives on&lt;br /&gt;
STDIN, to a JID, which it receives as an argument passed to the script,&lt;br /&gt;
as shown in Example 8-3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''The cvsmsg Python script''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import jabber import sys&lt;br /&gt;
&lt;br /&gt;
Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;br /&gt;
Resource = 'cvsmsg'&lt;br /&gt;
&lt;br /&gt;
cvsuser  = sys.argv[1] message  = ''&lt;br /&gt;
&lt;br /&gt;
for line in sys.stdin.readlines(): message = message + line&lt;br /&gt;
&lt;br /&gt;
con = jabber.Client(host=Server)&lt;br /&gt;
&lt;br /&gt;
try: con.connect() except IOError, e: print &amp;quot;Couldn't connect: %s&amp;quot; % e&lt;br /&gt;
sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
con.auth(Username,Password,Resource) con.send(jabber.Message(cvsuser,&lt;br /&gt;
message, subject=&amp;quot;CVS Watch Alarm&amp;quot;)) con.disconnect()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's not that long but worth breaking down to examine piece by  piece.&lt;br /&gt;
&lt;br /&gt;
We're going to use the &amp;lt;tt&amp;gt;Jabberpy&amp;lt;/tt&amp;gt; Python library for Jabber, so&lt;br /&gt;
the first thing we do in the script is import it.  We also import the&lt;br /&gt;
&amp;lt;tt&amp;gt;sys&amp;lt;/tt&amp;gt; module for reading from STDIN:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import jabber import sys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As the usage of the script will be fairly static, we can get away here&lt;br /&gt;
with hardcoding a few parameters:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password =&lt;br /&gt;
'secret' Resource = 'cvsmsg'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Specified here are the connection and authentication details for the&lt;br /&gt;
&amp;lt;tt&amp;gt;cvsmsg&amp;lt;/tt&amp;gt; script itself. If it's to send a message via Jabber, it&lt;br /&gt;
must itself connect to Jabber. The &amp;lt;tt&amp;gt;Server&amp;lt;/tt&amp;gt; variable specifies&lt;br /&gt;
which Jabber server to connect to, and the &amp;lt;tt&amp;gt;Username&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;Password&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;Resource&amp;lt;/tt&amp;gt; variables contain the rest of&lt;br /&gt;
the information for the script's own JID&lt;br /&gt;
(&amp;lt;tt&amp;gt;cvsmsg@gnu.pipetree.com/cvsmsg&amp;lt;/tt&amp;gt;) and password.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cvsuser  = sys.argv[1] message  = ''&lt;br /&gt;
&lt;br /&gt;
for line in sys.stdin.readlines(): message = message + line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;sys.argv[1]&amp;lt;/tt&amp;gt; refers to the notification recipient's JID,&lt;br /&gt;
which will be specified by the CVS notification mechanism, as it is&lt;br /&gt;
substituted for the &amp;lt;tt&amp;gt;%s&amp;lt;/tt&amp;gt; in the notify file's formula. This is&lt;br /&gt;
saved in the &amp;lt;tt&amp;gt;cvsuser&amp;lt;/tt&amp;gt; variable. We then build up the content of&lt;br /&gt;
our message body we're going to send via Jabber by reading what's&lt;br /&gt;
available on STDIN. Typically this will look  like what we saw in the&lt;br /&gt;
email message body in Example 8-1:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;testproject file4 --- Triggered edit watch on&lt;br /&gt;
/usr/local/cvsroot/testproject By piers&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con = jabber.Client(host=Server)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another &amp;lt;tt&amp;gt;Jabberpy&amp;lt;/tt&amp;gt; module, &amp;lt;tt&amp;gt;xmlstream&amp;lt;/tt&amp;gt;, handles the&lt;br /&gt;
connection to the Jabber server. We don't have to use that module&lt;br /&gt;
explicitly, however; the &amp;lt;tt&amp;gt;jabber&amp;lt;/tt&amp;gt; module  wraps and uses it,&lt;br /&gt;
shielding us from the details—hence the call to instantiate a new&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Client&amp;lt;/tt&amp;gt; object into &amp;lt;tt&amp;gt;con&amp;lt;/tt&amp;gt;, to lay the way for our&lt;br /&gt;
connection to the host specified in our &amp;lt;tt&amp;gt;Server&amp;lt;/tt&amp;gt; variable: &lt;br /&gt;
&amp;lt;tt&amp;gt;gnu.pipetree.com&amp;lt;/tt&amp;gt;. If no port is explicitly specified, the&lt;br /&gt;
standard port (5222), on which the &amp;lt;tt&amp;gt;c2s&amp;lt;/tt&amp;gt; service listens, is&lt;br /&gt;
assumed.&lt;br /&gt;
&lt;br /&gt;
The instantiation causes a number of parameters and variables to be&lt;br /&gt;
initialized, and internally an &amp;lt;tt&amp;gt;xmlstream.Client&amp;lt;/tt&amp;gt; object is &lt;br /&gt;
instantiated; various parameters are passed through from the&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Client&amp;lt;/tt&amp;gt; object (for example, for logging and debugging&lt;br /&gt;
purposes), and an XML parser object is instantiated.  This will be used&lt;br /&gt;
to parse fragments of XML that come in over the XML stream.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;try: con.connect() except IOError, e: print &amp;quot;Couldn't connect:&lt;br /&gt;
%s&amp;quot; % e sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A connection is attempted with the &amp;lt;tt&amp;gt;connect()&amp;lt;/tt&amp;gt; method of the&lt;br /&gt;
connection object in &amp;lt;tt&amp;gt;con&amp;lt;/tt&amp;gt;. This is serviced by the&lt;br /&gt;
&amp;lt;tt&amp;gt;xmlstream.Client&amp;lt;/tt&amp;gt; object and an XML stream header, as described&lt;br /&gt;
in Section 5.3, is sent to  &amp;lt;tt&amp;gt;gnu.pipetree.com:5222&amp;lt;/tt&amp;gt; in an attempt&lt;br /&gt;
to establish a client connection. An &amp;lt;tt&amp;gt;IOError&amp;lt;/tt&amp;gt; exception is&lt;br /&gt;
raised if the connection cannot be established; we trap this, after a&lt;br /&gt;
fashion, with the &amp;lt;tt&amp;gt;try: ... except&amp;lt;/tt&amp;gt; as shown.&lt;br /&gt;
&lt;br /&gt;
Once connected (meaning the client has successfully exchanged XML stream&lt;br /&gt;
headers with the server) we need to authenticate:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.auth(Username,Password,Resource)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;auth&amp;lt;/tt&amp;gt; method of the &amp;lt;tt&amp;gt;jabber.Client&amp;lt;/tt&amp;gt; object provides&lt;br /&gt;
us with a simple way of carrying out the authentication negotiation,&lt;br /&gt;
qualified with the &amp;lt;tt&amp;gt;jabber:iq:auth&amp;lt;/tt&amp;gt; namespace and described in&lt;br /&gt;
detail in Section 7.3. Although we supply our password here in the&lt;br /&gt;
script in plaintext (&amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt;), the &amp;lt;tt&amp;gt;auth&amp;lt;/tt&amp;gt; method will use&lt;br /&gt;
the IQ-get (&amp;lt;tt&amp;gt;&amp;amp;lt;iq type='get'...&amp;amp;gt;&amp;lt;/tt&amp;gt;) to retrieve  a list of&lt;br /&gt;
authentication methods supported by the server. It will try to use the&lt;br /&gt;
most secure, &amp;quot;gracefully degrading&amp;quot; to the least, until it finds  one&lt;br /&gt;
that is supported. This is shown in Figure 8-1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:jab_0801.png|Graceful degradation in authentication|center|350 px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;/code&amp;gt; Note the presence of&lt;br /&gt;
&amp;lt;tt&amp;gt;Resource&amp;lt;/tt&amp;gt; in the call. This  is required for a successful client&lt;br /&gt;
authentication regardless of the  authentication method. Sending an&lt;br /&gt;
IQ-set (&amp;lt;tt&amp;gt;&amp;amp;lt;iq type='set'...&amp;amp;gt;&amp;lt;/tt&amp;gt;) in the&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber:iq:auth&amp;lt;/tt&amp;gt; namespace without  specifying a value in a&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;resource/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag results in a &amp;quot;Not Acceptable&amp;quot; error 406;&lt;br /&gt;
see Table 5-3 for a list of standard error codes and texts.&lt;br /&gt;
&lt;br /&gt;
We're connected and authenticated. &amp;quot;The world is now our lobster,&amp;quot; as an&lt;br /&gt;
old friend used to say. We're not necessarily ''expecting'' to receive&lt;br /&gt;
anything at this stage, and even if we did, we wouldn't really want to&lt;br /&gt;
do anything with what we received anyway. So we don't bother setting up&lt;br /&gt;
any mechanism for handling elements that might appear on the stream.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.send(jabber.Message(cvsuser, message, subject=&amp;quot;CVS Watch&lt;br /&gt;
Alarm&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next step is to send the notification message (in &amp;lt;tt&amp;gt;message&amp;lt;/tt&amp;gt;)&lt;br /&gt;
to the user (in &amp;lt;tt&amp;gt;cvsuser&amp;lt;/tt&amp;gt;). There are actually two calls here.&lt;br /&gt;
The innermost call, &amp;lt;tt&amp;gt;jabber.Message()&amp;lt;/tt&amp;gt;, creates a simple message&lt;br /&gt;
element that looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;message to='[value in cvsuser variable]'&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;subject&amp;amp;gt;CVS Watch Alarm&amp;amp;lt;/subject&amp;amp;gt; &amp;amp;lt;body&amp;amp;gt;[value in&lt;br /&gt;
message variable]&amp;amp;lt;/body&amp;amp;gt; &amp;amp;lt;/message&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It takes two positional (and required) parameters; any other information&lt;br /&gt;
to be passed (such as the &amp;lt;tt&amp;gt;subject&amp;lt;/tt&amp;gt; in this example) must be&lt;br /&gt;
supplied as ''key=value'' pairs. The outermost call,&lt;br /&gt;
&amp;lt;tt&amp;gt;con.send()&amp;lt;/tt&amp;gt;, sends whatever it is given over the XML stream that&lt;br /&gt;
the &amp;lt;tt&amp;gt;jabber.Client&amp;lt;/tt&amp;gt; object &amp;lt;tt&amp;gt;con&amp;lt;/tt&amp;gt; represents. In the case&lt;br /&gt;
of the  &amp;lt;tt&amp;gt;jabber.Message&amp;lt;/tt&amp;gt; call, this is the string representation&lt;br /&gt;
of the object so created (i.e., the &amp;lt;tt&amp;gt;&amp;amp;lt;message/&amp;amp;gt;&amp;lt;/tt&amp;gt; element).&lt;br /&gt;
&lt;br /&gt;
Once the notification message has been sent, the script's work is done. &lt;br /&gt;
We can therefore disconnect from the server before exiting the script:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.disconnect()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Calling the &amp;lt;tt&amp;gt;disconnect()&amp;lt;/tt&amp;gt; method of the  &amp;lt;tt&amp;gt;jabber.Client&amp;lt;/tt&amp;gt;&lt;br /&gt;
sends an  ''unavailable'' presence element to the server on behalf of&lt;br /&gt;
the user who is connected:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence type='unavailable'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is sent regardless of whether a  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element&lt;br /&gt;
was sent during the conversation but does no harm if one wasn't.&lt;br /&gt;
&lt;br /&gt;
After sending the unavailable presence information, the XML stream is &lt;br /&gt;
closed by sending the stream's closing tag:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;/stream:stream&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This signifes to the server that the client wishes to end the&lt;br /&gt;
conversation. Finally, the socket is closed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialup System Watch == &lt;br /&gt;
&amp;lt;br&amp;gt;These days, it's becoming increasingly common&lt;br /&gt;
to have a server at home with a dialup connection to the Internet. Your&lt;br /&gt;
data, your latest developments, and your mail are stored on there. This&lt;br /&gt;
works really well when you're telecommuting and pulling those late night&lt;br /&gt;
hacking sessions at home; you have access to all your information  and&lt;br /&gt;
can connect to the Net.&lt;br /&gt;
&lt;br /&gt;
For many people, however, the reality is that it's not just at home&lt;br /&gt;
where the work gets done. Consultants, freelancers, and people with many&lt;br /&gt;
customers have their work cut out for them in  traveling to different&lt;br /&gt;
sites to complete jobs. One of the biggest issues in this respect,&lt;br /&gt;
especially in Europe where dialup and  pay-per-minute connections still&lt;br /&gt;
outweigh fixed or flat-rate connections, is the accessibility of the&lt;br /&gt;
information on the server at home, sitting behind a modem. In a lot of&lt;br /&gt;
cases, the expense of leaving the server dialed up for the duration of&lt;br /&gt;
the trip is far too great to be justified.&lt;br /&gt;
&lt;br /&gt;
One solution is to have the server dial up and connect to the Internet&lt;br /&gt;
at regular intervals, say, every hour or two, and remain connected  for&lt;br /&gt;
5 or 10 minutes. If you need access to the information or need to log on&lt;br /&gt;
to your server and run a few tests, you can hold the connection open,&lt;br /&gt;
once you've connected to it,  by running a ping, for example.&lt;br /&gt;
&lt;br /&gt;
The problem here, though, is timing. Due to the inevitable&lt;br /&gt;
synchronization problems between wristwatch and PC clock, eddies in the&lt;br /&gt;
space-time continuum, and the fact that people simply forget to check&lt;br /&gt;
the time, the online window of the server's dialup is often missed.&lt;br /&gt;
&lt;br /&gt;
The essence of this problem is a ''presence'' thing. We need to know&lt;br /&gt;
about the presence, the availability, of our server at home, with&lt;br /&gt;
respect to the Internet.&lt;br /&gt;
&lt;br /&gt;
Using Jabber as your IM mechanism at work, it's likely that you'll have&lt;br /&gt;
a Jabber client of some sort on your laptop or desktop at the customer&lt;br /&gt;
sites.  Whether it's WinJab on Windows, Jarl in Command Line Interface&lt;br /&gt;
(CLI) mode on a remote server over an SSH connection, or any other type&lt;br /&gt;
of Jabber client and connection, the point is that the client turns out&lt;br /&gt;
to be an ideal ready-made component for solving the dialup timing&lt;br /&gt;
problem. Here's how it works:&lt;br /&gt;
&lt;br /&gt;
* Get the server to dial up and connect to the Internet regularly. * On&lt;br /&gt;
connection, start a script that sends Jabber presence to you. * On&lt;br /&gt;
disconnection, get the script to end. If you add to your roster a JID&lt;br /&gt;
that represents the server at home, it would be possible to subscribe to&lt;br /&gt;
the server's presence and know when it was available—connected to the&lt;br /&gt;
Internet—and when it wasn't.&lt;br /&gt;
&lt;br /&gt;
The script we're going to write to send Jabber presence is called&lt;br /&gt;
''HostAlive''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Preparations for Execution === &lt;br /&gt;
&amp;lt;br&amp;gt;Before diving into the script,&lt;br /&gt;
it's necessary to do a bit of preparation. We're going to be using the&lt;br /&gt;
''presence subscription'' concept, which was described in Chapter 5 and&lt;br /&gt;
is covered in more detail in the next section in this chapter. We're&lt;br /&gt;
also going to have to get the script to run, and stay running, when the&lt;br /&gt;
dialup connection is made and have it stop when the dialup connection is&lt;br /&gt;
ended.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Presence ==== &lt;br /&gt;
&amp;lt;br&amp;gt;Rather than get involved in the nitty-gritty of&lt;br /&gt;
presence subcriptions right now, let's use the tools that are around us&lt;br /&gt;
to get things set up. In order for this to work, we need to be&lt;br /&gt;
subscribed to the presence of the script that will be invoked when the&lt;br /&gt;
server dials up and connects to the Internet. The script will connect to&lt;br /&gt;
the Jabber server using a JID with a username that represents the Linux&lt;br /&gt;
server: ''myserver@gnu.pipetree.com''. My JID in this case is&lt;br /&gt;
''dj@gnu.pipetree.com'', so we just use whatever Jabber client happens&lt;br /&gt;
to be at hand, say, Jabber Instant Messenger (JIM), to effect both sides&lt;br /&gt;
of the subscription.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; Step 1: Create JID myserver@gnu.pipetree.com&lt;br /&gt;
: We need to create the script's JID if it doesn't already exist. We can&lt;br /&gt;
: use the reguser script we wrote in  Section 7.4 to do this: : &lt;br /&gt;
&amp;lt;code&amp;gt; [dj@yak dj]$ &amp;lt;tt&amp;gt;./reguser gnu.pipetree.com username=myserver&lt;br /&gt;
password=secret&amp;lt;/tt&amp;gt; [Attempt] (myserver) Successful registration&lt;br /&gt;
[dj@yak dj]$ &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Step 2: Subscribe to myserver's presence&lt;br /&gt;
: We start JIM with the JID ''dj@gnu.pipetree.com'' and then add&lt;br /&gt;
: ''myserver@gnu.pipetree.com'' to the roster. This should automatically&lt;br /&gt;
: send a presence subscription request to the JID. Adding the JID to the&lt;br /&gt;
: roster using JIM is shown in  Figure 8-2. &lt;br /&gt;
; Step 3: Accept presence subscription as myserver&lt;br /&gt;
: Using the JIM client, we reconnect with the ''myserver'' JID and&lt;br /&gt;
: accept the presence subscription request from Step 2, so that&lt;br /&gt;
: ''dj@gnu.pipetree.com'' will automatically receive&lt;br /&gt;
: ''myserver@gnu.pipetree.com'''s availability information. Whether or&lt;br /&gt;
: not ''myserver'' subscribes to ''dj'''s presence is irrelevant in this&lt;br /&gt;
: case, as the script itself is not interested in the availability of&lt;br /&gt;
: anyone at all. &lt;br /&gt;
[[image:jab_0802.png|Adding myserver@gnu.pipetree.com to the&lt;br /&gt;
roster|center|350 px]]&lt;br /&gt;
&amp;lt;/code&amp;gt; At this stage, the entry in&lt;br /&gt;
''dj@gnu.pipetree.com'''s roster that represents the Linux server will&lt;br /&gt;
indicate whether the script run at dialup time is active. If we continue&lt;br /&gt;
to use the JIM client, we will see that active status is shown by a&lt;br /&gt;
yellow bulb and inactive by no icon at all.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Starting and stopping the script ==== &lt;br /&gt;
&amp;lt;br&amp;gt;The dialup connection is set&lt;br /&gt;
up using the Point-to-Point Protocol daemon pppd. This uses a program&lt;br /&gt;
such as  chat to talk to the modem and get it to dial the ISP. The pppd&lt;br /&gt;
mechanism affords us an ideal way to start and stop a script on the&lt;br /&gt;
respective connection and disconnection of the line. When the &lt;br /&gt;
connection has been made, the script /etc/ppp/ip-up is invoked and&lt;br /&gt;
passed a number of connection-related parameters. Similarly&lt;br /&gt;
/etc/ppp/ip-down is invoked when the  connection is closed.&lt;br /&gt;
&lt;br /&gt;
Some implementations of pppd also offer  /etc/ppp/ip-up.local and&lt;br /&gt;
/etc/ppp/ip-down.local, which should be used  in place of the ip-up and&lt;br /&gt;
ip-down scripts if they exist. These &amp;lt;tt&amp;gt;.local&amp;lt;/tt&amp;gt; versions are&lt;br /&gt;
intended to separate out system-specific connection-related activities&lt;br /&gt;
from general connection-related activities, in a similar way to how the&lt;br /&gt;
rc.local file allows system-specific startup activities to be defined in&lt;br /&gt;
the  /etc/rc.d/ Unix System V set of runlevel directories.&lt;br /&gt;
&lt;br /&gt;
So what we want to do is start ''HostAlive'' with &lt;br /&gt;
&amp;lt;tt&amp;gt;ip-up[.local]&amp;lt;/tt&amp;gt; and stop it with &amp;lt;tt&amp;gt;ip-down[.local]&amp;lt;/tt&amp;gt;. What&lt;br /&gt;
these starter and stopper  scripts might look like is shown in Example&lt;br /&gt;
8-4 and Example 8-5. They are simply shell scripts that share the&lt;br /&gt;
process ID (PID) of the Jabber script via a temporary file. The starter&lt;br /&gt;
starts the Jabber script and writes the PID of that script to a file.&lt;br /&gt;
The stopper kills the script using the PID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''An ip-up starter script''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
# Change to working directory&lt;br /&gt;
cd /jabber/java/&lt;br /&gt;
&lt;br /&gt;
# Call the Jabber script and put to background&lt;br /&gt;
/usr/java/jdk1.3.1/bin/java -classpath jabberbeans.jar:. HostAlive $5&lt;br /&gt;
/&amp;amp;amp;&lt;br /&gt;
&lt;br /&gt;
# Write the running script's PID&lt;br /&gt;
echo $! &amp;amp;gt; /tmp/HostAlive.pid&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''An ip-down stopper script''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
# Simply kill the process using the JID written by the starter script&lt;br /&gt;
/bin/kill `cat /tmp/HostAlive.pid`&lt;br /&gt;
&lt;br /&gt;
# Remove the PID file&lt;br /&gt;
/bin/rm /tmp/HostAlive.pid&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example 8-4 shows that we're passing through one of the parameters that&lt;br /&gt;
pppd gives to the ''ip-up'' script: the remote IP address—by  which the&lt;br /&gt;
server is known during its temporary connection to the Internet—in the&lt;br /&gt;
&amp;lt;tt&amp;gt;$5&amp;lt;/tt&amp;gt; variable.&amp;lt;ref&amp;gt;The parameters that are passed from pppd to&lt;br /&gt;
the ''ip-up'' script are:  ''interface-name'', ''tty-device'',&lt;br /&gt;
''speed'', ''local-link-local-address'', ''remote-link-local-address'',&lt;br /&gt;
and ''ipparam''. It's the  ''remote-link-local-address'' that we're&lt;br /&gt;
interested in here. &amp;lt;/ref&amp;gt; This IP address can be passed along as part&lt;br /&gt;
of the availability information in the &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
element, so that the recipient (''dj'') can see what IP address has been&lt;br /&gt;
assigned to the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The HostAlive Script === &lt;br /&gt;
&amp;lt;br&amp;gt;As you might have guessed from looking at&lt;br /&gt;
Example 8-4, we're going to write ''HostAlive'' in Java, shown in&lt;br /&gt;
Example 8-6. We'll use the &amp;lt;tt&amp;gt;JabberBeans&amp;lt;/tt&amp;gt; library; see Section P.4&lt;br /&gt;
in the Preface for details of where to get this library and what the&lt;br /&gt;
requirements are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''The HostAlive script, written in Java''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import org.jabber.jabberbeans.*; import&lt;br /&gt;
org.jabber.jabberbeans.Extension.*; import java.net.InetAddress;&lt;br /&gt;
&lt;br /&gt;
public class HostAlive { public static final String SERVER   =&lt;br /&gt;
&amp;quot;gnu.pipetree.com&amp;quot;; public static final String USER     = &amp;quot;myserver&amp;quot;;&lt;br /&gt;
public static final String PASSWORD = &amp;quot;secret&amp;quot;; public static final&lt;br /&gt;
String RESOURCE = &amp;quot;alive&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public static void main(String argv[]) {&lt;br /&gt;
&lt;br /&gt;
    ConnectionBean cb=new ConnectionBean();&lt;br /&gt;
&lt;br /&gt;
    InetAddress addr;&lt;br /&gt;
&lt;br /&gt;
    try { cb.connect(addr=InetAddress.getByName(SERVER));&lt;br /&gt;
    }&lt;br /&gt;
    catch (java.net.UnknownHostException e) { &lt;br /&gt;
      //from getByName()&lt;br /&gt;
      System.out.println(&amp;quot;Cannot resolve &amp;quot; + SERVER + &amp;quot;:&amp;quot; +&lt;br /&gt;
      e.toString()); return;&lt;br /&gt;
    }&lt;br /&gt;
    catch (java.io.IOException e) {&lt;br /&gt;
      //from connect()&lt;br /&gt;
       System.out.println(&amp;quot;Cannot connect to &amp;quot; + SERVER); return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    InfoQueryBuilder iqb=new InfoQueryBuilder(); InfoQuery iq;&lt;br /&gt;
    IQAuthBuilder iqAuthb=new IQAuthBuilder();&lt;br /&gt;
&lt;br /&gt;
    iqb.setType(&amp;quot;set&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    iqAuthb.setUsername(USER); iqAuthb.setPassword(PASSWORD);&lt;br /&gt;
    iqAuthb.setResource(RESOURCE);&lt;br /&gt;
&lt;br /&gt;
    try { iqb.addExtension(iqAuthb.build());&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) {&lt;br /&gt;
      //building failed ?&lt;br /&gt;
      System.out.println(&amp;quot;Fatal Error on Auth object build:&amp;quot;);&lt;br /&gt;
      System.out.println(e.toString()); System.exit(0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
      //build the full InfoQuery packet&lt;br /&gt;
      iq=(InfoQuery)iqb.build();&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) {&lt;br /&gt;
      //building failed ?&lt;br /&gt;
      System.out.println(&amp;quot;Fatal Error on IQ object build:&amp;quot;);&lt;br /&gt;
      System.out.println(e.toString()); return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cb.send(iq);&lt;br /&gt;
&lt;br /&gt;
    PresenceBuilder pb=new PresenceBuilder(); pb.setStatus(argv[0]);&lt;br /&gt;
&lt;br /&gt;
    try { cb.send(pb.build());&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) { System.out.println(&amp;quot;Fatal Error&lt;br /&gt;
    on Presence object build:&amp;quot;); System.out.println(e.toString());&lt;br /&gt;
    return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    while (true) { try { Thread.sleep(9999);&lt;br /&gt;
      }&lt;br /&gt;
      catch (InterruptedException e) { System.out.println(&amp;quot;timeout!&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Step by Step === &lt;br /&gt;
&amp;lt;br&amp;gt;We'll examine the script a chunk at a time. We&lt;br /&gt;
start by importing the libraries (the classes) we would like to  use:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import org.jabber.jabberbeans.*; import&lt;br /&gt;
org.jabber.jabberbeans.Extension.*; import java.net.InetAddress;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;JabberBeans&amp;lt;/tt&amp;gt; library is highly modular and designed so we&lt;br /&gt;
can pick only the features that we need; in this case, however, we're&lt;br /&gt;
just going to import the whole set of classes within the &lt;br /&gt;
&amp;lt;tt&amp;gt;org.jabber.jabberbeans&amp;lt;/tt&amp;gt; and &lt;br /&gt;
&amp;lt;tt&amp;gt;org.jabber.jabberbeans.Extension&amp;lt;/tt&amp;gt; packages, for simplicity.&lt;br /&gt;
&lt;br /&gt;
We're also going to be manipulating the Jabber server's hostname, so we&lt;br /&gt;
pull in the &amp;lt;tt&amp;gt;InetAddress&amp;lt;/tt&amp;gt; class for convenience.&lt;br /&gt;
&lt;br /&gt;
The script must connect to the Jabber server on  ''gnu.pipetree.com'' as&lt;br /&gt;
the ''myserver'' user. We define some constants for this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;public class HostAlive { public static final String SERVER   =&lt;br /&gt;
&amp;quot;gnu.pipetree.com&amp;quot;; public static final String USER     = &amp;quot;myserver&amp;quot;;&lt;br /&gt;
public static final String PASSWORD = &amp;quot;secret&amp;quot;; public static final&lt;br /&gt;
String RESOURCE = &amp;quot;alive&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the same way as with the Python-based CVS notification script earlier&lt;br /&gt;
in this chapter, we also start off by building a connection to the&lt;br /&gt;
Jabber server. As before, it's a two-stage process. The first stage is&lt;br /&gt;
to create the connection object:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;  public static void main(String argv[]) {&lt;br /&gt;
&lt;br /&gt;
    ConnectionBean cb=new ConnectionBean();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;ConnectionBean&amp;lt;/tt&amp;gt; object represents the connection between the&lt;br /&gt;
script and the Jabber server. All XML fragments (Jabber elements) pass&lt;br /&gt;
through this object.&lt;br /&gt;
&lt;br /&gt;
Then it's time to attempt the socket connection and the exchange of XML&lt;br /&gt;
stream headers:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    InetAddress addr;&lt;br /&gt;
&lt;br /&gt;
    try { cb.connect(addr=InetAddress.getByName(SERVER));&lt;br /&gt;
    }&lt;br /&gt;
    catch (java.net.UnknownHostException e) { &lt;br /&gt;
      //from getByName()&lt;br /&gt;
      System.out.println(&amp;quot;Cannot resolve &amp;quot; + SERVER + &amp;quot;:&amp;quot; +&lt;br /&gt;
      e.toString()); return;&lt;br /&gt;
    }&lt;br /&gt;
    catch (java.io.IOException e) {&lt;br /&gt;
      //from connect()&lt;br /&gt;
       System.out.println(&amp;quot;Cannot connect to &amp;quot; + SERVER); return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We create an Internet address object in &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; from the hostname&lt;br /&gt;
assigned to the &amp;lt;tt&amp;gt;SERVER&amp;lt;/tt&amp;gt; constant. As the creation of the&lt;br /&gt;
&amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; instance may throw an exception (''Unknown Host''), we&lt;br /&gt;
combine the  instantiation with the &amp;lt;tt&amp;gt;connection()&amp;lt;/tt&amp;gt; call on the&lt;br /&gt;
&amp;lt;tt&amp;gt;ConnectionBean&amp;lt;/tt&amp;gt; object, which may also throw an exception of its&lt;br /&gt;
own—if there is a problem connecting.&lt;br /&gt;
&lt;br /&gt;
At this stage, we're connected and have successfully exchanged the XML&lt;br /&gt;
stream headers with the Jabber server. So now we must authenticate:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    InfoQueryBuilder iqb=new InfoQueryBuilder(); InfoQuery iq;&lt;br /&gt;
IQAuthBuilder iqAuthb=new IQAuthBuilder();&lt;br /&gt;
&lt;br /&gt;
    iqb.setType(&amp;quot;set&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    iqAuthb.setUsername(USER); iqAuthb.setPassword(PASSWORD);&lt;br /&gt;
    iqAuthb.setResource(RESOURCE);&lt;br /&gt;
&lt;br /&gt;
    try { iqb.addExtension(iqAuthb.build());&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) {&lt;br /&gt;
      //building failed ?&lt;br /&gt;
      System.out.println(&amp;quot;Fatal Error on Auth object build:&amp;quot;);&lt;br /&gt;
      System.out.println(e.toString()); System.exit(0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
      //build the full InfoQuery packet&lt;br /&gt;
      iq=(InfoQuery)iqb.build();&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) {&lt;br /&gt;
      //building failed ?&lt;br /&gt;
      System.out.println(&amp;quot;Fatal Error on IQ object build:&amp;quot;);&lt;br /&gt;
      System.out.println(e.toString()); return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cb.send(iq);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Yes, that's an awful lot. Let's take it bit by bit.&lt;br /&gt;
&lt;br /&gt;
Figure 8-3 shows how the objects in this  section of code interrelate&lt;br /&gt;
and represent various parts of what we're trying to do—which is to&lt;br /&gt;
construct an authorization packet. This takes the form of an IQ-set&lt;br /&gt;
containing a  &amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag qualified by the&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber:iq:auth&amp;lt;/tt&amp;gt; namespace like this:&amp;lt;ref&amp;gt;We're not bothering in&lt;br /&gt;
this example to ask the server for the authentication methods it&lt;br /&gt;
supports and are just going ahead with a plaintext attempt. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;iq type='set'&amp;amp;gt; &amp;amp;lt;query xmlns='jabber:iq:auth'&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;username&amp;amp;gt;myserver&amp;amp;lt;/username&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;password&amp;amp;gt;secret&amp;amp;lt;/password&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;resource&amp;amp;gt;alive&amp;amp;lt;/resource&amp;amp;gt; &amp;amp;lt;/query&amp;amp;gt; &amp;amp;lt;/iq&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Constructing Jabber elements with the &amp;lt;tt&amp;gt;JabberBeans&amp;lt;/tt&amp;gt; library uses&lt;br /&gt;
so-called ''builders'' that allow individual element components to be&lt;br /&gt;
created separately and then fused together into a final structure. In&lt;br /&gt;
the code, we use two builders: an &amp;lt;tt&amp;gt;InfoQueryBuilder&amp;lt;/tt&amp;gt; to construct&lt;br /&gt;
the  &amp;lt;tt&amp;gt;&amp;amp;lt;iq/&amp;amp;gt;&amp;lt;/tt&amp;gt; envelope and an  &amp;lt;tt&amp;gt;IQAuthBuilder&amp;lt;/tt&amp;gt; to&lt;br /&gt;
construct the  &amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; content.&lt;br /&gt;
&lt;br /&gt;
Taking the code step by step, we create or declare each of the three&lt;br /&gt;
things, &amp;lt;tt&amp;gt;iqb&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;iq&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;iqAuthb&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    InfoQueryBuilder iqb=new InfoQueryBuilder(); InfoQuery iq;&lt;br /&gt;
IQAuthBuilder iqAuthb=new IQAuthBuilder();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;iqb&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is the builder object with which we can build &lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;amp;lt;iq/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. &lt;br /&gt;
; &amp;lt;tt&amp;gt;iq&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is the &amp;lt;tt&amp;gt;&amp;amp;lt;iq/&amp;amp;gt;&amp;lt;/tt&amp;gt; element that we're going to build. &lt;br /&gt;
; &amp;lt;tt&amp;gt;iqAuthb&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is another builder object with which we can build IQ extensions&lt;br /&gt;
: (&amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; tags) qualified by the&lt;br /&gt;
: &amp;lt;tt&amp;gt;jabber:iq:auth&amp;lt;/tt&amp;gt; namespace. The process of creating the&lt;br /&gt;
: authorization packet is detailed in Figure 8-3. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:jab_0803.png|Creating the authorization packet|center|350 px]]&amp;lt;/code&amp;gt; There are numbered steps in&lt;br /&gt;
Figure 8-3; these follow what happens in the rest of the authentication &lt;br /&gt;
preparation:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; Step 1: Set the type attribute of the IQ&lt;br /&gt;
: We call the &amp;lt;tt&amp;gt;setType()&amp;lt;/tt&amp;gt; method on the &amp;lt;tt&amp;gt;iqb&amp;lt;/tt&amp;gt; object that&lt;br /&gt;
: represents the outer IQ envelope to set the value of the &amp;lt;tt&amp;gt;type&amp;lt;/tt&amp;gt;&lt;br /&gt;
: attribute: : &lt;br /&gt;
&amp;lt;code&amp;gt;    iqb.setType(&amp;quot;set&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Step 2: Set the values for the parts of the authorization section of&lt;br /&gt;
the element&lt;br /&gt;
: Having constructed the &amp;lt;tt&amp;gt;iqAuthb&amp;lt;/tt&amp;gt; object, which represents the &lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; portion of the element, we fill the values&lt;br /&gt;
: with these calls: : &lt;br /&gt;
&amp;lt;code&amp;gt;    iqAuthb.setUsername(USER); iqAuthb.setPassword(PASSWORD);&lt;br /&gt;
iqAuthb.setResource(RESOURCE);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Steps 3a and 3b: Generate iqAuthb and add it to the iqb object&lt;br /&gt;
: Once the values inside the authorization &amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag&lt;br /&gt;
: are set, we can call the &amp;lt;tt&amp;gt;build()&amp;lt;/tt&amp;gt; method on the object&lt;br /&gt;
: representing that tag in &amp;lt;tt&amp;gt;iqAuthb&amp;lt;/tt&amp;gt; to generate an extension&lt;br /&gt;
: object (in other words, to ''assemble'' the tag) that can then be&lt;br /&gt;
: attached to the &amp;lt;tt&amp;gt;iqb&amp;lt;/tt&amp;gt; object using the &amp;lt;tt&amp;gt;addExtension()&amp;lt;/tt&amp;gt;&lt;br /&gt;
: method: : &lt;br /&gt;
&amp;lt;code&amp;gt;    try { iqb.addExtension(iqAuthb.build());&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Step 4: Generate iqb and assign it to the IQ object&lt;br /&gt;
: In the same way that we generated the authorization&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;amp;lt;query/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag, we can generate the whole element and&lt;br /&gt;
: assign it to &amp;lt;tt&amp;gt;iq&amp;lt;/tt&amp;gt;: : &lt;br /&gt;
&amp;lt;code&amp;gt;    try {&lt;br /&gt;
      //build the full InfoQuery packet&lt;br /&gt;
      iq=(InfoQuery)iqb.build();&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Once we've constructed the authorization element, now held as the&lt;br /&gt;
&amp;lt;tt&amp;gt;iq&amp;lt;/tt&amp;gt; object, we can send it down the stream to the Jabber server&lt;br /&gt;
with the &amp;lt;tt&amp;gt;send()&amp;lt;/tt&amp;gt; method of the &amp;lt;tt&amp;gt;ConnectionBean&amp;lt;/tt&amp;gt; object&lt;br /&gt;
&amp;lt;tt&amp;gt;cb&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    cb.send(iq);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, once we've authenticated, we can construct the presence packet&lt;br /&gt;
and send it using the same technique as before.&amp;lt;ref&amp;gt;We're assuming the&lt;br /&gt;
password is correct here, to keep this example straightforward. If it&lt;br /&gt;
isn't correct, there's not much we can do at this point anyway. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We construct a new object to represent the presence packet denoting&lt;br /&gt;
general availability—&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    PresenceBuilder pb=new PresenceBuilder();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this case, there are no namespace-qualified extensions to add to the &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element, but we do want to  add the IP&lt;br /&gt;
address that was passed into the script and available in&lt;br /&gt;
&amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt;. We can use the &amp;lt;tt&amp;gt;setStatus()&amp;lt;/tt&amp;gt; method on the&lt;br /&gt;
presence object to set the optional &amp;lt;tt&amp;gt;&amp;amp;lt;status/&amp;amp;gt;&amp;lt;/tt&amp;gt; to contain&lt;br /&gt;
that IP address:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    pb.setStatus(argv[0]);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After this, we can go ahead and generate the element, which will look&lt;br /&gt;
like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence&amp;amp;gt; &amp;amp;lt;status&amp;amp;gt;123.45.67.89&amp;amp;lt;/status&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;/presence&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After the generation with the &amp;lt;tt&amp;gt;build()&amp;lt;/tt&amp;gt; call, we send it down the&lt;br /&gt;
stream in the same way as the authorization &amp;lt;tt&amp;gt;&amp;amp;lt;iq/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
element:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    try { cb.send(pb.build());&lt;br /&gt;
    }&lt;br /&gt;
    catch (InstantiationException e) { System.out.println(&amp;quot;Fatal Error&lt;br /&gt;
    on Presence object build:&amp;quot;); System.out.println(e.toString());&lt;br /&gt;
    return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As for each of the &amp;lt;tt&amp;gt;build()&amp;lt;/tt&amp;gt; calls, we must  trap a possible&lt;br /&gt;
exception that &amp;lt;tt&amp;gt;build()&amp;lt;/tt&amp;gt; throws if it can't complete (for&lt;br /&gt;
example, due to lack of information). This is the&lt;br /&gt;
&amp;lt;tt&amp;gt;InstantiationException&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
We can see the results of ''myserver'' sending such an information-laden&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element to  ''dj'' in  Figure 8-4. As the&lt;br /&gt;
server connects to the Internet, the Java script is started via the&lt;br /&gt;
''ip-up'' script, and it relays the assigned IP address, which is shown&lt;br /&gt;
in Jarl's status bar as the availability information reaches ''dj'''s&lt;br /&gt;
client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 [[image:jab_0804.png|myserver becoming available and relaying its IP address|center|350 px]]&lt;br /&gt;
 &amp;lt;br&amp;gt;&amp;lt;/code&amp;gt; All that remains for the script&lt;br /&gt;
to do now is to hang around. While  the XML stream to the Jabber server&lt;br /&gt;
remains, and the connection is  not broken, its availability will remain&lt;br /&gt;
as it was as described by the simple &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element&lt;br /&gt;
we sent. So we simply go into a sort of hibernation. We have no hope of&lt;br /&gt;
escaping, but it should be taken care of by the ''ip-down'' script as&lt;br /&gt;
described earlier.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    while (true) { try { Thread.sleep(9999);&lt;br /&gt;
      }&lt;br /&gt;
      catch (InterruptedException e) { System.out.println(&amp;quot;timeout!&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In fact, when the ''ip-down'' script kills the script, the socket&lt;br /&gt;
connection will be closed, but there was no clean disconnect—no&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence type='unavailable'/&amp;amp;gt;&amp;lt;/tt&amp;gt; was sent by the script to&lt;br /&gt;
the Jabber server. In this case, the Jabber server will  notice that the&lt;br /&gt;
socket was closed and generate an unavailable &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element on behalf of the client.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Presence-Sensitive CVS Notification == &lt;br /&gt;
&amp;lt;br&amp;gt;In Section 8.1 early in this&lt;br /&gt;
chapter, we  replaced the email-based CVS notification mechanism with a&lt;br /&gt;
Jabber-based one. The script used was extremely simple—it connected to&lt;br /&gt;
the Jabber server specified, authenticated, and sent off the&lt;br /&gt;
notification message to the  recipient JID.&lt;br /&gt;
&lt;br /&gt;
What if we wanted to make the script &amp;quot;sensitive&amp;quot;? Jabber's presence&lt;br /&gt;
concept could help us here; if we extended the mechanism to allow for&lt;br /&gt;
the building of presence-based relationships between the notification&lt;br /&gt;
script and the  notification recipients, we can make the sending of the&lt;br /&gt;
notification message dependent on the recipient's availability.&lt;br /&gt;
&amp;quot;Presence-based relationships&amp;quot; refers to the ''presence subscription''&lt;br /&gt;
mechanism described in Section 5.4.2.3.&lt;br /&gt;
&lt;br /&gt;
Here's how it would work:&lt;br /&gt;
&lt;br /&gt;
* Each potential recipient adds the JID used by the CVS notification&lt;br /&gt;
script to his roster and sends a subscription request to it.&amp;lt;ref&amp;gt;The&lt;br /&gt;
process of adding a JID to the roster and making a subscription request&lt;br /&gt;
is an atomic action in many clients. It is generally assumed that &lt;br /&gt;
adding a JID to your roster means that you're going to want to know when&lt;br /&gt;
that entity is available, so the action of adding a JID to the roster&lt;br /&gt;
will often generate a presence subscription request automatically.&lt;br /&gt;
&amp;lt;/ref&amp;gt; &lt;br /&gt;
* The notification script, called ''cvsmsg-s''&lt;br /&gt;
(&amp;quot;cvsmsg-''sensitive''&amp;quot;), on receipt of the presence subscription from a&lt;br /&gt;
recipient, accepts the request and reciprocates by sending a&lt;br /&gt;
subscription request back to that recipient. &lt;br /&gt;
* On receipt of the&lt;br /&gt;
presence subscription from the  notification script, the recipient&lt;br /&gt;
accepts the request. &lt;br /&gt;
* When the notification script starts up to send a&lt;br /&gt;
message, it announces its own availability with a&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;  element, which causes the availability of&lt;br /&gt;
the JIDs to which it has a presence subscription to be sent to it. Based&lt;br /&gt;
on these  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; packets received, it can  make a&lt;br /&gt;
decision as to whether to send the notification message or not. &lt;br /&gt;
* The&lt;br /&gt;
decision we're going to use here is an arbitrary one: if the recipient&lt;br /&gt;
is online, we'll send the message, unless he's specified that he doesn't&lt;br /&gt;
want to be disturbed, with the &amp;lt;tt&amp;gt;&amp;amp;lt;show&amp;amp;gt;dnd&amp;amp;lt;/show&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
element.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subscription Relationships === &lt;br /&gt;
&amp;lt;br&amp;gt;This method will result in &amp;quot;balanced&amp;quot;&lt;br /&gt;
subscription relationships between script and recipients. In other&lt;br /&gt;
words, the script is subscribed to a recipient's presence, and vice&lt;br /&gt;
versa.&lt;br /&gt;
&lt;br /&gt;
Of the two presence subscription &amp;quot;directions,&amp;quot; the one where the&lt;br /&gt;
''notification script'' subscribes to the  ''recipient's'' presence (as&lt;br /&gt;
opposed to the one where the ''recipient'' subscribes to the&lt;br /&gt;
''notification script's'' presence) is by far the most important. While&lt;br /&gt;
it's not critical that the recipients know when the  notification script&lt;br /&gt;
is connected and active, it's essential that the  notification script&lt;br /&gt;
know about a recipient's availability at the time it wants to send a&lt;br /&gt;
message.&lt;br /&gt;
&lt;br /&gt;
So would it be more appropriate to create &amp;quot;unbalanced&amp;quot; subscription&lt;br /&gt;
relationships?&lt;br /&gt;
&lt;br /&gt;
An unbalanced relationship is one where one party knows about the other&lt;br /&gt;
party's availability but ''not'' vice versa. The idea for sensitizing&lt;br /&gt;
the notification script will work as long as the script can know about&lt;br /&gt;
the availability of the recipients. Whether or not the opposite is true&lt;br /&gt;
is largely irrelevant.&lt;br /&gt;
&lt;br /&gt;
Nevertheless, it's worth basing the interaction on balanced, or&lt;br /&gt;
reciprocal, presence subscriptions, primarily for simplicity's sake and&lt;br /&gt;
also for the fact that most Jabber clients (and most ''users'' of these&lt;br /&gt;
clients) tend to cope well and consistently with balanced subscriptions,&lt;br /&gt;
whereby the representation and interpretation of unbalanced&lt;br /&gt;
relationships is dealt with and understood in different manners. Some&lt;br /&gt;
clients use a  &amp;lt;tt&amp;gt;lurker&amp;lt;/tt&amp;gt; group to classify one-way presence&lt;br /&gt;
subscriptions from other JIDs (a &amp;quot;lurker&amp;quot; being one that can see you &lt;br /&gt;
while you can't see it).&lt;br /&gt;
&lt;br /&gt;
Far from being nebulous concepts, balanced and unbalanced subscription&lt;br /&gt;
relationships are characterized technically by values of a certain&lt;br /&gt;
attribute specified in each item—each JID—in a roster: the &lt;br /&gt;
&amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt; attribute of the  &amp;lt;tt&amp;gt;&amp;amp;lt;item/&amp;amp;gt;&amp;lt;/tt&amp;gt; tags&lt;br /&gt;
within the roster. As we  progress through the extensions to the CVS&lt;br /&gt;
notification script,we'll be examining these values at various stages in&lt;br /&gt;
this recipe description in Section 8.3.3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Sidebar|AnthropomorphismIt's worth pointing out at this stage that&lt;br /&gt;
adding a JID that's used by a  ''script'' to connect to Jabber is&lt;br /&gt;
slightly symbolic of the extension of the instant messaging world into&lt;br /&gt;
the wider arena of A2P messaging. Adding a ''service'' JID to your&lt;br /&gt;
roster and  sharing presence information with that service immediately&lt;br /&gt;
widens the  scope of what's possible with a humble instant messaging&lt;br /&gt;
client, and  blurs the boundaries between people and applications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== The cvsmsg-s Script === &lt;br /&gt;
&amp;lt;br&amp;gt;The script, as it stands in Section 8.1.3,&lt;br /&gt;
is what we want to extend and make sensitive to presence. Example 8-7&lt;br /&gt;
looks at the extended script,  ''cvsmsg-s'', and then walks through the&lt;br /&gt;
additions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''The cvsmsg-s script''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import jabber import sys from string import split&lt;br /&gt;
&lt;br /&gt;
Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;br /&gt;
Resource = 'cvsmsg'&lt;br /&gt;
&lt;br /&gt;
cvsuser  = sys.argv[1] message  = ''&lt;br /&gt;
&lt;br /&gt;
def presenceCB(con, prs):&lt;br /&gt;
&lt;br /&gt;
    type = prs.getType() parts = split(prs.getFrom(), '/') who =&lt;br /&gt;
    parts[0]&lt;br /&gt;
&lt;br /&gt;
    if type == None: type = 'available'&lt;br /&gt;
&lt;br /&gt;
    # Subscription request: - Accept their subscription - Send request&lt;br /&gt;
    # for subscription to their presence&lt;br /&gt;
    if type == 'subscribe': print &amp;quot;subscribe request from %s&amp;quot; % (who)&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribe'))&lt;br /&gt;
&lt;br /&gt;
    # Unsubscription request: - Accept their unsubscription - Send&lt;br /&gt;
    # request for unsubscription to their presence&lt;br /&gt;
    elif type == 'unsubscribe': print &amp;quot;unsubscribe request from %s&amp;quot; %&lt;br /&gt;
    (who) con.send(jabber.Presence(to=who, type='unsubscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='unsubscribe'))&lt;br /&gt;
&lt;br /&gt;
    elif type == 'subscribed': print &amp;quot;we are now subscribed to %s&amp;quot; %&lt;br /&gt;
    (who)&lt;br /&gt;
&lt;br /&gt;
    elif type == 'unsubscribed': print &amp;quot;we are now unsubscribed to %s&amp;quot; %&lt;br /&gt;
    (who)&lt;br /&gt;
&lt;br /&gt;
    elif type == 'available': print &amp;quot;%s is available (%s/%s)&amp;quot; % (who,&lt;br /&gt;
    prs.getShow(), prs.getStatus()) if prs.getShow() != 'dnd' and who ==&lt;br /&gt;
    cvsuser: con.send(jabber.Message(cvsuser, message, subject=&amp;quot;CVS&lt;br /&gt;
    Watch Alarm&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    elif type == 'unavailable': print &amp;quot;%s is unavailable&amp;quot; % (who)&lt;br /&gt;
&lt;br /&gt;
for line in sys.stdin.readlines(): message = message + line&lt;br /&gt;
&lt;br /&gt;
con = jabber.Client(host=Server)&lt;br /&gt;
&lt;br /&gt;
try: con.connect() except IOError, e: print &amp;quot;Couldn't connect: %s&amp;quot; % e&lt;br /&gt;
sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
con.auth(Username,Password,Resource)&lt;br /&gt;
&lt;br /&gt;
con.setPresenceHandler(presenceCB) con.requestRoster()&lt;br /&gt;
con.sendInitPresence()&lt;br /&gt;
&lt;br /&gt;
for i in range(5): con.process(1)&lt;br /&gt;
&lt;br /&gt;
con.disconnect()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Taking the cvsmsg-s Script Step by Step === &lt;br /&gt;
&amp;lt;br&amp;gt;Now it's time to examine&lt;br /&gt;
the script step by step.  We'll concentrate mostly on the additions to&lt;br /&gt;
the original ''cvsmsg'' script.&lt;br /&gt;
&lt;br /&gt;
We bring in a string function that we'll be needing later in the script&lt;br /&gt;
to chop up JIDs into their component parts (''username'', ''hostname'',&lt;br /&gt;
and ''resource''):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;import jabber import sys &amp;lt;tt&amp;gt;from string import split&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Server   = 'gnu.pipetree.com' Username = 'cvsmsg' Password = 'secret'&lt;br /&gt;
Resource = 'cvsmsg'&lt;br /&gt;
&lt;br /&gt;
cvsuser  = sys.argv[1] message  = ''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Presence callback ==== &lt;br /&gt;
&amp;lt;br&amp;gt;The next addition to the script is a&lt;br /&gt;
callback to handle  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. The callback in&lt;br /&gt;
this script takes the form of a subroutine called &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt;&lt;br /&gt;
(&amp;quot;presence callback&amp;quot;). Callbacks, in relation to programming with&lt;br /&gt;
Jabber, are explained in Section 8.3.4.&lt;br /&gt;
&lt;br /&gt;
This is what the callback for handling &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
elements looks like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;def presenceCB(con, prs):&lt;br /&gt;
&lt;br /&gt;
    type = prs.getType() parts = split(prs.getFrom(), '/') who =&lt;br /&gt;
    parts[0]&lt;br /&gt;
&lt;br /&gt;
    if type == None: type = 'available'&lt;br /&gt;
&lt;br /&gt;
    # Subscription request: - Accept their subscription - Send request&lt;br /&gt;
    # for subscription to their presence&lt;br /&gt;
    if type == 'subscribe': print &amp;quot;subscribe request from %s&amp;quot; % (who)&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribe'))&lt;br /&gt;
&lt;br /&gt;
    # Unsubscription request: - Accept their unsubscription - Send&lt;br /&gt;
    # request for unsubscription to their presence&lt;br /&gt;
    elif type == 'unsubscribe': print &amp;quot;unsubscribe request from %s&amp;quot; %&lt;br /&gt;
    (who) con.send(jabber.Presence(to=who, type='unsubscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='unsubscribe'))&lt;br /&gt;
&lt;br /&gt;
    elif type == 'subscribed': print &amp;quot;we are now subscribed to %s&amp;quot; %&lt;br /&gt;
    (who)&lt;br /&gt;
&lt;br /&gt;
    elif type == 'unsubscribed': print &amp;quot;we are now unsubscribed to %s&amp;quot; %&lt;br /&gt;
    (who)&lt;br /&gt;
&lt;br /&gt;
    elif type == 'available': print &amp;quot;%s is available (%s/%s)&amp;quot; % (who,&lt;br /&gt;
    prs.getShow(), prs.getStatus()) if prs.getShow() != 'dnd' and who ==&lt;br /&gt;
    cvsuser: con.send(jabber.Message(cvsuser, message, subject=&amp;quot;CVS&lt;br /&gt;
    Watch Alarm&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    elif type == 'unavailable': print &amp;quot;%s is unavailable&amp;quot; % (who)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Phew! Let's take it a bit at a time. The first thing to note is what's&lt;br /&gt;
specified in the subroutine declaration:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;def presenceCB(con, prs):&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a handler, the subroutine &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt; will be passed the&lt;br /&gt;
''connection object'' in &amp;lt;tt&amp;gt;con&amp;lt;/tt&amp;gt;, and the ''presence node'' in&lt;br /&gt;
&amp;lt;tt&amp;gt;prs&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;con&amp;lt;/tt&amp;gt; is the same connection object that is created&lt;br /&gt;
later in the script (&amp;lt;tt&amp;gt;con = jabber.Client(host=Server)&amp;lt;/tt&amp;gt;) and is&lt;br /&gt;
passed in for convenience, as it's quite likely we're going to want to&lt;br /&gt;
use it, say, to send something back over the stream.&lt;br /&gt;
&lt;br /&gt;
The presence node in &amp;lt;tt&amp;gt;prs&amp;lt;/tt&amp;gt; is an object representation of the XML&lt;br /&gt;
fragment that came in over the stream and was parsed into  its component&lt;br /&gt;
parts. The object is an instance of the  &amp;lt;tt&amp;gt;jabber.Presence&amp;lt;/tt&amp;gt; class,&lt;br /&gt;
which is simply a specialization of the more generic&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Protocol&amp;lt;/tt&amp;gt; class, as are the other classes that represent&lt;br /&gt;
the other two Jabber protocol elements that are to be expected:&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Message&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;jabber.Iq&amp;lt;/tt&amp;gt;. The&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Protocol&amp;lt;/tt&amp;gt; class represents protocol elements in general.&lt;br /&gt;
&lt;br /&gt;
As such, there are a number of &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
element-specific methods we can call on the &amp;lt;tt&amp;gt;prs&amp;lt;/tt&amp;gt; object, such as&lt;br /&gt;
&amp;lt;tt&amp;gt;getShow()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;getStatus()&amp;lt;/tt&amp;gt; (which return the values of&lt;br /&gt;
the  &amp;lt;tt&amp;gt;&amp;amp;lt;show/&amp;amp;gt;&amp;lt;/tt&amp;gt; and  &amp;lt;tt&amp;gt;&amp;amp;lt;status/&amp;amp;gt;&amp;lt;/tt&amp;gt; tags—children&lt;br /&gt;
of the &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element—respectively) and general&lt;br /&gt;
element methods such as &amp;lt;tt&amp;gt;getID&amp;lt;/tt&amp;gt;, which returns the value of any&lt;br /&gt;
&amp;lt;tt&amp;gt;id&amp;lt;/tt&amp;gt; attribute assigned to the element, and &amp;lt;tt&amp;gt;setTo()&amp;lt;/tt&amp;gt;,&lt;br /&gt;
which can be used to address the element—to set the value of the&lt;br /&gt;
&amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; attribute.&lt;br /&gt;
&lt;br /&gt;
The first thing the handler does is to call a few of these element&lt;br /&gt;
methods to determine the ''type'' of  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element&lt;br /&gt;
(presence types are described in Section 5.4.2), and who it's coming&lt;br /&gt;
from:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    type = prs.getType() parts = split(prs.getFrom(), '/') who =&lt;br /&gt;
parts[0]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the notification script is called, the JID found in the CVS  users&lt;br /&gt;
file is substituted for the &amp;lt;tt&amp;gt;%s&amp;lt;/tt&amp;gt; in the formula contained in the&lt;br /&gt;
CVS notify file. So if the user ''dj'' were to be notified, the JID&lt;br /&gt;
passed to the script would be ''dj@gnu.pipetree.com''.&lt;br /&gt;
&lt;br /&gt;
The way JIDs are passed around ''independently'' of the context of a&lt;br /&gt;
Jabber session is usually in the simpler &lt;br /&gt;
form—''username''&amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt;''hostname'', that is, without the  resource&lt;br /&gt;
suffix—''username''&amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt;''hostname''&amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;''resource''.   As&lt;br /&gt;
described in  Chapter 5, the resource is primarily used to  distinguish&lt;br /&gt;
individual sessions belonging to one Jabber user.&lt;br /&gt;
&lt;br /&gt;
But when the Jabber library—and subsequently a handler subroutine in the&lt;br /&gt;
script—receives an element, it contains a  &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; attribute whose&lt;br /&gt;
value has been stamped  by the Jabber server as it passes through. The&lt;br /&gt;
value represents the session, the ''connection'', from which the&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element was sent and, as such, includes a&lt;br /&gt;
resource suffix. So in order to properly match up the source JID for any&lt;br /&gt;
incoming &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element with the JID specified when&lt;br /&gt;
the script was invoked (contained in the &amp;lt;tt&amp;gt;cvsuser&amp;lt;/tt&amp;gt; variable), we&lt;br /&gt;
need to strip off this resource suffix. The remaining&lt;br /&gt;
''username''&amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt;''hostname'' part is captured in the &amp;lt;tt&amp;gt;who&amp;lt;/tt&amp;gt;&lt;br /&gt;
variable.&lt;br /&gt;
&lt;br /&gt;
There's one more step to determine the presence type. The &amp;lt;tt&amp;gt;type&amp;lt;/tt&amp;gt;&lt;br /&gt;
attribute is ''optional''; its absence signifies the default presence&lt;br /&gt;
type, which is &amp;lt;tt&amp;gt;available&amp;lt;/tt&amp;gt;. So we effect this default&lt;br /&gt;
substitution here to make the subsequent code clearer:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    if type == None: type = 'available'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this stage, we want to take different actions depending on what sort&lt;br /&gt;
of presence information has arrived. Recalling the sequence of events in&lt;br /&gt;
the reciprocal presence subscription exchange described earlier in this&lt;br /&gt;
chapter, one of the activities is for a potential notification recipient&lt;br /&gt;
to subscribe to the presence of the script's JID.&lt;br /&gt;
&lt;br /&gt;
This subscription request is carried in a  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
element, with a type of &amp;lt;tt&amp;gt;subscribe&amp;lt;/tt&amp;gt;. Example 8-8 shows what a&lt;br /&gt;
typical subscription request would look like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''A presence subscription request from dj@gnu.pipetree.com''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence type='subscribe' to='cvsmsg@gnu.pipetree.com'&lt;br /&gt;
from='dj@gnu.pipetree.com/work'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this stage, ''dj@gnu.pipetree.com'' has  just sent a request to&lt;br /&gt;
subscribe to the script's presence. The subscription relationship&lt;br /&gt;
between the two parties is nondescript, and this is reflected in the&lt;br /&gt;
details of the item in ''dj'''s roster that relates to the script's JID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='cvsmsg@gnu.pipetree.com' subscription='none'&lt;br /&gt;
ask='subscribe'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The relationship itself is reflected in the &amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt;&lt;br /&gt;
attribute, and the current state of the relationship is reflected in the&lt;br /&gt;
 &amp;lt;tt&amp;gt;ask&amp;lt;/tt&amp;gt; attribute.&lt;br /&gt;
&lt;br /&gt;
If a subscription request is received, we want the script to respond by&lt;br /&gt;
accepting the subscription request. Once the request  has been accepted,&lt;br /&gt;
a presence subscription request is made in return.&lt;br /&gt;
&lt;br /&gt;
This incoming subscription request is handled here:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    # Subscription request: &lt;br /&gt;
    # - Accept their subscription - Send request for subscription to&lt;br /&gt;
    # their presence&lt;br /&gt;
    if type == 'subscribe': print &amp;quot;subscribe request from %s&amp;quot; % (who)&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='subscribe'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Each call to the &amp;lt;tt&amp;gt;jabber.Presence&amp;lt;/tt&amp;gt; class constructor creates a&lt;br /&gt;
node representing a &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element. The two&lt;br /&gt;
parameters passed in the call are fairly self-explanatory: we specify&lt;br /&gt;
''to whom'' the &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element should be sent, and&lt;br /&gt;
the ''type''.&lt;br /&gt;
&lt;br /&gt;
If the presence subscription request came in from the JID &lt;br /&gt;
''dj@gnu.pipetree.com'', then the XML represented by the node created in&lt;br /&gt;
the first call here (specifying a presence type of &amp;lt;tt&amp;gt;subscribed&amp;lt;/tt&amp;gt;)&lt;br /&gt;
would look something like that in Example 8-9.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Acceptance of a presence subscription request from&lt;br /&gt;
dj@gnu.pipetree.com''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence type='subscribed' to='dj@gnu.pipetree.com'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Sidebar|Addressing &amp;amp;lt;presence/&amp;amp;gt; ElementsIt's worth pointing out&lt;br /&gt;
here that there's a subtle difference between sending&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements in a presence  subscription&lt;br /&gt;
conversation and sending general &amp;quot;availability&amp;quot; &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements.&lt;br /&gt;
&lt;br /&gt;
In the first case, we use a &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; attribute, because our&lt;br /&gt;
conversation is one-to-one. In the second, we don't; our unaddressed&lt;br /&gt;
availability information is caught by the server and in turn sent on to&lt;br /&gt;
those entities that are subscribed to your presence.&lt;br /&gt;
&lt;br /&gt;
Although you ''can'' send &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements that&lt;br /&gt;
convey availability information directly ''to'' a JID, it's not normal.&lt;br /&gt;
However, explicitly addressing the elements in a subscription scenario&lt;br /&gt;
is essential.&lt;br /&gt;
&lt;br /&gt;
There's another situation in which such &amp;quot;directed&amp;quot; (explicitly&lt;br /&gt;
addressed) &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements are used—to  partake of&lt;br /&gt;
the services of the availability tracker. This is described in the&lt;br /&gt;
Section 5.4.2.4.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Once constructed, each of the &amp;lt;tt&amp;gt;jabber.Presence&amp;lt;/tt&amp;gt; nodes is sent&lt;br /&gt;
back along the stream with the &amp;lt;tt&amp;gt;con.send()&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
Now that the script has accepted ''dj'''s subscription request, ''dj'''s&lt;br /&gt;
roster item for the script reflects the new relationship:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='cvsmsg@gnu.pipetree.com' subscription='to'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;subscription='to'&amp;lt;/tt&amp;gt; denotes that the subscription relationship is&lt;br /&gt;
currently one way—''dj'' has a subscription to the script. There's no&lt;br /&gt;
&amp;lt;tt&amp;gt;ask&amp;lt;/tt&amp;gt; attribute as there's no current request going from ''dj''&lt;br /&gt;
to the script.&lt;br /&gt;
&lt;br /&gt;
While ''dj'''s roster item for the script shows a &amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt;&lt;br /&gt;
value of &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt;, the ''script'''s roster item for ''dj'' shows a&lt;br /&gt;
&amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='dj@gnu.pipetree.com' subscription='from'&lt;br /&gt;
ask='subscribe'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
which shows that the script has a subscription ''from''''dj''.&lt;br /&gt;
&lt;br /&gt;
Furthermore, remember that the script not only accepts ''dj'''s&lt;br /&gt;
subscription request, it sends a reciprocal one of its own. (Hence the&lt;br /&gt;
&amp;lt;tt&amp;gt;ask=&amp;quot;subscribe'&amp;lt;/tt&amp;gt; status in the item.) When ''dj'' accepts this&lt;br /&gt;
request, the roster item changes yet again to reflect the balanced&lt;br /&gt;
relationship:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='cvsmsg@gnu.pipetree.com' subscription='both'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We want the script to handle requests to &amp;lt;tt&amp;gt;unsubscribe&amp;lt;/tt&amp;gt; from its&lt;br /&gt;
presence in the same way:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    # Unsubscription request: &lt;br /&gt;
    # - Accept their unsubscription - Send request for unsubscription to&lt;br /&gt;
    # their presence&lt;br /&gt;
    elif type == 'unsubscribe': print &amp;quot;unsubscribe request from %s&amp;quot; %&lt;br /&gt;
    (who) con.send(jabber.Presence(to=who, type='unsubscribed'))&lt;br /&gt;
    con.send(jabber.Presence(to=who, type='unsubscribe'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The only difference between this section and the previous one is that it&lt;br /&gt;
deals with requests to &amp;lt;tt&amp;gt;unsubscribe&amp;lt;/tt&amp;gt; as opposed to &lt;br /&gt;
&amp;lt;tt&amp;gt;subscribe&amp;lt;/tt&amp;gt; to presence. Otherwise it works in exactly the same&lt;br /&gt;
way. A sequence of &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements used in an&lt;br /&gt;
&amp;quot;unsubscription conversation&amp;quot; between  ''dj'' and the script, and the&lt;br /&gt;
changes to the roster &amp;lt;tt&amp;gt;&amp;amp;lt;item/&amp;amp;gt;&amp;lt;/tt&amp;gt; tags on each side, is shown&lt;br /&gt;
in Figure 8-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:jab_0805.png|&amp;amp;lt;presence/&amp;amp;gt; elements and roster &amp;amp;lt;item/&amp;amp;gt;s in&lt;br /&gt;
an unsubscription conversation|center|350 px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;/code&amp;gt; While we&lt;br /&gt;
must take action on presence types &amp;lt;tt&amp;gt;subscribe&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;unsubscribe&amp;lt;/tt&amp;gt;, we don't really need to do anything for their&lt;br /&gt;
''acknowledgment'' counterparts: &amp;lt;tt&amp;gt;subscribed&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;unsubscribed&amp;lt;/tt&amp;gt; (&amp;quot;I have accepted your request, and  you are now&lt;br /&gt;
subscribed/unsubscribed to my presence&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Nevertheless, just for illustration purposes, we'll include a couple of&lt;br /&gt;
conditions to show what's going on when the script runs:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    elif type == 'subscribed': print &amp;quot;we are now subscribed to&lt;br /&gt;
%s&amp;quot; % (who)&lt;br /&gt;
&lt;br /&gt;
    elif type == 'unsubscribed': print &amp;quot;we are now unsubscribed to %s&amp;quot; %&lt;br /&gt;
    (who)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Apart from the types of &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element  covering the&lt;br /&gt;
presence subscription process, we should also expect the basic&lt;br /&gt;
availability elements:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence&amp;amp;gt;...&amp;amp;lt;/presence&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence type='unavailable'/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's an available &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element that the&lt;br /&gt;
functionality of the script hinges on:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    elif type == 'available': print &amp;quot;%s is available (%s/%s)&amp;quot; %&lt;br /&gt;
(who, prs.getShow(), prs.getStatus()) if prs.getShow() != 'dnd' and who&lt;br /&gt;
== cvsuser: con.send(jabber.Message(cvsuser, message, subject=&amp;quot;CVS Watch&lt;br /&gt;
Alarm&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt; subroutine is set up to handle&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. In a typical  execution scenario,&lt;br /&gt;
where the script is subscribed to the presence of many potential CVS&lt;br /&gt;
notification recipients, the subroutine is going to be called to handle&lt;br /&gt;
the availability information of all  recipients who happen to be&lt;br /&gt;
connected to Jabber at the moment of  notification. We're interested in&lt;br /&gt;
the availability information of only one particular recipient (&amp;lt;tt&amp;gt;who&lt;br /&gt;
== cvsuser&amp;lt;/tt&amp;gt;), and we want to check on the contents of the &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;show/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
If we get a match, we can send the notification message by creating a&lt;br /&gt;
&amp;lt;tt&amp;gt;jabber.Message&amp;lt;/tt&amp;gt; node that will look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;message to='dj@gnu.pipetree.com'&amp;amp;gt; &amp;amp;lt;subject&amp;amp;gt;CVS Watch&lt;br /&gt;
Alarm&amp;amp;lt;/subject&amp;amp;gt; &amp;amp;lt;body&amp;amp;gt; testproject file4 --- Triggered edit&lt;br /&gt;
watch on /usr/local/cvsroot/testproject By piers &amp;amp;lt;/body&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;/message&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As in the ''cvsmsg'' script, once created, the node can be sent with the&lt;br /&gt;
&amp;lt;tt&amp;gt;con.send()&amp;lt;/tt&amp;gt; method call.&lt;br /&gt;
&lt;br /&gt;
Like the conditions for the presence subscription and unsubscription &lt;br /&gt;
acknowledgments, we're including a final condition to deal with the case&lt;br /&gt;
where a recipient disconnects from the Jabber server during the&lt;br /&gt;
execution of the script: an&lt;br /&gt;
&amp;lt;tt&amp;gt;unavailable&amp;lt;/tt&amp;gt;&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element will be sent:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;    elif type == 'unavailable': print &amp;quot;%s is unavailable&amp;quot; % (who)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We're simply logging such an event for illustration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Connection and authentication ==== &lt;br /&gt;
&amp;lt;br&amp;gt;Most of the main part of the&lt;br /&gt;
script is the same as the nonsensitive version from Section 8.1: reading&lt;br /&gt;
in the  notification message, preparing a connection to the Jabber&lt;br /&gt;
server, and trying to connect:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;for line in sys.stdin.readlines(): message = message + line&lt;br /&gt;
&lt;br /&gt;
con = jabber.Client(host=Server)&lt;br /&gt;
&lt;br /&gt;
try: con.connect() except IOError, e: print &amp;quot;Couldn't connect: %s&amp;quot; % e&lt;br /&gt;
sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
con.auth(Username,Password,Resource)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Registration of &amp;amp;lt;presence/&amp;amp;gt; handler ==== &lt;br /&gt;
&amp;lt;br&amp;gt;While we've&lt;br /&gt;
''defined'' the &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt; subroutine to handle&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; packets, we haven't actually told the Jabber&lt;br /&gt;
library about it. The call to the &amp;lt;tt&amp;gt;setPresenceHandler()&amp;lt;/tt&amp;gt; method&lt;br /&gt;
of the connection object does this for us, performing the &amp;quot;Register&lt;br /&gt;
handler&amp;quot; step shown in  Figure 8-6. The steps shown in Figure 8-6 are&lt;br /&gt;
described in  Section 8.3.4.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.setPresenceHandler(presenceCB)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:jab_0806.png|Handlers and the relationship between the Jabber library&lt;br /&gt;
and your script|center|350 px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Request for roster ==== &lt;br /&gt;
&amp;lt;br&amp;gt;It's easy to guess what the next method&lt;br /&gt;
call does:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.requestRoster()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It makes a request for the roster by sending an IQ-get with a  query&lt;br /&gt;
qualified by the &amp;lt;tt&amp;gt;jabber:iq:roster&amp;lt;/tt&amp;gt; namespace:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;iq type='get' id='3'&amp;amp;gt; &amp;amp;lt;query&lt;br /&gt;
xmlns=&amp;quot;jabber:iq:roster'/&amp;amp;gt; &amp;amp;lt;/iq&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
to which the server responds with an IQ-result:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;iq type='result' id='3'&amp;amp;gt; &amp;amp;lt;query&lt;br /&gt;
xmlns='jabber:iq:roster'&amp;amp;gt; &amp;amp;lt;item jid='dj@gnu.pipetree.com'&lt;br /&gt;
subscription='both'/&amp;amp;gt; &amp;amp;lt;item jid='piers@jabber.org'&lt;br /&gt;
subscription='both'/&amp;amp;gt; &amp;amp;lt;item jid='shiels@jabber.org'&lt;br /&gt;
subscription='both'/&amp;amp;gt; ... &amp;amp;lt;/query&amp;amp;gt; &amp;amp;lt;/iq&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, as there are no explicit references to the roster anywhere in&lt;br /&gt;
the script, it's not as easy to guess why we request the roster in the&lt;br /&gt;
first place. We know that the client-side copy is merely a &amp;quot;slave&amp;quot; copy,&lt;br /&gt;
and, even more relevant here, we know that &amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt;&lt;br /&gt;
information in the roster &amp;lt;tt&amp;gt;&amp;amp;lt;item/&amp;amp;gt;&amp;lt;/tt&amp;gt; tags is managed by the&lt;br /&gt;
server—we as a client don't need to (in fact, ''shouldn't'') do anything&lt;br /&gt;
to maintain  the &amp;lt;tt&amp;gt;subscription&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ask&amp;lt;/tt&amp;gt; attributes and&lt;br /&gt;
keep them up to date.&lt;br /&gt;
&lt;br /&gt;
So why do we request it?  Basically, it's because there's a fundamental&lt;br /&gt;
difference between &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements used to convey&lt;br /&gt;
availability information and &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements used to&lt;br /&gt;
convey presence subscription information. If John sends Jim availability&lt;br /&gt;
information in a &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element, whether directly&lt;br /&gt;
(with a &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; attribute) or indirectly (through the distribution&lt;br /&gt;
of that element by the server to Jim as a subscriber to John's&lt;br /&gt;
presence), and Jim's offline on holiday, it doesn't make sense to store&lt;br /&gt;
and forward the message to him when he next connects:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Jabber server: &amp;quot;''Here's some availability information for&lt;br /&gt;
John, dated 9 days ago.''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Jim: &amp;quot;''Who cares?''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;The &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements conveying&lt;br /&gt;
availability information are ''not'' stored and forwarded if they can't&lt;br /&gt;
be delivered because the intended recipient is offline. What would be&lt;br /&gt;
the point?&lt;br /&gt;
&lt;br /&gt;
However, &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements that convey subscription&lt;br /&gt;
information are a different kettle of fish. While it's not important&lt;br /&gt;
that a user is sent out of date availability information when he next&lt;br /&gt;
connects to his Jabber client, any subscription (or unsubscription)&lt;br /&gt;
requests or confirmations that were sent to him ''are'' important. So&lt;br /&gt;
they need to be stored and forwarded.&lt;br /&gt;
&lt;br /&gt;
As we've already seen, the presence subscription mechanism and rosters&lt;br /&gt;
are inextricably linked. And if we look briefly under the covers, we see&lt;br /&gt;
how this is so. When a presence subscription request is sent to a user,&lt;br /&gt;
it runs the gauntlet of modules in the JSM (see  Section 4.4.4 for&lt;br /&gt;
details on what these modules are). The roster-handling module&lt;br /&gt;
''mod_roster'' grabs this request, and, just in case the recipient turns&lt;br /&gt;
out not to  be connected, ''stores'' it.&lt;br /&gt;
&lt;br /&gt;
And here's how intertwined the presence subscription mechanism and&lt;br /&gt;
rosters really are: the request is stored as a cluster of attribute&lt;br /&gt;
details within an &amp;lt;tt&amp;gt;&amp;amp;lt;item/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag in the roster belonging to&lt;br /&gt;
the ''recipient'' of the presence subscription request. It looks like&lt;br /&gt;
this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='user@hostname' subscription='none' subscribe=''&lt;br /&gt;
hidden=''/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On receipt of a presence subscription request, the ''mod_roster'' module&lt;br /&gt;
will create the roster item if it doesn't exist already and then assign&lt;br /&gt;
the attributes related to presence&lt;br /&gt;
subscription—&amp;lt;tt&amp;gt;subscription=&amp;quot;none'&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;subscribe=&amp;quot;'&amp;lt;/tt&amp;gt;—to&lt;br /&gt;
it. There's no  &amp;lt;tt&amp;gt;ask&amp;lt;/tt&amp;gt; attribute, as this is assigned only to the&lt;br /&gt;
item on the roster belonging to the ''sender'', not the one belonging to&lt;br /&gt;
the ''receiver'', of the subscription request.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;subscribe&amp;lt;/tt&amp;gt; attribute is used to store the reason for the&lt;br /&gt;
request, that, if specified, is carried in the  &amp;lt;tt&amp;gt;&amp;amp;lt;status/&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
tag of the &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element that conveys the request.&lt;br /&gt;
If no reason is given, the value for the attribute is empty, as shown&lt;br /&gt;
here. Otherwise, it will contain what was stored in the&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;status/&amp;amp;gt;&amp;lt;/tt&amp;gt; tag. Example 8-10 shows a presence subscription&lt;br /&gt;
request that carries a reason.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''A presence subscription request with a reason''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence to='dj@gnu.pipetree.com'&amp;amp;gt; &amp;amp;lt;status&amp;amp;gt;I'd like&lt;br /&gt;
to keep my eye on you!&amp;amp;lt;/status&amp;amp;gt; &amp;amp;lt;/presence&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;hidden&amp;lt;/tt&amp;gt; attribute here:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;item jid='user@hostname' subscription='none' subscribe=''&lt;br /&gt;
hidden=''/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
is used internally by ''mod_roster'' to mark the item as nondisplayable;&lt;br /&gt;
it effectively is a pseudo &amp;lt;tt&amp;gt;&amp;amp;lt;item/&amp;amp;gt;&amp;lt;/tt&amp;gt; that, when brought to&lt;br /&gt;
life, actually turns out to be a  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element. So&lt;br /&gt;
when a request for the roster is made, ''mod_roster'' makes sure that it&lt;br /&gt;
doesn't send these &amp;quot;hidden&amp;quot; items. The &amp;lt;tt&amp;gt;hidden&amp;lt;/tt&amp;gt; attribute always&lt;br /&gt;
has an empty value, as shown here.&lt;br /&gt;
&lt;br /&gt;
After storing the subscription request, ''mod_roster'' will actually&lt;br /&gt;
send the original &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element that conveyed that&lt;br /&gt;
request to the recipient—that is, if the recipient is online  ''and'' if&lt;br /&gt;
the recipient has already made a request for his roster. As sending an&lt;br /&gt;
availability presence packet:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
causes the ''mod_offline'' module to forward any  messages stored&lt;br /&gt;
offline in that user's absence, so requesting the roster:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;iq type='get'&amp;amp;gt;&amp;amp;lt;query&lt;br /&gt;
xmlns='jabber:iq:roster'/&amp;amp;gt;&amp;amp;lt;/iq&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
causes the ''mod_roster'' module to forward any subscription requests&lt;br /&gt;
stored offline in that user's absence.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending of availability information ==== &lt;br /&gt;
&amp;lt;br&amp;gt;OK. We've connected,&lt;br /&gt;
authenticated, defined, and registered the callback to handle&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements, and requested the roster, so&lt;br /&gt;
''mod_roster'' will send us any presence subscription (or&lt;br /&gt;
unsubscription) requests. Now we need to make an availability&lt;br /&gt;
announcement in the form of a simple &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We can do this by calling the &amp;lt;tt&amp;gt;sendInitPresence()&amp;lt;/tt&amp;gt; method on the&lt;br /&gt;
connection object:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.sendInitPresence()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This availability information will be distributed to all the  entities&lt;br /&gt;
that are subscribed to the script's presence and are online at that&lt;br /&gt;
moment. It will also signify to the Jabber server that we are properly&lt;br /&gt;
online—in which case it can forward to us any messages that had been&lt;br /&gt;
stored up in our absence.&lt;br /&gt;
&lt;br /&gt;
We're not really expecting any &amp;lt;tt&amp;gt;&amp;amp;lt;message/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements;&lt;br /&gt;
indeed, we haven't set up any subroutine to handle them, so  they'd just&lt;br /&gt;
be thrown away by the library anyway. The real reason for sending&lt;br /&gt;
presence is so that the server will actively go and  probe those in a&lt;br /&gt;
presence subscription relationship with the script and report back on&lt;br /&gt;
those who are available (who have themselves sent their presence during&lt;br /&gt;
their current session). This causes  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements&lt;br /&gt;
to arrive on the stream and make their way to the &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt;&lt;br /&gt;
handler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Waiting for packets ==== &lt;br /&gt;
&amp;lt;br&amp;gt;Once everything is set up, and the script&lt;br /&gt;
has announced its presence, it really just needs to sit back and listen&lt;br /&gt;
to the  &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements that come in. If one of&lt;br /&gt;
these is from the intended notification recipient, and the availability&lt;br /&gt;
state is right (i.e., not in &amp;lt;tt&amp;gt;dnd&amp;lt;/tt&amp;gt; mode),  we know that the&lt;br /&gt;
circumstances are appropriate for sending the notification.&lt;br /&gt;
&lt;br /&gt;
But the elements being sent over the stream from the server don't&lt;br /&gt;
spontaneously get received, parsed, and dispatched; we can control when&lt;br /&gt;
that happens from the script. This is the nub of the symbiosis between&lt;br /&gt;
the element events and the procedural routines, and it's name is&lt;br /&gt;
&amp;lt;tt&amp;gt;process()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Calling &amp;lt;tt&amp;gt;process()&amp;lt;/tt&amp;gt; will check on the stream to see if any XML&lt;br /&gt;
fragments have arrived and are waiting to be picked up. If there are&lt;br /&gt;
any, Steps 3 through 5, shown in Figure 8-6 and described in  Section&lt;br /&gt;
8.3.4, are executed. The numeric value specified in the call to&lt;br /&gt;
&amp;lt;tt&amp;gt;process()&amp;lt;/tt&amp;gt; is the number of seconds to wait for incoming&lt;br /&gt;
fragments if none is currently waiting to be picked up. Specifying no&lt;br /&gt;
value (or 0) means that the method won't hang around if nothing has&lt;br /&gt;
arrived. Specifying a  value of 30 means that it will wait up to half a&lt;br /&gt;
minute. We really want something in between, and it turns out that&lt;br /&gt;
waiting for up to a second for fragments in a finite loop like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;for i in range(5): con.process(1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
will allow for a slightly stuttered arrival of the&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements that are sent to the script as a&lt;br /&gt;
result of the server-initiated probes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Finishing up ==== &lt;br /&gt;
&amp;lt;br&amp;gt;We're just about done. The&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements that arrive and find their way to&lt;br /&gt;
the callback are examined, and the CVS notification message is sent off&lt;br /&gt;
if appropriate. Once the  &amp;lt;tt&amp;gt;process()&amp;lt;/tt&amp;gt; calls have finished, and,&lt;br /&gt;
implicitly, the (potentially) multiple calls to &amp;lt;tt&amp;gt;presenceCB&amp;lt;/tt&amp;gt;,&lt;br /&gt;
there's nothing left to do. So we simply disconnect from the Jabber&lt;br /&gt;
server, as before:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;con.disconnect()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Jabber Programming and Callbacks === &lt;br /&gt;
&amp;lt;br&amp;gt;When programming all but the&lt;br /&gt;
simplest Jabber scripts, you're going  to be using ''callbacks'', as&lt;br /&gt;
we've seen in this recipe. Callbacks are also known as ''handlers''.&lt;br /&gt;
&lt;br /&gt;
Rather than purely procedural programming (&amp;quot;do this, then do that,  then&lt;br /&gt;
do the other&amp;quot;), we need a different model to cope with the &lt;br /&gt;
''event-based'' nature of Jabber or, more precisely, the event-based&lt;br /&gt;
nature of how we converse using the Jabber protocol over an XML stream.&lt;br /&gt;
Although we control what we   ''send'' over the XML stream connection&lt;br /&gt;
that we've established with the Jabber server, we can't control what we&lt;br /&gt;
''receive'', and more importantly, we can't  control ''when'' we receive&lt;br /&gt;
it. We need an  event-based programming model to be able to ''handle''&lt;br /&gt;
the protocol elements as they arrive.&lt;br /&gt;
&lt;br /&gt;
The libraries available for programming with Jabber offer  ''callback''&lt;br /&gt;
mechanisms. With these callback mechanisms, we can register subroutines&lt;br /&gt;
with the part of the library that's handling the reception of XML&lt;br /&gt;
document stream fragments. Then, whenever an  element appears on the&lt;br /&gt;
incoming stream (a fragment in the stream  document that the Jabber&lt;br /&gt;
server is sending to us), the library can pass it to the appropriate&lt;br /&gt;
subroutine in the script for us to act upon—to be &amp;quot;handled.&amp;quot; This&lt;br /&gt;
passing of elements to be handled by callbacks is referred to as&lt;br /&gt;
''dispatching''.&lt;br /&gt;
&lt;br /&gt;
Figure 8-6 shows the relationship between the library and script, and&lt;br /&gt;
the sequence of events surrounding registering a handler and having it&lt;br /&gt;
called. Here are the steps shown:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; Step 1: Register handler&lt;br /&gt;
: The script uses a library function to register a subroutine—in this&lt;br /&gt;
: case, it's &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt;—as a handler with the library. In the&lt;br /&gt;
: registration, the subroutine is assigned as a handler for&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. &lt;br /&gt;
; Step 2: &amp;amp;lt;presence/&amp;amp;gt; element arrives&lt;br /&gt;
: An XML fragment arrives on the stream, sent by the Jabber server. &lt;br /&gt;
; Step 3: Parse, and create node&lt;br /&gt;
: The fragment is parsed into its component parts by an XML parser, and&lt;br /&gt;
: a node is created. A &amp;quot;node&amp;quot; is simply a term used to describe a&lt;br /&gt;
: succinct XML fragment—containing attributes, data, and child tags—that&lt;br /&gt;
: is  usually in the form of an object that is programmatically&lt;br /&gt;
: accessible. The node creation step is theoretically optional; we could&lt;br /&gt;
: have the library pass on the fragment in a simple string&lt;br /&gt;
: representation  form, but that would put the onus on the script to&lt;br /&gt;
: parse the string before being able to manipulate the fragment that the&lt;br /&gt;
: string represented. &lt;br /&gt;
; Step 4: Determine handler&lt;br /&gt;
: Once parsed, the library looks at what sort of element, or node, the&lt;br /&gt;
: fragment is and determines what (if any) handler has been registered.&lt;br /&gt;
: In this case, it's a &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; element, and it finds&lt;br /&gt;
: that the subroutine &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt; has been registered as a&lt;br /&gt;
: handler for &amp;lt;tt&amp;gt;&amp;amp;lt;presence/&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. &lt;br /&gt;
; Step 5: Call handler&lt;br /&gt;
: The library calls the handler &amp;lt;tt&amp;gt;presenceCB()&amp;lt;/tt&amp;gt; in the script,&lt;br /&gt;
: passing in the node. It may pass in other information too (for&lt;br /&gt;
: example, the &amp;lt;tt&amp;gt;Jabberpy&amp;lt;/tt&amp;gt; library also passes in the stream&lt;br /&gt;
: connection object, as we saw earlier, and the Perl library&lt;br /&gt;
: &amp;lt;tt&amp;gt;Net::Jabber&amp;lt;/tt&amp;gt; also passes in a session ID relating to the&lt;br /&gt;
: stream).&amp;lt;ref&amp;gt;This session ID is currently part of a new development&lt;br /&gt;
: within the  &amp;lt;tt&amp;gt;Net::Jabber&amp;lt;/tt&amp;gt; library and is currently not used for&lt;br /&gt;
: anything. &amp;lt;/ref&amp;gt;&amp;lt;/content&amp;gt;&amp;lt;/chapter&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mikeh</name></author>	</entry>

	</feed>