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