Mailing list header changes (fuck you Google)
[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 void _terminate_session(void) {
146         slrp_highest();
147         terminate_session();
148 }
149
150 HashList *GetWholistHash(StrBuf *Target, WCTemplputParams *TP)
151
152 {
153         const char *ch = NULL;
154         int HashUniq = 1;
155         long len;
156         StrBuf *FilterNameStr = NULL;
157         StrBuf *Buf;
158         HashList *List;
159         time_t now;
160
161         Buf = NewStrBuf();
162
163         serv_puts("TIME");
164         StrBuf_ServGetln(Buf);
165         if (GetServerStatus(Buf, NULL)  == 2) {
166                 const char *pos = ChrPtr(Buf) + 4;
167                 now = StrBufExtractNext_long(Buf, &pos, '|');
168         }
169         else {
170                 now = time(NULL);
171         }
172         if (HaveTemplateTokenString(NULL, TP, 2, &ch, &len))
173         {
174                 FilterNameStr = NewStrBuf();
175                 GetTemplateTokenString(FilterNameStr, TP, 2, &ch, &len);
176                 HashUniq = 0;
177         }
178
179         List = NewHash(HashUniq, NULL);
180         GetWholistSection(List, now, Buf, ch, len);
181         FreeStrBuf(&Buf);
182         FreeStrBuf(&FilterNameStr);
183         return List;
184 }
185
186
187 void DeleteWholistHash(HashList **KillMe)
188 {
189         DeleteHash(KillMe);
190 }
191
192 void tmplput_who_username(StrBuf *Target, WCTemplputParams *TP)
193 {
194         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
195         StrBufAppendTemplate(Target, TP, User->UserName, 0);
196 }
197
198 void tmplput_who_UserAgent(StrBuf *Target, WCTemplputParams *TP)
199 {
200         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
201         StrBufAppendTemplate(Target, TP, User->UserAgent, 0);
202 }
203
204 void tmplput_who_room(StrBuf *Target, WCTemplputParams *TP)
205 {
206         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
207         StrBufAppendTemplate(Target, TP, User->Room, 0);
208 }
209
210 void tmplput_who_host(StrBuf *Target, WCTemplputParams *TP)
211 {
212         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
213         StrBufAppendTemplate(Target, TP, User->Host, 0);
214 }
215
216 void tmplput_who_realroom(StrBuf *Target, WCTemplputParams *TP)
217 {
218         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
219         StrBufAppendTemplate(Target, TP, User->RealRoom, 0);
220 }
221 int conditional_who_realroom(StrBuf *Target, WCTemplputParams *TP)
222 {
223         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
224         return StrLength(User->RealRoom) > 0;
225 }
226
227 void tmplput_who_realhost(StrBuf *Target, WCTemplputParams *TP)
228 {
229         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
230         StrBufAppendTemplate(Target, TP, User->RealHost, 0);
231 }
232 int conditional_who_realhost(StrBuf *Target, WCTemplputParams *TP)
233 {
234         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
235         return StrLength(User->RealHost) > 0;
236 }
237
238 void tmplput_who_lastactive(StrBuf *Target, WCTemplputParams *TP)
239 {
240         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
241         StrBufAppendPrintf(Target, "%d", User->LastActive);
242 }
243
244 void tmplput_who_idlesince(StrBuf *Target, WCTemplputParams *TP)
245 {
246         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
247         StrBufAppendPrintf(Target, "%d", User->IdleSince);
248 }
249
250 void tmplput_who_session(StrBuf *Target, WCTemplputParams *TP)
251 {
252         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
253         StrBufAppendPrintf(Target, "%d", User->Session);
254 }
255
256 int conditional_who_idle(StrBuf *Target, WCTemplputParams *TP)
257 {
258         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
259         return User->Idle;
260 }
261
262 int conditional_who_nsessions(StrBuf *Target, WCTemplputParams *TP)
263 {
264         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
265         return User->SessionCount;
266 }
267
268 void tmplput_who_nsessions(StrBuf *Target, WCTemplputParams *TP)
269 {
270         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
271         StrBufAppendPrintf(Target, "%d", User->SessionCount);
272 }
273
274 int conditional_who_isme(StrBuf *Target, WCTemplputParams *TP)
275 {
276         UserStateStruct *User = (UserStateStruct*) CTX(CTX_WHO);
277         return (User->Session == WC->ctdl_pid);
278 }
279
280 void 
281 InitModule_WHO
282 (void)
283 {
284         RegisterCTX(CTX_WHO);
285
286         WebcitAddUrlHandler(HKEY("terminate_session"), "", 0, _terminate_session, 0);
287
288         RegisterIterator("WHOLIST", 1, NULL, GetWholistHash, NULL, DeleteWholistHash, CTX_WHO, CTX_NONE, IT_NOFLAG);
289
290         RegisterNamespace("WHO:NAME",        0, 1, tmplput_who_username, NULL, CTX_WHO);
291         RegisterNamespace("WHO:USERAGENT",   0, 1, tmplput_who_UserAgent, NULL, CTX_WHO);
292         RegisterNamespace("WHO:ROOM",        0, 1, tmplput_who_room, NULL, CTX_WHO);
293         RegisterNamespace("WHO:HOST",        0, 1, tmplput_who_host, NULL, CTX_WHO);
294         RegisterNamespace("WHO:REALROOM",    0, 1, tmplput_who_realroom, NULL, CTX_WHO);
295         RegisterNamespace("WHO:REALHOST",    0, 1, tmplput_who_realhost, NULL, CTX_WHO);
296         RegisterNamespace("WHO:LASTACTIVE",  0, 1, tmplput_who_lastactive, NULL, CTX_WHO);
297         RegisterNamespace("WHO:IDLESINCE",   0, 1, tmplput_who_idlesince, NULL, CTX_WHO);
298         RegisterNamespace("WHO:SESSION",     0, 1, tmplput_who_session, NULL, CTX_WHO);
299         RegisterNamespace("WHO:NSESSIONS",   0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
300         RegisterNamespace("WHO:NSESSIONS",   0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
301
302         RegisterConditional("WHO:IDLE",      1, conditional_who_idle, CTX_WHO);
303         RegisterConditional("WHO:NSESSIONS", 1, conditional_who_nsessions, CTX_WHO);
304         RegisterConditional("WHO:ISME",      1, conditional_who_isme, CTX_WHO);
305         RegisterConditional("WHO:REALROOM",  1, conditional_who_realroom, CTX_WHO);
306         RegisterConditional("WHO:REALHOST",  1, conditional_who_realhost, CTX_WHO);
307 }