]> code.citadel.org Git - citadel.git/blobdiff - webcit/useredit.c
* use load_message in the useredit form
[citadel.git] / webcit / useredit.c
index ca9bf2045eb1102227755fbed07e82c6b582a6a5..02aea240ea596d133049299a0a32907da2bcbb02 100644 (file)
@@ -11,7 +11,7 @@
  *  message the header message???
  *  preselect which user should be selected in the browser
  */
-void select_user_to_edit(char *message, char *preselect)
+void select_user_to_edit(const char *message, const char *preselect)
 {
        output_headers(1, 0, 0, 0, 1, 0);
        do_template("edituser_select", NULL);
@@ -60,6 +60,7 @@ UserListEntry* NewUserListOneEntry(StrBuf *SerializedUser)
 void DeleteUserListEntry(void *vUserList)
 {
        UserListEntry *ul = (UserListEntry*) vUserList;
+       if (!ul) return;
        FreeStrBuf(&ul->UserName);
        FreeStrBuf(&ul->Passvoid);
        free(ul);
@@ -93,16 +94,22 @@ UserListEntry* NewUserListEntry(StrBuf *SerializedUserList)
  */
 int CompareUserListName(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName));
 }
 int CompareUserListNameRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+       return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
+}
+int GroupchangeUserListName(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
-       return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
+       return ChrPtr(u2->UserName)[0] != ChrPtr(u1->UserName)[0];
 }
 
 /*
@@ -110,17 +117,24 @@ int CompareUserListNameRev(const void *vUser1, const void *vUser2)
  */
 int CompareAccessLevel(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->AccessLevel > u2->AccessLevel);
 }
 int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->AccessLevel > u1->AccessLevel);
+}
+int GroupchangeAccessLevel(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->AccessLevel > u1->AccessLevel);
+       return u2->AccessLevel != u1->AccessLevel;
 }
 
 
@@ -129,17 +143,24 @@ int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
  */
 int CompareUID(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->UID > u2->UID);
 }
 int CompareUIDRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->UID > u1->UID);
+}
+int GroupchangeUID(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->UID > u1->UID);
+       return (u2->UID / 10) != (u1->UID / 10);
 }
 
 /*
@@ -147,17 +168,24 @@ int CompareUIDRev(const void *vUser1, const void *vUser2)
  */
 int CompareLastLogon(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->LastLogonT > u2->LastLogonT);
 }
 int CompareLastLogonRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->LastLogonT > u1->LastLogonT);
+}
+int GroupchangeLastLogon(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->LastLogonT > u1->LastLogonT);
+       return (u2->LastLogonT != u1->LastLogonT);
 }
 
 /*
@@ -165,17 +193,24 @@ int CompareLastLogonRev(const void *vUser1, const void *vUser2)
  */
 int ComparenLogons(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->nLogons > u2->nLogons);
 }
 int ComparenLogonsRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->nLogons > u1->nLogons);
+}
+int GroupchangenLogons(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->nLogons > u1->nLogons);
+       return (u2->nLogons / 100) != (u1->nLogons / 100);
 }
 
 /*
@@ -183,39 +218,53 @@ int ComparenLogonsRev(const void *vUser1, const void *vUser2)
  */
 int ComparenPosts(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->nPosts > u2->nPosts);
 }
 int ComparenPostsRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->nPosts > u1->nPosts);
+}
+int GroupchangenPosts(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->nPosts > u1->nPosts);
+       return (u2->nPosts / 100) != (u1->nPosts / 100);
 }
 
 
-HashList *iterate_load_userlist(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
 {
+       int Done = 0;
+       CompareFunc SortIt;
        HashList *Hash;
-       char buf[SIZ];
        StrBuf *Buf;
        UserListEntry* ul;
        char nnn[64];
        int nUsed;
-       int Order;
        int len;
-       
+       WCTemplputParams SubTP;
+
+       memset(&SubTP, 0, sizeof(WCTemplputParams));    
         serv_puts("LIST");
-        serv_getln(buf, sizeof buf);
-        if (buf[0] == '1') {
+       Buf = NewStrBuf();
+       StrBuf_ServGetlnBuffered(Buf);
+       if (GetServerStatus(Buf, NULL) == 1) {
                Hash = NewHash(1, NULL);
 
-               Buf = NewStrBuf();
-               while ((len = StrBuf_ServGetln(Buf),
-                       strcmp(ChrPtr(Buf), "000"))) {
+               while (!Done) {
+                       len = StrBuf_ServGetlnBuffered(Buf);
+                       if ((len == 3) &&
+                           (strcmp(ChrPtr(Buf), "000")==0)) {
+                               Done = 1;
+                               break;
+                       }
                        ul = NewUserListEntry(Buf);
                        if (ul == NULL)
                                continue;
@@ -223,121 +272,95 @@ HashList *iterate_load_userlist(StrBuf *Target, int nArgs, WCTemplateToken *Toke
                        nUsed = snprintf(nnn, sizeof(nnn), "%d", nUsed+1);
                        Put(Hash, nnn, nUsed, ul, DeleteUserListEntry); 
                }
-               FreeStrBuf(&Buf);
-               Order = ibstr("SortOrder");
-               switch (ibstr("SortBy")){
-               case 1: /*NAME*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareUserListName:
-                                     CompareUserListNameRev);
-                       break;
-               case 2: /*AccessLevel*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareAccessLevel:
-                                     CompareAccessLevelRev);
-                       break;
-               case 3: /*nLogons*/
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenLogons:
-                                     ComparenLogonsRev);
-                       break;
-               case 4: /*UID*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareUID:
-                                     CompareUIDRev);
-                       break;
-               case 5: /*LastLogon*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareLastLogon:
-                                     CompareLastLogonRev);
-                       break;
-               case 6: /* nLogons */
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenLogons:
-                                     ComparenLogonsRev);
-                       break;
-               case 7: /* Posts */
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenPosts:
-                                     ComparenPostsRev);
-                       break;
-               }
+               SubTP.Filter.ContextType = CTX_USERLIST;
+               SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
+               if (SortIt != NULL)
+                       SortByPayload(Hash, SortIt);
+               else 
+                       SortByPayload(Hash, CompareUID);
                return Hash;
         }
+       FreeStrBuf(&Buf);
        return NULL;
 }
 
 
-void tmplput_USERLIST_UserName(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_UserName(StrBuf *Target, WCTemplputParams *TP)
+{
+       UserListEntry *ul = (UserListEntry*) CTX;
+       StrBufAppendTemplate(Target, TP, ul->UserName, 0);
+}
+
+void tmplput_USERLIST_Password(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
-       StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, ul->UserName, 0);
+       UserListEntry *ul = (UserListEntry*) CTX;
+       StrBufAppendTemplate(Target, TP, ul->Passvoid, 0);
 }
 
-void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->AccessLevel, 0);
 }
 
-void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
        
        StrBufAppendBufPlain(Target, _(axdefs[ul->AccessLevel]), -1, 0);
 }
 
-void tmplput_USERLIST_UID(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_UID(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->UID, 0);
 }
 
-void tmplput_USERLIST_LastLogonNo(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_LastLogonNo(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target,"%ld", ul->LastLogonT, 0);
 }
-void tmplput_USERLIST_LastLogonStr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_LastLogonStr(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
        StrEscAppend(Target, NULL, asctime(localtime(&ul->LastLogonT)), 0, 0);
 }
 
-void tmplput_USERLIST_nLogons(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_nLogons(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->nLogons, 0);
 }
 
-void tmplput_USERLIST_nPosts(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_nPosts(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->nPosts, 0);
 }
 
-void tmplput_USERLIST_Flags(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_Flags(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->Flags, 0);
 }
 
-void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
        StrBufAppendPrintf(Target, "%d", ul->DaysTillPurge, 0);
 }
 
-int ConditionalUser(WCTemplateToken *Tokens, void *Context, int ContextType)
+int ConditionalUser(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
        if (havebstr("usernum")) {
                return ibstr("usernum") == ul->UID;
        }
@@ -348,82 +371,87 @@ int ConditionalUser(WCTemplateToken *Tokens, void *Context, int ContextType)
                return 0;
 }
 
-int ConditionalFlagINetEmail(WCTemplateToken *Tokens, void *Context, int ContextType)
+int ConditionalFlagINetEmail(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
        return (ul->Flags & US_INTERNET) != 0;
 }
 
-int ConditionalUserAccess(WCTemplateToken *Tokens, void *Context, int ContextType)
+int ConditionalUserAccess(StrBuf *Target, WCTemplputParams *TP)
 {
-       UserListEntry *ul = (UserListEntry*) Context;
+       UserListEntry *ul = (UserListEntry*) CTX;
 
-       if (Tokens->Params[3]->Type == TYPE_LONG)
-               return (Tokens->Params[3]->lvalue == ul->AccessLevel);
+       if (TP->Tokens->Params[3]->Type == TYPE_LONG)
+               return (TP->Tokens->Params[3]->lvalue == ul->AccessLevel);
        else
                return 0;
 }
 
-/**
+/*
  *  Locate the message number of a user's vCard in the current room
- *  username the plaintext name of the user
- *  usernum the number of the user on the citadel server
- * \return the message id of his vcard
+ *  Returns the message id of his vcard
  */
-long locate_user_vcard(char *username, long usernum) {
-       char buf[SIZ];
-       long vcard_msgnum = (-1L);
-       char content_type[SIZ];
-       char partnum[SIZ];
-       int already_tried_creating_one = 0;
+long locate_user_vcard_in_this_room(message_summary **VCMsg,
+                                   wc_mime_attachment **VCAtt)
+{
+       wcsession *WCC = WC;
+       HashPos *at;
+       HashPos *att;
+       const char *HashKey;
+       long HKLen;
+       void *vMsg;
+       message_summary *Msg;
+       wc_mime_attachment *Att;
 
-       struct stuff_t {
-               struct stuff_t *next;
-               long msgnum;
-       };
 
-       struct stuff_t *stuff = NULL;
-       struct stuff_t *ptr;
+       int Done;
+       StrBuf *Buf;
+       long vcard_msgnum = (-1L);
+       int already_tried_creating_one = 0;
+       StrBuf *FoundCharset = NewStrBuf();
+       StrBuf *Error = NULL;
 
+       
+       Buf = NewStrBuf();
 TRYAGAIN:
+       Done = 0;
        /** Search for the user's vCard */
-       serv_puts("MSGS ALL");
-       serv_getln(buf, sizeof buf);
-       if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
-               ptr = malloc(sizeof(struct stuff_t));
-               ptr->msgnum = atol(buf);
-               ptr->next = stuff;
-               stuff = ptr;
-       }
-
-       /** Iterate through the message list looking for vCards */
-       while (stuff != NULL) {
-               serv_printf("MSG0 %ld|2", stuff->msgnum);
-               serv_getln(buf, sizeof buf);
-               if (buf[0]=='1') {
-                       while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
-                               if (!strncasecmp(buf, "part=", 5)) {
-                                       extract_token(partnum, &buf[5], 2, '|', sizeof partnum);
-                                       extract_token(content_type, &buf[5], 4, '|', sizeof content_type);
-                                       if (  (!strcasecmp(content_type, "text/x-vcard"))
-                                          || (!strcasecmp(content_type, "text/vcard")) ) {
-                                               vcard_msgnum = stuff->msgnum;
+       if (load_msg_ptrs("MSGS ALL||||1", 1) > 0) {
+               at = GetNewHashPos(WCC->summ, 0);
+               while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
+                       Msg = (message_summary*) vMsg;          
+                       Msg->MsgBody =  (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
+                       memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
+                       Msg->MsgBody->msgnum = Msg->msgnum;
+
+                       load_message(Msg, 
+                                    FoundCharset,
+                                    &Error);
+                       
+                       if (Msg->AllAttach != NULL) {
+                               att = GetNewHashPos(Msg->AllAttach, 0);
+                               while (GetNextHashPos(Msg->AllAttach, att, &HKLen, &HashKey, &vMsg)) {
+                                       Att = (wc_mime_attachment*) vMsg;
+                                       if (  (strcasecmp(ChrPtr(Att->ContentType), "text/x-vcard") == 0) ||
+                                             (strcasecmp(ChrPtr(Att->ContentType), "text/vcard")   == 0) ) {
+                                               *VCAtt = Att;
+                                               *VCMsg = Msg;
+                                               if (Att->Data == NULL)
+                                                       MimeLoadData(Att);
                                        }
                                }
                        }
+                       FreeStrBuf(&Error); /*< don't care... */
+                       
                }
-
-               ptr = stuff->next;
-               free(stuff);
-               stuff = ptr;
+               DeleteHashPos(&at);             
        }
-
        /** If there's no vcard, create one */
-       if ((vcard_msgnum < 0) && (already_tried_creating_one == 0)) {
+       if ((*VCMsg == NULL) && (already_tried_creating_one == 0)) {
                already_tried_creating_one = 1;
                serv_puts("ENT0 1|||4");
-               serv_getln(buf, sizeof buf);
-               if (buf[0] == '4') {
+               StrBuf_ServGetlnBuffered(Buf);
+               if (GetServerStatus(Buf, NULL) != 4) {
                        serv_puts("Content-type: text/x-vcard");
                        serv_puts("");
                        serv_puts("begin:vcard");
@@ -432,7 +460,7 @@ TRYAGAIN:
                }
                goto TRYAGAIN;
        }
-
+       FreeStrBuf(&Buf);
        return(vcard_msgnum);
 }
 
@@ -442,50 +470,59 @@ TRYAGAIN:
  *  username the name of the user
  *  usernum the citadel-uid of the user
  */
-void display_edit_address_book_entry(char *username, long usernum) {
+void display_edit_address_book_entry(const char *username, long usernum) {
+       message_summary *VCMsg = NULL;
+       wc_mime_attachment *VCAtt = NULL;
        char roomname[SIZ];
-       char buf[SIZ];
+       StrBuf *Buf;
        char error_message[SIZ];
        long vcard_msgnum = (-1L);
 
        /** Locate the user's config room, creating it if necessary */
-       sprintf(roomname, "%010ld.%s", usernum, USERCONFIGROOM);
-       serv_printf("GOTO %s||1", roomname);
-       serv_getln(buf, sizeof buf);
-       if (buf[0] != '2') {
-               serv_printf("CRE8 1|%s|5|||1|", roomname);
-               serv_getln(buf, sizeof buf);
-               serv_printf("GOTO %s||1", roomname);
-               serv_getln(buf, sizeof buf);
-               if (buf[0] != '2') {
+       Buf = NewStrBuf();
+       serv_printf("GOTO %010ld.%s||1", usernum, USERCONFIGROOM);
+       StrBuf_ServGetlnBuffered(Buf);
+       if (GetServerStatus(Buf, NULL) != 2) {
+               serv_printf("CRE8 1|%010ld.%s|5|||1|", usernum, USERCONFIGROOM);
+               StrBuf_ServGetlnBuffered(Buf);
+               GetServerStatus(Buf, NULL);
+               serv_printf("GOTO %010ld.%s||1", usernum, USERCONFIGROOM);
+               StrBuf_ServGetlnBuffered(Buf);
+               if (GetServerStatus(Buf, NULL) != 2) {
+                       StrBufCutLeft(Buf, 4);
                        sprintf(error_message,
                                "<img src=\"static/error.gif\" align=center>"
-                               "%s<br /><br />\n", &buf[4]);
+                               "%s<br /><br />\n", ChrPtr(Buf));
                        select_user_to_edit(error_message, username);
+                       FreeStrBuf(&Buf);
                        return;
                }
        }
+       FreeStrBuf(&Buf);
 
-       vcard_msgnum = locate_user_vcard(username, usernum);
+       locate_user_vcard_in_this_room(&VCMsg, &VCAtt);
 
-       if (vcard_msgnum < 0) {
+       if (VCMsg == NULL) {
                sprintf(error_message,
                        "<img src=\"static/error.gif\" align=center>%s<br /><br />\n",
                        _("An error occurred while trying to create or edit this address book entry.")
-               );
+                       );
                select_user_to_edit(error_message, username);
                return;
        }
 
-       do_edit_vcard(vcard_msgnum, "1", "select_user_to_edit", roomname);
+       do_edit_vcard(vcard_msgnum, "1", 
+                     VCMsg,
+                     VCAtt,
+                     "select_user_to_edit", 
+                     roomname);
 }
 
 
-void display_edituser(char *supplied_username, int is_new) {
+void display_edituser(const char *supplied_username, int is_new) {
        UserListEntry* UL;
        StrBuf *Buf;
        char error_message[1024];
-       char MajorStatus;
        char username[256];
 
        if (supplied_username != NULL) {
@@ -497,11 +534,10 @@ void display_edituser(char *supplied_username, int is_new) {
 
        Buf = NewStrBuf();
        serv_printf("AGUP %s", username);
-       StrBuf_ServGetln(Buf);
-       MajorStatus = ChrPtr(Buf)[0];
-       StrBufCutLeft(Buf, 4);
-       if (MajorStatus != '2') {
-               ///TODO ImportantMessage
+       StrBuf_ServGetlnBuffered(Buf);
+       if (GetServerStatus(Buf, NULL) != 2) {
+               StrBufCutLeft(Buf, 4);
+               /*TODO ImportantMessage */
                sprintf(error_message,
                        "<img src=\"static/error.gif\" align=center>"
                        "%s<br /><br />\n", ChrPtr(Buf));
@@ -510,16 +546,21 @@ void display_edituser(char *supplied_username, int is_new) {
                return;
        }
        else {
+               StrBufCutLeft(Buf, 4);
                UL = NewUserListOneEntry(Buf);
-               if (havebstr("edit_abe_button")) {
+               if ((UL != NULL) && havebstr("edit_abe_button")) {
                        display_edit_address_book_entry(username, UL->UID);
                }
-               else if (havebstr("delete_button")) {
+               else if ((UL != NULL) && havebstr("delete_button")) {
                        delete_user(username);
                }
-               else {
+               else if (UL != NULL) {
+                       WCTemplputParams SubTP;
+                       memset(&SubTP, 0, sizeof(WCTemplputParams));
+                       SubTP.Filter.ContextType = CTX_USERLIST;
+                       SubTP.Context = UL;
                        output_headers(1, 0, 0, 0, 1, 0);
-                       DoTemplate(HKEY("userlist_detailview"), NULL, (void*) UL, CTX_USERLIST);
+                       DoTemplate(HKEY("userlist_detailview"), NULL, &SubTP);
                        end_burst();
                }
                DeleteUserListEntry(UL);
@@ -533,10 +574,9 @@ void display_edituser(char *supplied_username, int is_new) {
  */
 void edituser(void) {
        char message[SIZ];
-       char buf[SIZ];
        int is_new = 0;
        unsigned int flags = 0;
-       char *username;
+       const char *username;
 
        is_new = ibstr("is_new");
        safestrncpy(message, "", sizeof message);
@@ -544,9 +584,10 @@ void edituser(void) {
 
        if (!havebstr("ok_button")) {
                safestrncpy(message, _("Changes were not saved."), sizeof message);
-       }
-       
+       }       
        else {
+               StrBuf *Buf = NewStrBuf();
+
                flags = ibstr("flags");
                if (yesbstr("inetmail")) {
                        flags |= US_INTERNET;
@@ -557,11 +598,12 @@ void edituser(void) {
 
                if ((havebstr("newname")) && (strcasecmp(bstr("username"), bstr("newname")))) {
                        serv_printf("RENU %s|%s", bstr("username"), bstr("newname"));
-                       serv_getln(buf, sizeof buf);
-                       if (buf[0] != '2') {
+                       StrBuf_ServGetlnBuffered(Buf);
+                       if (GetServerStatus(Buf, NULL) == 2) {
+                               StrBufCutLeft(Buf, 4);
                                sprintf(&message[strlen(message)],
                                        "<img src=\"static/error.gif\" align=center>"
-                                       "%s<br /><br />\n", &buf[4]);
+                                       "%s<br /><br />\n", ChrPtr(Buf));
                        }
                        else {
                                username = bstr("newname");
@@ -579,12 +621,14 @@ void edituser(void) {
                        bstr("lastcall"),
                        bstr("purgedays")
                );
-               serv_getln(buf, sizeof buf);
-               if (buf[0] != '2') {
+               StrBuf_ServGetlnBuffered(Buf);
+               if (GetServerStatus(Buf, NULL) == 2) {
+                       StrBufCutLeft(Buf, 4);
                        sprintf(&message[strlen(message)],
                                "<img src=\"static/error.gif\" align=center>"
-                               "%s<br /><br />\n", &buf[4]);
+                               "%s<br /><br />\n", ChrPtr(Buf));
                }
+               FreeStrBuf(&Buf);
        }
 
        /**
@@ -604,20 +648,23 @@ void edituser(void) {
  *  username the name of the user to remove
  */
 void delete_user(char *username) {
-       char buf[SIZ];
+       StrBuf *Buf;
        char message[SIZ];
 
+       Buf = NewStrBuf();
        serv_printf("ASUP %s|0|0|0|0|0|", username);
-       serv_getln(buf, sizeof buf);
-       if (buf[0] != '2') {
+       StrBuf_ServGetlnBuffered(Buf);
+       if (GetServerStatus(Buf, NULL) == 2) {
+               StrBufCutLeft(Buf, 4);
                sprintf(message,
                        "<img src=\"static/error.gif\" align=center>"
-                       "%s<br /><br />\n", &buf[4]);
+                       "%s<br /><br />\n", ChrPtr(Buf));
        }
        else {
                safestrncpy(message, "", sizeof message);
        }
        select_user_to_edit(message, bstr("username"));
+       FreeStrBuf(&Buf);
 }
                
 
@@ -627,20 +674,20 @@ void delete_user(char *username) {
  * take the web environment username and create it on the citadel server
  */
 void create_user(void) {
-       char buf[SIZ];
+       long FullState;
+       StrBuf *Buf;
        char error_message[SIZ];
-       char username[SIZ];
-
-       safestrncpy(username, bstr("username"), sizeof username);
+       const char *username;
 
+       Buf = NewStrBuf();
+       username = bstr("username");
        serv_printf("CREU %s", username);
-       serv_getln(buf, sizeof buf);
-
-       if (buf[0] == '2') {
+       StrBuf_ServGetlnBuffered(Buf);
+       if (GetServerStatus(Buf, &FullState) == 2) {
                sprintf(WC->ImportantMessage, _("A new user has been created."));
                display_edituser(username, 1);
        }
-       else if (!strncmp(buf, "570", 3)) {
+       else if (FullState == 570) {
                sprintf(error_message,
                        "<img src=\"static/error.gif\" align=center>"
                        "%s<br /><br />\n",
@@ -651,12 +698,13 @@ void create_user(void) {
                select_user_to_edit(error_message, NULL);
        }
        else {
+               StrBufCutLeft(Buf, 4);
                sprintf(error_message,
                        "<img src=\"static/error.gif\" align=center>"
-                       "%s<br /><br />\n", &buf[4]);
+                       "%s<br /><br />\n", ChrPtr(Buf));
                select_user_to_edit(error_message, NULL);
        }
-
+       FreeStrBuf(&Buf);
 }
 
 
@@ -673,6 +721,7 @@ InitModule_USEREDIT
        WebcitAddUrlHandler(HKEY("create_user"), create_user, 0);
 
        RegisterNamespace("USERLIST:USERNAME",      0, 1, tmplput_USERLIST_UserName, CTX_USERLIST);
+       RegisterNamespace("USERLIST:PASSWD",        0, 1, tmplput_USERLIST_Password, CTX_USERLIST);
        RegisterNamespace("USERLIST:ACCLVLNO",      0, 0, tmplput_USERLIST_AccessLevelNo, CTX_USERLIST);
        RegisterNamespace("USERLIST:ACCLVLSTR",     0, 0, tmplput_USERLIST_AccessLevelStr, CTX_USERLIST);
        RegisterNamespace("USERLIST:UID",           0, 0, tmplput_USERLIST_UID, CTX_USERLIST);
@@ -688,5 +737,49 @@ InitModule_USEREDIT
        RegisterConditional(HKEY("COND:USERACCESS"), 0,   ConditionalUserAccess, CTX_USERLIST);
        RegisterConditional(HKEY("COND:USERLIST:FLAG:USE_INTERNET"), 0, ConditionalFlagINetEmail, CTX_USERLIST);
 
-       RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE);
+       RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
+       
+
+
+       RegisterSortFunc(HKEY("user:name"),
+                        HKEY("userlist"),
+                        CompareUserListName,
+                        CompareUserListNameRev,
+                        GroupchangeUserListName,
+                        CTX_USERLIST);
+       RegisterSortFunc(HKEY("user:accslvl"),
+                        HKEY("userlist"),
+                        CompareAccessLevel,
+                        CompareAccessLevelRev,
+                        GroupchangeAccessLevel,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:nlogons"),
+                        HKEY("userlist"),
+                        ComparenLogons,
+                        ComparenLogonsRev,
+                        GroupchangenLogons,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:uid"),
+                        HKEY("userlist"),
+                        CompareUID,
+                        CompareUIDRev,
+                        GroupchangeUID,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:lastlogon"),
+                        HKEY("userlist"),
+                        CompareLastLogon,
+                        CompareLastLogonRev,
+                        GroupchangeLastLogon,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:nmsgposts"),
+                        HKEY("userlist"),
+                        ComparenPosts,
+                        ComparenPostsRev,
+                        GroupchangenPosts,
+                        CTX_USERLIST);
+
 }