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