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