time_t timep = log->when;
struct tm *tm = localtime(&timep);
- snprintf(buf, sizeof(buf), "%02d:%02d [%s] %s: ",
- tm->tm_hour, tm->tm_min,
- log->channel, log->from);
+ if (log->channel && log->from)
+ snprintf(buf, sizeof(buf), "%02d:%02d [%s] %s: ",
+ tm->tm_hour, tm->tm_min,
+ log->channel, log->from);
+ else if (log->channel)
+ snprintf(buf, sizeof(buf), "%02d:%02d [%s] *** ",
+ tm->tm_hour, tm->tm_min, log->channel);
+ else if (log->from)
+ snprintf(buf, sizeof(buf), "%02d:%02d *** %s: ",
+ tm->tm_hour, tm->tm_min, log->from);
+ else
+ snprintf(buf, sizeof(buf), "%02d:%02d *** ",
+ tm->tm_hour, tm->tm_min);
+
while (*hdr)
print_word(&hdr, row, &col, indent, print);
XMPP_RECV_SUCCESS,
XMPP_SEND_BIND,
XMPP_RECV_JID,
+ XMPP_PRESENCE,
XMPP_ENCRYPT,
XMPP_RESTART,
XMPP_READY,
int connect;
const char *host;
int port;
+ const char *muc;
+ const char *nick;
const char *jid;
const char *user;
const char *pass;
buf_t buf;
int indent;
+ int in_error;
+
struct xmpp_server_t *next;
} xmpp_server_t;
static xmpp_channel_t *channels;
/* Local functions */
+const char *find_attr(const char **attrs, const char *name)
+{
+ for (int i = 0; attrs[i] && attrs[i+1]; i += 2)
+ if (match(attrs[i+0], name))
+ return attrs[i+1];
+ return NULL;
+}
+
static xmpp_server_t *find_server(const char *name, int create)
{
xmpp_server_t *cur = NULL, *last = NULL;
}
if (srv->state == XMPP_RECV_JID) {
if (match(tag, "jid")) {
- debug("xmpp: jid -> ready");
- srv->state = XMPP_READY;
+ debug("xmpp: jid -> presence");
+ srv->state = XMPP_PRESENCE;
}
}
+
+ /* Info queries */
+ if (srv->state == XMPP_READY) {
+ if (match(tag, "item"))
+ chat_notice(NULL, NULL, "item: [%s] %s",
+ find_attr(attrs, "jid"),
+ find_attr(attrs, "name"));
+ if (match(tag, "identity"))
+ chat_notice(NULL, NULL, "identity: %s",
+ find_attr(attrs, "name"));
+ if (match(tag, "feature"))
+ chat_notice(NULL, NULL, "feature: %s",
+ find_attr(attrs, "var"));
+ }
+
+ /* Error handling */
+ if (match(tag, "stream:error"))
+ srv->in_error = 1;
}
static void on_end(void *_srv, const char *tag)
{
xmpp_server_t *srv = _srv;
+ const char *data = srv->buf.data;
/* Debug print */
if (srv->buf.len) {
chat_recv("#test", NULL, data);
}
}
+
+ /* Error handling */
+ if (match(tag, "stream:error"))
+ srv->in_error = 0;
+ if (srv->in_error) {
+ if (match(tag, "text")) {
+ debug("xmpp: error: %s", data);
+ chat_notice(NULL, NULL, "error: %s", data);
+ }
+ }
}
static void on_data(void *_srv, const char *data, int len)
srv->state = XMPP_RECV_JID;
}
}
+ if (srv->state == XMPP_PRESENCE) {
+ for (xmpp_channel_t *chan = channels; chan; chan = chan->next) {
+ if (!chan->join)
+ continue;
+ net_print(&srv->net,
+ "<presence id='join' from='%s' to='%s@%s/%s'>"
+ "<x xmlns='http://jabber.org/protocol/muc'/>"
+ "</presence>",
+ srv->jid, chan->channel, srv->muc, srv->nick);
+ }
+ srv->state = XMPP_READY;
+ }
if (srv->state == XMPP_ENCRYPT) {
/* Encrypt connection */
net_encrypt(&srv->net);
srv->host = get_string(value);
else if (match(key, "port"))
srv->port = get_number(value);
+ else if (match(key, "muc"))
+ srv->muc = get_string(value);
+ else if (match(key, "nick"))
+ srv->nick = get_string(value);
else if (match(key, "jid"))
srv->jid = get_string(value);
else if (match(key, "user"))
void xmpp_send(const char *channel, const char *msg)
{
+ const char *arg;
+
xmpp_channel_t *chan = find_channel(channel, 0);
if (!chan)
return;
if (!srv || !srv->protocol)
return;
- net_print(&srv->net,
- "<message to='%s'><body>%s</body></message>",
- "andy@pileus.org", msg);
+ /* Handle commands */
+ if (msg[0] == '/') {
+ if (prefix(msg, "/items", &arg)) {
+ net_print(&srv->net,
+ "<iq id='items' type='get' from='%s' to='%s'>"
+ "<query xmlns='http://jabber.org/protocol/disco#items' />"
+ "</iq>",
+ srv->jid, arg ?: srv->host);
+ }
+ else if (prefix(msg, "/info", &arg)) {
+ net_print(&srv->net,
+ "<iq id='info' type='get' from='%s' to='%s'>"
+ "<query xmlns='http://jabber.org/protocol/disco#info' />"
+ "</iq>",
+ srv->jid, arg ?: srv->host);
+ }
+ else if (prefix(msg, "/list", &arg)) {
+ net_print(&srv->net,
+ "<iq id='list' type='get' from='%s' to='%s'>"
+ "<query xmlns='http://jabber.org/protocol/disco#items' />"
+ "</iq>",
+ srv->jid, arg ?: srv->muc);
+ }
+ else if (prefix(msg, "/join", &arg)) {
+ if (!arg) {
+ chat_notice(NULL, NULL, "usage: /join <channel>");
+ return;
+ }
+ net_print(&srv->net,
+ "<presence id='join' from='%s' to='%s@%s/%s'>"
+ "<x xmlns='http://jabber.org/protocol/muc'/>"
+ "</presence>",
+ srv->jid, arg, srv->muc, srv->nick);
+ }
+ else {
+ debug("unknown: [%s]", msg);
+ chat_notice(NULL, NULL,
+ "unknown command %s", msg);
+ }
+ } else {
+ debug("message: [%s]", msg);
+ net_print(&srv->net,
+ "<message to='%s'><body>%s</body></message>",
+ "andy@pileus.org", msg);
+ }
}
void xmpp_exit(void)