* start migrating important message to strbuf; have both meanwhile.
[citadel.git] / webcit / useredit.c
1 /*
2  * $Id$
3  */
4
5 #include "webcit.h"
6 #include "webserver.h"
7
8
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
13  */
14 void select_user_to_edit(const char *message, const char *preselect)
15 {
16         output_headers(1, 0, 0, 0, 1, 0);
17         do_template("edituser_select", NULL);
18         end_burst();
19 }
20
21
22 typedef struct _UserListEntry {
23         int UID;
24         int AccessLevel;
25         int nLogons;
26         int nPosts;
27
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;
35
36
37 UserListEntry* NewUserListOneEntry(StrBuf *SerializedUser)
38 {
39         UserListEntry *ul;
40
41         if (StrLength(SerializedUser) < 8) 
42                 return NULL;
43
44         ul = (UserListEntry*) malloc(sizeof(UserListEntry));
45         ul->UserName = NewStrBuf();
46         ul->Passvoid = NewStrBuf();
47
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;
58 }
59
60 void DeleteUserListEntry(void *vUserList)
61 {
62         UserListEntry *ul = (UserListEntry*) vUserList;
63         if (!ul) return;
64         FreeStrBuf(&ul->UserName);
65         FreeStrBuf(&ul->Passvoid);
66         free(ul);
67 }
68
69 UserListEntry* NewUserListEntry(StrBuf *SerializedUserList)
70 {
71         UserListEntry *ul;
72
73         if (StrLength(SerializedUserList) < 8) 
74                 return NULL;
75
76         ul = (UserListEntry*) malloc(sizeof(UserListEntry));
77         ul->UserName = NewStrBuf();
78         ul->Passvoid = NewStrBuf();
79
80         StrBufExtract_token(ul->UserName, SerializedUserList, 0, '|');
81         ul->AccessLevel = StrBufExtract_int(SerializedUserList, 1, '|');
82         ul->UID = StrBufExtract_int(SerializedUserList, 2, '|');
83         ul->LastLogonT = StrBufExtract_long(SerializedUserList, 3, '|');
84         ul->nLogons = StrBufExtract_int(SerializedUserList, 4, '|');
85         ul->nPosts = StrBufExtract_int(SerializedUserList, 5, '|');
86         StrBufExtract_token(ul->Passvoid, SerializedUserList, 6, '|');
87         ul->Flags = 0;
88         ul->DaysTillPurge = -1;
89         return ul;
90 }
91
92 /*
93  * Sort by Username
94  */
95 int CompareUserListName(const void *vUser1, const void *vUser2)
96 {
97         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
98         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
99
100         return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName));
101 }
102 int CompareUserListNameRev(const void *vUser1, const void *vUser2)
103 {
104         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
105         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
106         return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
107 }
108 int GroupchangeUserListName(const void *vUser1, const void *vUser2)
109 {
110         UserListEntry *u1 = (UserListEntry*) vUser1;
111         UserListEntry *u2 = (UserListEntry*) vUser2;
112         return ChrPtr(u2->UserName)[0] != ChrPtr(u1->UserName)[0];
113 }
114
115 /*
116  * Sort by AccessLevel
117  */
118 int CompareAccessLevel(const void *vUser1, const void *vUser2)
119 {
120         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
121         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
122
123         return (u1->AccessLevel > u2->AccessLevel);
124 }
125 int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
126 {
127         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
128         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
129
130         return (u2->AccessLevel > u1->AccessLevel);
131 }
132 int GroupchangeAccessLevel(const void *vUser1, const void *vUser2)
133 {
134         UserListEntry *u1 = (UserListEntry*) vUser1;
135         UserListEntry *u2 = (UserListEntry*) vUser2;
136
137         return u2->AccessLevel != u1->AccessLevel;
138 }
139
140
141 /*
142  * Sort by UID
143  */
144 int CompareUID(const void *vUser1, const void *vUser2)
145 {
146         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
147         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
148
149         return (u1->UID > u2->UID);
150 }
151 int CompareUIDRev(const void *vUser1, const void *vUser2)
152 {
153         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
154         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
155
156         return (u2->UID > u1->UID);
157 }
158 int GroupchangeUID(const void *vUser1, const void *vUser2)
159 {
160         UserListEntry *u1 = (UserListEntry*) vUser1;
161         UserListEntry *u2 = (UserListEntry*) vUser2;
162
163         return (u2->UID / 10) != (u1->UID / 10);
164 }
165
166 /*
167  * Sort By Date /// TODO!
168  */
169 int CompareLastLogon(const void *vUser1, const void *vUser2)
170 {
171         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
172         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
173
174         return (u1->LastLogonT > u2->LastLogonT);
175 }
176 int CompareLastLogonRev(const void *vUser1, const void *vUser2)
177 {
178         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
179         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
180
181         return (u2->LastLogonT > u1->LastLogonT);
182 }
183 int GroupchangeLastLogon(const void *vUser1, const void *vUser2)
184 {
185         UserListEntry *u1 = (UserListEntry*) vUser1;
186         UserListEntry *u2 = (UserListEntry*) vUser2;
187
188         return (u2->LastLogonT != u1->LastLogonT);
189 }
190
191 /*
192  * Sort By Number of Logons
193  */
194 int ComparenLogons(const void *vUser1, const void *vUser2)
195 {
196         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
197         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
198
199         return (u1->nLogons > u2->nLogons);
200 }
201 int ComparenLogonsRev(const void *vUser1, const void *vUser2)
202 {
203         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
204         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
205
206         return (u2->nLogons > u1->nLogons);
207 }
208 int GroupchangenLogons(const void *vUser1, const void *vUser2)
209 {
210         UserListEntry *u1 = (UserListEntry*) vUser1;
211         UserListEntry *u2 = (UserListEntry*) vUser2;
212
213         return (u2->nLogons / 100) != (u1->nLogons / 100);
214 }
215
216 /*
217  * Sort By Number of Posts
218  */
219 int ComparenPosts(const void *vUser1, const void *vUser2)
220 {
221         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
222         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
223
224         return (u1->nPosts > u2->nPosts);
225 }
226 int ComparenPostsRev(const void *vUser1, const void *vUser2)
227 {
228         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
229         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
230
231         return (u2->nPosts > u1->nPosts);
232 }
233 int GroupchangenPosts(const void *vUser1, const void *vUser2)
234 {
235         UserListEntry *u1 = (UserListEntry*) vUser1;
236         UserListEntry *u2 = (UserListEntry*) vUser2;
237
238         return (u2->nPosts / 100) != (u1->nPosts / 100);
239 }
240
241
242 HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
243 {
244         int Done = 0;
245         CompareFunc SortIt;
246         HashList *Hash;
247         StrBuf *Buf;
248         UserListEntry* ul;
249         char nnn[64];
250         int nUsed;
251         int len;
252         WCTemplputParams SubTP;
253
254         memset(&SubTP, 0, sizeof(WCTemplputParams));    
255         serv_puts("LIST");
256         Buf = NewStrBuf();
257         StrBuf_ServGetlnBuffered(Buf);
258         if (GetServerStatus(Buf, NULL) == 1) {
259                 Hash = NewHash(1, NULL);
260
261                 while (!Done) {
262                         len = StrBuf_ServGetlnBuffered(Buf);
263                         if ((len == 3) &&
264                             (strcmp(ChrPtr(Buf), "000")==0)) {
265                                 Done = 1;
266                                 break;
267                         }
268                         ul = NewUserListEntry(Buf);
269                         if (ul == NULL)
270                                 continue;
271                         nUsed = GetCount(Hash);
272                         nUsed = snprintf(nnn, sizeof(nnn), "%d", nUsed+1);
273                         Put(Hash, nnn, nUsed, ul, DeleteUserListEntry); 
274                 }
275                 SubTP.Filter.ContextType = CTX_USERLIST;
276                 SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
277                 if (SortIt != NULL)
278                         SortByPayload(Hash, SortIt);
279                 else 
280                         SortByPayload(Hash, CompareUID);
281                 return Hash;
282         }
283         FreeStrBuf(&Buf);
284         return NULL;
285 }
286
287
288 void tmplput_USERLIST_UserName(StrBuf *Target, WCTemplputParams *TP)
289 {
290         UserListEntry *ul = (UserListEntry*) CTX;
291         StrBufAppendTemplate(Target, TP, ul->UserName, 0);
292 }
293
294 void tmplput_USERLIST_Password(StrBuf *Target, WCTemplputParams *TP)
295 {
296         UserListEntry *ul = (UserListEntry*) CTX;
297         StrBufAppendTemplate(Target, TP, ul->Passvoid, 0);
298 }
299
300 void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, WCTemplputParams *TP)
301 {
302         UserListEntry *ul = (UserListEntry*) CTX;
303
304         StrBufAppendPrintf(Target, "%d", ul->AccessLevel, 0);
305 }
306
307 void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, WCTemplputParams *TP)
308 {
309         UserListEntry *ul = (UserListEntry*) CTX;
310         
311         StrBufAppendBufPlain(Target, _(axdefs[ul->AccessLevel]), -1, 0);
312 }
313
314 void tmplput_USERLIST_UID(StrBuf *Target, WCTemplputParams *TP)
315 {
316         UserListEntry *ul = (UserListEntry*) CTX;
317
318         StrBufAppendPrintf(Target, "%d", ul->UID, 0);
319 }
320
321 void tmplput_USERLIST_LastLogonNo(StrBuf *Target, WCTemplputParams *TP)
322 {
323         UserListEntry *ul = (UserListEntry*) CTX;
324
325         StrBufAppendPrintf(Target,"%ld", ul->LastLogonT, 0);
326 }
327 void tmplput_USERLIST_LastLogonStr(StrBuf *Target, WCTemplputParams *TP)
328 {
329         UserListEntry *ul = (UserListEntry*) CTX;
330         StrEscAppend(Target, NULL, asctime(localtime(&ul->LastLogonT)), 0, 0);
331 }
332
333 void tmplput_USERLIST_nLogons(StrBuf *Target, WCTemplputParams *TP)
334 {
335         UserListEntry *ul = (UserListEntry*) CTX;
336
337         StrBufAppendPrintf(Target, "%d", ul->nLogons, 0);
338 }
339
340 void tmplput_USERLIST_nPosts(StrBuf *Target, WCTemplputParams *TP)
341 {
342         UserListEntry *ul = (UserListEntry*) CTX;
343
344         StrBufAppendPrintf(Target, "%d", ul->nPosts, 0);
345 }
346
347 void tmplput_USERLIST_Flags(StrBuf *Target, WCTemplputParams *TP)
348 {
349         UserListEntry *ul = (UserListEntry*) CTX;
350
351         StrBufAppendPrintf(Target, "%d", ul->Flags, 0);
352 }
353
354 void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, WCTemplputParams *TP)
355 {
356         UserListEntry *ul = (UserListEntry*) CTX;
357
358         StrBufAppendPrintf(Target, "%d", ul->DaysTillPurge, 0);
359 }
360
361 int ConditionalUser(StrBuf *Target, WCTemplputParams *TP)
362 {
363         UserListEntry *ul = (UserListEntry*) CTX;
364         if (havebstr("usernum")) {
365                 return ibstr("usernum") == ul->UID;
366         }
367         else if (havebstr("username")) {
368                 return strcmp(bstr("username"), ChrPtr(ul->UserName)) == 0;
369         }
370         else 
371                 return 0;
372 }
373
374 int ConditionalFlagINetEmail(StrBuf *Target, WCTemplputParams *TP)
375 {
376         UserListEntry *ul = (UserListEntry*) CTX;
377         return (ul->Flags & US_INTERNET) != 0;
378 }
379
380 int ConditionalUserAccess(StrBuf *Target, WCTemplputParams *TP)
381 {
382         UserListEntry *ul = (UserListEntry*) CTX;
383
384         if (TP->Tokens->Params[3]->Type == TYPE_LONG)
385                 return (TP->Tokens->Params[3]->lvalue == ul->AccessLevel);
386         else
387                 return 0;
388 }
389
390 /*
391  *  Locate the message number of a user's vCard in the current room
392  *  Returns the message id of his vcard
393  */
394 long locate_user_vcard_in_this_room(message_summary **VCMsg,
395                                     wc_mime_attachment **VCAtt)
396 {
397         wcsession *WCC = WC;
398         HashPos *at;
399         HashPos *att;
400         const char *HashKey;
401         long HKLen;
402         void *vMsg;
403         message_summary *Msg;
404         wc_mime_attachment *Att;
405
406
407         int Done;
408         StrBuf *Buf;
409         long vcard_msgnum = (-1L);
410         int already_tried_creating_one = 0;
411         StrBuf *FoundCharset = NewStrBuf();
412         StrBuf *Error = NULL;
413
414         
415         Buf = NewStrBuf();
416 TRYAGAIN:
417         Done = 0;
418         /** Search for the user's vCard */
419         if (load_msg_ptrs("MSGS ALL||||1", 1) > 0) {
420                 at = GetNewHashPos(WCC->summ, 0);
421                 while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
422                         Msg = (message_summary*) vMsg;          
423                         Msg->MsgBody =  (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
424                         memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
425                         Msg->MsgBody->msgnum = Msg->msgnum;
426
427                         load_message(Msg, 
428                                      FoundCharset,
429                                      &Error);
430                         
431                         if (Msg->AllAttach != NULL) {
432                                 att = GetNewHashPos(Msg->AllAttach, 0);
433                                 while (GetNextHashPos(Msg->AllAttach, att, &HKLen, &HashKey, &vMsg)) {
434                                         Att = (wc_mime_attachment*) vMsg;
435                                         if (  (strcasecmp(ChrPtr(Att->ContentType), "text/x-vcard") == 0) ||
436                                               (strcasecmp(ChrPtr(Att->ContentType), "text/vcard")   == 0) ) {
437                                                 *VCAtt = Att;
438                                                 *VCMsg = Msg;
439                                                 if (Att->Data == NULL)
440                                                         MimeLoadData(Att);
441                                         }
442                                 }
443                         }
444                         FreeStrBuf(&Error); /*< don't care... */
445                         
446                 }
447                 DeleteHashPos(&at);             
448         }
449         /** If there's no vcard, create one */
450         if ((*VCMsg == NULL) && (already_tried_creating_one == 0)) {
451                 already_tried_creating_one = 1;
452                 serv_puts("ENT0 1|||4");
453                 StrBuf_ServGetlnBuffered(Buf);
454                 if (GetServerStatus(Buf, NULL) != 4) {
455                         serv_puts("Content-type: text/x-vcard");
456                         serv_puts("");
457                         serv_puts("begin:vcard");
458                         serv_puts("end:vcard");
459                         serv_puts("000");
460                 }
461                 goto TRYAGAIN;
462         }
463         FreeStrBuf(&Buf);
464         return(vcard_msgnum);
465 }
466
467
468 /**
469  *  Display the form for editing a user's address book entry
470  *  username the name of the user
471  *  usernum the citadel-uid of the user
472  */
473 void display_edit_address_book_entry(const char *username, long usernum) {
474         message_summary *VCMsg = NULL;
475         wc_mime_attachment *VCAtt = NULL;
476         StrBuf *roomname;
477         StrBuf *Buf;
478         char error_message[SIZ];
479         long vcard_msgnum = (-1L);
480
481         /** Locate the user's config room, creating it if necessary */
482         Buf = NewStrBuf();
483         roomname = NewStrBuf();
484         StrBufPrintf(roomname, "%010ld.%s", usernum, USERCONFIGROOM);
485         serv_printf("GOTO %s||1", ChrPtr(roomname));
486         StrBuf_ServGetlnBuffered(Buf);
487         if (GetServerStatus(Buf, NULL) != 2) {
488                 serv_printf("CRE8 1|%s|5|||1|", ChrPtr(roomname));
489                 StrBuf_ServGetlnBuffered(Buf);
490                 GetServerStatus(Buf, NULL);
491                 serv_printf("GOTO %s||1", ChrPtr(roomname));
492                 StrBuf_ServGetlnBuffered(Buf);
493                 if (GetServerStatus(Buf, NULL) != 2) {
494                         StrBufCutLeft(Buf, 4);
495                         sprintf(error_message,
496                                 "<img src=\"static/error.gif\" align=center>"
497                                 "%s<br /><br />\n", ChrPtr(Buf));
498                         select_user_to_edit(error_message, username);
499                         FreeStrBuf(&Buf);
500                         FreeStrBuf(&roomname);
501                         return;
502                 }
503         }
504         FreeStrBuf(&Buf);
505
506         locate_user_vcard_in_this_room(&VCMsg, &VCAtt);
507
508         if (VCMsg == NULL) {
509                 sprintf(error_message,
510                         "<img src=\"static/error.gif\" align=center>%s<br /><br />\n",
511                         _("An error occurred while trying to create or edit this address book entry.")
512                         );
513                 select_user_to_edit(error_message, username);
514                 FreeStrBuf(&roomname);
515                 return;
516         }
517
518         do_edit_vcard(vcard_msgnum, "1", 
519                       VCMsg,
520                       VCAtt,
521                       "select_user_to_edit", 
522                       ChrPtr(roomname));
523         FreeStrBuf(&roomname);
524 }
525
526
527 void display_edituser(const char *supplied_username, int is_new) {
528         UserListEntry* UL;
529         StrBuf *Buf;
530         char error_message[1024];
531         char username[256];
532
533         if (supplied_username != NULL) {
534                 safestrncpy(username, supplied_username, sizeof username);
535         }
536         else {
537                 safestrncpy(username, bstr("username"), sizeof username);
538         }
539
540         Buf = NewStrBuf();
541         serv_printf("AGUP %s", username);
542         StrBuf_ServGetlnBuffered(Buf);
543         if (GetServerStatus(Buf, NULL) != 2) {
544                 StrBufCutLeft(Buf, 4);
545                 /*TODO ImportantMessage */
546                 sprintf(error_message,
547                         "<img src=\"static/error.gif\" align=center>"
548                         "%s<br /><br />\n", ChrPtr(Buf));
549                 select_user_to_edit(error_message, username);
550                 FreeStrBuf(&Buf);
551                 return;
552         }
553         else {
554                 StrBufCutLeft(Buf, 4);
555                 UL = NewUserListOneEntry(Buf);
556                 if ((UL != NULL) && havebstr("edit_abe_button")) {
557                         display_edit_address_book_entry(username, UL->UID);
558                 }
559                 else if ((UL != NULL) && havebstr("delete_button")) {
560                         delete_user(username);
561                 }
562                 else if (UL != NULL) {
563                         WCTemplputParams SubTP;
564                         memset(&SubTP, 0, sizeof(WCTemplputParams));
565                         SubTP.Filter.ContextType = CTX_USERLIST;
566                         SubTP.Context = UL;
567                         output_headers(1, 0, 0, 0, 1, 0);
568                         DoTemplate(HKEY("userlist_detailview"), NULL, &SubTP);
569                         end_burst();
570                 }
571                 DeleteUserListEntry(UL);
572                 
573         }
574         FreeStrBuf(&Buf);
575 }
576
577 /**
578  *  do the backend operation of the user edit on the server
579  */
580 void edituser(void) {
581         char message[SIZ];
582         int is_new = 0;
583         unsigned int flags = 0;
584         const char *username;
585
586         is_new = ibstr("is_new");
587         safestrncpy(message, "", sizeof message);
588         username = bstr("username");
589
590         if (!havebstr("ok_button")) {
591                 safestrncpy(message, _("Changes were not saved."), sizeof message);
592         }       
593         else {
594                 StrBuf *Buf = NewStrBuf();
595
596                 flags = ibstr("flags");
597                 if (yesbstr("inetmail")) {
598                         flags |= US_INTERNET;
599                 }
600                 else {
601                         flags &= ~US_INTERNET ;
602                 }
603
604                 if ((havebstr("newname")) && (strcasecmp(bstr("username"), bstr("newname")))) {
605                         serv_printf("RENU %s|%s", bstr("username"), bstr("newname"));
606                         StrBuf_ServGetlnBuffered(Buf);
607                         if (GetServerStatus(Buf, NULL) == 2) {
608                                 StrBufCutLeft(Buf, 4);
609                                 sprintf(&message[strlen(message)],
610                                         "<img src=\"static/error.gif\" align=center>"
611                                         "%s<br /><br />\n", ChrPtr(Buf));
612                         }
613                         else {
614                                 username = bstr("newname");
615                         }
616                 }
617
618                 serv_printf("ASUP %s|%s|%d|%s|%s|%s|%s|%s|%s|",
619                         username,
620                         bstr("password"),
621                         flags,
622                         bstr("timescalled"),
623                         bstr("msgsposted"),
624                         bstr("axlevel"),
625                         bstr("usernum"),
626                         bstr("lastcall"),
627                         bstr("purgedays")
628                 );
629                 StrBuf_ServGetlnBuffered(Buf);
630                 if (GetServerStatus(Buf, NULL) == 2) {
631                         StrBufCutLeft(Buf, 4);
632                         sprintf(&message[strlen(message)],
633                                 "<img src=\"static/error.gif\" align=center>"
634                                 "%s<br /><br />\n", ChrPtr(Buf));
635                 }
636                 FreeStrBuf(&Buf);
637         }
638
639         /**
640          * If we are in the middle of creating a new user, move on to
641          * the vCard edit screen.
642          */
643         if (is_new) {
644                 display_edit_address_book_entry(username, lbstr("usernum") );
645         }
646         else {
647                 select_user_to_edit(message, username);
648         }
649 }
650
651 /*
652  *  burge a user 
653  *  username the name of the user to remove
654  */
655 void delete_user(char *username) {
656         StrBuf *Buf;
657         char message[SIZ];
658
659         Buf = NewStrBuf();
660         serv_printf("ASUP %s|0|0|0|0|0|", username);
661         StrBuf_ServGetlnBuffered(Buf);
662         if (GetServerStatus(Buf, NULL) == 2) {
663                 StrBufCutLeft(Buf, 4);
664                 sprintf(message,
665                         "<img src=\"static/error.gif\" align=center>"
666                         "%s<br /><br />\n", ChrPtr(Buf));
667         }
668         else {
669                 safestrncpy(message, "", sizeof message);
670         }
671         select_user_to_edit(message, bstr("username"));
672         FreeStrBuf(&Buf);
673 }
674                 
675
676
677 /**
678  *  create a new user
679  * take the web environment username and create it on the citadel server
680  */
681 void create_user(void) {
682         long FullState;
683         StrBuf *Buf;
684         char error_message[SIZ];
685         const char *username;
686
687         Buf = NewStrBuf();
688         username = bstr("username");
689         serv_printf("CREU %s", username);
690         StrBuf_ServGetlnBuffered(Buf);
691         if (GetServerStatus(Buf, &FullState) == 2) {
692                 sprintf(WC->ImportantMessage, _("A new user has been created."));
693                 display_edituser(username, 1);
694         }
695         else if (FullState == 570) {
696                 sprintf(error_message,
697                         "<img src=\"static/error.gif\" align=center>"
698                         "%s<br /><br />\n",
699                         _("You are attempting to create a new user from within Citadel "
700                         "while running in host based authentication mode.  In this mode, "
701                         "you must create new users on the host system, not within Citadel.")
702                 );
703                 select_user_to_edit(error_message, NULL);
704         }
705         else {
706                 StrBufCutLeft(Buf, 4);
707                 sprintf(error_message,
708                         "<img src=\"static/error.gif\" align=center>"
709                         "%s<br /><br />\n", ChrPtr(Buf));
710                 select_user_to_edit(error_message, NULL);
711         }
712         FreeStrBuf(&Buf);
713 }
714
715
716 void _select_user_to_edit(void){select_user_to_edit(NULL, NULL);}
717 void _display_edituser(void) {display_edituser(NULL, 0);}
718
719 void 
720 InitModule_USEREDIT
721 (void)
722 {
723         WebcitAddUrlHandler(HKEY("select_user_to_edit"), _select_user_to_edit, 0);
724         WebcitAddUrlHandler(HKEY("display_edituser"), _display_edituser, 0);
725         WebcitAddUrlHandler(HKEY("edituser"), edituser, 0);
726         WebcitAddUrlHandler(HKEY("create_user"), create_user, 0);
727
728         RegisterNamespace("USERLIST:USERNAME",      0, 1, tmplput_USERLIST_UserName, CTX_USERLIST);
729         RegisterNamespace("USERLIST:PASSWD",        0, 1, tmplput_USERLIST_Password, CTX_USERLIST);
730         RegisterNamespace("USERLIST:ACCLVLNO",      0, 0, tmplput_USERLIST_AccessLevelNo, CTX_USERLIST);
731         RegisterNamespace("USERLIST:ACCLVLSTR",     0, 0, tmplput_USERLIST_AccessLevelStr, CTX_USERLIST);
732         RegisterNamespace("USERLIST:UID",           0, 0, tmplput_USERLIST_UID, CTX_USERLIST);
733         RegisterNamespace("USERLIST:LASTLOGON:STR", 0, 0, tmplput_USERLIST_LastLogonStr, CTX_USERLIST);
734         RegisterNamespace("USERLIST:LASTLOGON:NO",  0, 0, tmplput_USERLIST_LastLogonNo, CTX_USERLIST);
735         RegisterNamespace("USERLIST:NLOGONS",       0, 0, tmplput_USERLIST_nLogons, CTX_USERLIST);
736         RegisterNamespace("USERLIST:NPOSTS",        0, 0, tmplput_USERLIST_nPosts, CTX_USERLIST);
737                                                     
738         RegisterNamespace("USERLIST:FLAGS",         0, 0, tmplput_USERLIST_Flags, CTX_USERLIST);
739         RegisterNamespace("USERLIST:DAYSTILLPURGE", 0, 0, tmplput_USERLIST_DaysTillPurge, CTX_USERLIST);
740
741         RegisterConditional(HKEY("COND:USERNAME"),  0,    ConditionalUser, CTX_USERLIST);
742         RegisterConditional(HKEY("COND:USERACCESS"), 0,   ConditionalUserAccess, CTX_USERLIST);
743         RegisterConditional(HKEY("COND:USERLIST:FLAG:USE_INTERNET"), 0, ConditionalFlagINetEmail, CTX_USERLIST);
744
745         RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
746         
747
748
749         RegisterSortFunc(HKEY("user:name"),
750                          HKEY("userlist"),
751                          CompareUserListName,
752                          CompareUserListNameRev,
753                          GroupchangeUserListName,
754                          CTX_USERLIST);
755         RegisterSortFunc(HKEY("user:accslvl"),
756                          HKEY("userlist"),
757                          CompareAccessLevel,
758                          CompareAccessLevelRev,
759                          GroupchangeAccessLevel,
760                          CTX_USERLIST);
761
762         RegisterSortFunc(HKEY("user:nlogons"),
763                          HKEY("userlist"),
764                          ComparenLogons,
765                          ComparenLogonsRev,
766                          GroupchangenLogons,
767                          CTX_USERLIST);
768
769         RegisterSortFunc(HKEY("user:uid"),
770                          HKEY("userlist"),
771                          CompareUID,
772                          CompareUIDRev,
773                          GroupchangeUID,
774                          CTX_USERLIST);
775
776         RegisterSortFunc(HKEY("user:lastlogon"),
777                          HKEY("userlist"),
778                          CompareLastLogon,
779                          CompareLastLogonRev,
780                          GroupchangeLastLogon,
781                          CTX_USERLIST);
782
783         RegisterSortFunc(HKEY("user:nmsgposts"),
784                          HKEY("userlist"),
785                          ComparenPosts,
786                          ComparenPostsRev,
787                          GroupchangenPosts,
788                          CTX_USERLIST);
789
790 }