cb886b9c543b67dfd6566466d5658067a01be40c
[citadel.git] / webcit / who.c
1
2 #include "webcit.h"
3
4 CtxType CTX_WHO = CTX_NONE;
5
6 typedef struct UserStateStruct {
7         StrBuf *UserName;
8         StrBuf *Room;
9         StrBuf *Host;
10         StrBuf *UserAgent;
11         StrBuf *RealRoom;
12         StrBuf *RealHost;
13         long LastActive;
14         int Session;
15         int Idle;
16         int IdleSince;
17         int SessionCount;
18 } UserStateStruct;
19
20 void DestroyUserStruct(void *vUser)
21 {
22         UserStateStruct *User = (UserStateStruct*) vUser;
23         FreeStrBuf(&User->UserName);
24         FreeStrBuf(&User->Room);
25         FreeStrBuf(&User->Host);
26         FreeStrBuf(&User->RealRoom);
27         FreeStrBuf(&User->RealHost);
28         FreeStrBuf(&User->UserAgent);
29         free(User);
30 }
31
32 int CompareUserStruct(const void *VUser1, const void *VUser2)
33 {
34         const UserStateStruct *User1 = (UserStateStruct*) GetSearchPayload(VUser1);
35         const UserStateStruct *User2 = (UserStateStruct*) GetSearchPayload(VUser2);
36         
37         if (User1->Idle != User2->Idle)
38                 return User1->Idle > User2->Idle;
39         return strcasecmp(ChrPtr(User1->UserName), 
40                           ChrPtr(User2->UserName));
41 }
42
43
44 int GetWholistSection(HashList *List, time_t now, StrBuf *Buf, const char *FilterName, long FNLen)
45 {
46         wcsession *WCC = WC;
47         UserStateStruct *User, *OldUser;
48         void *VOldUser;
49         size_t BufLen;
50         const char *Pos;
51
52         serv_puts("RWHO");
53         StrBuf_ServGetln(Buf);
54         if (GetServerStatus(Buf, NULL) == 1) {
55                 while (BufLen = StrBuf_ServGetln(Buf), 
56                        ((BufLen >= 0) && 
57                         ((BufLen != 3) || strcmp(ChrPtr(Buf), "000"))))
58                 {
59                         if (BufLen <= 0)
60                             continue;
61                         Pos = NULL;
62                         User = (UserStateStruct*) malloc(sizeof(UserStateStruct));
63                         User->Session = StrBufExtractNext_int(Buf, &Pos, '|');
64
65                         User->UserName = NewStrBufPlain(NULL, BufLen);
66                         StrBufExtract_NextToken(User->UserName, Buf, &Pos, '|');
67                         
68                         User->Room = NewStrBufPlain(NULL, BufLen);
69                         StrBufExtract_NextToken(User->Room, Buf, &Pos, '|');
70
71                         User->Host = NewStrBufPlain(NULL, BufLen);
72                         StrBufExtract_NextToken(User->Host, Buf, &Pos, '|');
73
74                         User->UserAgent = NewStrBufPlain(NULL, BufLen);
75                         StrBufExtract_NextToken(User->UserAgent, Buf, &Pos, '|');
76
77                         User->LastActive = StrBufExtractNext_long(Buf, &Pos, '|');
78                         StrBufSkip_NTokenS(Buf, &Pos, '|', 3);
79
80                         User->RealRoom = NewStrBufPlain(NULL, BufLen);
81                         StrBufExtract_NextToken(User->RealRoom, Buf, &Pos, '|');
82
83                         User->RealHost = NewStrBufPlain(NULL, BufLen);
84                         StrBufExtract_NextToken(User->RealHost, Buf, &Pos, '|');
85                         
86                         User->Idle = (now - User->LastActive) > 900L;
87                         User->IdleSince = (now - User->LastActive) / 60;
88                         User->SessionCount = 1;
89
90                         if (FilterName == NULL) {
91                                 if (GetHash(List, 
92                                             SKEY(User->UserName), 
93                                             &VOldUser)) {
94                                         OldUser = VOldUser;
95                                         OldUser->SessionCount++;
96                                         if (!User->Idle) {
97                                                 if (User->Session == WCC->ctdl_pid) 
98                                                         OldUser->Session = User->Session;
99                                                 
100                                                 OldUser->Idle = User->Idle;
101                                                 OldUser->LastActive = User->LastActive;
102                                         }
103                                         DestroyUserStruct(User);
104                                 }
105                                 else
106                                         Put(List, 
107                                             SKEY(User->UserName), 
108                                             User, DestroyUserStruct);
109                         }
110                         else {
111                                 if (strcmp(FilterName, ChrPtr(User->UserName)) == 0)
112                                 {
113                                         Put(List, 
114                                             SKEY(User->UserName), 
115                                             User, DestroyUserStruct);
116                                 }
117                                 else 
118                                 {
119                                         DestroyUserStruct(User);
120                                 }
121                         }
122                 }
123                 if (FilterName == NULL)
124                         SortByPayload(List, CompareUserStruct);
125                 return 1;
126         }
127         else {
128                 return 0;
129         }
130 }
131
132 /*
133  * end session
134  */
135 void terminate_session(void)
136 {
137         char buf[SIZ];
138
139         serv_printf("TERM %s", bstr("which_session"));
140         serv_getln(buf, sizeof buf);
141         url_do_template();
142 }
143
144
145 /*
146  * Change your session info (fake roomname and hostname)
147  */
148 void edit_me(void)
149 {
150         char buf[SIZ];
151
152         output_headers(1, 0, 0, 0, 0, 0);
153         if (havebstr("change_room_name_button")) {
154                 serv_printf("RCHG %s", bstr("fake_roomname"));
155                 serv_getln(buf, sizeof buf);
156                 do_template("who");
157         } else if (havebstr("change_host_name_button")) {
158                 serv_printf("HCHG %s", bstr("fake_hostname"));
159                 serv_getln(buf, sizeof buf);
160                 do_template("who");
161         } else if (havebstr("change_user_name_button")) {
162                 serv_printf("UCHG %s", bstr("fake_username"));
163                 serv_getln(buf, sizeof buf);
164                 do_template("who");
165         } else if (havebstr("cancel_button")) {
166                 do_template("who");
167         } else {
168                 do_template("who_edit");
169         }
170         end_burst();
171 }
172
173 void _terminate_session(void) {
174         slrp_highest();
175         terminate_session();
176 }
177
178 HashList *GetWholistHash(StrBuf *Target, WCTemplputParams *TP)
179
180 {
181         const char *ch = NULL;
182         int HashUniq = 1;
183         long len;
184         StrBuf *FilterNameStr = NULL;
185         StrBuf *Buf;
186         HashList *List;
187         time_t now;
188
189         Buf = NewStrBuf();
190
191         serv_puts("TIME");
192         StrBuf_ServGetln(Buf);
193         if (GetServerStatus(Buf, NULL)  == 2) {
194                 const char *pos = ChrPtr(Buf) + 4;
195                 now = StrBufExtractNext_long(Buf, &pos, '|');
196         }
197         else {
198                 now = time(NULL);
199         }
200         if (HaveTemplateTokenString(NULL, TP, 2, &ch, &len))
201         {
202                 FilterNameStr = NewStrBuf();
203                 GetTemplateTokenString(FilterNameStr, TP, 2, &ch, &len);
204                 HashUniq = 0;
205         }
206
207         List = NewHash(HashUniq, NULL);
208         GetWholistSection(List, now, Buf, ch, len);
209         FreeStrBuf(&Buf);
210         FreeStrBuf(&FilterNameStr);
211         return List;
212 }
213
214
215 void DeleteWholistHash(HashList **KillMe)
216 {
217         DeleteHash(KillMe);
218 }
219
220 void tmplput_who_username(StrBuf *Target, WCTemplputParams *TP)
221 {
222         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
223         StrBufAppendTemplate(Target, TP, User->UserName, 0);
224 }
225
226 void tmplput_who_UserAgent(StrBuf *Target, WCTemplputParams *TP)
227 {
228         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
229         StrBufAppendTemplate(Target, TP, User->UserAgent, 0);
230 }
231
232 void tmplput_who_room(StrBuf *Target, WCTemplputParams *TP)
233 {
234         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
235         StrBufAppendTemplate(Target, TP, User->Room, 0);
236 }
237
238 void tmplput_who_host(StrBuf *Target, WCTemplputParams *TP)
239 {
240         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
241         StrBufAppendTemplate(Target, TP, User->Host, 0);
242 }
243
244 void tmplput_who_realroom(StrBuf *Target, WCTemplputParams *TP)
245 {
246         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
247         StrBufAppendTemplate(Target, TP, User->RealRoom, 0);
248 }
249 int conditional_who_realroom(StrBuf *Target, WCTemplputParams *TP)
250 {
251         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
252         return StrLength(User->RealRoom) > 0;
253 }
254
255 void tmplput_who_realhost(StrBuf *Target, WCTemplputParams *TP)
256 {
257         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
258         StrBufAppendTemplate(Target, TP, User->RealHost, 0);
259 }
260 int conditional_who_realhost(StrBuf *Target, WCTemplputParams *TP)
261 {
262         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
263         return StrLength(User->RealHost) > 0;
264 }
265
266 void tmplput_who_lastactive(StrBuf *Target, WCTemplputParams *TP)
267 {
268         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
269         StrBufAppendPrintf(Target, "%d", User->LastActive);
270 }
271
272 void tmplput_who_idlesince(StrBuf *Target, WCTemplputParams *TP)
273 {
274         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
275         StrBufAppendPrintf(Target, "%d", User->IdleSince);
276 }
277
278 void tmplput_who_session(StrBuf *Target, WCTemplputParams *TP)
279 {
280         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
281         StrBufAppendPrintf(Target, "%d", User->Session);
282 }
283
284 int conditional_who_idle(StrBuf *Target, WCTemplputParams *TP)
285 {
286         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
287         return User->Idle;
288 }
289
290 int conditional_who_nsessions(StrBuf *Target, WCTemplputParams *TP)
291 {
292         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
293         return User->SessionCount;
294 }
295
296 void tmplput_who_nsessions(StrBuf *Target, WCTemplputParams *TP)
297 {
298         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
299         StrBufAppendPrintf(Target, "%d", User->SessionCount);
300 }
301
302 int conditional_who_isme(StrBuf *Target, WCTemplputParams *TP)
303 {
304         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
305         return (User->Session == WC->ctdl_pid);
306 }
307
308 void 
309 InitModule_WHO
310 (void)
311 {
312         RegisterCTX(CTX_WHO);
313
314         WebcitAddUrlHandler(HKEY("terminate_session"), "", 0, _terminate_session, 0);
315         WebcitAddUrlHandler(HKEY("edit_me"), "", 0, edit_me, 0);
316
317         RegisterIterator("WHOLIST", 1, NULL, GetWholistHash, NULL, DeleteWholistHash, CTX_WHO, CTX_NONE, IT_NOFLAG);
318
319         RegisterNamespace("WHO:NAME",        0, 1, tmplput_who_username, NULL, CTX_WHO);
320         RegisterNamespace("WHO:USERAGENT",   0, 1, tmplput_who_UserAgent, NULL, CTX_WHO);
321         RegisterNamespace("WHO:ROOM",        0, 1, tmplput_who_room, NULL, CTX_WHO);
322         RegisterNamespace("WHO:HOST",        0, 1, tmplput_who_host, NULL, CTX_WHO);
323         RegisterNamespace("WHO:REALROOM",    0, 1, tmplput_who_realroom, NULL, CTX_WHO);
324         RegisterNamespace("WHO:REALHOST",    0, 1, tmplput_who_realhost, NULL, CTX_WHO);
325         RegisterNamespace("WHO:LASTACTIVE",  0, 1, tmplput_who_lastactive, NULL, CTX_WHO);
326         RegisterNamespace("WHO:IDLESINCE",   0, 1, tmplput_who_idlesince, NULL, CTX_WHO);
327         RegisterNamespace("WHO:SESSION",     0, 1, tmplput_who_session, NULL, CTX_WHO);
328         RegisterNamespace("WHO:NSESSIONS",   0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
329         RegisterNamespace("WHO:NSESSIONS",   0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
330
331         RegisterConditional("WHO:IDLE",      1, conditional_who_idle, CTX_WHO);
332         RegisterConditional("WHO:NSESSIONS", 1, conditional_who_nsessions, CTX_WHO);
333         RegisterConditional("WHO:ISME",      1, conditional_who_isme, CTX_WHO);
334         RegisterConditional("WHO:REALROOM",  1, conditional_who_realroom, CTX_WHO);
335         RegisterConditional("WHO:REALHOST",  1, conditional_who_realhost, CTX_WHO);
336 }