* fix another off by one while retrieving the iterator counter params
[citadel.git] / webcit / useredit.c
blob17bd25a74ff4c2aed4864027c8ee1333a93c36bc
1 /*
2 * $Id$
3 */
5 #include "webcit.h"
6 #include "webserver.h"
9 /**
10 * show a list of available users to edit them
11 * message the header message???
12 * preselect which user should be selected in the browser
14 void select_user_to_edit(char *message, char *preselect)
16 output_headers(1, 0, 0, 0, 1, 0);
17 do_template("edituser_select", NULL);
18 end_burst();
22 typedef struct _UserListEntry {
23 int UID;
24 int AccessLevel;
25 int nLogons;
26 int nPosts;
28 StrBuf *UserName;
29 StrBuf *Passvoid;
30 time_t LastLogonT;
31 /* Just available for Single users to view: */
32 unsigned int Flags;
33 int DaysTillPurge;
34 } UserListEntry;
37 UserListEntry* NewUserListOneEntry(StrBuf *SerializedUser)
39 UserListEntry *ul;
41 if (StrLength(SerializedUser) < 8)
42 return NULL;
44 ul = (UserListEntry*) malloc(sizeof(UserListEntry));
45 ul->UserName = NewStrBuf();
46 ul->Passvoid = NewStrBuf();
48 StrBufExtract_token(ul->UserName, SerializedUser, 0, '|');
49 StrBufExtract_token(ul->Passvoid, SerializedUser, 1, '|');
50 ul->Flags = (unsigned int)StrBufExtract_long(SerializedUser, 2, '|');
51 ul->nLogons = StrBufExtract_int(SerializedUser, 3, '|');
52 ul->nPosts = StrBufExtract_int(SerializedUser, 4, '|');
53 ul->AccessLevel = StrBufExtract_int(SerializedUser, 5, '|');
54 ul->UID = StrBufExtract_int(SerializedUser, 6, '|');
55 ul->LastLogonT = StrBufExtract_long(SerializedUser, 7, '|');
56 ul->DaysTillPurge = StrBufExtract_int(SerializedUser, 8, '|');
57 return ul;
60 void DeleteUserListEntry(void *vUserList)
62 UserListEntry *ul = (UserListEntry*) vUserList;
63 FreeStrBuf(&ul->UserName);
64 FreeStrBuf(&ul->Passvoid);
65 free(ul);
68 UserListEntry* NewUserListEntry(StrBuf *SerializedUserList)
70 UserListEntry *ul;
72 if (StrLength(SerializedUserList) < 8)
73 return NULL;
75 ul = (UserListEntry*) malloc(sizeof(UserListEntry));
76 ul->UserName = NewStrBuf();
77 ul->Passvoid = NewStrBuf();
79 StrBufExtract_token(ul->UserName, SerializedUserList, 0, '|');
80 ul->AccessLevel = StrBufExtract_int(SerializedUserList, 1, '|');
81 ul->UID = StrBufExtract_int(SerializedUserList, 2, '|');
82 ul->LastLogonT = StrBufExtract_long(SerializedUserList, 3, '|');
83 ul->nLogons = StrBufExtract_int(SerializedUserList, 4, '|');
84 ul->nPosts = StrBufExtract_int(SerializedUserList, 5, '|');
85 StrBufExtract_token(ul->Passvoid, SerializedUserList, 6, '|');
86 ul->Flags = 0;
87 ul->DaysTillPurge = -1;
88 return ul;
92 * Sort by Username
94 int CompareUserListName(const void *vUser1, const void *vUser2)
96 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
97 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
99 return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName));
101 int CompareUserListNameRev(const void *vUser1, const void *vUser2)
103 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
104 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
105 return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
107 int GroupchangeUserListName(const void *vUser1, const void *vUser2)
109 UserListEntry *u1 = (UserListEntry*) vUser1;
110 UserListEntry *u2 = (UserListEntry*) vUser2;
111 return ChrPtr(u2->UserName)[0] != ChrPtr(u1->UserName)[0];
115 * Sort by AccessLevel
117 int CompareAccessLevel(const void *vUser1, const void *vUser2)
119 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
120 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
122 return (u1->AccessLevel > u2->AccessLevel);
124 int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
126 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
127 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
129 return (u2->AccessLevel > u1->AccessLevel);
131 int GroupchangeAccessLevel(const void *vUser1, const void *vUser2)
133 UserListEntry *u1 = (UserListEntry*) vUser1;
134 UserListEntry *u2 = (UserListEntry*) vUser2;
136 return u2->AccessLevel != u1->AccessLevel;
141 * Sort by UID
143 int CompareUID(const void *vUser1, const void *vUser2)
145 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
146 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
148 return (u1->UID > u2->UID);
150 int CompareUIDRev(const void *vUser1, const void *vUser2)
152 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
153 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
155 return (u2->UID > u1->UID);
157 int GroupchangeUID(const void *vUser1, const void *vUser2)
159 UserListEntry *u1 = (UserListEntry*) vUser1;
160 UserListEntry *u2 = (UserListEntry*) vUser2;
162 return (u2->UID / 10) != (u1->UID / 10);
166 * Sort By Date /// TODO!
168 int CompareLastLogon(const void *vUser1, const void *vUser2)
170 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
171 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
173 return (u1->LastLogonT > u2->LastLogonT);
175 int CompareLastLogonRev(const void *vUser1, const void *vUser2)
177 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
178 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
180 return (u2->LastLogonT > u1->LastLogonT);
182 int GroupchangeLastLogon(const void *vUser1, const void *vUser2)
184 UserListEntry *u1 = (UserListEntry*) vUser1;
185 UserListEntry *u2 = (UserListEntry*) vUser2;
187 return (u2->LastLogonT != u1->LastLogonT);
191 * Sort By Number of Logons
193 int ComparenLogons(const void *vUser1, const void *vUser2)
195 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
196 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
198 return (u1->nLogons > u2->nLogons);
200 int ComparenLogonsRev(const void *vUser1, const void *vUser2)
202 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
203 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
205 return (u2->nLogons > u1->nLogons);
207 int GroupchangenLogons(const void *vUser1, const void *vUser2)
209 UserListEntry *u1 = (UserListEntry*) vUser1;
210 UserListEntry *u2 = (UserListEntry*) vUser2;
212 return (u2->nLogons / 100) != (u1->nLogons / 100);
216 * Sort By Number of Posts
218 int ComparenPosts(const void *vUser1, const void *vUser2)
220 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
221 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
223 return (u1->nPosts > u2->nPosts);
225 int ComparenPostsRev(const void *vUser1, const void *vUser2)
227 UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
228 UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
230 return (u2->nPosts > u1->nPosts);
232 int GroupchangenPosts(const void *vUser1, const void *vUser2)
234 UserListEntry *u1 = (UserListEntry*) vUser1;
235 UserListEntry *u2 = (UserListEntry*) vUser2;
237 return (u2->nPosts / 100) != (u1->nPosts / 100);
241 HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
243 CompareFunc SortIt;
244 HashList *Hash;
245 char buf[SIZ];
246 StrBuf *Buf;
247 UserListEntry* ul;
248 char nnn[64];
249 int nUsed;
250 int len;
251 WCTemplputParams SubTP;
253 memset(&SubTP, 0, sizeof(WCTemplputParams));
254 serv_puts("LIST");
255 serv_getln(buf, sizeof buf);
256 if (buf[0] == '1') {
257 Hash = NewHash(1, NULL);
259 Buf = NewStrBuf();
260 while ((len = StrBuf_ServGetln(Buf),
261 strcmp(ChrPtr(Buf), "000"))) {
262 ul = NewUserListEntry(Buf);
263 if (ul == NULL)
264 continue;
265 nUsed = GetCount(Hash);
266 nUsed = snprintf(nnn, sizeof(nnn), "%d", nUsed+1);
267 Put(Hash, nnn, nUsed, ul, DeleteUserListEntry);
269 FreeStrBuf(&Buf);
270 SubTP.Filter.ContextType = CTX_USERLIST;
271 SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
272 if (SortIt != NULL)
273 SortByPayload(Hash, SortIt);
274 else
275 SortByPayload(Hash, CompareUID);
276 return Hash;
278 return NULL;
282 void tmplput_USERLIST_UserName(StrBuf *Target, WCTemplputParams *TP)
284 UserListEntry *ul = (UserListEntry*) CTX;
285 StrBufAppendTemplate(Target, TP, ul->UserName, 0);
288 void tmplput_USERLIST_Password(StrBuf *Target, WCTemplputParams *TP)
290 UserListEntry *ul = (UserListEntry*) CTX;
291 StrBufAppendTemplate(Target, TP, ul->Passvoid, 0);
294 void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, WCTemplputParams *TP)
296 UserListEntry *ul = (UserListEntry*) CTX;
298 StrBufAppendPrintf(Target, "%d", ul->AccessLevel, 0);
301 void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, WCTemplputParams *TP)
303 UserListEntry *ul = (UserListEntry*) CTX;
305 StrBufAppendBufPlain(Target, _(axdefs[ul->AccessLevel]), -1, 0);
308 void tmplput_USERLIST_UID(StrBuf *Target, WCTemplputParams *TP)
310 UserListEntry *ul = (UserListEntry*) CTX;
312 StrBufAppendPrintf(Target, "%d", ul->UID, 0);
315 void tmplput_USERLIST_LastLogonNo(StrBuf *Target, WCTemplputParams *TP)
317 UserListEntry *ul = (UserListEntry*) CTX;
319 StrBufAppendPrintf(Target,"%ld", ul->LastLogonT, 0);
321 void tmplput_USERLIST_LastLogonStr(StrBuf *Target, WCTemplputParams *TP)
323 UserListEntry *ul = (UserListEntry*) CTX;
324 StrEscAppend(Target, NULL, asctime(localtime(&ul->LastLogonT)), 0, 0);
327 void tmplput_USERLIST_nLogons(StrBuf *Target, WCTemplputParams *TP)
329 UserListEntry *ul = (UserListEntry*) CTX;
331 StrBufAppendPrintf(Target, "%d", ul->nLogons, 0);
334 void tmplput_USERLIST_nPosts(StrBuf *Target, WCTemplputParams *TP)
336 UserListEntry *ul = (UserListEntry*) CTX;
338 StrBufAppendPrintf(Target, "%d", ul->nPosts, 0);
341 void tmplput_USERLIST_Flags(StrBuf *Target, WCTemplputParams *TP)
343 UserListEntry *ul = (UserListEntry*) CTX;
345 StrBufAppendPrintf(Target, "%d", ul->Flags, 0);
348 void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, WCTemplputParams *TP)
350 UserListEntry *ul = (UserListEntry*) CTX;
352 StrBufAppendPrintf(Target, "%d", ul->DaysTillPurge, 0);
355 int ConditionalUser(StrBuf *Target, WCTemplputParams *TP)
357 UserListEntry *ul = (UserListEntry*) CTX;
358 if (havebstr("usernum")) {
359 return ibstr("usernum") == ul->UID;
361 else if (havebstr("username")) {
362 return strcmp(bstr("username"), ChrPtr(ul->UserName)) == 0;
364 else
365 return 0;
368 int ConditionalFlagINetEmail(StrBuf *Target, WCTemplputParams *TP)
370 UserListEntry *ul = (UserListEntry*) CTX;
371 return (ul->Flags & US_INTERNET) != 0;
374 int ConditionalUserAccess(StrBuf *Target, WCTemplputParams *TP)
376 UserListEntry *ul = (UserListEntry*) CTX;
378 if (TP->Tokens->Params[3]->Type == TYPE_LONG)
379 return (TP->Tokens->Params[3]->lvalue == ul->AccessLevel);
380 else
381 return 0;
385 * Locate the message number of a user's vCard in the current room
386 * Returns the message id of his vcard
388 long locate_user_vcard_in_this_room() {
389 char buf[SIZ];
390 long vcard_msgnum = (-1L);
391 char content_type[SIZ];
392 char partnum[SIZ];
393 int already_tried_creating_one = 0;
395 struct stuff_t {
396 struct stuff_t *next;
397 long msgnum;
400 struct stuff_t *stuff = NULL;
401 struct stuff_t *ptr;
403 TRYAGAIN:
404 /** Search for the user's vCard */
405 serv_puts("MSGS ALL");
406 serv_getln(buf, sizeof buf);
407 if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
408 ptr = malloc(sizeof(struct stuff_t));
409 ptr->msgnum = atol(buf);
410 ptr->next = stuff;
411 stuff = ptr;
414 /** Iterate through the message list looking for vCards */
415 while (stuff != NULL) {
416 serv_printf("MSG0 %ld|2", stuff->msgnum);
417 serv_getln(buf, sizeof buf);
418 if (buf[0]=='1') {
419 while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
420 if (!strncasecmp(buf, "part=", 5)) {
421 extract_token(partnum, &buf[5], 2, '|', sizeof partnum);
422 extract_token(content_type, &buf[5], 4, '|', sizeof content_type);
423 if ( (!strcasecmp(content_type, "text/x-vcard"))
424 || (!strcasecmp(content_type, "text/vcard")) ) {
425 vcard_msgnum = stuff->msgnum;
431 ptr = stuff->next;
432 free(stuff);
433 stuff = ptr;
436 /** If there's no vcard, create one */
437 if ((vcard_msgnum < 0) && (already_tried_creating_one == 0)) {
438 already_tried_creating_one = 1;
439 serv_puts("ENT0 1|||4");
440 serv_getln(buf, sizeof buf);
441 if (buf[0] == '4') {
442 serv_puts("Content-type: text/x-vcard");
443 serv_puts("");
444 serv_puts("begin:vcard");
445 serv_puts("end:vcard");
446 serv_puts("000");
448 goto TRYAGAIN;
451 return(vcard_msgnum);
456 * Display the form for editing a user's address book entry
457 * username the name of the user
458 * usernum the citadel-uid of the user
460 void display_edit_address_book_entry(char *username, long usernum) {
461 char roomname[SIZ];
462 char buf[SIZ];
463 char error_message[SIZ];
464 long vcard_msgnum = (-1L);
466 /** Locate the user's config room, creating it if necessary */
467 sprintf(roomname, "%010ld.%s", usernum, USERCONFIGROOM);
468 serv_printf("GOTO %s||1", roomname);
469 serv_getln(buf, sizeof buf);
470 if (buf[0] != '2') {
471 serv_printf("CRE8 1|%s|5|||1|", roomname);
472 serv_getln(buf, sizeof buf);
473 serv_printf("GOTO %s||1", roomname);
474 serv_getln(buf, sizeof buf);
475 if (buf[0] != '2') {
476 sprintf(error_message,
477 "<img src=\"static/error.gif\" align=center>"
478 "%s<br /><br />\n", &buf[4]);
479 select_user_to_edit(error_message, username);
480 return;
484 vcard_msgnum = locate_user_vcard_in_this_room();
486 if (vcard_msgnum < 0) {
487 sprintf(error_message,
488 "<img src=\"static/error.gif\" align=center>%s<br /><br />\n",
489 _("An error occurred while trying to create or edit this address book entry.")
491 select_user_to_edit(error_message, username);
492 return;
495 do_edit_vcard(vcard_msgnum, "1", "select_user_to_edit", roomname);
499 void display_edituser(char *supplied_username, int is_new) {
500 UserListEntry* UL;
501 StrBuf *Buf;
502 char error_message[1024];
503 char MajorStatus;
504 char username[256];
506 if (supplied_username != NULL) {
507 safestrncpy(username, supplied_username, sizeof username);
509 else {
510 safestrncpy(username, bstr("username"), sizeof username);
513 Buf = NewStrBuf();
514 serv_printf("AGUP %s", username);
515 StrBuf_ServGetln(Buf);
516 MajorStatus = ChrPtr(Buf)[0];
517 StrBufCutLeft(Buf, 4);
518 if (MajorStatus != '2') {
519 /*TODO ImportantMessage */
520 sprintf(error_message,
521 "<img src=\"static/error.gif\" align=center>"
522 "%s<br /><br />\n", ChrPtr(Buf));
523 select_user_to_edit(error_message, username);
524 FreeStrBuf(&Buf);
525 return;
527 else {
528 UL = NewUserListOneEntry(Buf);
529 if (havebstr("edit_abe_button")) {
530 display_edit_address_book_entry(username, UL->UID);
532 else if (havebstr("delete_button")) {
533 delete_user(username);
535 else {
536 WCTemplputParams SubTP;
537 memset(&SubTP, 0, sizeof(WCTemplputParams));
538 SubTP.Filter.ContextType = CTX_USERLIST;
539 SubTP.Context = UL;
540 output_headers(1, 0, 0, 0, 1, 0);
541 DoTemplate(HKEY("userlist_detailview"), NULL, &SubTP);
542 end_burst();
544 DeleteUserListEntry(UL);
547 FreeStrBuf(&Buf);
551 * do the backend operation of the user edit on the server
553 void edituser(void) {
554 char message[SIZ];
555 char buf[SIZ];
556 int is_new = 0;
557 unsigned int flags = 0;
558 char *username;
560 is_new = ibstr("is_new");
561 safestrncpy(message, "", sizeof message);
562 username = bstr("username");
564 if (!havebstr("ok_button")) {
565 safestrncpy(message, _("Changes were not saved."), sizeof message);
568 else {
569 flags = ibstr("flags");
570 if (yesbstr("inetmail")) {
571 flags |= US_INTERNET;
573 else {
574 flags &= ~US_INTERNET ;
577 if ((havebstr("newname")) && (strcasecmp(bstr("username"), bstr("newname")))) {
578 serv_printf("RENU %s|%s", bstr("username"), bstr("newname"));
579 serv_getln(buf, sizeof buf);
580 if (buf[0] != '2') {
581 sprintf(&message[strlen(message)],
582 "<img src=\"static/error.gif\" align=center>"
583 "%s<br /><br />\n", &buf[4]);
585 else {
586 username = bstr("newname");
590 serv_printf("ASUP %s|%s|%d|%s|%s|%s|%s|%s|%s|",
591 username,
592 bstr("password"),
593 flags,
594 bstr("timescalled"),
595 bstr("msgsposted"),
596 bstr("axlevel"),
597 bstr("usernum"),
598 bstr("lastcall"),
599 bstr("purgedays")
601 serv_getln(buf, sizeof buf);
602 if (buf[0] != '2') {
603 sprintf(&message[strlen(message)],
604 "<img src=\"static/error.gif\" align=center>"
605 "%s<br /><br />\n", &buf[4]);
610 * If we are in the middle of creating a new user, move on to
611 * the vCard edit screen.
613 if (is_new) {
614 display_edit_address_book_entry(username, lbstr("usernum") );
616 else {
617 select_user_to_edit(message, username);
622 * burge a user
623 * username the name of the user to remove
625 void delete_user(char *username) {
626 char buf[SIZ];
627 char message[SIZ];
629 serv_printf("ASUP %s|0|0|0|0|0|", username);
630 serv_getln(buf, sizeof buf);
631 if (buf[0] != '2') {
632 sprintf(message,
633 "<img src=\"static/error.gif\" align=center>"
634 "%s<br /><br />\n", &buf[4]);
636 else {
637 safestrncpy(message, "", sizeof message);
639 select_user_to_edit(message, bstr("username"));
645 * create a new user
646 * take the web environment username and create it on the citadel server
648 void create_user(void) {
649 char buf[SIZ];
650 char error_message[SIZ];
651 char username[SIZ];
653 safestrncpy(username, bstr("username"), sizeof username);
655 serv_printf("CREU %s", username);
656 serv_getln(buf, sizeof buf);
658 if (buf[0] == '2') {
659 sprintf(WC->ImportantMessage, _("A new user has been created."));
660 display_edituser(username, 1);
662 else if (!strncmp(buf, "570", 3)) {
663 sprintf(error_message,
664 "<img src=\"static/error.gif\" align=center>"
665 "%s<br /><br />\n",
666 _("You are attempting to create a new user from within Citadel "
667 "while running in host based authentication mode. In this mode, "
668 "you must create new users on the host system, not within Citadel.")
670 select_user_to_edit(error_message, NULL);
672 else {
673 sprintf(error_message,
674 "<img src=\"static/error.gif\" align=center>"
675 "%s<br /><br />\n", &buf[4]);
676 select_user_to_edit(error_message, NULL);
682 void _select_user_to_edit(void){select_user_to_edit(NULL, NULL);}
683 void _display_edituser(void) {display_edituser(NULL, 0);}
685 void
686 InitModule_USEREDIT
687 (void)
689 WebcitAddUrlHandler(HKEY("select_user_to_edit"), _select_user_to_edit, 0);
690 WebcitAddUrlHandler(HKEY("display_edituser"), _display_edituser, 0);
691 WebcitAddUrlHandler(HKEY("edituser"), edituser, 0);
692 WebcitAddUrlHandler(HKEY("create_user"), create_user, 0);
694 RegisterNamespace("USERLIST:USERNAME", 0, 1, tmplput_USERLIST_UserName, CTX_USERLIST);
695 RegisterNamespace("USERLIST:PASSWD", 0, 1, tmplput_USERLIST_Password, CTX_USERLIST);
696 RegisterNamespace("USERLIST:ACCLVLNO", 0, 0, tmplput_USERLIST_AccessLevelNo, CTX_USERLIST);
697 RegisterNamespace("USERLIST:ACCLVLSTR", 0, 0, tmplput_USERLIST_AccessLevelStr, CTX_USERLIST);
698 RegisterNamespace("USERLIST:UID", 0, 0, tmplput_USERLIST_UID, CTX_USERLIST);
699 RegisterNamespace("USERLIST:LASTLOGON:STR", 0, 0, tmplput_USERLIST_LastLogonStr, CTX_USERLIST);
700 RegisterNamespace("USERLIST:LASTLOGON:NO", 0, 0, tmplput_USERLIST_LastLogonNo, CTX_USERLIST);
701 RegisterNamespace("USERLIST:NLOGONS", 0, 0, tmplput_USERLIST_nLogons, CTX_USERLIST);
702 RegisterNamespace("USERLIST:NPOSTS", 0, 0, tmplput_USERLIST_nPosts, CTX_USERLIST);
704 RegisterNamespace("USERLIST:FLAGS", 0, 0, tmplput_USERLIST_Flags, CTX_USERLIST);
705 RegisterNamespace("USERLIST:DAYSTILLPURGE", 0, 0, tmplput_USERLIST_DaysTillPurge, CTX_USERLIST);
707 RegisterConditional(HKEY("COND:USERNAME"), 0, ConditionalUser, CTX_USERLIST);
708 RegisterConditional(HKEY("COND:USERACCESS"), 0, ConditionalUserAccess, CTX_USERLIST);
709 RegisterConditional(HKEY("COND:USERLIST:FLAG:USE_INTERNET"), 0, ConditionalFlagINetEmail, CTX_USERLIST);
711 RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE, IT_NOFLAG);
714 RegisterSortFunc(HKEY("user:name"),
715 HKEY("userlist"),
716 CompareUserListName,
717 CompareUserListNameRev,
718 GroupchangeUserListName,
719 CTX_USERLIST);
720 RegisterSortFunc(HKEY("user:accslvl"),
721 HKEY("userlist"),
722 CompareAccessLevel,
723 CompareAccessLevelRev,
724 GroupchangeAccessLevel,
725 CTX_USERLIST);
727 RegisterSortFunc(HKEY("user:nlogons"),
728 HKEY("userlist"),
729 ComparenLogons,
730 ComparenLogonsRev,
731 GroupchangenLogons,
732 CTX_USERLIST);
734 RegisterSortFunc(HKEY("user:uid"),
735 HKEY("userlist"),
736 CompareUID,
737 CompareUIDRev,
738 GroupchangeUID,
739 CTX_USERLIST);
741 RegisterSortFunc(HKEY("user:lastlogon"),
742 HKEY("userlist"),
743 CompareLastLogon,
744 CompareLastLogonRev,
745 GroupchangeLastLogon,
746 CTX_USERLIST);
748 RegisterSortFunc(HKEY("user:nmsgposts"),
749 HKEY("userlist"),
750 ComparenPosts,
751 ComparenPostsRev,
752 GroupchangenPosts,
753 CTX_USERLIST);