[0ff8d110] | 1 | ############################################################################## |
---|
| 2 | # |
---|
| 3 | # This library is free software; you can redistribute it and/or |
---|
| 4 | # modify it under the terms of the GNU Library General Public |
---|
| 5 | # License as published by the Free Software Foundation; either |
---|
| 6 | # version 2 of the License, or (at your option) any later version. |
---|
| 7 | # |
---|
| 8 | # This library is distributed in the hope that it will be useful, |
---|
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
| 11 | # Library General Public License for more details. |
---|
| 12 | # |
---|
| 13 | # You should have received a copy of the GNU Library General Public |
---|
| 14 | # License along with this library; if not, write to the |
---|
| 15 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
| 16 | # Boston, MA 02111-1307, USA. |
---|
| 17 | # |
---|
| 18 | # Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/ |
---|
| 19 | # |
---|
| 20 | ############################################################################## |
---|
| 21 | |
---|
| 22 | package Net::XMPP::Namespaces; |
---|
| 23 | |
---|
| 24 | =head1 NAME |
---|
| 25 | |
---|
| 26 | Net::XMPP::Namespaces - In depth discussion on how namespaces are handled |
---|
| 27 | |
---|
| 28 | =head1 SYNOPSIS |
---|
| 29 | |
---|
| 30 | Net::XMPP::Namespaces provides an depth look at how Net::XMPP handles |
---|
| 31 | namespacs, and how to add your own custom ones. It also serves as the |
---|
| 32 | storage bin for all of the Namespace information Net::XMPP requires. |
---|
| 33 | |
---|
| 34 | =head1 DESCRIPTION |
---|
| 35 | |
---|
| 36 | XMPP as a protocol is very well defined. There are three main top |
---|
| 37 | level packets (message, iq, and presence). There is also a way to |
---|
| 38 | extend the protocol in a very clear and strucutred way, via namespaces. |
---|
| 39 | |
---|
| 40 | Two major ways that namespaces are used in Jabber is for making the |
---|
| 41 | <iq/> a generic wrapper, and as a way for adding data to any packet via |
---|
| 42 | a child tag <x/>. We will use <x/> to represent the packet, but in |
---|
| 43 | reality it could be any child tag: <foo/>, <data/>, <error/>, etc. |
---|
| 44 | |
---|
| 45 | The Info/Query <iq/> packet uses namespaces to determine the type of |
---|
| 46 | information to access. Usually there is a <query/> tag in the <iq/> |
---|
| 47 | that represents the namespace, but in fact it can be any tag. The |
---|
| 48 | definition of the Query portion, is the first tag that has a namespace. |
---|
| 49 | |
---|
| 50 | <iq type="get"><query xmlns="..."/></iq> |
---|
| 51 | |
---|
| 52 | or |
---|
| 53 | |
---|
| 54 | <iq type="get"><foo xmlns="..."/></iq> |
---|
| 55 | |
---|
| 56 | After that Query stanza can be any number of other stanzas (<x/> tags) |
---|
| 57 | you want to include. The Query packet is represented and available by |
---|
| 58 | calling GetQuery() or GetChild(), and the other namespaces are |
---|
| 59 | available by calling GetChild(). |
---|
| 60 | |
---|
| 61 | The X tag is just a way to piggy back data on other packets. Like |
---|
| 62 | embedding the timestamp for a message using jabber:x:delay, or signing |
---|
| 63 | you presence for encryption using jabber:x:signed. |
---|
| 64 | |
---|
| 65 | To this end, Net::XMPP has sought to find a way to easily, and clearly |
---|
| 66 | define the functions needed to access the XML for a namespace. We will |
---|
| 67 | go over the full docs, and then show two examples of real namespaces so |
---|
| 68 | that you can see what we are talking about. |
---|
| 69 | |
---|
| 70 | =head2 Overview |
---|
| 71 | |
---|
| 72 | To avoid a lot of nasty modules populating memory that are not used, |
---|
| 73 | and to avoid having to change 15 modules when a minor change is |
---|
| 74 | introduced, the Net::XMPP modules have taken AUTOLOADing to the |
---|
| 75 | extreme. Namespaces.pm is nothing but a set of function calls that |
---|
| 76 | generates a big hash of hashes. The hash is accessed by the Stanza.pm |
---|
| 77 | AUTOLOAD function to do something. (This will make sense, I promise.) |
---|
| 78 | |
---|
| 79 | Before going on, I highly suggest you read a Perl book on AUTOLOAD and |
---|
| 80 | how it works. From this point on I will assume that you understand it. |
---|
| 81 | |
---|
| 82 | When you create a Net::XMPP::IQ object and add a Query to it (NewChild) |
---|
| 83 | several things are happening in the background. The argument to |
---|
| 84 | NewChild is the namespace you want to add. (custom-namespace) |
---|
| 85 | |
---|
| 86 | Now that you have a Query object to work with you will call the GetXXX |
---|
| 87 | functions, and SetXXX functions to set the data. There are no defined |
---|
| 88 | GetXXX and SetXXXX functions. You cannot look in the Namespaces.pm |
---|
| 89 | file and find them. Instead you will find something like this: |
---|
| 90 | |
---|
| 91 | &add_ns(ns => "mynamespace", |
---|
| 92 | tag => "mytag", |
---|
| 93 | xpath => { |
---|
| 94 | JID => { type=>'jid', path => '@jid' }, |
---|
| 95 | Username => { path => 'username/text()' }, |
---|
| 96 | Test => { type => 'master' } |
---|
| 97 | } |
---|
| 98 | ); |
---|
| 99 | |
---|
| 100 | When the GetUsername() function is called, the AUTOLOAD function looks |
---|
| 101 | in the Namespaces.pm hash for a "Username" key. Based on the "type" of |
---|
| 102 | the field (scalar being the default) it will use the "path" as an XPath |
---|
| 103 | to retrieve the data and call the XPathGet() method in Stanza.pm. |
---|
| 104 | |
---|
| 105 | Confused yet? |
---|
| 106 | |
---|
| 107 | =head2 Net::XMPP private namespaces |
---|
| 108 | |
---|
| 109 | Now this is where this starts to get a little sticky. When you see a |
---|
| 110 | namespace with __netxmpp__, or __netjabber__ from Net::Jabber, at the |
---|
| 111 | beginning it is usually something custom to Net::XMPP and NOT part of |
---|
| 112 | the actual XMPP protocol. |
---|
| 113 | |
---|
| 114 | There are some places where the structure of the XML allows for |
---|
| 115 | multiple children with the same name. The main places you will see |
---|
| 116 | this behavior is where you have multiple tags with the same name and |
---|
| 117 | those have children under them (jabber:iq:roster). |
---|
| 118 | |
---|
| 119 | In jabber:iq:roster, the <item/> tag can be repeated multiple times, |
---|
| 120 | and is sort of like a mini-namespace in itself. To that end, we treat |
---|
| 121 | it like a seperate namespace and defined a __netxmpp__:iq:roster:item |
---|
| 122 | namespace to hold it. What happens is this, in my code I define that |
---|
| 123 | the <item/>s tag is "item" and anything with that tag name is to create |
---|
| 124 | a new Net::XMPP::Stanza object with the namespace |
---|
| 125 | __netxmpp__:iq:roster:item which then becomes a child of the |
---|
| 126 | jabber:iq:roster Stanza object. Also, when you want to add a new item |
---|
| 127 | to a jabber:iq:roster project you call NewQuery with the private |
---|
| 128 | namespace. |
---|
| 129 | |
---|
| 130 | I know this sounds complicated. And if after reading this entire |
---|
| 131 | document it is still complicated, email me, ask questions, and I will |
---|
| 132 | monitor it and adjust these docs to answer the questions that people |
---|
| 133 | ask. |
---|
| 134 | |
---|
| 135 | =head2 add_ns() |
---|
| 136 | |
---|
| 137 | To repeat, here is an example call to add_ns(): |
---|
| 138 | |
---|
| 139 | &add_ns(ns => "mynamespace", |
---|
| 140 | tag => "mytag", |
---|
| 141 | xpath => { |
---|
| 142 | JID => { type=>'jid', path => '@jid' }, |
---|
| 143 | Username => { path => 'username/text()' }, |
---|
| 144 | Test => { type => 'master' } |
---|
| 145 | } |
---|
| 146 | ); |
---|
| 147 | |
---|
| 148 | ns - This is the new namespace that you are trying to add. |
---|
| 149 | |
---|
| 150 | tag - This is the root tag to use for objects based on this namespace. |
---|
| 151 | |
---|
| 152 | xpath - The hash reference passed in the add_ns call to each name of |
---|
| 153 | entry tells Net::XMPP how to handle subsequent GetXXXX(), SetXXXX(), |
---|
| 154 | DefinedXXXX(), RemoveXXXX(), AddXXXX() calls. The basic options you |
---|
| 155 | can pass in are: |
---|
| 156 | |
---|
| 157 | type - This tells Stanza how to handle the call. The possible |
---|
| 158 | values are: |
---|
| 159 | |
---|
| 160 | array - The value to set and returned is an an array |
---|
| 161 | reference. For example, <group/> in jabber:iq:roster. |
---|
| 162 | |
---|
| 163 | child - This tells Stanza that it needs to look for the |
---|
| 164 | __netxmpp__ style namesapced children. AddXXX() adds |
---|
| 165 | a new child, and GetXXX() will return a new Stanza |
---|
| 166 | object representing the packet. |
---|
| 167 | |
---|
| 168 | flag - This is for child elements that are tags by themselves: |
---|
| 169 | <foo/>. Since the presence of the tag is what is |
---|
| 170 | important, and there is no cdata to store, we just call |
---|
| 171 | it a flag. |
---|
| 172 | |
---|
| 173 | jid - The value is a Jabber ID. GetXXX() will return a |
---|
| 174 | Net::XMPP::JID object unless you pass it "jid", then it |
---|
| 175 | returns a string. |
---|
| 176 | |
---|
| 177 | master - The GetXXX() and SetXXX() calls return and take a |
---|
| 178 | hash representing all of the GetXXX() and SetXXX() |
---|
| 179 | calls. For example: |
---|
| 180 | |
---|
| 181 | SetTest(foo=>"bar", |
---|
| 182 | bar=>"baz"); |
---|
| 183 | |
---|
| 184 | Translates into: |
---|
| 185 | |
---|
| 186 | SetFoo("bar"); |
---|
| 187 | SetBar("baz"); |
---|
| 188 | |
---|
| 189 | GetTest() would return a hash containing what the |
---|
| 190 | packet contains: |
---|
| 191 | |
---|
| 192 | { foo=>"bar", bar=>"baz" } |
---|
| 193 | |
---|
| 194 | raw - This will stick whatever raw XML you specify directly |
---|
| 195 | into the Stanza at the point where the path specifies. |
---|
| 196 | |
---|
| 197 | scalar - This will set and get a scalar value. This is the |
---|
| 198 | main workhorse as attributes and CDATA is represented |
---|
| 199 | by a scalar. This is the default setting if you do |
---|
| 200 | not provide one. |
---|
| 201 | |
---|
| 202 | special - The special type is unique in that instead of a |
---|
| 203 | string "special", you actually give it an array: |
---|
| 204 | |
---|
| 205 | [ "special" , <subtype> ] |
---|
| 206 | |
---|
| 207 | This allows Net::XMPP to be able to handle the |
---|
| 208 | SetXXXX() call in a special manner according to your |
---|
| 209 | choosing. Right now this is mainly used by |
---|
| 210 | jabber:iq:time to automatically set the time info in |
---|
| 211 | the correct format, and jabber:iq:version to set the |
---|
| 212 | machine OS and add the Net::Jabber version to the |
---|
| 213 | return packet. You will likely NOT need to use |
---|
| 214 | this, but I wanted to mention it. |
---|
| 215 | |
---|
| 216 | timestamp - If you call SetXXX() but do not pass it anything, |
---|
| 217 | or pass it "", then Net::XMPP will place a |
---|
| 218 | timestamp in the xpath location. |
---|
| 219 | |
---|
| 220 | path - This is the XPath path to where the bit data lives. The |
---|
| 221 | difference. Now, this is not full XPath due to the nature |
---|
| 222 | of how it gets used. Instead of providing a rooted path |
---|
| 223 | all the way to the top, it's a relative path ignoring what |
---|
| 224 | the parent is. For example, if the "tag" you specified was |
---|
| 225 | "foo", and the path is "bar/text()", then the XPath will be |
---|
| 226 | rooted in the XML of the <foo/> packet. It will set and get |
---|
| 227 | the CDATA from: |
---|
| 228 | |
---|
| 229 | <foo><bar>xxxxx</bar></foo> |
---|
| 230 | |
---|
| 231 | For a flag and a child type, just specify the child element. |
---|
| 232 | Take a look at the code in this file for more help on what |
---|
| 233 | this means. Also, read up on XPath if you don't already know |
---|
| 234 | what it is. |
---|
| 235 | |
---|
| 236 | child - This is a hash reference that tells Net::XMPP how to handle |
---|
| 237 | adding and getting child objects. The keys for the hash are |
---|
| 238 | as follows: |
---|
| 239 | |
---|
| 240 | ns - the real or custom (__netxmpp__) namesapce to use for |
---|
| 241 | this child packet. |
---|
| 242 | |
---|
| 243 | skip_xmlns => 1 - this tells Net::XMPP not to add an |
---|
| 244 | xmlns='' into the XML for the child |
---|
| 245 | object. |
---|
| 246 | |
---|
| 247 | specify_name => 1 - allows you to call NewChild("ns","tag") |
---|
| 248 | and specify the tag to use for the child |
---|
| 249 | object. This, IMHO, is BAD XML |
---|
| 250 | practice. You should always know what |
---|
| 251 | the tag of the child is and use an |
---|
| 252 | attribute or CDATA to change the type |
---|
| 253 | of the stanza. You do not want to use |
---|
| 254 | this. |
---|
| 255 | |
---|
| 256 | tag - If you use specify_name, then this is the default tag |
---|
| 257 | to use. You do not want to use this. |
---|
| 258 | |
---|
| 259 | calls - Array reference telling Net::XMPP what functions to create |
---|
| 260 | for this name. For most of the types above you will get |
---|
| 261 | Get, Set, Defined, and Remove. For child types you need to |
---|
| 262 | decide how you API will look and specify them yourself: |
---|
| 263 | |
---|
| 264 | ["Get","Defined"] |
---|
| 265 | ["Add"] |
---|
| 266 | ["Get","Add","Defined"] |
---|
| 267 | |
---|
| 268 | It all depends on how you want your API to look. |
---|
| 269 | |
---|
| 270 | Once more... The following: |
---|
| 271 | |
---|
| 272 | &add_ns(ns => "mynamespace", |
---|
| 273 | tag => "mytag", |
---|
| 274 | xpath => { |
---|
| 275 | JID => { type=>'jid', path => '@jid' }, |
---|
| 276 | Username => { path => 'username/text()' }, |
---|
| 277 | Test => { type => 'master' } |
---|
| 278 | } |
---|
| 279 | ); |
---|
| 280 | |
---|
| 281 | generates the following API calls: |
---|
| 282 | |
---|
| 283 | GetJID() |
---|
| 284 | SetJID() |
---|
| 285 | DefinedJID() |
---|
| 286 | RemoveJID() |
---|
| 287 | GetUsername() |
---|
| 288 | SetUsername() |
---|
| 289 | DefinedUsername() |
---|
| 290 | RemoveUsername() |
---|
| 291 | GetTest() |
---|
| 292 | SetTest() |
---|
| 293 | |
---|
| 294 | =head2 Wrap Up |
---|
| 295 | |
---|
| 296 | Well. I hope that I have not scared you off from writing a custom |
---|
| 297 | namespace for you application and use Net::XMPP. Look in the |
---|
| 298 | Net::XMPP::Protocol manpage for an example on using the add_ns() |
---|
| 299 | function to register your custom namespace so that Net::XMPP can |
---|
| 300 | properly handle it. |
---|
| 301 | |
---|
| 302 | =head1 AUTHOR |
---|
| 303 | |
---|
| 304 | Ryan Eatmon |
---|
| 305 | |
---|
| 306 | =head1 COPYRIGHT |
---|
| 307 | |
---|
| 308 | This module is free software; you can redistribute it and/or modify |
---|
| 309 | it under the same terms as Perl itself. |
---|
| 310 | |
---|
| 311 | =cut |
---|
| 312 | |
---|
| 313 | use vars qw ( %NS %SKIPNS ); |
---|
| 314 | |
---|
| 315 | $SKIPNS{'__netxmpp__'} = 1; |
---|
| 316 | |
---|
| 317 | #------------------------------------------------------------------------------ |
---|
| 318 | # __netxmpp__:child:test |
---|
| 319 | #------------------------------------------------------------------------------ |
---|
| 320 | { |
---|
| 321 | &add_ns(ns => "__netxmpptest__:child:test", |
---|
| 322 | tag => "test", |
---|
| 323 | xpath => { |
---|
| 324 | Bar => { path => 'bar/text()' }, |
---|
| 325 | Foo => { path => '@foo' }, |
---|
| 326 | Test => { type => 'master' } |
---|
| 327 | } |
---|
| 328 | ); |
---|
| 329 | } |
---|
| 330 | |
---|
| 331 | #------------------------------------------------------------------------------ |
---|
| 332 | # __netxmpp__:child:test:two |
---|
| 333 | #------------------------------------------------------------------------------ |
---|
| 334 | { |
---|
| 335 | &add_ns(ns => "__netxmpptest__:child:test:two", |
---|
| 336 | tag => "test", |
---|
| 337 | xpath => { |
---|
| 338 | Bob => { path => 'owner/@bob' }, |
---|
| 339 | Joe => { path => 'joe/text()' }, |
---|
| 340 | Test => { type => 'master' } |
---|
| 341 | } |
---|
| 342 | ); |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | #----------------------------------------------------------------------------- |
---|
| 346 | # urn:ietf:params:xml:ns:xmpp-bind |
---|
| 347 | #----------------------------------------------------------------------------- |
---|
| 348 | { |
---|
| 349 | &add_ns(ns => "urn:ietf:params:xml:ns:xmpp-bind", |
---|
| 350 | tag => "bind", |
---|
| 351 | xpath => { |
---|
| 352 | JID => { type => 'jid', |
---|
| 353 | path => 'jid/text()', |
---|
| 354 | }, |
---|
| 355 | Resource => { path => 'resource/text()' }, |
---|
| 356 | Bind => { type => 'master' }, |
---|
| 357 | }, |
---|
| 358 | docs => { |
---|
| 359 | module => 'Net::XMPP', |
---|
| 360 | }, |
---|
| 361 | ); |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | #----------------------------------------------------------------------------- |
---|
| 365 | # urn:ietf:params:xml:ns:xmpp-session |
---|
| 366 | #----------------------------------------------------------------------------- |
---|
| 367 | { |
---|
| 368 | &add_ns(ns => "urn:ietf:params:xml:ns:xmpp-session", |
---|
| 369 | tag => "session", |
---|
| 370 | xpath => { Session => { type => 'master' } }, |
---|
| 371 | docs => { |
---|
| 372 | module => 'Net::XMPP', |
---|
| 373 | }, |
---|
| 374 | ); |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | #----------------------------------------------------------------------------- |
---|
| 378 | # jabber:iq:auth |
---|
| 379 | #----------------------------------------------------------------------------- |
---|
| 380 | { |
---|
| 381 | &add_ns(ns => "jabber:iq:auth", |
---|
| 382 | tag => "query", |
---|
| 383 | xpath => { |
---|
| 384 | Digest => { path => 'digest/text()' }, |
---|
| 385 | Hash => { path => 'hash/text()' }, |
---|
| 386 | Password => { path => 'password/text()' }, |
---|
| 387 | Resource => { path => 'resource/text()' }, |
---|
| 388 | Sequence => { path => 'sequence/text()' }, |
---|
| 389 | Token => { path => 'token/text()' }, |
---|
| 390 | Username => { path => 'username/text()' }, |
---|
| 391 | Auth => { type => 'master' }, |
---|
| 392 | }, |
---|
| 393 | docs => { |
---|
| 394 | module => 'Net::XMPP', |
---|
| 395 | }, |
---|
| 396 | ); |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | #----------------------------------------------------------------------------- |
---|
| 400 | # jabber:iq:privacy |
---|
| 401 | #----------------------------------------------------------------------------- |
---|
| 402 | { |
---|
| 403 | &add_ns(ns => "jabber:iq:privacy", |
---|
| 404 | tag => "query", |
---|
| 405 | xpath => { |
---|
| 406 | Active => { path => 'active/@name' }, |
---|
| 407 | Default => { path => 'default/@name' }, |
---|
| 408 | List => { |
---|
| 409 | type => 'child', |
---|
| 410 | path => 'list', |
---|
| 411 | child => { ns => '__netxmpp__:iq:privacy:list', }, |
---|
| 412 | calls => [ 'Add' ], |
---|
| 413 | }, |
---|
| 414 | Lists => { |
---|
| 415 | type => 'child', |
---|
| 416 | path => 'list', |
---|
| 417 | child => { ns => '__netxmpp__:iq:privacy:list', }, |
---|
| 418 | }, |
---|
| 419 | Privacy => { type => 'master' }, |
---|
| 420 | }, |
---|
| 421 | docs => { |
---|
| 422 | module => 'Net::XMPP', |
---|
| 423 | }, |
---|
| 424 | ); |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | #----------------------------------------------------------------------------- |
---|
| 428 | # __netxmpp__:iq:privacy:list |
---|
| 429 | #----------------------------------------------------------------------------- |
---|
| 430 | { |
---|
| 431 | &add_ns(ns => '__netxmpp__:iq:privacy:list', |
---|
| 432 | xpath => { |
---|
| 433 | Name => { path => '@name' }, |
---|
| 434 | Item => { |
---|
| 435 | type => 'child', |
---|
| 436 | path => 'item', |
---|
| 437 | child => { ns => '__netxmpp__:iq:privacy:list:item', }, |
---|
| 438 | calls => [ 'Add' ], |
---|
| 439 | }, |
---|
| 440 | Items => { |
---|
| 441 | type => 'child', |
---|
| 442 | path => 'item', |
---|
| 443 | child => { ns => '__netxmpp__:iq:privacy:item', }, |
---|
| 444 | }, |
---|
| 445 | List => { type => 'master' }, |
---|
| 446 | }, |
---|
| 447 | docs => { |
---|
| 448 | module => 'Net::XMPP', |
---|
| 449 | name => 'jabber:iq:privacy - list objects', |
---|
| 450 | }, |
---|
| 451 | ); |
---|
| 452 | } |
---|
| 453 | |
---|
| 454 | #----------------------------------------------------------------------------- |
---|
| 455 | # __netxmpp__:iq:privacy:list:item |
---|
| 456 | #----------------------------------------------------------------------------- |
---|
| 457 | { |
---|
| 458 | &add_ns(ns => '__netxmpp__:iq:privacy:list:item', |
---|
| 459 | xpath => { |
---|
| 460 | Action => { path => '@action' }, |
---|
| 461 | IQ => { |
---|
| 462 | type => 'flag', |
---|
| 463 | path => 'iq', |
---|
| 464 | }, |
---|
| 465 | Message => { |
---|
| 466 | type => 'flag', |
---|
| 467 | path => 'message', |
---|
| 468 | }, |
---|
| 469 | Order => { path => '@order' }, |
---|
| 470 | PresenceIn => { |
---|
| 471 | type => 'flag', |
---|
| 472 | path => 'presence-in', |
---|
| 473 | }, |
---|
| 474 | PresenceOut => { |
---|
| 475 | type => 'flag', |
---|
| 476 | path => 'presence-out', |
---|
| 477 | }, |
---|
| 478 | Type => { path => '@type' }, |
---|
| 479 | Value => { path => '@value' }, |
---|
| 480 | Item => { type => 'master' }, |
---|
| 481 | }, |
---|
| 482 | docs => { |
---|
| 483 | module => 'Net::XMPP', |
---|
| 484 | name => 'jabber:iq:privacy - item objects', |
---|
| 485 | }, |
---|
| 486 | ); |
---|
| 487 | } |
---|
| 488 | |
---|
| 489 | #----------------------------------------------------------------------------- |
---|
| 490 | # jabber:iq:register |
---|
| 491 | #----------------------------------------------------------------------------- |
---|
| 492 | { |
---|
| 493 | &add_ns(ns => "jabber:iq:register", |
---|
| 494 | tag => "query", |
---|
| 495 | xpath => { |
---|
| 496 | Address => { path => 'address/text()' }, |
---|
| 497 | City => { path => 'city/text()' }, |
---|
| 498 | Date => { path => 'date/text()' }, |
---|
| 499 | Email => { path => 'email/text()' }, |
---|
| 500 | First => { path => 'first/text()' }, |
---|
| 501 | Instructions => { path => 'instructions/text()' }, |
---|
| 502 | Key => { path => 'key/text()' }, |
---|
| 503 | Last => { path => 'last/text()' }, |
---|
| 504 | Misc => { path => 'misc/text()' }, |
---|
| 505 | Name => { path => 'name/text()' }, |
---|
| 506 | Nick => { path => 'nick/text()' }, |
---|
| 507 | Password => { path => 'password/text()' }, |
---|
| 508 | Phone => { path => 'phone/text()' }, |
---|
| 509 | Registered => { |
---|
| 510 | type => 'flag', |
---|
| 511 | path => 'registered', |
---|
| 512 | }, |
---|
| 513 | Remove => { |
---|
| 514 | type => 'flag', |
---|
| 515 | path => 'password/text()', |
---|
| 516 | }, |
---|
| 517 | State => { path => 'state/text()' }, |
---|
| 518 | Text => { path => 'text/text()' }, |
---|
| 519 | URL => { path => 'url/text()' }, |
---|
| 520 | Username => { path => 'username/text()' }, |
---|
| 521 | Zip => { path => 'zip/text()' }, |
---|
| 522 | Register => { type => 'master' }, |
---|
| 523 | }, |
---|
| 524 | docs => { |
---|
| 525 | module => 'Net::XMPP', |
---|
| 526 | }, |
---|
| 527 | ); |
---|
| 528 | } |
---|
| 529 | |
---|
| 530 | #----------------------------------------------------------------------------- |
---|
| 531 | # jabber:iq:roster |
---|
| 532 | #----------------------------------------------------------------------------- |
---|
| 533 | { |
---|
| 534 | &add_ns(ns => 'jabber:iq:roster', |
---|
| 535 | tag => "query", |
---|
| 536 | xpath => { |
---|
| 537 | Item => { |
---|
| 538 | type => 'child', |
---|
| 539 | path => 'item', |
---|
| 540 | child => { ns => '__netxmpp__:iq:roster:item', }, |
---|
| 541 | calls => [ 'Add' ], |
---|
| 542 | }, |
---|
| 543 | Items => { |
---|
| 544 | type => 'child', |
---|
| 545 | path => 'item', |
---|
| 546 | child => { ns => '__netxmpp__:iq:roster:item', }, |
---|
| 547 | calls => [ 'Get' ], |
---|
| 548 | }, |
---|
| 549 | Roster => { type => 'master' }, |
---|
| 550 | }, |
---|
| 551 | docs => { |
---|
| 552 | module => 'Net::XMPP', |
---|
| 553 | }, |
---|
| 554 | ); |
---|
| 555 | } |
---|
| 556 | |
---|
| 557 | #----------------------------------------------------------------------------- |
---|
| 558 | # __netxmpp__:iq:roster:item |
---|
| 559 | #----------------------------------------------------------------------------- |
---|
| 560 | { |
---|
| 561 | &add_ns(ns => "__netxmpp__:iq:roster:item", |
---|
| 562 | xpath => { |
---|
| 563 | Ask => { path => '@ask' }, |
---|
| 564 | Group => { |
---|
| 565 | type => 'array', |
---|
| 566 | path => 'group/text()', |
---|
| 567 | }, |
---|
| 568 | JID => { |
---|
| 569 | type => 'jid', |
---|
| 570 | path => '@jid', |
---|
| 571 | }, |
---|
| 572 | Name => { path => '@name' }, |
---|
| 573 | Subscription => { path => '@subscription' }, |
---|
| 574 | Item => { type => 'master' }, |
---|
| 575 | }, |
---|
| 576 | docs => { |
---|
| 577 | module => 'Net::XMPP', |
---|
| 578 | name => 'jabber:iq:roster - item objects', |
---|
| 579 | }, |
---|
| 580 | ); |
---|
| 581 | } |
---|
| 582 | |
---|
| 583 | |
---|
| 584 | |
---|
| 585 | sub add_ns |
---|
| 586 | { |
---|
| 587 | my (%args) = @_; |
---|
| 588 | |
---|
| 589 | # XXX error check... |
---|
| 590 | |
---|
| 591 | $NS{$args{ns}}->{tag} = $args{tag} if exists($args{tag}); |
---|
| 592 | $NS{$args{ns}}->{xpath} = $args{xpath}; |
---|
| 593 | if (exists($args{docs})) |
---|
| 594 | { |
---|
| 595 | $NS{$args{ns}}->{docs} = $args{docs}; |
---|
| 596 | $NS{$args{ns}}->{docs}->{name} = $args{ns} |
---|
| 597 | unless exists($args{docs}->{name}); |
---|
| 598 | } |
---|
| 599 | } |
---|
| 600 | |
---|
| 601 | |
---|
| 602 | 1; |
---|