CtdlCheckExpress() now accepts a session context.
[citadel.git] / citadel / server / modules / rwho / serv_rwho.c
1 // This module implements server commands related to the display and
2 // manipulation of the "Who's online" list.
3 //
4 // Copyright (c) 1987-2024 by the citadel.org team
5 //
6 // This program is open source software.  Use, duplication, or disclosure
7 // is subject to the terms of the GNU General Public License, version 3.
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 #include <time.h>
19 #include <sys/wait.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <libcitadel.h>
23 #include "../../citadel_defs.h"
24 #include "../../server.h"
25 #include "../../citserver.h"
26 #include "../../support.h"
27 #include "../../config.h"
28 #include "../../control.h"
29 #include "../../user_ops.h"
30 #include "../../database.h"
31 #include "../../msgbase.h"
32 #include "../../ctdl_module.h"
33
34 // Don't show the names of private rooms unless the viewing
35 // user also knows the rooms.
36 void GenerateRoomDisplay(char *real_room, CitContext *viewed, CitContext *viewer) {
37         int ra;
38
39         strcpy(real_room, viewed->room.QRname);
40
41         if (viewed->room.QRflags & QR_MAILBOX) {
42                 strcpy(real_room, &real_room[11]);
43         }
44
45         if (viewed->room.QRflags & QR_PRIVATE) {
46                 CtdlRoomAccess(&viewed->room, &viewer->user, &ra, NULL);
47                 if ( (ra & UA_KNOWN) == 0) {
48                         strcpy(real_room, " ");
49                 }
50         }
51
52         if (viewed->cs_flags & CS_CHAT) {
53                 while (strlen(real_room) < 14) {
54                         strcat(real_room, " ");
55                 }
56                 strcpy(&real_room[14], "<chat>");
57         }
58
59 }
60
61
62 // display who's online
63 void cmd_rwho(char *argbuf) {
64         struct CitContext *nptr;
65         int nContexts, i;
66         int spoofed = 0;
67         int aide;
68         char room[ROOMNAMELEN];
69         char flags[5];
70         
71         // So that we don't keep the context list locked for a long time
72         // we create a copy of it first
73         nptr = CtdlGetContextArray(&nContexts) ;
74         if (!nptr) {
75                 // Couldn't malloc so we have to bail but stick to the protocol
76                 cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress(CC) );
77                 cprintf("000\n");
78                 return;
79         }
80         
81         aide = ( (CC->user.axlevel >= AxAideU) || (CC->internal_pgm) ) ;
82         cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress(CC) );
83         
84         for (i=0; i<nContexts; i++)  {
85                 flags[0] = '\0';
86                 spoofed = 0;
87                 
88                 if (!aide && nptr[i].state == CON_SYS)
89                         continue;
90
91                 if (!aide && nptr[i].kill_me != 0)
92                         continue;
93
94                 if (nptr[i].cs_flags & CS_POSTING) {
95                         strcat(flags, "*");
96                 }
97                 else {
98                         strcat(flags, ".");
99                 }
100                    
101                 GenerateRoomDisplay(room, &nptr[i], CC);
102
103                 if ((aide) && (spoofed)) {
104                         strcat(flags, "+");
105                 }
106                 
107                 if ((nptr[i].cs_flags & CS_STEALTH) && (aide)) {
108                         strcat(flags, "-");
109                 }
110                 
111                 if (((nptr[i].cs_flags&CS_STEALTH)==0) || (aide)) {
112
113                         cprintf("%d|%s|%s|%s|%s|%ld|%s|%s|",
114                                 nptr[i].cs_pid,
115                                 (nptr[i].logged_in ? nptr[i].curr_user : NLI),
116                                 room,
117                                 nptr[i].cs_host,
118                                 nptr[i].cs_clientname,
119                                 (long)(nptr[i].lastidle),
120                                 nptr[i].lastcmdname,
121                                 flags
122                         );
123
124                         cprintf("|");   // no spoofed user names anymore
125                         cprintf("|");   // no spoofed room names anymore
126                         cprintf("|");   // no spoofed host names anymore
127         
128                         cprintf("%d\n", nptr[i].logged_in);
129                 }
130         }
131         
132         // release our copy of the context list
133         free(nptr);
134
135         // Now it's magic time.  Before we finish, call any EVT_RWHO hooks
136         // so that external paging modules such as serv_icq can add more
137         // content to the Wholist.
138         PerformSessionHooks(EVT_RWHO);
139         cprintf("000\n");
140 }
141
142
143 // enter or exit "stealth mode"
144 void cmd_stel(char *cmdbuf) {
145         int requested_mode;
146
147         requested_mode = extract_int(cmdbuf,0);
148
149         if (CtdlAccessCheck(ac_logged_in)) return;
150
151         if (requested_mode == 1) {
152                 CC->cs_flags = CC->cs_flags | CS_STEALTH;
153                 PerformSessionHooks(EVT_STEALTH);
154         }
155         if (requested_mode == 0) {
156                 CC->cs_flags = CC->cs_flags & ~CS_STEALTH;
157                 PerformSessionHooks(EVT_UNSTEALTH);
158         }
159
160         cprintf("%d %d\n", CIT_OK,
161                 ((CC->cs_flags & CS_STEALTH) ? 1 : 0) );
162 }
163
164
165 // Initialization function, called from modules_init.c
166 char *ctdl_module_init_rwho(void) {
167         if (!threading) {
168                 CtdlRegisterProtoHook(cmd_rwho, "RWHO", "Display who is online");
169                 CtdlRegisterProtoHook(cmd_stel, "STEL", "Enter/exit stealth mode");
170
171         }
172         
173         // return our module name for the log
174         return "rwho";
175 }