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