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