util/xmppstream.lua

changeset 3987
8fbf57722368
parent 3927
1b57e83266f0
child 3989
692d221ef9bd
equal deleted inserted replaced
3986:671a660b20f9 3987:8fbf57722368
7 -- 7 --
8 8
9 9
10 local lxp = require "lxp"; 10 local lxp = require "lxp";
11 local st = require "util.stanza"; 11 local st = require "util.stanza";
12 local stanza_mt = st.stanza_mt;
12 13
13 local tostring = tostring; 14 local tostring = tostring;
14 local t_insert = table.insert; 15 local t_insert = table.insert;
15 local t_concat = table.concat; 16 local t_concat = table.concat;
17 local t_remove = table.remove;
18 local setmetatable = setmetatable;
16 19
17 local default_log = require "util.logger".init("xmppstream"); 20 local default_log = require "util.logger".init("xmppstream");
18 21
19 local error = error; 22 local error = error;
20 23
51 end 54 end
52 local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error"); 55 local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error");
53 56
54 local stream_default_ns = stream_callbacks.default_ns; 57 local stream_default_ns = stream_callbacks.default_ns;
55 58
59 local stack = {};
56 local chardata, stanza = {}; 60 local chardata, stanza = {};
57 local non_streamns_depth = 0; 61 local non_streamns_depth = 0;
58 function xml_handlers:StartElement(tagname, attr) 62 function xml_handlers:StartElement(tagname, attr)
59 if stanza and #chardata > 0 then 63 if stanza and #chardata > 0 then
60 -- We have some character data in the buffer 64 -- We have some character data in the buffer
61 stanza:text(t_concat(chardata)); 65 t_insert(stanza, t_concat(chardata));
62 chardata = {}; 66 chardata = {};
63 end 67 end
64 local curr_ns,name = tagname:match(ns_pattern); 68 local curr_ns,name = tagname:match(ns_pattern);
65 if name == "" then 69 if name == "" then
66 curr_ns, name = "", curr_ns; 70 curr_ns, name = "", curr_ns;
100 end 104 end
101 if curr_ns == "jabber:client" and name ~= "iq" and name ~= "presence" and name ~= "message" then 105 if curr_ns == "jabber:client" and name ~= "iq" and name ~= "presence" and name ~= "message" then
102 cb_error(session, "invalid-top-level-element"); 106 cb_error(session, "invalid-top-level-element");
103 end 107 end
104 108
105 stanza = st.stanza(name, attr); 109 stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
106 else -- we are inside a stanza, so add a tag 110 else -- we are inside a stanza, so add a tag
107 stanza:tag(name, attr); 111 t_insert(stack, stanza);
112 local oldstanza = stanza;
113 stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
114 t_insert(oldstanza, stanza);
115 t_insert(oldstanza.tags, stanza);
108 end 116 end
109 end 117 end
110 function xml_handlers:CharacterData(data) 118 function xml_handlers:CharacterData(data)
111 if stanza then 119 if stanza then
112 t_insert(chardata, data); 120 t_insert(chardata, data);
117 non_streamns_depth = non_streamns_depth - 1; 125 non_streamns_depth = non_streamns_depth - 1;
118 end 126 end
119 if stanza then 127 if stanza then
120 if #chardata > 0 then 128 if #chardata > 0 then
121 -- We have some character data in the buffer 129 -- We have some character data in the buffer
122 stanza:text(t_concat(chardata)); 130 t_insert(stanza, t_concat(chardata));
123 chardata = {}; 131 chardata = {};
124 end 132 end
125 -- Complete stanza 133 -- Complete stanza
126 local last_add = stanza.last_add; 134 if #stack == 0 then
127 if not last_add or #last_add == 0 then
128 if tagname ~= stream_error_tag then 135 if tagname ~= stream_error_tag then
129 cb_handlestanza(session, stanza); 136 cb_handlestanza(session, stanza);
130 else 137 else
131 cb_error(session, "stream-error", stanza); 138 cb_error(session, "stream-error", stanza);
132 end 139 end
133 stanza = nil; 140 stanza = nil;
134 else 141 else
135 stanza:up(); 142 stanza = t_remove(stack);
136 end 143 end
137 else 144 else
138 if tagname == stream_tag then 145 if tagname == stream_tag then
139 if cb_streamclosed then 146 if cb_streamclosed then
140 cb_streamclosed(session); 147 cb_streamclosed(session);
145 curr_ns, name = "", curr_ns; 152 curr_ns, name = "", curr_ns;
146 end 153 end
147 cb_error(session, "parse-error", "unexpected-element-close", name); 154 cb_error(session, "parse-error", "unexpected-element-close", name);
148 end 155 end
149 stanza, chardata = nil, {}; 156 stanza, chardata = nil, {};
157 stack = {};
150 end 158 end
151 end 159 end
152 160
153 local function reset() 161 local function reset()
154 stanza, chardata = nil, {}; 162 stanza, chardata = nil, {};
163 stack = {};
155 end 164 end
156 165
157 local function set_session(stream, new_session) 166 local function set_session(stream, new_session)
158 session = new_session; 167 session = new_session;
159 log = new_session.log or default_log; 168 log = new_session.log or default_log;

mercurial