indent -kr -i8 -brf -bbb -fnc -l132 -nce on all of webcit-classic
[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         UserStateStruct *User = (UserStateStruct *) vUser;
22         FreeStrBuf(&User->UserName);
23         FreeStrBuf(&User->Room);
24         FreeStrBuf(&User->Host);
25         FreeStrBuf(&User->RealRoom);
26         FreeStrBuf(&User->RealHost);
27         FreeStrBuf(&User->UserAgent);
28         free(User);
29 }
30
31 int CompareUserStruct(const void *VUser1, const void *VUser2) {
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), ChrPtr(User2->UserName));
38 }
39
40
41 int GetWholistSection(HashList * List, time_t now, StrBuf * Buf, const char *FilterName, long FNLen) {
42         UserStateStruct *User, *OldUser;
43         void *VOldUser;
44         size_t BufLen;
45         const char *Pos;
46
47         serv_puts("RWHO");
48         StrBuf_ServGetln(Buf);
49         if (GetServerStatus(Buf, NULL) == 1) {
50                 while (BufLen = StrBuf_ServGetln(Buf), ((BufLen >= 0) && ((BufLen != 3) || strcmp(ChrPtr(Buf), "000")))) {
51                         if (BufLen <= 0)
52                                 continue;
53                         Pos = NULL;
54                         User = (UserStateStruct *) malloc(sizeof(UserStateStruct));
55                         User->Session = StrBufExtractNext_int(Buf, &Pos, '|');
56
57                         User->UserName = NewStrBufPlain(NULL, BufLen);
58                         StrBufExtract_NextToken(User->UserName, Buf, &Pos, '|');
59
60                         User->Room = NewStrBufPlain(NULL, BufLen);
61                         StrBufExtract_NextToken(User->Room, Buf, &Pos, '|');
62
63                         User->Host = NewStrBufPlain(NULL, BufLen);
64                         StrBufExtract_NextToken(User->Host, Buf, &Pos, '|');
65
66                         User->UserAgent = NewStrBufPlain(NULL, BufLen);
67                         StrBufExtract_NextToken(User->UserAgent, Buf, &Pos, '|');
68
69                         User->LastActive = StrBufExtractNext_long(Buf, &Pos, '|');
70                         StrBufSkip_NTokenS(Buf, &Pos, '|', 3);
71
72                         User->RealRoom = NewStrBufPlain(NULL, BufLen);
73                         StrBufExtract_NextToken(User->RealRoom, Buf, &Pos, '|');
74
75                         User->RealHost = NewStrBufPlain(NULL, BufLen);
76                         StrBufExtract_NextToken(User->RealHost, Buf, &Pos, '|');
77
78                         User->Idle = (now - User->LastActive) > 900L;
79                         User->IdleSince = (now - User->LastActive) / 60;
80                         User->SessionCount = 1;
81
82                         if (FilterName == NULL) {
83                                 if (GetHash(List, SKEY(User->UserName), &VOldUser)) {
84                                         OldUser = VOldUser;
85                                         OldUser->SessionCount++;
86                                         if (!User->Idle) {
87                                                 if (User->Session == WC->ctdl_pid)
88                                                         OldUser->Session = User->Session;
89
90                                                 OldUser->Idle = User->Idle;
91                                                 OldUser->LastActive = User->LastActive;
92                                         }
93                                         DestroyUserStruct(User);
94                                 }
95                                 else
96                                         Put(List, SKEY(User->UserName), User, DestroyUserStruct);
97                         }
98                         else {
99                                 if (strcmp(FilterName, ChrPtr(User->UserName)) == 0) {
100                                         Put(List, SKEY(User->UserName), User, DestroyUserStruct);
101                                 }
102                                 else {
103                                         DestroyUserStruct(User);
104                                 }
105                         }
106                 }
107                 if (FilterName == NULL)
108                         SortByPayload(List, CompareUserStruct);
109                 return 1;
110         }
111         else {
112                 return 0;
113         }
114 }
115
116 /*
117  * end session
118  */
119 void terminate_session(void) {
120         char buf[SIZ];
121
122         serv_printf("TERM %s", bstr("which_session"));
123         serv_getln(buf, sizeof buf);
124         url_do_template();
125 }
126
127
128 void _terminate_session(void) {
129         slrp_highest();
130         terminate_session();
131 }
132
133 HashList *GetWholistHash(StrBuf * Target, WCTemplputParams * TP) {
134         const char *ch = NULL;
135         int HashUniq = 1;
136         long len;
137         StrBuf *FilterNameStr = NULL;
138         StrBuf *Buf;
139         HashList *List;
140         time_t now;
141
142         Buf = NewStrBuf();
143
144         serv_puts("TIME");
145         StrBuf_ServGetln(Buf);
146         if (GetServerStatus(Buf, NULL) == 2) {
147                 const char *pos = ChrPtr(Buf) + 4;
148                 now = StrBufExtractNext_long(Buf, &pos, '|');
149         }
150         else {
151                 now = time(NULL);
152         }
153         if (HaveTemplateTokenString(NULL, TP, 2, &ch, &len)) {
154                 FilterNameStr = NewStrBuf();
155                 GetTemplateTokenString(FilterNameStr, TP, 2, &ch, &len);
156                 HashUniq = 0;
157         }
158
159         List = NewHash(HashUniq, NULL);
160         GetWholistSection(List, now, Buf, ch, len);
161         FreeStrBuf(&Buf);
162         FreeStrBuf(&FilterNameStr);
163         return List;
164 }
165
166
167 void DeleteWholistHash(HashList ** KillMe) {
168         DeleteHash(KillMe);
169 }
170
171 void tmplput_who_username(StrBuf * Target, WCTemplputParams * TP) {
172         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
173         StrBufAppendTemplate(Target, TP, User->UserName, 0);
174 }
175
176 void tmplput_who_UserAgent(StrBuf * Target, WCTemplputParams * TP) {
177         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
178         StrBufAppendTemplate(Target, TP, User->UserAgent, 0);
179 }
180
181 void tmplput_who_room(StrBuf * Target, WCTemplputParams * TP) {
182         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
183         StrBufAppendTemplate(Target, TP, User->Room, 0);
184 }
185
186 void tmplput_who_host(StrBuf * Target, WCTemplputParams * TP) {
187         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
188         StrBufAppendTemplate(Target, TP, User->Host, 0);
189 }
190
191 void tmplput_who_realroom(StrBuf * Target, WCTemplputParams * TP) {
192         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
193         StrBufAppendTemplate(Target, TP, User->RealRoom, 0);
194 }
195 int conditional_who_realroom(StrBuf * Target, WCTemplputParams * TP) {
196         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
197         return StrLength(User->RealRoom) > 0;
198 }
199
200 void tmplput_who_realhost(StrBuf * Target, WCTemplputParams * TP) {
201         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
202         StrBufAppendTemplate(Target, TP, User->RealHost, 0);
203 }
204 int conditional_who_realhost(StrBuf * Target, WCTemplputParams * TP) {
205         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
206         return StrLength(User->RealHost) > 0;
207 }
208
209 void tmplput_who_lastactive(StrBuf * Target, WCTemplputParams * TP) {
210         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
211         StrBufAppendPrintf(Target, "%d", User->LastActive);
212 }
213
214 void tmplput_who_idlesince(StrBuf * Target, WCTemplputParams * TP) {
215         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
216         StrBufAppendPrintf(Target, "%d", User->IdleSince);
217 }
218
219 void tmplput_who_session(StrBuf * Target, WCTemplputParams * TP) {
220         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
221         StrBufAppendPrintf(Target, "%d", User->Session);
222 }
223
224 int conditional_who_idle(StrBuf * Target, WCTemplputParams * TP) {
225         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
226         return User->Idle;
227 }
228
229 int conditional_who_nsessions(StrBuf * Target, WCTemplputParams * TP) {
230         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
231         return User->SessionCount;
232 }
233
234 void tmplput_who_nsessions(StrBuf * Target, WCTemplputParams * TP) {
235         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
236         StrBufAppendPrintf(Target, "%d", User->SessionCount);
237 }
238
239 int conditional_who_isme(StrBuf * Target, WCTemplputParams * TP) {
240         UserStateStruct *User = (UserStateStruct *) CTX(CTX_WHO);
241         return (User->Session == WC->ctdl_pid);
242 }
243
244 void InitModule_WHO(void) {
245         RegisterCTX(CTX_WHO);
246
247         WebcitAddUrlHandler(HKEY("terminate_session"), "", 0, _terminate_session, 0);
248
249         RegisterIterator("WHOLIST", 1, NULL, GetWholistHash, NULL, DeleteWholistHash, CTX_WHO, CTX_NONE, IT_NOFLAG);
250
251         RegisterNamespace("WHO:NAME", 0, 1, tmplput_who_username, NULL, CTX_WHO);
252         RegisterNamespace("WHO:USERAGENT", 0, 1, tmplput_who_UserAgent, NULL, CTX_WHO);
253         RegisterNamespace("WHO:ROOM", 0, 1, tmplput_who_room, NULL, CTX_WHO);
254         RegisterNamespace("WHO:HOST", 0, 1, tmplput_who_host, NULL, CTX_WHO);
255         RegisterNamespace("WHO:REALROOM", 0, 1, tmplput_who_realroom, NULL, CTX_WHO);
256         RegisterNamespace("WHO:REALHOST", 0, 1, tmplput_who_realhost, NULL, CTX_WHO);
257         RegisterNamespace("WHO:LASTACTIVE", 0, 1, tmplput_who_lastactive, NULL, CTX_WHO);
258         RegisterNamespace("WHO:IDLESINCE", 0, 1, tmplput_who_idlesince, NULL, CTX_WHO);
259         RegisterNamespace("WHO:SESSION", 0, 1, tmplput_who_session, NULL, CTX_WHO);
260         RegisterNamespace("WHO:NSESSIONS", 0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
261         RegisterNamespace("WHO:NSESSIONS", 0, 1, tmplput_who_nsessions, NULL, CTX_WHO);
262
263         RegisterConditional("WHO:IDLE", 1, conditional_who_idle, CTX_WHO);
264         RegisterConditional("WHO:NSESSIONS", 1, conditional_who_nsessions, CTX_WHO);
265         RegisterConditional("WHO:ISME", 1, conditional_who_isme, CTX_WHO);
266         RegisterConditional("WHO:REALROOM", 1, conditional_who_realroom, CTX_WHO);
267         RegisterConditional("WHO:REALHOST", 1, conditional_who_realhost, CTX_WHO);
268 }