Software /
code /
prosody
Comparison
util/xmppstream.lua @ 2920:f3335285b20d
util.xmppstream: Initial commit
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 22 Mar 2010 16:24:49 +0000 |
parent | 2506:core/xmlhandlers.lua@d11a781baf13 |
child | 2921:f0ddfd7739ea |
comparison
equal
deleted
inserted
replaced
2919:8ce6b680975a | 2920:f3335285b20d |
---|---|
1 -- Prosody IM | |
2 -- Copyright (C) 2008-2009 Matthew Wild | |
3 -- Copyright (C) 2008-2009 Waqas Hussain | |
4 -- | |
5 -- This project is MIT/X11 licensed. Please see the | |
6 -- COPYING file in the source package for more information. | |
7 -- | |
8 | |
9 | |
10 | |
11 require "util.stanza" | |
12 | |
13 local st = stanza; | |
14 local tostring = tostring; | |
15 local t_insert = table.insert; | |
16 local t_concat = table.concat; | |
17 | |
18 local default_log = require "util.logger".init("xmlhandlers"); | |
19 | |
20 local error = error; | |
21 | |
22 module "xmppstream" | |
23 | |
24 local ns_prefixes = { | |
25 ["http://www.w3.org/XML/1998/namespace"] = "xml"; | |
26 }; | |
27 | |
28 local xmlns_streams = "http://etherx.jabber.org/streams"; | |
29 | |
30 local ns_separator = "\1"; | |
31 local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$"; | |
32 | |
33 function new(session, stream_callbacks) | |
34 local chardata = {}; | |
35 local xml_handlers = {}; | |
36 local log = session.log or default_log; | |
37 | |
38 local cb_streamopened = stream_callbacks.streamopened; | |
39 local cb_streamclosed = stream_callbacks.streamclosed; | |
40 local cb_error = stream_callbacks.error or function(session, e) error("XML stream error: "..tostring(e)); end; | |
41 local cb_handlestanza = stream_callbacks.handlestanza; | |
42 | |
43 local stream_ns = stream_callbacks.stream_ns or xmlns_streams; | |
44 local stream_tag = stream_ns..ns_separator..(stream_callbacks.stream_tag or "stream"); | |
45 local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error"); | |
46 | |
47 local stream_default_ns = stream_callbacks.default_ns; | |
48 | |
49 local stanza; | |
50 function xml_handlers:StartElement(tagname, attr) | |
51 if stanza and #chardata > 0 then | |
52 -- We have some character data in the buffer | |
53 stanza:text(t_concat(chardata)); | |
54 chardata = {}; | |
55 end | |
56 local curr_ns,name = tagname:match(ns_pattern); | |
57 if name == "" then | |
58 curr_ns, name = "", curr_ns; | |
59 end | |
60 | |
61 if curr_ns ~= stream_default_ns then | |
62 attr.xmlns = curr_ns; | |
63 end | |
64 | |
65 -- FIXME !!!!! | |
66 for i=1,#attr do | |
67 local k = attr[i]; | |
68 attr[i] = nil; | |
69 local ns, nm = k:match(ns_pattern); | |
70 if nm ~= "" then | |
71 ns = ns_prefixes[ns]; | |
72 if ns then | |
73 attr[ns..":"..nm] = attr[k]; | |
74 attr[k] = nil; | |
75 end | |
76 end | |
77 end | |
78 | |
79 if not stanza then --if we are not currently inside a stanza | |
80 if session.notopen then | |
81 if tagname == stream_tag then | |
82 if cb_streamopened then | |
83 cb_streamopened(session, attr); | |
84 end | |
85 else | |
86 -- Garbage before stream? | |
87 cb_error(session, "no-stream"); | |
88 end | |
89 return; | |
90 end | |
91 if curr_ns == "jabber:client" and name ~= "iq" and name ~= "presence" and name ~= "message" then | |
92 cb_error(session, "invalid-top-level-element"); | |
93 end | |
94 | |
95 stanza = st.stanza(name, attr); | |
96 else -- we are inside a stanza, so add a tag | |
97 attr.xmlns = nil; | |
98 if curr_ns ~= stream_default_ns then | |
99 attr.xmlns = curr_ns; | |
100 end | |
101 stanza:tag(name, attr); | |
102 end | |
103 end | |
104 function xml_handlers:CharacterData(data) | |
105 if stanza then | |
106 t_insert(chardata, data); | |
107 end | |
108 end | |
109 function xml_handlers:EndElement(tagname) | |
110 if stanza then | |
111 if #chardata > 0 then | |
112 -- We have some character data in the buffer | |
113 stanza:text(t_concat(chardata)); | |
114 chardata = {}; | |
115 end | |
116 -- Complete stanza | |
117 if #stanza.last_add == 0 then | |
118 if tagname ~= stream_error_tag then | |
119 cb_handlestanza(session, stanza); | |
120 else | |
121 cb_error(session, "stream-error", stanza); | |
122 end | |
123 stanza = nil; | |
124 else | |
125 stanza:up(); | |
126 end | |
127 else | |
128 if tagname == stream_tag then | |
129 if cb_streamclosed then | |
130 cb_streamclosed(session); | |
131 end | |
132 else | |
133 local curr_ns,name = tagname:match(ns_pattern); | |
134 if name == "" then | |
135 curr_ns, name = "", curr_ns; | |
136 end | |
137 cb_error(session, "parse-error", "unexpected-element-close", name); | |
138 end | |
139 stanza, chardata = nil, {}; | |
140 end | |
141 end | |
142 return xml_handlers; | |
143 end | |
144 | |
145 return _M; |