18bool put(
char *out,
size_t cap,
size_t *n,
const char *s)
20 size_t sl = strnlen(s, cap + 1);
23 memcpy(out + *n, s, sl);
29bool put_escaped(
char *out,
size_t cap,
size_t *n,
const char *s)
33 const char *rep =
nullptr;
56 if (!put(out, cap, n, rep))
70bool put_attr(
char *out,
size_t cap,
size_t *n,
const char *attr,
const char *value)
74 return put(out, cap, n,
" ") && put(out, cap, n, attr) && put(out, cap, n,
"=\"") &&
75 put_escaped(out, cap, n, value) && put(out, cap, n,
"\"");
78size_t finish(
char *out,
size_t n,
bool ok)
87size_t detws_xmpp_escape(
const char *in,
size_t in_len,
char *out,
size_t cap)
92 for (
size_t i = 0; i < in_len; i++)
94 char one[2] = {in[i],
'\0'};
95 if (!put_escaped(out, cap, &n, one))
98 return finish(out, n,
true);
101size_t detws_xmpp_stream_open(
const char *from,
const char *to,
char *out,
size_t cap)
105 put(out, cap, &n,
"<?xml version='1.0'?><stream:stream") && put_attr(out, cap, &n,
"from", from) &&
106 put_attr(out, cap, &n,
"to", to) &&
107 put(out, cap, &n,
" xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
108 return finish(out, n, ok);
111size_t detws_xmpp_message(
const char *to,
const char *from,
const char *type,
const char *body,
char *out,
size_t cap)
114 bool ok = put(out, cap, &n,
"<message") && put_attr(out, cap, &n,
"to", to) &&
115 put_attr(out, cap, &n,
"from", from) && put_attr(out, cap, &n,
"type", type) && put(out, cap, &n,
">");
117 ok = put(out, cap, &n,
"<body>") && put_escaped(out, cap, &n, body) && put(out, cap, &n,
"</body>");
118 ok = ok && put(out, cap, &n,
"</message>");
119 return finish(out, n, ok);
122size_t detws_xmpp_presence(
const char *type,
char *out,
size_t cap)
125 bool ok = put(out, cap, &n,
"<presence") && put_attr(out, cap, &n,
"type", type) && put(out, cap, &n,
"/>");
126 return finish(out, n, ok);
129size_t detws_xmpp_iq(
const char *type,
const char *
id,
const char *child_xml,
char *out,
size_t cap)
132 bool ok = put(out, cap, &n,
"<iq") && put_attr(out, cap, &n,
"type", type) && put_attr(out, cap, &n,
"id",
id) &&
133 put(out, cap, &n,
">");
135 ok = put(out, cap, &n, child_xml);
136 ok = ok && put(out, cap, &n,
"</iq>");
137 return finish(out, n, ok);
140size_t detws_xmpp_stanza_name(
const char *xml,
size_t len,
char *out,
size_t cap)
142 if (!xml || !out || cap == 0)
144 for (
size_t i = 0; i + 1 < len; i++)
149 if (c ==
'?' || c ==
'!' || c ==
'/')
151 size_t j = i + 1, k = 0;
152 while (j < len && xml[j] !=
' ' && xml[j] !=
'>' && xml[j] !=
'/' && xml[j] !=
'\t' && xml[j] !=
'\n')
164size_t detws_xmpp_attr(
const char *xml,
size_t len,
const char *attr,
char *out,
size_t cap)
166 if (!xml || !attr || !out || cap == 0)
168 size_t al = strnlen(attr, len + 1);
171 while (end < len && xml[end] !=
'>')
173 for (
size_t i = 0; i + al + 2 < end; i++)
176 if (!((i == 0 || xml[i - 1] ==
' ') && strncmp(xml + i, attr, al) == 0 && xml[i + al] ==
'='))
178 char q = xml[i + al + 1];
179 if (q !=
'"' && q !=
'\'')
181 size_t j = i + al + 2, k = 0;
182 while (j < end && xml[j] != q)
XMPP (RFC 6120) stanza codec (DETWS_ENABLE_XMPP).