57aaae864676efad02894694df23e4efe8ee5914
[citadel.git] / webcit / useredit.c
1 /*
2  * Copyright (c) 1996-2011 by the citadel.org team
3  *
4  * This program is open source software.  You can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 3 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18
19 #include "webcit.h"
20 #include "webserver.h"
21
22
23 /*
24  *  show a list of available users to edit them
25  *  message the header message???
26  *  preselect = which user should be selected in the browser
27  */
28 void select_user_to_edit(const char *preselect)
29 {
30         output_headers(1, 0, 0, 0, 1, 0);
31         do_template("aide_edituser_select");
32         end_burst();
33 }
34
35
36 typedef struct _UserListEntry {
37         int UID;
38         int AccessLevel;
39         int nLogons;
40         int nPosts;
41
42         StrBuf *UserName;
43         StrBuf *Passvoid;
44         time_t LastLogonT;
45         /* Just available for Single users to view: */
46         unsigned int Flags;
47         int DaysTillPurge;
48         int HasBio;
49 } UserListEntry;
50
51
52 UserListEntry* NewUserListOneEntry(StrBuf *SerializedUser, const char *Pos)
53 {
54         UserListEntry *ul;
55
56         if (StrLength(SerializedUser) < 8) 
57                 return NULL;
58
59         ul = (UserListEntry*) malloc(sizeof(UserListEntry));
60         ul->UserName = NewStrBuf();
61         ul->Passvoid = NewStrBuf();
62
63         StrBufExtract_NextToken(ul->UserName,               SerializedUser, &Pos, '|');
64         StrBufExtract_NextToken(ul->Passvoid,               SerializedUser, &Pos, '|');
65         ul->Flags         = StrBufExtractNext_unsigned_long(SerializedUser, &Pos, '|');
66         ul->nLogons       = StrBufExtractNext_int(          SerializedUser, &Pos, '|');
67         ul->nPosts        = StrBufExtractNext_int(          SerializedUser, &Pos, '|');
68         ul->AccessLevel   = StrBufExtractNext_int(          SerializedUser, &Pos, '|');
69         ul->UID           = StrBufExtractNext_int(          SerializedUser, &Pos, '|');
70         ul->LastLogonT    = StrBufExtractNext_long(         SerializedUser, &Pos, '|');
71         ul->DaysTillPurge = StrBufExtractNext_int(          SerializedUser, &Pos, '|');
72         return ul;
73 }
74
75 void DeleteUserListEntry(void *vUserList)
76 {
77         UserListEntry *ul = (UserListEntry*) vUserList;
78         if (!ul) return;
79         FreeStrBuf(&ul->UserName);
80         FreeStrBuf(&ul->Passvoid);
81         free(ul);
82 }
83
84 UserListEntry* NewUserListEntry(StrBuf *SerializedUserList)
85 {
86         const char *Pos = NULL;
87         UserListEntry *ul;
88
89         if (StrLength(SerializedUserList) < 8) 
90                 return NULL;
91
92         ul = (UserListEntry*) malloc(sizeof(UserListEntry));
93         ul->UserName = NewStrBuf();
94         ul->Passvoid = NewStrBuf();
95
96         StrBufExtract_NextToken(ul->UserName,    SerializedUserList, &Pos, '|');
97         ul->AccessLevel = StrBufExtractNext_int( SerializedUserList, &Pos, '|');
98         ul->UID         = StrBufExtractNext_int( SerializedUserList, &Pos, '|');
99         ul->LastLogonT  = StrBufExtractNext_long(SerializedUserList, &Pos, '|');
100         ul->nLogons     = StrBufExtractNext_int( SerializedUserList, &Pos, '|');
101         ul->nPosts      = StrBufExtractNext_int( SerializedUserList, &Pos, '|');
102         StrBufExtract_NextToken(ul->Passvoid,    SerializedUserList, &Pos, '|');
103         ul->Flags = 0;
104         ul->HasBio = 0;
105         ul->DaysTillPurge = -1;
106         return ul;
107 }
108
109 /*
110  * Sort by Username
111  */
112 int CompareUserListName(const void *vUser1, const void *vUser2)
113 {
114         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
115         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
116
117         return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName));
118 }
119
120 int CompareUserListNameRev(const void *vUser1, const void *vUser2)
121 {
122         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
123         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
124         return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
125 }
126
127 int GroupchangeUserListName(const void *vUser1, const void *vUser2)
128 {
129         UserListEntry *u1 = (UserListEntry*) vUser1;
130         UserListEntry *u2 = (UserListEntry*) vUser2;
131         return ChrPtr(u2->UserName)[0] != ChrPtr(u1->UserName)[0];
132 }
133
134 /*
135  * Sort by access level
136  */
137 int CompareAccessLevel(const void *vUser1, const void *vUser2)
138 {
139         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
140         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
141
142         return (u1->AccessLevel > u2->AccessLevel);
143 }
144
145 int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
146 {
147         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
148         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
149
150         return (u2->AccessLevel > u1->AccessLevel);
151 }
152
153 int GroupchangeAccessLevel(const void *vUser1, const void *vUser2)
154 {
155         UserListEntry *u1 = (UserListEntry*) vUser1;
156         UserListEntry *u2 = (UserListEntry*) vUser2;
157
158         return u2->AccessLevel != u1->AccessLevel;
159 }
160
161 /*
162  * Sort by UID
163  */
164 int CompareUID(const void *vUser1, const void *vUser2)
165 {
166         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
167         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
168
169         return (u1->UID > u2->UID);
170 }
171
172 int CompareUIDRev(const void *vUser1, const void *vUser2)
173 {
174         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
175         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
176
177         return (u2->UID > u1->UID);
178 }
179
180 int GroupchangeUID(const void *vUser1, const void *vUser2)
181 {
182         UserListEntry *u1 = (UserListEntry*) vUser1;
183         UserListEntry *u2 = (UserListEntry*) vUser2;
184
185         return (u2->UID / 10) != (u1->UID / 10);
186 }
187
188 /*
189  * Sort By Date /// TODO!
190  */
191 int CompareLastLogon(const void *vUser1, const void *vUser2)
192 {
193         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
194         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
195
196         return (u1->LastLogonT > u2->LastLogonT);
197 }
198
199 int CompareLastLogonRev(const void *vUser1, const void *vUser2)
200 {
201         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
202         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
203
204         return (u2->LastLogonT > u1->LastLogonT);
205 }
206
207 int GroupchangeLastLogon(const void *vUser1, const void *vUser2)
208 {
209         UserListEntry *u1 = (UserListEntry*) vUser1;
210         UserListEntry *u2 = (UserListEntry*) vUser2;
211
212         return (u2->LastLogonT != u1->LastLogonT);
213 }
214
215 /*
216  * Sort By Number of Logons
217  */
218 int ComparenLogons(const void *vUser1, const void *vUser2)
219 {
220         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
221         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
222
223         return (u1->nLogons > u2->nLogons);
224 }
225
226 int ComparenLogonsRev(const void *vUser1, const void *vUser2)
227 {
228         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
229         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
230
231         return (u2->nLogons > u1->nLogons);
232 }
233
234 int GroupchangenLogons(const void *vUser1, const void *vUser2)
235 {
236         UserListEntry *u1 = (UserListEntry*) vUser1;
237         UserListEntry *u2 = (UserListEntry*) vUser2;
238
239         return (u2->nLogons / 100) != (u1->nLogons / 100);
240 }
241
242 /*
243  * Sort By Number of Posts
244  */
245 int ComparenPosts(const void *vUser1, const void *vUser2)
246 {
247         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
248         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
249
250         return (u1->nPosts > u2->nPosts);
251 }
252
253 int ComparenPostsRev(const void *vUser1, const void *vUser2)
254 {
255         UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
256         UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
257
258         return (u2->nPosts > u1->nPosts);
259 }
260
261 int GroupchangenPosts(const void *vUser1, const void *vUser2)
262 {
263         UserListEntry *u1 = (UserListEntry*) vUser1;
264         UserListEntry *u2 = (UserListEntry*) vUser2;
265
266         return (u2->nPosts / 100) != (u1->nPosts / 100);
267 }
268
269
270 HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
271 {
272         int Done = 0;
273         CompareFunc SortIt;
274         HashList *Hash = NULL;
275         StrBuf *Buf;
276         UserListEntry* ul;
277         int len;
278         int UID;
279         void *vData;
280         WCTemplputParams SubTP;
281
282         memset(&SubTP, 0, sizeof(WCTemplputParams));    
283         serv_puts("LIST");
284         Buf = NewStrBuf();
285         StrBuf_ServGetln(Buf);
286         if (GetServerStatus(Buf, NULL) == 1) {
287                 Hash = NewHash(1, Flathash);
288
289                 while (!Done) {
290                         len = StrBuf_ServGetln(Buf);
291                         if ((len <0) || 
292                             ((len == 3) &&
293                              !strcmp(ChrPtr(Buf), "000")))
294                         {
295                                 Done = 1;
296                                 break;
297                         }
298                         ul = NewUserListEntry(Buf);
299                         if (ul == NULL)
300                                 continue;
301
302                         Put(Hash, IKEY(ul->UID), ul, DeleteUserListEntry); 
303                 }
304
305                 serv_puts("LBIO 1");
306                 StrBuf_ServGetln(Buf);
307                 if (GetServerStatus(Buf, NULL) == 1)
308                         Done = 0;
309                         while (!Done) {
310                         len = StrBuf_ServGetln(Buf);
311                         if ((len <0) || 
312                             ((len == 3) &&
313                              !strcmp(ChrPtr(Buf), "000")))
314                         {
315                                 Done = 1;
316                                 break;
317                         }
318                         UID = atoi(ChrPtr(Buf));
319                         if (GetHash(Hash, IKEY(UID), &vData) && vData != 0)
320                         {
321                                 ul = (UserListEntry*)vData;
322                                 ul->HasBio = 1;
323                         }
324                 }
325                 SubTP.Filter.ContextType = CTX_USERLIST;
326                 SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
327                 if (SortIt != NULL)
328                         SortByPayload(Hash, SortIt);
329                 else 
330                         SortByPayload(Hash, CompareUID);
331         }
332         FreeStrBuf(&Buf);
333         return Hash;
334 }
335
336
337 void tmplput_USERLIST_UserName(StrBuf *Target, WCTemplputParams *TP)
338 {
339         UserListEntry *ul = (UserListEntry*) CTX;
340         StrBufAppendTemplate(Target, TP, ul->UserName, 0);
341 }
342
343 void tmplput_USERLIST_Password(StrBuf *Target, WCTemplputParams *TP)
344 {
345         UserListEntry *ul = (UserListEntry*) CTX;
346         StrBufAppendTemplate(Target, TP, ul->Passvoid, 0);
347 }
348
349 void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, WCTemplputParams *TP)
350 {
351         UserListEntry *ul = (UserListEntry*) CTX;
352
353         StrBufAppendPrintf(Target, "%d", ul->AccessLevel, 0);
354 }
355
356 void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, WCTemplputParams *TP)
357 {
358         UserListEntry *ul = (UserListEntry*) CTX;
359         
360         StrBufAppendBufPlain(Target, _(axdefs[ul->AccessLevel]), -1, 0);
361 }
362
363 void tmplput_USERLIST_UID(StrBuf *Target, WCTemplputParams *TP)
364 {
365         UserListEntry *ul = (UserListEntry*) CTX;
366
367         StrBufAppendPrintf(Target, "%d", ul->UID, 0);
368 }
369
370 void tmplput_USERLIST_LastLogonNo(StrBuf *Target, WCTemplputParams *TP)
371 {
372         UserListEntry *ul = (UserListEntry*) CTX;
373
374         StrBufAppendPrintf(Target,"%ld", ul->LastLogonT, 0);
375 }
376 void tmplput_USERLIST_LastLogonStr(StrBuf *Target, WCTemplputParams *TP)
377 {
378         UserListEntry *ul = (UserListEntry*) CTX;
379         StrEscAppend(Target, NULL, asctime(localtime(&ul->LastLogonT)), 0, 0);
380 }
381
382 void tmplput_USERLIST_nLogons(StrBuf *Target, WCTemplputParams *TP)
383 {
384         UserListEntry *ul = (UserListEntry*) CTX;
385
386         StrBufAppendPrintf(Target, "%d", ul->nLogons, 0);
387 }
388
389 void tmplput_USERLIST_nPosts(StrBuf *Target, WCTemplputParams *TP)
390 {
391         UserListEntry *ul = (UserListEntry*) CTX;
392
393         StrBufAppendPrintf(Target, "%d", ul->nPosts, 0);
394 }
395
396 void tmplput_USERLIST_Flags(StrBuf *Target, WCTemplputParams *TP)
397 {
398         UserListEntry *ul = (UserListEntry*) CTX;
399
400         StrBufAppendPrintf(Target, "%d", ul->Flags, 0);
401 }
402
403 void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, WCTemplputParams *TP)
404 {
405         UserListEntry *ul = (UserListEntry*) CTX;
406
407         StrBufAppendPrintf(Target, "%d", ul->DaysTillPurge, 0);
408 }
409
410 int ConditionalUser(StrBuf *Target, WCTemplputParams *TP)
411 {
412         UserListEntry *ul = (UserListEntry*) CTX;
413         if (havebstr("usernum")) {
414                 return ibstr("usernum") == ul->UID;
415         }
416         else if (havebstr("username")) {
417                 return strcmp(bstr("username"), ChrPtr(ul->UserName)) == 0;
418         }
419         else 
420                 return 0;
421 }
422
423 int ConditionalFlagINetEmail(StrBuf *Target, WCTemplputParams *TP)
424 {
425         UserListEntry *ul = (UserListEntry*) CTX;
426         return (ul->Flags & US_INTERNET) != 0;
427 }
428
429 int ConditionalUserAccess(StrBuf *Target, WCTemplputParams *TP)
430 {
431         UserListEntry *ul = (UserListEntry*) CTX;
432         
433         if (ul == NULL)
434                 return 0;
435
436         return GetTemplateTokenNumber(Target, 
437                                       TP, 
438                                       3, 
439                                       AxNewU)
440                 ==
441                 ul->AccessLevel;
442 }
443 int ConditionalHaveBIO(StrBuf *Target, WCTemplputParams *TP)
444 {
445         UserListEntry *ul = (UserListEntry*) CTX;
446         
447         if (ul == NULL)
448                 return 0;
449         return ul->HasBio;
450 }
451
452 void tmplput_USER_BIO(StrBuf *Target, WCTemplputParams *TP)
453 {
454         int Done = 0;
455         StrBuf *Buf;
456         const char *who;
457         long len;
458
459         GetTemplateTokenString(Target, TP, 0, &who, &len);
460
461         Buf = NewStrBuf();
462         serv_printf("RBIO %s", who);
463         StrBuf_ServGetln(Buf);
464         if (GetServerStatus(Buf, NULL) == 1) {
465                 StrBuf *BioBuf = NewStrBufPlain(NULL, SIZ);
466                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
467                         if ( (StrLength(Buf)==3) && 
468                              !strcmp(ChrPtr(Buf), "000")) 
469                                 Done = 1;
470                         else
471                                 StrBufAppendBuf(BioBuf, Buf, 0);
472                 }
473                 StrBufAppendTemplate(Target, TP, BioBuf, 1);
474                 FreeStrBuf(&BioBuf);
475         }
476         FreeStrBuf(&Buf);
477 }
478
479 int Conditional_USER_HAS_PIC(StrBuf *Target, WCTemplputParams *TP)
480 {
481         StrBuf *Buf;
482         const char *who;
483         long len;
484
485         GetTemplateTokenString(Target, TP, 2, &who, &len);
486
487         Buf = NewStrBuf();
488         serv_printf("OIMG _userpic_|%s", who);
489         StrBuf_ServGetln(Buf);
490         if (GetServerStatus(Buf, NULL) != 2) {
491                 serv_puts("CLOS");
492                 StrBuf_ServGetln(Buf);
493                 GetServerStatus(Buf, NULL);
494                 FreeStrBuf(&Buf);
495                 return 1;
496         } else {
497                 FreeStrBuf(&Buf);
498                 return 0;
499         }
500 }
501
502
503 /*
504  *  Locate the message number of a user's vCard in the current room
505  *  Returns the message id of his vcard
506  */
507 long locate_user_vcard_in_this_room(message_summary **VCMsg, wc_mime_attachment **VCAtt)
508 {
509         wcsession *WCC = WC;
510         HashPos *at;
511         HashPos *att;
512         const char *HashKey;
513         long HKLen;
514         void *vMsg;
515         message_summary *Msg;
516         wc_mime_attachment *Att;
517         StrBuf *Buf;
518         long vcard_msgnum = (-1L);
519         int already_tried_creating_one = 0;
520         StrBuf *FoundCharset = NewStrBuf();
521         StrBuf *Error = NULL;
522         SharedMessageStatus Stat;
523
524
525         Buf = NewStrBuf();
526 TRYAGAIN:
527         memset(&Stat, 0, sizeof(SharedMessageStatus));
528         Stat.maxload = 10000;
529         Stat.lowest_found = (-1);
530         Stat.highest_found = (-1);
531         /* Search for the user's vCard */
532         if (load_msg_ptrs("MSGS ALL||||1", &Stat, NULL) > 0) {
533                 at = GetNewHashPos(WCC->summ, 0);
534                 while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
535                         Msg = (message_summary*) vMsg;          
536                         Msg->MsgBody =  (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
537                         memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
538                         Msg->MsgBody->msgnum = Msg->msgnum;
539
540                         load_message(Msg, FoundCharset, &Error);
541                         
542                         if (Msg->AllAttach != NULL) {
543                                 att = GetNewHashPos(Msg->AllAttach, 0);
544                                 while (GetNextHashPos(Msg->AllAttach, att, &HKLen, &HashKey, &vMsg) && 
545                                        (vcard_msgnum == -1)) {
546                                         Att = (wc_mime_attachment*) vMsg;
547                                         if (
548                                                 (strcasecmp(ChrPtr(Att->ContentType), "text/x-vcard") == 0)
549                                                 || (strcasecmp(ChrPtr(Att->ContentType), "text/vcard") == 0)
550                                         ) {
551                                                 *VCAtt = Att;
552                                                 *VCMsg = Msg;
553                                                 vcard_msgnum = Msg->msgnum;
554                                                 if (Att->Data == NULL) {
555                                                         MimeLoadData(Att);
556                                                 }
557                                         }
558                                 }
559                                 DeleteHashPos(&att);
560                         }
561                         FreeStrBuf(&Error);     /* don't care... */
562                         
563                 }
564                 DeleteHashPos(&at);             
565         }
566
567         /* If there's no vcard, create one */
568         if ((*VCMsg == NULL) && (already_tried_creating_one == 0)) {
569                 FlushStrBuf(Buf);
570                 already_tried_creating_one = 1;
571                 serv_puts("ENT0 1|||4");
572                 StrBuf_ServGetln(Buf);
573                 if (GetServerStatus(Buf, NULL) == 4) {
574                         serv_puts("Content-type: text/x-vcard");
575                         serv_puts("");
576                         serv_puts("begin:vcard");
577                         serv_puts("end:vcard");
578                         serv_puts("000");
579                 }
580                 else 
581                         syslog(1, "Error while creating user vcard: %s\n", ChrPtr(Buf));
582                 goto TRYAGAIN;
583         }
584         FreeStrBuf(&Buf);
585         FreeStrBuf(&FoundCharset);
586
587         return(vcard_msgnum);
588 }
589
590
591 /*
592  *  Display the form for editing a user's address book entry
593  *  username the name of the user
594  *  usernum the citadel-uid of the user
595  */
596 void display_edit_address_book_entry(const char *username, long usernum) {
597         wcsession *WCC = WC;
598         message_summary *VCMsg = NULL;
599         wc_mime_attachment *VCAtt = NULL;
600         StrBuf *roomname;
601         StrBuf *Buf;
602         long vcard_msgnum = (-1L);
603
604         /* Locate the user's config room, creating it if necessary */
605         Buf = NewStrBuf();
606         roomname = NewStrBuf();
607         StrBufPrintf(roomname, "%010ld.%s", usernum, USERCONFIGROOM);
608         serv_printf("GOTO %s||1", ChrPtr(roomname));
609         StrBuf_ServGetln(Buf);
610         if (GetServerStatus(Buf, NULL) != 2) {
611                 serv_printf("CRE8 1|%s|5|||1|", ChrPtr(roomname));
612                 StrBuf_ServGetln(Buf);
613                 GetServerStatus(Buf, NULL);
614                 serv_printf("GOTO %s||1", ChrPtr(roomname));
615                 StrBuf_ServGetln(Buf);
616                 if (GetServerStatus(Buf, NULL) != 2) {
617                         FlushStrBuf(WCC->ImportantMsg);
618                         StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);
619                         select_user_to_edit(username);
620                         FreeStrBuf(&Buf);
621                         FreeStrBuf(&roomname);
622                         return;
623                 }
624         }
625         FreeStrBuf(&Buf);
626
627         locate_user_vcard_in_this_room(&VCMsg, &VCAtt);
628
629         if (VCMsg == NULL) {
630                 StrBufPlain(WCC->ImportantMsg, 
631                             _("An error occurred while trying to create or edit this address book entry."), 
632                             0);
633                 select_user_to_edit(username);
634                 FreeStrBuf(&roomname);
635                 return;
636         }
637
638         do_edit_vcard(vcard_msgnum, "1", 
639                       VCMsg,
640                       VCAtt,
641                       "select_user_to_edit", 
642                       ChrPtr(roomname));
643         FreeStrBuf(&roomname);
644 }
645
646 /*
647  *  burge a user 
648  *  username the name of the user to remove
649  */
650 void delete_user(char *username) {
651         wcsession *WCC = WC;
652         StrBuf *Buf;
653         
654         Buf = NewStrBuf();
655         serv_printf("ASUP %s|0|0|0|0|0|", username);
656         StrBuf_ServGetln(Buf);
657         if (GetServerStatus(Buf, NULL) != 2) 
658                 StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);
659
660         select_user_to_edit( bstr("username"));
661         FreeStrBuf(&Buf);
662 }
663                 
664
665 void display_edituser(const char *supplied_username, int is_new) {
666         const char *Pos;
667         wcsession *WCC = WC;
668         UserListEntry* UL;
669         StrBuf *Buf;
670         char username[256];
671
672         if (supplied_username != NULL) {
673                 safestrncpy(username, supplied_username, sizeof username);
674         }
675         else {
676                 safestrncpy(username, bstr("username"), sizeof username);
677         }
678
679         Buf = NewStrBuf();
680         serv_printf("AGUP %s", username);
681         StrBuf_ServGetln(Buf);
682         if (GetServerStatus(Buf, NULL) != 2) {
683                 FlushStrBuf(WCC->ImportantMsg);
684                 StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);
685                 select_user_to_edit(username);
686                 FreeStrBuf(&Buf);
687                 return;
688         }
689         else {
690                 Pos = ChrPtr(Buf) + 4;
691                 UL = NewUserListOneEntry(Buf, Pos);
692                 if ((UL != NULL) && havebstr("edit_abe_button")) {
693                         display_edit_address_book_entry(username, UL->UID);
694                 }
695                 else if ((UL != NULL) && havebstr("delete_button")) {
696                         delete_user(username);
697                 }
698                 else if (UL != NULL) {
699                         WCTemplputParams SubTP;
700                         memset(&SubTP, 0, sizeof(WCTemplputParams));
701                         SubTP.Filter.ContextType = CTX_USERLIST;
702                         SubTP.Context = UL;
703                         output_headers(1, 0, 0, 0, 1, 0);
704                         DoTemplate(HKEY("aide_edituser_detailview"), NULL, &SubTP);
705                         end_burst();
706                 }
707                 DeleteUserListEntry(UL);
708                 
709         }
710         FreeStrBuf(&Buf);
711 }
712
713 /*
714  *  do the backend operation of the user edit on the server
715  */
716 void edituser(void) {
717         wcsession *WCC = WC;
718         int is_new = 0;
719         unsigned int flags = 0;
720         const char *username;
721
722         is_new = ibstr("is_new");
723         username = bstr("username");
724
725         if (!havebstr("ok_button")) {
726                 StrBufPlain(WCC->ImportantMsg, _("Changes were not saved."), -1);
727         }       
728         else {
729                 StrBuf *Buf = NewStrBuf();
730
731                 flags = ibstr("flags");
732                 if (yesbstr("inetmail")) {
733                         flags |= US_INTERNET;
734                 }
735                 else {
736                         flags &= ~US_INTERNET ;
737                 }
738
739                 if ((havebstr("newname")) && (strcasecmp(bstr("username"), bstr("newname")))) {
740                         serv_printf("RENU %s|%s", bstr("username"), bstr("newname"));
741                         StrBuf_ServGetln(Buf);
742                         if (GetServerStatus(Buf, NULL) == 2) {
743                                 FlushStrBuf(WCC->ImportantMsg);
744                                 StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);                             
745                         }
746                         else {
747                                 username = bstr("newname");
748                         }
749                 }
750
751                 serv_printf("ASUP %s|%s|%d|%s|%s|%s|%s|%s|%s|",
752                         username,
753                         bstr("password"),
754                         flags,
755                         bstr("timescalled"),
756                         bstr("msgsposted"),
757                         bstr("axlevel"),
758                         bstr("usernum"),
759                         bstr("lastcall"),
760                         bstr("purgedays")
761                 );
762                 StrBuf_ServGetln(Buf);
763                 if (GetServerStatus(Buf, NULL) == 2) {
764                         StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);
765                 }
766                 FreeStrBuf(&Buf);
767         }
768
769         /*
770          * If we are in the middle of creating a new user, move on to
771          * the vCard edit screen.
772          */
773         if (is_new) {
774                 display_edit_address_book_entry(username, lbstr("usernum") );
775         }
776         else {
777                 select_user_to_edit(username);
778         }
779 }
780
781
782
783 /*
784  *  create a new user
785  * take the web environment username and create it on the citadel server
786  */
787 void create_user(void) {
788         wcsession *WCC = WC;
789         long FullState;
790         StrBuf *Buf;
791         const char *username;
792
793         Buf = NewStrBuf();
794         username = bstr("username");
795         serv_printf("CREU %s", username);
796         StrBuf_ServGetln(Buf);
797         if (GetServerStatus(Buf, &FullState) == 2) {
798                 sprintf(WC->ImportantMessage, _("A new user has been created."));
799                 display_edituser(username, 1);
800         }
801         else if (FullState == 570) {
802                 StrBufPlain(WCC->ImportantMsg, 
803                             _("You are attempting to create a new user from within Citadel "
804                               "while running in host based authentication mode.  In this mode, "
805                               "you must create new users on the host system, not within Citadel."), 
806                             0);
807                 select_user_to_edit(NULL);
808         }
809         else {
810                 StrBufAppendBuf(WCC->ImportantMsg, Buf, 4);
811                 select_user_to_edit(NULL);
812         }
813         FreeStrBuf(&Buf);
814 }
815
816
817 void _select_user_to_edit(void) {
818         select_user_to_edit(NULL);
819 }
820
821
822 void _display_edituser(void) {
823         display_edituser(NULL, 0);
824 }
825
826 void showuser(void)
827 {
828         output_headers(1, 0, 0, 0, 1, 0);
829         do_template("user_show");
830         end_burst();
831 }
832
833
834 void 
835 InitModule_USEREDIT
836 (void)
837 {
838         WebcitAddUrlHandler(HKEY("showuser"), "", 0, showuser, 0);
839         WebcitAddUrlHandler(HKEY("select_user_to_edit"), "", 0, _select_user_to_edit, 0);
840         WebcitAddUrlHandler(HKEY("display_edituser"), "", 0, _display_edituser, 0);
841         WebcitAddUrlHandler(HKEY("edituser"), "", 0, edituser, 0);
842         WebcitAddUrlHandler(HKEY("create_user"), "", 0, create_user, 0);
843
844         RegisterNamespace("USERLIST:USERNAME",      0, 1, tmplput_USERLIST_UserName, NULL, CTX_USERLIST);
845         RegisterNamespace("USERLIST:PASSWD",        0, 1, tmplput_USERLIST_Password, NULL, CTX_USERLIST);
846         RegisterNamespace("USERLIST:ACCLVLNO",      0, 0, tmplput_USERLIST_AccessLevelNo, NULL, CTX_USERLIST);
847         RegisterNamespace("USERLIST:ACCLVLSTR",     0, 0, tmplput_USERLIST_AccessLevelStr, NULL, CTX_USERLIST);
848         RegisterNamespace("USERLIST:UID",           0, 0, tmplput_USERLIST_UID, NULL, CTX_USERLIST);
849         RegisterNamespace("USERLIST:LASTLOGON:STR", 0, 0, tmplput_USERLIST_LastLogonStr, NULL, CTX_USERLIST);
850         RegisterNamespace("USERLIST:LASTLOGON:NO",  0, 0, tmplput_USERLIST_LastLogonNo, NULL, CTX_USERLIST);
851         RegisterNamespace("USERLIST:NLOGONS",       0, 0, tmplput_USERLIST_nLogons, NULL, CTX_USERLIST);
852         RegisterNamespace("USERLIST:NPOSTS",        0, 0, tmplput_USERLIST_nPosts, NULL, CTX_USERLIST);
853                                                     
854         RegisterNamespace("USERLIST:FLAGS",         0, 0, tmplput_USERLIST_Flags, NULL, CTX_USERLIST);
855         RegisterNamespace("USERLIST:DAYSTILLPURGE", 0, 0, tmplput_USERLIST_DaysTillPurge, NULL, CTX_USERLIST);
856
857         RegisterNamespace("USER:BIO", 1, 2, tmplput_USER_BIO,  NULL, CTX_NONE);
858
859         RegisterConditional(HKEY("COND:USERNAME"),  0,    ConditionalUser, CTX_USERLIST);
860         RegisterConditional(HKEY("COND:USERACCESS"), 0,   ConditionalUserAccess, CTX_USERLIST);
861         RegisterConditional(HKEY("COND:USERLIST:FLAG:USE_INTERNET"), 0, ConditionalFlagINetEmail, CTX_USERLIST);
862         RegisterConditional(HKEY("COND:USERLIST:HAVEBIO"), 0, ConditionalHaveBIO, CTX_USERLIST);
863
864         RegisterConditional(HKEY("COND:USER:PIC"), 1, Conditional_USER_HAS_PIC,  CTX_NONE);
865
866         RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
867         
868
869
870         RegisterSortFunc(HKEY("user:name"),
871                          HKEY("userlist"),
872                          CompareUserListName,
873                          CompareUserListNameRev,
874                          GroupchangeUserListName,
875                          CTX_USERLIST);
876         RegisterSortFunc(HKEY("user:accslvl"),
877                          HKEY("userlist"),
878                          CompareAccessLevel,
879                          CompareAccessLevelRev,
880                          GroupchangeAccessLevel,
881                          CTX_USERLIST);
882
883         RegisterSortFunc(HKEY("user:nlogons"),
884                          HKEY("userlist"),
885                          ComparenLogons,
886                          ComparenLogonsRev,
887                          GroupchangenLogons,
888                          CTX_USERLIST);
889
890         RegisterSortFunc(HKEY("user:uid"),
891                          HKEY("userlist"),
892                          CompareUID,
893                          CompareUIDRev,
894                          GroupchangeUID,
895                          CTX_USERLIST);
896
897         RegisterSortFunc(HKEY("user:lastlogon"),
898                          HKEY("userlist"),
899                          CompareLastLogon,
900                          CompareLastLogonRev,
901                          GroupchangeLastLogon,
902                          CTX_USERLIST);
903
904         RegisterSortFunc(HKEY("user:nmsgposts"),
905                          HKEY("userlist"),
906                          ComparenPosts,
907                          ComparenPostsRev,
908                          GroupchangenPosts,
909                          CTX_USERLIST);
910
911         REGISTERTokenParamDefine(AxDeleted);
912         REGISTERTokenParamDefine(AxNewU);
913         REGISTERTokenParamDefine(AxProbU);
914         REGISTERTokenParamDefine(AxLocU);
915         REGISTERTokenParamDefine(AxNetU);
916         REGISTERTokenParamDefine(AxPrefU);
917         REGISTERTokenParamDefine(AxAideU);
918 }
919