Done with doxygenizing
[citadel.git] / webcit / useredit.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup AdminTasks Administrative screen to add/change/delete user accounts
6  *
7  */
8 /*@{*/
9
10 #include "webcit.h"
11 #include "webserver.h"
12
13
14 /**
15  * \brief show a list of available users to edit them
16  * \param message the header message???
17  * \param preselect which user should be selected in the browser
18  */
19 void select_user_to_edit(char *message, char *preselect)
20 {
21         char buf[SIZ];
22         char username[SIZ];
23
24         output_headers(1, 1, 2, 0, 0, 0);
25         wprintf("<div id=\"banner\">\n");
26         wprintf("<table width=100%% border=0 bgcolor=#444455><tr>"
27                 "<td>"
28                 "<span class=\"titlebar\">"
29                 "<img src=\"static/usermanag_48x.gif\">");
30         wprintf(_("Edit or delete users"));
31         wprintf("</span></td></tr></table>\n"
32                 "</div>\n<div id=\"content\">\n"
33         );
34
35         if (message != NULL) wprintf(message);
36
37         wprintf("<TABLE border=0 CELLSPACING=10><TR VALIGN=TOP><TD>\n");
38
39         svprintf("BOXTITLE", WCS_STRING, _("Add users"));
40         do_template("beginbox");
41
42         wprintf(_("To create a new user account, enter the desired "
43                 "user name in the box below and click 'Create'."));
44         wprintf("<br /><br />");
45
46         wprintf("<CENTER><FORM METHOD=\"POST\" action=\"create_user\">\n");
47         wprintf(_("New user: "));
48         wprintf("<input type=\"text\" name=\"username\"><br />\n"
49                 "<input type=\"submit\" name=\"create_button\" value=\"%s\">"
50                 "</FORM></CENTER>\n", _("Create"));
51
52         do_template("endbox");
53
54         wprintf("</TD><TD>");
55
56         svprintf("BOXTITLE", WCS_STRING, _("Edit or Delete users"));
57         do_template("beginbox");
58
59         wprintf(_("To edit an existing user account, select the user "
60                 "name from the list and click 'Edit'."));
61         wprintf("<br /><br />");
62         
63         wprintf("<CENTER>"
64                 "<FORM METHOD=\"POST\" action=\"display_edituser\">\n");
65         wprintf("<SELECT NAME=\"username\" SIZE=10 STYLE=\"width:100%%\">\n");
66         serv_puts("LIST");
67         serv_getln(buf, sizeof buf);
68         if (buf[0] == '1') {
69                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
70                         extract_token(username, buf, 0, '|', sizeof username);
71                         wprintf("<OPTION");
72                         if (preselect != NULL)
73                            if (!strcasecmp(username, preselect))
74                               wprintf(" SELECTED");
75                         wprintf(">");
76                         escputs(username);
77                         wprintf("\n");
78                 }
79         }
80         wprintf("</SELECT><br />\n");
81
82         wprintf("<input type=\"submit\" name=\"edit_config_button\" value=\"%s\">", _("Edit configuration"));
83         wprintf("<input type=\"submit\" name=\"edit_abe_button\" value=\"%s\">", _("Edit address book entry"));
84         wprintf("<input type=\"submit\" name=\"delete_button\" value=\"%s\" "
85                 "onClick=\"return confirm('%s');\">", _("Delete user"), _("Delete this user?"));
86         wprintf("</FORM></CENTER>\n");
87         do_template("endbox");
88
89         wprintf("</TD></TR></TABLE>\n");
90
91         wDumpContent(1);
92 }
93
94
95
96 /**
97  * \brief Locate the message number of a user's vCard in the current room
98  * \param username the plaintext name of the user
99  * \param usernum the number of the user on the citadel server
100  * \return the message id of his vcard
101  */
102 long locate_user_vcard(char *username, long usernum) {
103         char buf[SIZ];
104         long vcard_msgnum = (-1L);
105         char content_type[SIZ];
106         char partnum[SIZ];
107         int already_tried_creating_one = 0;
108
109         struct stuff_t {
110                 struct stuff_t *next;
111                 long msgnum;
112         };
113
114         struct stuff_t *stuff = NULL;
115         struct stuff_t *ptr;
116
117 TRYAGAIN:
118         /** Search for the user's vCard */
119         serv_puts("MSGS ALL");
120         serv_getln(buf, sizeof buf);
121         if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
122                 ptr = malloc(sizeof(struct stuff_t));
123                 ptr->msgnum = atol(buf);
124                 ptr->next = stuff;
125                 stuff = ptr;
126         }
127
128         /** Iterate through the message list looking for vCards */
129         while (stuff != NULL) {
130                 serv_printf("MSG0 %ld|2", stuff->msgnum);
131                 serv_getln(buf, sizeof buf);
132                 if (buf[0]=='1') {
133                         while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
134                                 if (!strncasecmp(buf, "part=", 5)) {
135                                         extract_token(partnum, &buf[5], 2, '|', sizeof partnum);
136                                         extract_token(content_type, &buf[5], 4, '|', sizeof content_type);
137                                         if (!strcasecmp(content_type,
138                                            "text/x-vcard")) {
139                                                 vcard_msgnum = stuff->msgnum;
140                                         }
141                                 }
142                         }
143                 }
144
145                 ptr = stuff->next;
146                 free(stuff);
147                 stuff = ptr;
148         }
149
150         /** If there's no vcard, create one */
151         if (vcard_msgnum < 0) if (already_tried_creating_one == 0) {
152                 already_tried_creating_one = 1;
153                 serv_puts("ENT0 1|||4");
154                 serv_getln(buf, sizeof buf);
155                 if (buf[0] == '4') {
156                         serv_puts("Content-type: text/x-vcard");
157                         serv_puts("");
158                         serv_puts("begin:vcard");
159                         serv_puts("end:vcard");
160                         serv_puts("000");
161                 }
162                 goto TRYAGAIN;
163         }
164
165         return(vcard_msgnum);
166 }
167
168
169 /**
170  * \brief Display the form for editing a user's address book entry
171  * \param username the name of the user
172  * \param usernum the citadel-uid of the user
173  */
174 void display_edit_address_book_entry(char *username, long usernum) {
175         char roomname[SIZ];
176         char buf[SIZ];
177         char error_message[SIZ];
178         long vcard_msgnum = (-1L);
179
180         /** Locate the user's config room, creating it if necessary */
181         sprintf(roomname, "%010ld.%s", usernum, USERCONFIGROOM);
182         serv_printf("GOTO %s||1", roomname);
183         serv_getln(buf, sizeof buf);
184         if (buf[0] != '2') {
185                 serv_printf("CRE8 1|%s|5|||1|", roomname);
186                 serv_getln(buf, sizeof buf);
187                 serv_printf("GOTO %s||1", roomname);
188                 serv_getln(buf, sizeof buf);
189                 if (buf[0] != '2') {
190                         sprintf(error_message,
191                                 "<img src=\"static/error.gif\" ALIGN=CENTER>"
192                                 "%s<br /><br />\n", &buf[4]);
193                         select_user_to_edit(error_message, username);
194                         return;
195                 }
196         }
197
198         vcard_msgnum = locate_user_vcard(username, usernum);
199
200         if (vcard_msgnum < 0) {
201                 sprintf(error_message,
202                         "<img src=\"static/error.gif\" ALIGN=CENTER>%s<br /><br />\n",
203                         _("An error occurred while trying to create or edit this address book entry.")
204                 );
205                 select_user_to_edit(error_message, username);
206                 return;
207         }
208
209         do_edit_vcard(vcard_msgnum, "1", "select_user_to_edit");
210 }
211
212
213
214
215 /**
216  * \brief Edit a user.  
217  * If supplied_username is null, look in the "username"
218  * web variable for the name of the user to edit.
219  * 
220  * If "is_new" is set to nonzero, this screen will set the web variables
221  * to send the user to the vCard editor next.
222  * \param supplied_username user to look up or NULL if to search in the environment
223  * \param is_new should we create the user?
224  */
225 void display_edituser(char *supplied_username, int is_new) {
226         char buf[1024];
227         char error_message[1024];
228         time_t now;
229
230         char username[256];
231         char password[256];
232         unsigned int flags;
233         int timescalled;
234         int msgsposted;
235         int axlevel;
236         long usernum;
237         time_t lastcall;
238         int purgedays;
239         int i;
240
241         if (supplied_username != NULL) {
242                 safestrncpy(username, supplied_username, sizeof username);
243         }
244         else {
245                 safestrncpy(username, bstr("username"), sizeof username);
246         }
247
248         serv_printf("AGUP %s", username);
249         serv_getln(buf, sizeof buf);
250         if (buf[0] != '2') {
251                 sprintf(error_message,
252                         "<img src=\"static/error.gif\" ALIGN=CENTER>"
253                         "%s<br /><br />\n", &buf[4]);
254                 select_user_to_edit(error_message, username);
255                 return;
256         }
257
258         extract_token(username, &buf[4], 0, '|', sizeof username);
259         extract_token(password, &buf[4], 1, '|', sizeof password);
260         flags = extract_int(&buf[4], 2);
261         timescalled = extract_int(&buf[4], 3);
262         msgsposted = extract_int(&buf[4], 4);
263         axlevel = extract_int(&buf[4], 5);
264         usernum = extract_long(&buf[4], 6);
265         lastcall = extract_long(&buf[4], 7);
266         purgedays = extract_long(&buf[4], 8);
267
268         if (strlen(bstr("edit_abe_button")) > 0) {
269                 display_edit_address_book_entry(username, usernum);
270                 return;
271         }
272
273         if (strlen(bstr("delete_button")) > 0) {
274                 delete_user(username);
275                 return;
276         }
277
278         output_headers(1, 1, 2, 0, 0, 0);
279         wprintf("<div id=\"banner\">\n");
280         wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>");
281         wprintf("<SPAN CLASS=\"titlebar\">");
282         wprintf(_("Edit user account: "));
283         escputs(username);
284         wprintf("</SPAN></TD></TR></TABLE>\n");
285         wprintf("</div>\n<div id=\"content\">\n");
286
287         wprintf("<div class=\"fix_scrollbar_bug\">"
288                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
289         wprintf("<FORM METHOD=\"POST\" action=\"edituser\">\n"
290                 "<INPUT TYPE=\"hidden\" NAME=\"username\" VALUE=\"");
291         escputs(username);
292         wprintf("\">\n");
293         wprintf("<INPUT TYPE=\"hidden\" NAME=\"is_new\" VALUE=\"%d\">\n"
294                 "<INPUT TYPE=\"hidden\" NAME=\"usernum\" VALUE=\"%ld\">\n",
295                 is_new, usernum);
296
297         wprintf("<INPUT TYPE=\"hidden\" NAME=\"flags\" VALUE=\"%d\">\n", flags);
298
299         wprintf("<CENTER><TABLE>");
300
301         wprintf("<TR><TD>");
302         wprintf(_("Password"));
303         wprintf("</TD><TD>"
304                 "<INPUT TYPE=\"password\" NAME=\"password\" VALUE=\"");
305         escputs(password);
306         wprintf("\" MAXLENGTH=\"20\"></TD></TR>\n");
307
308         wprintf("<tr><td>");
309         wprintf(_("Permission to send Internet mail"));
310         wprintf("</td><td>");
311         wprintf("<input type=\"checkbox\" name=\"inetmail\" value=\"yes\" ");
312         if (flags & US_INTERNET) {
313                 wprintf("CHECKED ");
314         }
315         wprintf("></td></tr>\n");
316
317         wprintf("<TR><TD>");
318         wprintf(_("Number of logins"));
319         wprintf("</TD><TD>"
320                 "<INPUT TYPE=\"text\" NAME=\"timescalled\" VALUE=\"");
321         wprintf("%d", timescalled);
322         wprintf("\" MAXLENGTH=\"6\"></TD></TR>\n");
323
324         wprintf("<TR><TD>");
325         wprintf(_("Messages submitted"));
326         wprintf("</TD><TD>"
327                 "<INPUT TYPE=\"text\" NAME=\"msgsposted\" VALUE=\"");
328         wprintf("%d", msgsposted);
329         wprintf("\" MAXLENGTH=\"6\"></TD></TR>\n");
330
331         wprintf("<TR><TD>");
332         wprintf(_("Access level"));
333         wprintf("</TD><TD>"
334                 "<SELECT NAME=\"axlevel\">\n");
335         for (i=0; i<7; ++i) {
336                 wprintf("<OPTION ");
337                 if (axlevel == i) {
338                         wprintf("SELECTED ");
339                 }
340                 wprintf("VALUE=\"%d\">%d - %s</OPTION>\n",
341                         i, i, axdefs[i]);
342         }
343         wprintf("</SELECT></TD></TR>\n");
344
345         wprintf("<TR><TD>");
346         wprintf(_("User ID number"));
347         wprintf("</TD><TD>"
348                 "<INPUT TYPE=\"text\" NAME=\"usernum\" VALUE=\"");
349         wprintf("%ld", usernum);
350         wprintf("\" MAXLENGTH=\"7\"></TD></TR>\n");
351
352         now = time(NULL);
353         wprintf("<TR><TD>");
354         wprintf(_("Date and time of last login"));
355         wprintf("</TD><TD>"
356                 "<SELECT NAME=\"lastcall\">\n");
357
358         wprintf("<OPTION SELECTED VALUE=\"%ld\">", lastcall);
359         escputs(asctime(localtime(&lastcall)));
360         wprintf("</OPTION>\n");
361
362         wprintf("<OPTION VALUE=\"%ld\">", now);
363         escputs(asctime(localtime(&now)));
364         wprintf("</OPTION>\n");
365
366         wprintf("</SELECT></TD></TR>");
367
368         wprintf("<TR><TD>");
369         wprintf(_("Auto-purge after this many days"));
370         wprintf("</TD><TD>"
371                 "<INPUT TYPE=\"text\" NAME=\"purgedays\" VALUE=\"");
372         wprintf("%d", purgedays);
373         wprintf("\" MAXLENGTH=\"5\"></TD></TR>\n");
374
375         wprintf("</TABLE>\n");
376
377         wprintf("<INPUT type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">\n"
378                 "&nbsp;"
379                 "<INPUT type=\"submit\" NAME=\"cancel\" VALUE=\"%s\">\n"
380                 "<br /><br /></FORM>\n", _("Save changes"), _("Cancel"));
381
382         wprintf("</CENTER>\n");
383         wprintf("</td></tr></table></div>\n");
384         wDumpContent(1);
385
386 }
387
388
389 /**
390  * \brief do the backend operation of the user edit on the server
391  */
392 void edituser(void) {
393         char message[SIZ];
394         char buf[SIZ];
395         int is_new = 0;
396         unsigned int flags = 0;
397
398         is_new = atoi(bstr("is_new"));
399
400         if (strlen(bstr("ok_button")) == 0) {
401                 safestrncpy(message, _("Changes were not saved."), sizeof message);
402         }
403         else {
404                 flags = atoi(bstr("flags"));
405                 if (!strcasecmp(bstr("inetmail"), "yes")) {
406                         flags |= US_INTERNET;
407                 }
408                 else {
409                         flags &= ~US_INTERNET ;
410                 }
411
412                 serv_printf("ASUP %s|%s|%d|%s|%s|%s|%s|%s|%s|",
413                         bstr("username"),
414                         bstr("password"),
415                         flags,
416                         bstr("timescalled"),
417                         bstr("msgsposted"),
418                         bstr("axlevel"),
419                         bstr("usernum"),
420                         bstr("lastcall"),
421                         bstr("purgedays")
422                 );
423                 serv_getln(buf, sizeof buf);
424                 if (buf[0] != '2') {
425                         sprintf(message,
426                                 "<img src=\"static/error.gif\" ALIGN=CENTER>"
427                                 "%s<br /><br />\n", &buf[4]);
428                 }
429                 else {
430                         safestrncpy(message, "", sizeof message);
431                 }
432         }
433
434         /**
435          * If we are in the middle of creating a new user, move on to
436          * the vCard edit screen.
437          */
438         if (is_new) {
439                 display_edit_address_book_entry( bstr("username"), atol(bstr("usernum")) );
440         }
441         else {
442                 select_user_to_edit(message, bstr("username"));
443         }
444 }
445
446 /**
447  * \brief burge a user 
448  * \param username the name of the user to remove
449  */
450 void delete_user(char *username) {
451         char buf[SIZ];
452         char message[SIZ];
453
454         serv_printf("ASUP %s|0|0|0|0|0|", username);
455         serv_getln(buf, sizeof buf);
456         if (buf[0] != '2') {
457                 sprintf(message,
458                         "<img src=\"static/error.gif\" ALIGN=CENTER>"
459                         "%s<br /><br />\n", &buf[4]);
460         }
461         else {
462                 safestrncpy(message, "", sizeof message);
463         }
464         select_user_to_edit(message, bstr("username"));
465 }
466                 
467
468
469 /**
470  * \brief create a new user
471  * take the web environment username and create it on the citadel server
472  */
473 void create_user(void) {
474         char buf[SIZ];
475         char error_message[SIZ];
476         char username[SIZ];
477
478         safestrncpy(username, bstr("username"), sizeof username);
479
480         serv_printf("CREU %s", username);
481         serv_getln(buf, sizeof buf);
482
483         if (buf[0] == '2') {
484                 sprintf(WC->ImportantMessage,
485                         _("A new user has been created."));
486                 display_edituser(username, 1);
487         }
488         else {
489                 sprintf(error_message,
490                         "<img src=\"static/error.gif\" ALIGN=CENTER>"
491                         "%s<br /><br />\n", &buf[4]);
492                 select_user_to_edit(error_message, NULL);
493         }
494
495 }
496
497
498
499 /*@}*/