4 * Handle XMPP presence exchanges
6 * Copyright (c) 2007 by Art Cancro
7 * This code is released under the terms of the GNU General Public License.
19 #include <sys/types.h>
21 #if TIME_WITH_SYS_TIME
22 # include <sys/time.h>
26 # include <sys/time.h>
37 #include <libcitadel.h>
40 #include "citserver.h"
43 #include "internet_addressing.h"
45 #include "ctdl_module.h"
46 #include "serv_xmpp.h"
50 * Initial dump of the entire wholist
52 void jabber_wholist_presence_dump(void)
54 struct CitContext
*cptr
= NULL
;
57 int aide
= (CC
->user
.axlevel
>= 6);
59 cptr
= CtdlGetContextArray(&nContexts
);
61 return ; /** FIXME: Does jabber need to send something to maintain the protocol? */
63 for (i
=0; i
<nContexts
; i
++) {
64 if (cptr
[i
].logged_in
) {
66 (((cptr
[i
].cs_flags
&CS_STEALTH
)==0) || (aide
)) /* aides see everyone */
67 && (cptr
[i
].user
.usernum
!= CC
->user
.usernum
) /* don't show myself */
69 cprintf("<presence type=\"available\" from=\"%s\"></presence>",
70 cptr
[i
].cs_inet_email
);
80 * When a user logs in or out of the local Citadel system, notify all Jabber sessions
83 void xmpp_presence_notify(char *presence_jid
, int event_type
) {
84 struct CitContext
*cptr
;
85 static int unsolicited_id
;
86 int visible_sessions
= 0;
88 int aide
= (CC
->user
.axlevel
>= 6);
90 if (IsEmptyStr(presence_jid
)) return;
92 cptr
= CtdlGetContextArray(&nContexts
);
94 return ; /** FIXME: Does jabber need to send something to maintain the protocol? */
96 /* Count the visible sessions for this user */
97 for (i
=0; i
<nContexts
; i
++) {
98 if (cptr
[i
].logged_in
) {
99 if ( (!strcasecmp(cptr
[i
].cs_inet_email
, presence_jid
))
100 && (((cptr
[i
].cs_flags
&CS_STEALTH
)==0) || (aide
))
107 CtdlLogPrintf(CTDL_DEBUG
, "%d sessions for <%s> are now visible to session %d\n",
108 visible_sessions
, presence_jid
, CC
->cs_pid
);
110 if ( (event_type
== XMPP_EVT_LOGIN
) && (visible_sessions
== 1) ) {
112 CtdlLogPrintf(CTDL_DEBUG
, "Telling session %d that <%s> logged in\n", CC
->cs_pid
, presence_jid
);
114 /* Do an unsolicited roster update that adds a new contact. */
115 for (i
=0; i
<nContexts
; i
++) {
116 if (cptr
[i
].logged_in
) {
117 if (!strcasecmp(cptr
[i
].cs_inet_email
, presence_jid
)) {
118 cprintf("<iq id=\"unsolicited_%x\" type=\"result\">",
120 cprintf("<query xmlns=\"jabber:iq:roster\">");
121 jabber_roster_item(&cptr
[i
]);
128 /* Transmit presence information */
129 cprintf("<presence type=\"available\" from=\"%s\"></presence>", presence_jid
);
132 if (visible_sessions
== 0) {
133 CtdlLogPrintf(CTDL_DEBUG
, "Telling session %d that <%s> logged out\n", CC
->cs_pid
, presence_jid
);
135 /* Transmit non-presence information */
136 cprintf("<presence type=\"unavailable\" from=\"%s\"></presence>", presence_jid
);
137 cprintf("<presence type=\"unsubscribed\" from=\"%s\"></presence>", presence_jid
);
139 /* Do an unsolicited roster update that deletes the contact. */
140 cprintf("<iq id=\"unsolicited_%x\" type=\"result\">", ++unsolicited_id
);
141 cprintf("<query xmlns=\"jabber:iq:roster\">");
142 cprintf("<item jid=\"%s\" subscription=\"remove\">", presence_jid
);
143 cprintf("<group>%s</group>", config
.c_humannode
);