PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/linkedfs/usr/lib/perl5/vendor_perl/5.8.4/Net/Jabber/Namespaces.pm

https://bitbucket.org/harakiri/trk
Perl | 440 lines | 332 code | 87 blank | 21 comment | 31 complexity | 5fb35219f749b75e0b3450d37874ad59 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-3.0
  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. # Jabber
  19. # Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
  20. #
  21. ##############################################################################
  22. package Net::Jabber::Namespaces;
  23. =head1 NAME
  24. Net::Jabber::Namespaces - In depth discussion on how
  25. namespaces are handled
  26. =head1 SYNOPSIS
  27. Net::Jabber::Namespaces is a pure documentation
  28. module. It provides no code for execution, just
  29. documentation on how the Net::Jabber modules handle
  30. namespaces.
  31. =head1 DESCRIPTION
  32. Jabber as a protocol is very well defined. There are
  33. three main top level packets (message, iq, and presence).
  34. There is also a way to extend the protocol in a very
  35. clear and strucutred way, via namespaces.
  36. Two major ways that namespaces are used in Jabber is
  37. for making the <iq/> a generic wrapper, and as a way
  38. for adding data to any packet via <x/>.
  39. The Info/Query <iq/> packet uses namespaces to determine
  40. the type of information to access. Usually there is
  41. a <query/> tag in the <iq/> that represents the
  42. namespace, but in fact it can be any tag. The
  43. definition of the Query portion, is the first
  44. tag that has a namespace.
  45. <iq type="get"><query xmlns="..."/></iq>
  46. or
  47. <iq type="get"><foo xmlns="..."/></iq>
  48. After that Query cna be any number of <x/> tags you want
  49. to include.
  50. The X tag is just a way to piggy back data on other
  51. packets. Like embedding the timestamp for a message
  52. using jabber:x:delay, or signing you presence for
  53. encryption using jabber:x:signed.
  54. To this end, Net::Jabber has sought to find a way to
  55. easily, and clearly define the functions needed to
  56. access the XML for a namespace. We will go over the
  57. full docs, and then show two examples of real namespaces
  58. so that you can see what we are talking about.
  59. =head2 Overview
  60. To avoid a lot of nasty modules populating memory that
  61. are not used, and to avoid having to change 15 modules
  62. when a minor change is introduced, the Net::Jabber
  63. modules have taken AUTOLOADing to the extreme.
  64. Query.pm, X.pm and Data.pm are nothing but a hash of
  65. hashes data structure that is accessed by the Jabber.pm
  66. AutoLoad function to do something. (This will make
  67. sense.)
  68. Before going on, I highly suggest you read a Perl book
  69. on AUTOLOAD and how it works. From this point on I
  70. will assume that you understand it.
  71. When you create a Net::Jabber::IQ object and add a
  72. Query to it (NewQuery) somethings are happening in
  73. the background. The argument to NewQuery is the
  74. namespace you want to add. (jabber:iq:register)
  75. Now that you have a Query object to work with you
  76. will call the GetXXX functions, and SetXXX functions
  77. to set the data. There are no defined GetXXX and
  78. SetXXXX functions. You cannot look in the Query.pm
  79. file and find them. Instead you will find this:
  80. $NAMESPACES{"jabber:iq:register"}->{Username}->{Get} =
  81. "username";
  82. $NAMESPACES{"jabber:iq:register"}->{Username}->{Set} =
  83. ["scalar","username"];
  84. $NAMESPACES{"jabber:iq:register"}->{Username}->{Defined} =
  85. "username";
  86. $NAMESPACES{"jabber:iq:register"}->{Username}->{Hash} =
  87. "child-data";
  88. When the GetUsername() function is called, the AUTOLOAD
  89. function looks in the Query.pm %NAMESPACES hash for
  90. a "Username" key, and then for a "Get" key under that. It
  91. will then use that value was the argument to a Get()
  92. function defined in Jabber.pm.
  93. =head2 Net::Jabber private namespaces
  94. Now this is where this starts to get a little sticky.
  95. When you see a namespace with __netjabber__ at
  96. the beginning it is usually something custom to
  97. Net::Jabber and NOT part of the actual Jabber protocol.
  98. There are some places where the structure of the XML
  99. is a little more loose and not strongly structured.
  100. While it is still strongly defined, it is not 100%
  101. clear on how exactly to handle the tags. The main
  102. places you will see this behavior is where you have
  103. multiple tags with the same name and those have
  104. children under them (jabber:iq:roster), or where the
  105. tags are not defined but are to be treated as children
  106. just because they are there (jabber:iq:browse).
  107. In jabber:iq:roster, the <item/> tag can be repeated
  108. multiple times, and is sort of like a mini-namespace
  109. in itself. To that end, I treat it like a seperate
  110. namespace and defined a __netjabber__:iq:roster:item
  111. namespace to hold it. What happens is this, in my code
  112. I define that the <item/>s tag is "item" and anything
  113. with that tag name is to create a new Net::Jabber::Query
  114. object with the namespace __netjabber__:iq:roster:item
  115. which then becomes a {query} child of the jabber:iq:roster
  116. Query object. Also, when you want to add a new item
  117. to a jabber:iq:roster project you call NewQuery with
  118. the private namespace.
  119. In jabber:iq:browse, the children are not defined.
  120. Any child node you see under that <iq/> tag defines
  121. what the child type is. So I again created a private
  122. namespace, and add every child, except <ns/>, as a
  123. new Queyr object.
  124. I know this sounds complicated. And if after reading
  125. this entire document it is still complicated, email me,
  126. ask questions, and I will monitor it and adjust these
  127. docs to answer the questions that people ask.
  128. =head2 Get() function
  129. The values of the argument come in two forms, either a string
  130. or an array. For the most part, you will only use a string.
  131. The string is the key into the hash in the Query object.
  132. So above code would look into the Query hash for the
  133. "username" key and return the value from there. The string
  134. also represents the value of the tag or attribute in the XML.
  135. "username" -> hash{username} -> <username/>
  136. One of the functions introduced early on in the Net::Jabber
  137. lifecycle was one that you could call and set all of the
  138. values of an object. SetIQ() in the IQ.pm module for
  139. example. Moving into this new AUTOLOAD format I added
  140. a GetIQ() function that would return a hash with the values
  141. populated as if you had called SetIQ(). This is done when
  142. you set the string to "__netjabber__:master". So for the
  143. jabber:iq:register example above:
  144. $NAMESPACES{"jabber:iq:register"}->{Register}->{Get} =
  145. "__netjabber__:master";
  146. $NAMESPACES{"jabber:iq:register"}->{Register}->{Set} =
  147. ["master"];
  148. GetReigster() would return a hash with the data in the
  149. Query.
  150. The second form is an array:
  151. [ key, namespace ]
  152. like GetItem under the jabber:iq:search namespace:
  153. [ "query", "__netjabber__:iq:search" ]
  154. This is used only when the GetXXXXX function is supposed
  155. to return another object. For example, under
  156. jabber:iq:search, the agent can return multiple <item/>
  157. tags. These are turned in to Query objects as well and
  158. stored in the {DATA}->{query} hash array. The array value
  159. tells the Get() function where to look "query", and which
  160. Query objects to return, anything with the namespace
  161. "__netjabber__:iq:search".
  162. =head2 Set() function
  163. This arguement value is always an array. Though the
  164. array can take a few forms depending on what you are
  165. trying to set.
  166. The first is the simplest, and the one you will more
  167. than likely only use:
  168. [ type, key ]
  169. In our jabber:iq:register example above {Username}->{Set}
  170. is [ "scalar", "username" ]. The type is scalar, and
  171. the key is username (again the key is the hash entry, and
  172. the XML Tag or attribute). The valid types are:
  173. scalar - store the value as a string or number
  174. array - store the value as an array (like in
  175. jabber:iq:roster with <group/>)
  176. flag - sets the value to "" just to show that the
  177. XML should appear as a flag. <tag/>
  178. jid - Stores the value as a Net::Jabber::JID
  179. object
  180. master - run through all of the SetXXXX functions
  181. and set the value based on the hash passed
  182. in as an argument. (More on this below...)
  183. special - there are several cases where we want to
  184. default the value if there is none there.
  185. mainly used in the jabber:iq:time and
  186. jabber:iq:version functions, these will
  187. default the value to something that makes
  188. sense. You will probably never use this.
  189. As I mentioned, one of the functions introduced early on
  190. in the Net::Jabber lifecycle was one that you could call
  191. and set all of the values of an object. SetIQ() in the
  192. IQ.pm module for example. This is where the "master"
  193. type comes in. When you declare that something is the
  194. "master" it means that it can set all of the things in
  195. the object via the SetXXXXXX functions based on the hash
  196. that is passed to it. So for jabber:iq:register:
  197. $NAMESPACES{"jabber:iq:register"}->{Register}->{Set} =
  198. ["master"];
  199. SetRegister(%hash) is considered to be the "master"
  200. function for that namespace.
  201. The second is more complicated and involves adding a new
  202. XML child into the current tag. This is only done
  203. inside of the ParseTree function when taking XML and
  204. building the Net::Jabber::xxxxxx objects that represent
  205. the tree. It takes the form:
  206. [ "add", object type, namespace ]
  207. [ "add", object type, namespace, tags to ignore ]
  208. Looking at the jabber:iq:roster namespace:
  209. $NAMESPACES{"jabber:iq:roster"}->{Item}->{Set} =
  210. ["add","Query","__netjabber__:iq:roster:item"];
  211. A call to SetItem will add a new Net::Jabber::Query,
  212. with the namespace __netjabber__:iq:roster:item, and
  213. then populate the new Query object with the data you
  214. passed to the SetItem function. (This will be covered
  215. more under the ParseTree function described at the end.)
  216. Looking at the __netjabber__:iq:browse:item namespace:
  217. $NAMESPACES{"__netjabber__:iq:browse"}->{Item}->{Set} =
  218. ["add","Query","__netjabber__:iq:browse","ns"];
  219. Everything looks the same except for the extra "ns"
  220. at the end. This tells Net::Jabber that you can create
  221. a new object from this XML data *UNLESS* the tag name
  222. is <ns/>. If you look at the jabber:iq:browse namespace
  223. in the JPG, you will see that the children can have
  224. any name, except for <ns/> which is used to define which
  225. namespaces the jid provides. (This will be covered
  226. more under the ParseTree function described at the end.)
  227. =head2 Defined() function
  228. This function always takes a string as the argument.
  229. The string is the key value for the data hash, and tells
  230. Net::Jabber where to go look to see if the value is
  231. defined. This one should not need any more explantion
  232. other than that. All it does is check for exists() on
  233. the data hash for this value.
  234. =head2 Hash() function
  235. This function takes only a string as its argument.
  236. The value of the string determines how this bit
  237. of data is handled when Net::Jabber attempts to read
  238. or set the XML. The valid values are:
  239. att - in the parent XML this bit of
  240. data is an attribute on the root
  241. tag in the XML you are currently
  242. processing.
  243. data - in the parent XML this bit of
  244. data is the CDATA of the root
  245. tag in the XML you are currently
  246. processing.
  247. child-data - in the parent XML this bit of
  248. data is the CDATA of a child tag
  249. (defined by the NAMESPACES hash)
  250. of the root tag in the XML you
  251. are currently processing.
  252. child-flag - in the parent XML this bit of
  253. data says to include an empty child
  254. tag (defined by the NAMESPACES hash)
  255. of the root tag in the XML you
  256. are currently processing.
  257. child-add - in the parent XML this bit of
  258. data says to create a new XML
  259. child and populate it by recursing
  260. and looking at the Hash() values
  261. for its data.
  262. att-<tag>-<att> - in the parent XML this bit of
  263. data says to set the <att>
  264. attribute on the child with tag
  265. <tag> in the root tag you are
  266. currently processing.
  267. I know this sounds really complicated, but its not.
  268. Just look over the %NAMESPACES structures and think
  269. about how the XML looks for the namespace you are
  270. looking at.
  271. =head2 Add() function
  272. This function takes an array as its argument. The array
  273. has two very similer forms:
  274. [ object type, namespace, Set* function to call ]
  275. [ object type, namespace, Set* function to call, tag value ]
  276. When the Add function gets called it will create a
  277. Net::Jabber::"object type" object with the namespace
  278. specified, and then call the SetXXXXX function based
  279. on the third value. If a tag value is specified in
  280. the array, then that becomes the root tag for that
  281. object, otherwise the first argument to the AddXXXXX
  282. function defines the root tag.
  283. Looking at the jabber:iq:roster namespace:
  284. $NAMESPACES{"jabber:iq:roster"}->{Item}->{Add} =
  285. ["Query","__netjabber__:iq:roster:item","Item","item"];
  286. A call to AddItem() will create a Net::Jabber::Query
  287. object with __netjabber__:iq:roster:item as the namespace.
  288. It will call SetItem on this new object to handle the
  289. data passed to AddItem(), *AND* it will set the root
  290. tag to "item" so that an <item/> tag is created.
  291. Looking at the jabber:iq:browse namespace:
  292. $NAMESPACES{"jabber:iq:browse"}->{Item}->{Add} =
  293. ["Query","__netjabber__:iq:browse","Browse"];
  294. A call to AddItem() will create a Net::Jabber::Query
  295. object with __netjabber__:iq:browse:item as the namespace.
  296. It will call SetBrowse on this new object to handle the
  297. data passed to AddItem(). The root tag of new object
  298. is not defined though. Instead, since the
  299. jabber:iq:browse namespaces does not define the
  300. children tags, and uses the value of the tag to
  301. set what the browse item means, the call to AddItem()
  302. must include the root tag as the first argument:
  303. my $browseItem =
  304. $browseQuery->
  305. AddItem("conference",
  306. type=>"private",
  307. jid=>"conference.jabber.org",
  308. name=>"Private Chatrooms");
  309. =head2 ParseTree() function
  310. This function you will never call, but it will
  311. be calling the functions that you define in your
  312. call to DefineNamespace. We will quickly run through
  313. how it works so you can get a better understanding
  314. of how the all of the above fits together.
  315. ParseTree() takes an XML::Stream::Hash tree and
  316. runs through every function that hash a {Set} entry
  317. in the definition Hash (see above). For each
  318. function it calls Hash() on that function name
  319. to get the method of XML access for that function.
  320. Based on that value, it reaches into the
  321. XML::Stream::Hash and pulls the needed data out and
  322. calls the appropritate SetXXXXXXX() function to store
  323. that data. If the Hash type is "child-add", then
  324. it calls Add() and passes it the XML::Stream::Hash
  325. tree with the {root} tag altered and ultimatly
  326. ParseTree is called on that new tree and starts again.
  327. After the defined {Set} functions have been looked at,
  328. the function looks for any child tags that have xmlns
  329. as an attribute. If the current object is an <iq/>
  330. then it treats the first tag with an xmlns as the
  331. <query/> and creates that. Otherwise, if the current
  332. object is a Query object, then this must be a private
  333. namespace for Net::Jabber, so create a Query object.
  334. Finally, if that fails, and this is not the first
  335. child with xmlns, or this is not a Query object then
  336. create an X object.
  337. Scrub.
  338. Rinse.
  339. Repeat.
  340. =head2 Wrap Up
  341. Well. I hope that I have not scared you off from
  342. writing a custom namespace for you application and
  343. use Net::Jabber. Look in the Net::Jabber::Protocol
  344. manpage for an example on using the DefineNamespace
  345. function to register your custom namespace so that
  346. Net::Jabber can properly handle it.
  347. =head1 AUTHOR
  348. By Ryan Eatmon in May 2001 for http://jabber.org/
  349. =head1 COPYRIGHT
  350. This module is free software; you can redistribute it and/or modify
  351. it under the same terms as Perl itself.
  352. =cut
  353. 1;