X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fuseredit.c;h=2446b3c2e9153964b22bbaf06ec291eedd8d2ca1;hb=e068f34784f285909c0c93d123a604d76bb244a9;hp=585a954db833cb8a29740f9323c8ae1104a89422;hpb=8d8c5af38e5026933ea3b9d5eb1b75f276df1d99;p=citadel.git diff --git a/webcit/useredit.c b/webcit/useredit.c index 585a954db..2446b3c2e 100644 --- a/webcit/useredit.c +++ b/webcit/useredit.c @@ -1,61 +1,61 @@ /* * $Id$ */ -/** - * \defgroup AdminTasks Administrative screen to add/change/delete user accounts - * \ingroup CitadelConfig - * - */ -/*@{*/ #include "webcit.h" #include "webserver.h" /** - * \brief show a list of available users to edit them - * \param message the header message??? - * \param preselect which user should be selected in the browser + * show a list of available users to edit them + * message the header message??? + * preselect which user should be selected in the browser */ void select_user_to_edit(char *message, char *preselect) -{ +{/* char buf[SIZ]; char username[SIZ]; + */ + output_headers(1, 0, 0, 0, 1, 0); + do_template("edituser_select", NULL); + end_burst(); + +/* output_headers(1, 1, 2, 0, 0, 0); wprintf("
\n"); - wprintf("" - "
" - "" - ""); + wprintf(""); + wprintf("

"); wprintf(_("Edit or delete users")); - wprintf("

\n" - "
\n
\n" - ); + wprintf(""); + wprintf("
"); + + wprintf("
\n"); if (message != NULL) wprintf(message); wprintf("
\n"); - svprintf("BOXTITLE", WCS_STRING, _("Add users")); - do_template("beginbox"); + svput("BOXTITLE", WCS_STRING, _("Add users")); + do_template("beginbox", NULL); wprintf(_("To create a new user account, enter the desired " "user name in the box below and click 'Create'.")); wprintf("

"); wprintf("
\n"); + wprintf("\n", WC->nonce); wprintf(_("New user: ")); wprintf("
\n" "" "
\n", _("Create")); - do_template("endbox"); + do_template("endbox", NULL); wprintf("
"); - svprintf("BOXTITLE", WCS_STRING, _("Edit or Delete users")); - do_template("beginbox"); + svput("BOXTITLE", WCS_STRING, _("Edit or Delete users")); + do_template("beginbox", NULL); wprintf(_("To edit an existing user account, select the user " "name from the list and click 'Edit'.")); @@ -63,6 +63,7 @@ void select_user_to_edit(char *message, char *preselect) wprintf("
" "
\n"); + wprintf("\n", WC->nonce); wprintf("", _("Delete user"), _("Delete this user?")); wprintf("
\n"); - do_template("endbox"); + do_template("endbox", NULL); wprintf("
\n"); wDumpContent(1); +*/ +} + + +typedef struct _UserListEntry { + int UID; + int AccessLevel; + int nLogons; + int nPosts; + + StrBuf *UserName; + StrBuf *Passvoid; + time_t LastLogonT; + /* Just available for Single users to view: */ + unsigned int Flags; + int DaysTillPurge; +} UserListEntry; + + +UserListEntry* NewUserListOneEntry(StrBuf *SerializedUser) +{ + UserListEntry *ul; + + if (StrLength(SerializedUser) < 8) + return NULL; + + ul = (UserListEntry*) malloc(sizeof(UserListEntry)); + ul->UserName = NewStrBuf(); + ul->Passvoid = NewStrBuf(); + + StrBufExtract_token(ul->UserName, SerializedUser, 0, '|'); + StrBufExtract_token(ul->Passvoid, SerializedUser, 1, '|'); + ul->Flags = (unsigned int)StrBufExtract_long(SerializedUser, 2, '|'); + ul->nLogons = StrBufExtract_int(SerializedUser, 3, '|'); + ul->nPosts = StrBufExtract_int(SerializedUser, 4, '|'); + ul->AccessLevel = StrBufExtract_int(SerializedUser, 5, '|'); + ul->UID = StrBufExtract_int(SerializedUser, 6, '|'); + ul->LastLogonT = StrBufExtract_long(SerializedUser, 7, '|'); + ul->DaysTillPurge = StrBufExtract_int(SerializedUser, 8, '|'); + return ul; +} + +void DeleteUserListEntry(void *vUserList) +{ + UserListEntry *ul = (UserListEntry*) vUserList; + FreeStrBuf(&ul->UserName); + FreeStrBuf(&ul->Passvoid); + free(ul); +} + +UserListEntry* NewUserListEntry(StrBuf *SerializedUserList) +{ + UserListEntry *ul; + + if (StrLength(SerializedUserList) < 8) + return NULL; + + ul = (UserListEntry*) malloc(sizeof(UserListEntry)); + ul->UserName = NewStrBuf(); + ul->Passvoid = NewStrBuf(); + + StrBufExtract_token(ul->UserName, SerializedUserList, 0, '|'); + ul->AccessLevel = StrBufExtract_int(SerializedUserList, 1, '|'); + ul->UID = StrBufExtract_int(SerializedUserList, 2, '|'); + ul->LastLogonT = StrBufExtract_long(SerializedUserList, 3, '|'); + ul->nLogons = StrBufExtract_int(SerializedUserList, 4, '|'); + ul->nPosts = StrBufExtract_int(SerializedUserList, 5, '|'); + StrBufExtract_token(ul->Passvoid, SerializedUserList, 6, '|'); + ul->Flags = 0; + ul->DaysTillPurge = -1; + return ul; +} + +/* + * Sort by Username + */ +int CompareUserListName(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName)); +} +int CompareUserListNameRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName)); +} + +/* + * Sort by AccessLevel + */ +int CompareAccessLevel(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u1->AccessLevel > u2->AccessLevel); +} +int CompareAccessLevelRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u2->AccessLevel > u1->AccessLevel); +} + + +/* + * Sort by UID + */ +int CompareUID(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u1->UID > u2->UID); +} +int CompareUIDRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u2->UID > u1->UID); +} + +/* + * Sort By Date /// TODO! + */ +int CompareLastLogon(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u1->LastLogonT > u2->LastLogonT); +} +int CompareLastLogonRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u2->LastLogonT > u1->LastLogonT); +} + +/* + * Sort By Number of Logons + */ +int ComparenLogons(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u1->nLogons > u2->nLogons); +} +int ComparenLogonsRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u2->nLogons > u1->nLogons); +} + +/* + * Sort By Number of Posts + */ +int ComparenPosts(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u1->nPosts > u2->nPosts); +} +int ComparenPostsRev(const void *vUser1, const void *vUser2) +{ + UserListEntry *u1 = (UserListEntry*) vUser1; + UserListEntry *u2 = (UserListEntry*) vUser2; + + return (u2->nPosts > u1->nPosts); +} + + +HashList *iterate_load_userlist(WCTemplateToken *Token) +{ + HashList *Hash; + char buf[SIZ]; + StrBuf *Buf; + UserListEntry* ul; + char nnn[64]; + int nUsed; + int Order; + int len; + + serv_puts("LIST"); + serv_getln(buf, sizeof buf); + if (buf[0] == '1') { + Hash = NewHash(1, NULL); + + Buf = NewStrBuf(); + while ((len = StrBuf_ServGetln(Buf), + strcmp(ChrPtr(Buf), "000"))) { + ul = NewUserListEntry(Buf); + if (ul == NULL) + continue; + nUsed = GetCount(Hash); + 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; + } + return Hash; + } + return NULL; +} + + +void tmplput_USERLIST_UserName(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; +/// TODO: X + StrBufAppendBuf(Target, ul->UserName, 0); } +void tmplput_USERLIST_AccessLevelNo(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target, "%d", ul->AccessLevel, 0); +} + +void tmplput_USERLIST_AccessLevelStr(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendBufPlain(Target, _(axdefs[ul->AccessLevel]), -1, 0); +} + +void tmplput_USERLIST_UID(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + StrBufAppendPrintf(Target, "%d", ul->UID, 0); +} + +void tmplput_USERLIST_LastLogonNo(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target,"%ld", ul->LastLogonT, 0); +} +void tmplput_USERLIST_LastLogonStr(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + StrEscAppend(Target, NULL, asctime(localtime(&ul->LastLogonT)), 0, 0); +} + +void tmplput_USERLIST_nLogons(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target, "%d", ul->nLogons, 0); +} + +void tmplput_USERLIST_nPosts(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target, "%d", ul->nPosts, 0); +} + +void tmplput_USERLIST_Flags(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target, "%d", ul->Flags, 0); +} + +void tmplput_USERLIST_DaysTillPurge(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + StrBufAppendPrintf(Target, "%d", ul->DaysTillPurge, 0); +} + +int ConditionalUser(WCTemplateToken *Tokens, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + if (havebstr("usernum")) { + return ibstr("usernum") == ul->UID; + } + else if (havebstr("username")) { + return strcmp(bstr("username"), ChrPtr(ul->UserName)) == 0; + } + else + return 0; +} + +int ConditionalFlagINetEmail(WCTemplateToken *Tokens, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + return (ul->Flags & US_INTERNET) != 0; +} + +int ConditionalUserAccess(WCTemplateToken *Tokens, void *Context, int ContextType) +{ + UserListEntry *ul = (UserListEntry*) Context; + + if (Tokens->Params[3]->Type == TYPE_LONG) + return (Tokens->Params[3]->lvalue == ul->AccessLevel); + else + return 0; +} /** - * \brief Locate the message number of a user's vCard in the current room - * \param username the plaintext name of the user - * \param usernum the number of the user on the citadel server + * 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 */ long locate_user_vcard(char *username, long usernum) { @@ -135,8 +482,8 @@ TRYAGAIN: 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")) { + if ( (!strcasecmp(content_type, "text/x-vcard")) + || (!strcasecmp(content_type, "text/vcard")) ) { vcard_msgnum = stuff->msgnum; } } @@ -168,9 +515,9 @@ TRYAGAIN: /** - * \brief Display the form for editing a user's address book entry - * \param username the name of the user - * \param usernum the citadel-uid of the user + * Display the form for editing a user's address book entry + * username the name of the user + * usernum the citadel-uid of the user */ void display_edit_address_book_entry(char *username, long usernum) { char roomname[SIZ]; @@ -207,22 +554,60 @@ void display_edit_address_book_entry(char *username, long usernum) { return; } - do_edit_vcard(vcard_msgnum, "1", "select_user_to_edit"); + do_edit_vcard(vcard_msgnum, "1", "select_user_to_edit", roomname); } +void display_edituser(char *supplied_username, int is_new) { + UserListEntry* UL; + StrBuf *Buf; + char error_message[1024]; + char MajorStatus; + char username[256]; + + if (supplied_username != NULL) { + safestrncpy(username, supplied_username, sizeof username); + } + else { + safestrncpy(username, bstr("username"), sizeof username); + } + Buf = NewStrBuf(); + serv_printf("AGUP %s", username); + StrBuf_ServGetln(Buf); + MajorStatus = ChrPtr(Buf)[0]; + StrBufCutLeft(Buf, 4); + if (MajorStatus != '2') { + ///TODO ImportantMessage + sprintf(error_message, + "" + "%s

\n", ChrPtr(Buf)); + select_user_to_edit(error_message, username); + FreeStrBuf(&Buf); + return; + } + else { + UL = NewUserListOneEntry(Buf); + output_headers(1, 0, 0, 0, 1, 0); + DoTemplate(HKEY("userlist_detailview"), NULL, (void*) UL, CTX_USERLIST); + end_burst(); + + } + FreeStrBuf(&Buf); +} -/** - * \brief Edit a user. + + +/* * + * Edit a user. * If supplied_username is null, look in the "username" * web variable for the name of the user to edit. * * If "is_new" is set to nonzero, this screen will set the web variables * to send the user to the vCard editor next. - * \param supplied_username user to look up or NULL if to search in the environment - * \param is_new should we create the user? - */ + * supplied_username user to look up or NULL if to search in the environment + * is_new should we create the user? + * / void display_edituser(char *supplied_username, int is_new) { char buf[1024]; char error_message[1024]; @@ -266,24 +651,25 @@ void display_edituser(char *supplied_username, int is_new) { lastcall = extract_long(&buf[4], 7); purgedays = extract_long(&buf[4], 8); - if (strlen(bstr("edit_abe_button")) > 0) { + if (havebstr("edit_abe_button")) { display_edit_address_book_entry(username, usernum); return; } - if (strlen(bstr("delete_button")) > 0) { + if (havebstr("delete_button")) { delete_user(username); return; } output_headers(1, 1, 2, 0, 0, 0); wprintf("
\n"); - wprintf("
"); - wprintf(""); + wprintf("

"); wprintf(_("Edit user account: ")); escputs(username); - wprintf("

\n"); - wprintf("
\n
\n"); + wprintf(""); + wprintf("
"); + + wprintf("
\n"); wprintf("
" "
\n"); @@ -294,11 +680,19 @@ void display_edituser(char *supplied_username, int is_new) { wprintf("\n" "\n", is_new, usernum); + wprintf("\n", WC->nonce); wprintf("\n", flags); wprintf("
"); + wprintf("\n"); + wprintf("
"); + wprintf(_("User name:")); + wprintf("" + "
"); wprintf(_("Password")); wprintf("" @@ -385,33 +779,50 @@ void display_edituser(char *supplied_username, int is_new) { wDumpContent(1); } - +*/ /** - * \brief do the backend operation of the user edit on the server + * do the backend operation of the user edit on the server */ void edituser(void) { char message[SIZ]; char buf[SIZ]; int is_new = 0; unsigned int flags = 0; + char *username; - is_new = atoi(bstr("is_new")); + is_new = ibstr("is_new"); + safestrncpy(message, "", sizeof message); + username = bstr("username"); - if (strlen(bstr("ok_button")) == 0) { + if (!havebstr("ok_button")) { safestrncpy(message, _("Changes were not saved."), sizeof message); } + else { - flags = atoi(bstr("flags")); - if (!strcasecmp(bstr("inetmail"), "yes")) { + flags = ibstr("flags"); + if (yesbstr("inetmail")) { flags |= US_INTERNET; } else { flags &= ~US_INTERNET ; } + 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') { + sprintf(&message[strlen(message)], + "" + "%s

\n", &buf[4]); + } + else { + username = bstr("newname"); + } + } + serv_printf("ASUP %s|%s|%d|%s|%s|%s|%s|%s|%s|", - bstr("username"), + username, bstr("password"), flags, bstr("timescalled"), @@ -423,13 +834,10 @@ void edituser(void) { ); serv_getln(buf, sizeof buf); if (buf[0] != '2') { - sprintf(message, + sprintf(&message[strlen(message)], "" "%s

\n", &buf[4]); } - else { - safestrncpy(message, "", sizeof message); - } } /** @@ -437,16 +845,16 @@ void edituser(void) { * the vCard edit screen. */ if (is_new) { - display_edit_address_book_entry( bstr("username"), atol(bstr("usernum")) ); + display_edit_address_book_entry(username, lbstr("usernum") ); } else { - select_user_to_edit(message, bstr("username")); + select_user_to_edit(message, username); } } -/** - * \brief burge a user - * \param username the name of the user to remove +/* + * burge a user + * username the name of the user to remove */ void delete_user(char *username) { char buf[SIZ]; @@ -468,7 +876,7 @@ void delete_user(char *username) { /** - * \brief create a new user + * create a new user * take the web environment username and create it on the citadel server */ void create_user(void) { @@ -482,10 +890,19 @@ void create_user(void) { serv_getln(buf, sizeof buf); if (buf[0] == '2') { - sprintf(WC->ImportantMessage, - _("A new user has been created.")); + sprintf(WC->ImportantMessage, _("A new user has been created.")); display_edituser(username, 1); } + else if (!strncmp(buf, "570", 3)) { + sprintf(error_message, + "" + "%s

\n", + _("You are attempting to create a new user from within Citadel " + "while running in host based authentication mode. In this mode, " + "you must create new users on the host system, not within Citadel.") + ); + select_user_to_edit(error_message, NULL); + } else { sprintf(error_message, "" @@ -496,5 +913,33 @@ void create_user(void) { } +void _select_user_to_edit(void){select_user_to_edit(NULL, NULL);} +void _display_edituser(void) {display_edituser(NULL, 0);} -/*@}*/ +void +InitModule_USEREDIT +(void) +{ + WebcitAddUrlHandler(HKEY("select_user_to_edit"), _select_user_to_edit, 0); + WebcitAddUrlHandler(HKEY("display_edituser"), _display_edituser, 0); + WebcitAddUrlHandler(HKEY("edituser"), edituser, 0); + WebcitAddUrlHandler(HKEY("create_user"), create_user, 0); + + RegisterNamespace("USERLIST:USERNAME", 0, 1, tmplput_USERLIST_UserName, 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); + RegisterNamespace("USERLIST:LASTLOGON:STR", 0, 0, tmplput_USERLIST_LastLogonStr, CTX_USERLIST); + RegisterNamespace("USERLIST:LASTLOGON:NO", 0, 0, tmplput_USERLIST_LastLogonNo, CTX_USERLIST); + RegisterNamespace("USERLIST:NLOGONS", 0, 0, tmplput_USERLIST_nLogons, CTX_USERLIST); + RegisterNamespace("USERLIST:NPOSTS", 0, 0, tmplput_USERLIST_nPosts, CTX_USERLIST); + + RegisterNamespace("USERLIST:FLAGS", 0, 0, tmplput_USERLIST_Flags, CTX_USERLIST); + RegisterNamespace("USERLIST:DAYSTILLPURGE", 0, 0, tmplput_USERLIST_DaysTillPurge, CTX_USERLIST); + + RegisterConditional(HKEY("COND:USERNAME"), 0, ConditionalUser, CTX_USERLIST); + 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); +}