be0e4865a91c73560149ce58feb96d5d39e66179
[citadel.git] / citadel / modules / rwho / serv_rwho.c
1 /*
2  * $Id$
3  *
4  * This module implements server commands related to the display and
5  * manipulation of the "Who's online" list.
6  *
7  */
8
9 #include "sysdep.h"
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <errno.h>
17 #include <sys/types.h>
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #include <sys/wait.h>
31 #include <string.h>
32 #include <limits.h>
33 #include <libcitadel.h>
34 #include "citadel.h"
35 #include "server.h"
36 #include "citserver.h"
37 #include "support.h"
38 #include "config.h"
39 #include "control.h"
40 #include "room_ops.h"
41 #include "user_ops.h"
42 #include "policy.h"
43 #include "database.h"
44 #include "msgbase.h"
45
46
47 #include "ctdl_module.h"
48
49
50 /*
51  * display who's online
52  */
53 void cmd_rwho(char *argbuf) {
54         struct CitContext *nptr;
55         int nContexts, i;
56         int spoofed = 0;
57         int user_spoofed = 0;
58         int room_spoofed = 0;
59         int host_spoofed = 0;
60         int aide;
61         char un[40];
62         char real_room[ROOMNAMELEN], room[ROOMNAMELEN];
63         char host[64], flags[5];
64         
65         /* So that we don't keep the context list locked for a long time
66          * we create a copy of it first
67          */
68         
69
70         nptr = CtdlGetContextArray(&nContexts) ;
71         if (!nptr)
72         {
73                 /* Couldn't malloc so we have to bail but stick to the protocol */
74                 cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
75                 cprintf("000\n");
76                 return;
77         }
78         
79         aide = CC->user.axlevel >= 6;
80         cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
81         
82         for (i=0; i<nContexts; i++) 
83         {
84                 flags[0] = '\0';
85                 spoofed = 0;
86                 user_spoofed = 0;
87                 room_spoofed = 0;
88                 host_spoofed = 0;
89                 
90                 if (nptr[i].cs_flags & CS_POSTING)
91                    strcat(flags, "*");
92                 else
93                    strcat(flags, ".");
94                    
95                 if (nptr[i].fake_username[0])
96                 {
97                    strcpy(un, nptr[i].fake_username);
98                    spoofed = 1;
99                    user_spoofed = 1;
100                 }
101                 else
102                    strcpy(un, nptr[i].curr_user);
103                    
104                 if (nptr[i].fake_hostname[0])
105                 {
106                    strcpy(host, nptr[i].fake_hostname);
107                    spoofed = 1;
108                    host_spoofed = 1;
109                 }
110                 else
111                    strcpy(host, nptr[i].cs_host);
112
113                 GenerateRoomDisplay(real_room, &nptr[i], CC);
114
115                 if (nptr[i].fake_roomname[0]) {
116                         strcpy(room, nptr[i].fake_roomname);
117                         spoofed = 1;
118                         room_spoofed = 1;
119                 }
120                 else {
121                         strcpy(room, real_room);
122                 }
123                 
124                 if ((aide) && (spoofed)) {
125                         strcat(flags, "+");
126                 }
127                 
128                 if ((nptr[i].cs_flags & CS_STEALTH) && (aide)) {
129                         strcat(flags, "-");
130                 }
131                 
132                 if (((nptr[i].cs_flags&CS_STEALTH)==0) || (aide))
133                 {
134                         cprintf("%d|%s|%s|%s|%s|%ld|%s|%s|",
135                                 nptr[i].cs_pid, un, room,
136                                 host, nptr[i].cs_clientname,
137                                 (long)(nptr[i].lastidle),
138                                 nptr[i].lastcmdname, flags
139                         );
140
141                         if ((user_spoofed) && (aide)) {
142                                 cprintf("%s|", nptr[i].curr_user);
143                         }
144                         else {
145                                 cprintf("|");
146                         }
147         
148                         if ((room_spoofed) && (aide)) {
149                                 cprintf("%s|", real_room);
150                         }
151                         else {
152                                 cprintf("|");
153                         }
154         
155                         if ((host_spoofed) && (aide)) {
156                                 cprintf("%s|", nptr[i].cs_host);
157                         }
158                         else {
159                                 cprintf("|");
160                         }
161         
162                         cprintf("%d\n", nptr[i].logged_in);
163                 }
164         }
165         
166         /* release out copy of the context list */
167         free(nptr);
168
169         /* Now it's magic time.  Before we finish, call any EVT_RWHO hooks
170          * so that external paging modules such as serv_icq can add more
171          * content to the Wholist.
172          */
173         PerformSessionHooks(EVT_RWHO);
174         cprintf("000\n");
175 }
176
177
178 /*
179  * Masquerade roomname
180  */
181 void cmd_rchg(char *argbuf)
182 {
183         char newroomname[ROOMNAMELEN];
184
185         extract_token(newroomname, argbuf, 0, '|', sizeof newroomname);
186         newroomname[ROOMNAMELEN-1] = 0;
187         if (!IsEmptyStr(newroomname)) {
188                 safestrncpy(CC->fake_roomname, newroomname,
189                         sizeof(CC->fake_roomname) );
190         }
191         else {
192                 safestrncpy(CC->fake_roomname, "", sizeof CC->fake_roomname);
193         }
194         cprintf("%d OK\n", CIT_OK);
195 }
196
197 /*
198  * Masquerade hostname 
199  */
200 void cmd_hchg(char *argbuf)
201 {
202         char newhostname[64];
203
204         extract_token(newhostname, argbuf, 0, '|', sizeof newhostname);
205         if (!IsEmptyStr(newhostname)) {
206                 safestrncpy(CC->fake_hostname, newhostname,
207                         sizeof(CC->fake_hostname) );
208         }
209         else {
210                 safestrncpy(CC->fake_hostname, "", sizeof CC->fake_hostname);
211         }
212         cprintf("%d OK\n", CIT_OK);
213 }
214
215
216 /*
217  * Masquerade username (aides only)
218  */
219 void cmd_uchg(char *argbuf)
220 {
221
222         char newusername[USERNAME_SIZE];
223
224         extract_token(newusername, argbuf, 0, '|', sizeof newusername);
225
226         if (CtdlAccessCheck(ac_aide)) return;
227
228         if (!IsEmptyStr(newusername)) {
229                 CC->cs_flags &= ~CS_STEALTH;
230                 memset(CC->fake_username, 0, 32);
231                 if (strncasecmp(newusername, CC->curr_user,
232                                 strlen(CC->curr_user)))
233                         safestrncpy(CC->fake_username, newusername,
234                                 sizeof(CC->fake_username));
235         }
236         else {
237                 CC->fake_username[0] = '\0';
238                 CC->cs_flags |= CS_STEALTH;
239         }
240         cprintf("%d\n",CIT_OK);
241 }
242
243
244
245
246 /*
247  * enter or exit "stealth mode"
248  */
249 void cmd_stel(char *cmdbuf)
250 {
251         int requested_mode;
252
253         requested_mode = extract_int(cmdbuf,0);
254
255         if (CtdlAccessCheck(ac_logged_in)) return;
256
257         if (requested_mode == 1) {
258                 CC->cs_flags = CC->cs_flags | CS_STEALTH;
259                 PerformSessionHooks(EVT_STEALTH);
260         }
261         if (requested_mode == 0) {
262                 CC->cs_flags = CC->cs_flags & ~CS_STEALTH;
263                 PerformSessionHooks(EVT_UNSTEALTH);
264         }
265
266         cprintf("%d %d\n", CIT_OK,
267                 ((CC->cs_flags & CS_STEALTH) ? 1 : 0) );
268 }
269
270
271 CTDL_MODULE_INIT(rwho)
272 {
273         if(!threading)
274         {
275                 CtdlRegisterProtoHook(cmd_rwho, "RWHO", "Display who is online");
276                 CtdlRegisterProtoHook(cmd_hchg, "HCHG", "Masquerade hostname");
277                 CtdlRegisterProtoHook(cmd_rchg, "RCHG", "Masquerade roomname");
278                 CtdlRegisterProtoHook(cmd_uchg, "UCHG", "Masquerade username");
279                 CtdlRegisterProtoHook(cmd_stel, "STEL", "Enter/exit stealth mode");
280         }
281         
282         /* return our Subversion id for the Log */
283         return "$Id$";
284 }