4 * Lots of different room-related operations.
13 #include <sys/types.h>
15 #include <sys/socket.h>
18 #include <netinet/in.h>
46 char floorlist[128][SIZ];
49 * load the list of floors
51 void load_floorlist(void)
56 for (a = 0; a < 128; ++a)
62 strcpy(floorlist[0], "Main Floor");
65 while (serv_gets(buf), strcmp(buf, "000")) {
66 extract(floorlist[extract_int(buf, 0)], buf, 1);
72 * remove a room from the march list
74 void remove_march(char *aaa)
76 struct march *mptr, *mptr2;
78 if (WC->march == NULL)
81 if (!strcasecmp(WC->march->march_name, aaa)) {
82 mptr = WC->march->next;
88 for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
89 if (!strcasecmp(mptr->march_name, aaa)) {
90 mptr2->next = mptr->next;
103 void room_tree_list(struct roomlisting *rp)
112 room_tree_list(rp->lnext);
114 strcpy(rmname, rp->rlname);
117 wprintf("<A HREF=\"/dotgoto&room=");
121 escputs1(rmname, 1, 1);
122 if ((f & QR_DIRECTORY) && (f & QR_NETWORK))
124 else if (f & QR_DIRECTORY)
126 else if (f & QR_NETWORK)
130 wprintf("</A><TT> </TT>\n");
132 room_tree_list(rp->rnext);
138 * Room ordering stuff (compare first by floor, then by order)
140 int rordercmp(struct roomlisting *r1, struct roomlisting *r2)
142 if ((r1 == NULL) && (r2 == NULL))
148 if (r1->rlfloor < r2->rlfloor)
150 if (r1->rlfloor > r2->rlfloor)
152 if (r1->rlorder < r2->rlorder)
154 if (r1->rlorder > r2->rlorder)
161 * Common code for all room listings
163 void listrms(char *variety)
168 struct roomlisting *rl = NULL;
169 struct roomlisting *rp;
170 struct roomlisting *rs;
173 /* Ask the server for a room list */
180 while (serv_gets(buf), strcmp(buf, "000")) {
182 rp = malloc(sizeof(struct roomlisting));
183 extract(rp->rlname, buf, 0);
184 rp->rlflags = extract_int(buf, 1);
185 rp->rlfloor = extract_int(buf, 2);
186 rp->rlorder = extract_int(buf, 3);
195 if (rordercmp(rp, rs) < 0) {
196 if (rs->lnext == NULL) {
203 if (rs->rnext == NULL) {
215 /* If no rooms were listed, print an nbsp to make the cell
216 * borders show up anyway.
218 if (num_rooms == 0) wprintf(" ");
223 * list all forgotten rooms
225 void zapped_list(void)
227 output_headers(1, 1, 0, 0, 0, 0, 0);
229 svprintf("BOXTITLE", WCS_STRING, "Zapped (forgotten) rooms");
230 do_template("beginbox");
234 wprintf("<br /><br />\n");
235 wprintf("Click on any room to un-zap it and goto that room.\n");
236 do_template("endbox");
242 * read this room's info file (set v to 1 for verbose mode)
251 fmout(NULL, "CENTER");
258 /* Display room graphic. The server doesn't actually
259 * need the room name, but we supply it in order to
260 * keep the browser from using a cached graphic from
263 void embed_room_graphic(void) {
266 serv_puts("OIMG _roompic_");
269 wprintf("<TD BGCOLOR=\"#444455\">");
270 wprintf("<IMG HEIGHT=64 SRC=\"/image&name=_roompic_&room=");
271 urlescputs(WC->wc_roomname);
280 /* Let the user know if new mail has arrived
282 void embed_newmail_button(void) {
283 if ( (WC->new_mail > WC->remember_new_mail) && (WC->new_mail>0) ) {
285 "<A HREF=\"/dotgoto?room=_MAIL_\">"
286 "<IMG SRC=\"/static/mail.gif\" border=0 "
287 "ALT=\"You have new mail\">"
288 "<br /><SPAN CLASS=\"youhavemail\">"
289 "%d new mail</SPAN></A>", WC->new_mail);
290 WC->remember_new_mail = WC->new_mail;
297 * Display the current view and offer an option to change it
299 void embed_view_o_matic(void) {
302 wprintf("<FORM NAME=\"viewomatic\">\n"
303 "<SELECT NAME=\"newview\" SIZE=\"1\" "
304 "OnChange=\"location.href=viewomatic.newview.options"
305 "[selectedIndex].value\">\n");
307 for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
309 * Only offer the views that make sense, given the default
310 * view for the room. For example, don't offer a Calendar
311 * view in a non-Calendar room.
315 || (i == WC->wc_default_view)
316 || ( (i == 0) && (WC->wc_default_view == 1) )
317 || ( (i == 1) && (WC->wc_default_view == 0) )
320 wprintf("<OPTION %s VALUE=\"/changeview?view=%d\">",
321 ((i == WC->wc_view) ? "SELECTED" : ""),
323 escputs(viewdefs[i]);
324 wprintf("</OPTION>\n");
327 wprintf("</SELECT></FORM>\n");
332 void embed_room_banner(char *got, int navbar_style) {
335 /* We need to have the information returned by a GOTO server command.
336 * If it isn't supplied, we fake it by issuing our own GOTO.
339 serv_printf("GOTO %s", WC->wc_roomname);
344 /* If the user happens to select the "make this my start page" link,
345 * we want it to remember the URL as a "/dotskip" one instead of
346 * a "skip" or "gotonext" or something like that.
348 snprintf(WC->this_page, sizeof(WC->this_page), "/dotskip&room=%s",
351 /* Check for new mail. */
352 WC->new_mail = extract_int(&got[4], 9);
353 WC->wc_view = extract_int(&got[4], 11);
355 svprintf("ROOMNAME", WCS_STRING, "%s", WC->wc_roomname);
356 svprintf("NEWMSGS", WCS_STRING, "%d", extract_int(&got[4], 1));
357 svprintf("TOTALMSGS", WCS_STRING, "%d", extract_int(&got[4], 2));
358 svcallback("ROOMPIC", embed_room_graphic);
359 svcallback("ROOMINFO", readinfo);
360 svcallback("YOUHAVEMAIL", embed_newmail_button);
361 svcallback("VIEWOMATIC", embed_view_o_matic);
362 svcallback("START", offer_start_page);
364 do_template("roombanner");
365 if (navbar_style != navbar_none) {
367 wprintf("<div style=\"position:absolute; bottom:0px; left:0px\">\n"
368 "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\"><tr>\n");
371 if (navbar_style == navbar_default) wprintf(
373 "<a href=\"/ungoto\">"
374 "<img align=\"middle\" src=\"/static/back.gif\" border=\"0\">"
375 "<span class=\"navbar_link\">Ungoto</span></A>"
379 if ( (navbar_style == navbar_default)
380 && (WC->wc_view != VIEW_CALENDAR)
381 && (WC->wc_view != VIEW_ADDRESSBOOK)
382 && (WC->wc_view != VIEW_NOTES)
383 && (WC->wc_view != VIEW_TASKS)
387 "<A HREF=\"/readnew\">"
388 "<img align=\"middle\" src=\"/static/readmsgs.gif\" border=\"0\">"
389 "<span class=\"navbar_link\">New messages</span></A>"
394 if (navbar_style == navbar_default) {
395 switch(WC->wc_view) {
396 case VIEW_ADDRESSBOOK:
399 "<A HREF=\"/readfwd\">"
400 "<img align=\"middle\" src=\"/static/readmsgs.gif\" "
402 "<span class=\"navbar_link\">"
410 "<A HREF=\"/readfwd?calview=day\">"
411 "<img align=\"middle\" src=\"/static/day_view.gif\" "
413 "<span class=\"navbar_link\">"
419 "<A HREF=\"/readfwd?calview=month\">"
420 "<img align=\"middle\" src=\"/static/month_view.gif\" "
422 "<span class=\"navbar_link\">"
430 "<A HREF=\"/readfwd\">"
431 "<img align=\"middle\" src=\"/static/readmsgs.gif\" "
433 "<span class=\"navbar_link\">"
441 "<A HREF=\"/readfwd\">"
442 "<img align=\"middle\" src=\"/static/readmsgs.gif\" "
444 "<span class=\"navbar_link\">"
452 "<A HREF=\"/readfwd\">"
453 "<img align=\"middle\" src=\"/static/readmsgs.gif\" "
455 "<span class=\"navbar_link\">"
463 if (navbar_style == navbar_default) {
466 "<A HREF=\"/display_enter\">"
467 "<img align=\"middle\" src=\"/static/enter.gif\" border=\"0\">"
468 "<span class=\"navbar_link\">"
470 switch(WC->wc_view) {
471 case VIEW_ADDRESSBOOK:
472 wprintf("Add new contact");
475 wprintf("Add new event");
478 wprintf("Add new task");
481 wprintf("Add new note");
484 wprintf("Enter a message");
487 wprintf("</span></a></td>\n");
490 if (navbar_style == navbar_default) wprintf(
493 "<span class=\"navbar_link\">Skip this room</span>"
494 "<img align=\"middle\" src=\"/static/forward.gif\" border=\"0\"></A>"
498 if (navbar_style == navbar_default) wprintf(
500 "<A HREF=\"/gotonext\">"
501 "<span class=\"navbar_link\">Goto next room</span>"
502 "<img align=\"middle\" src=\"/static/forward.gif\" border=\"0\"></A>"
506 wprintf("</tr></table></div>\n");
516 * back end routine to take the session to a new room
519 void gotoroom(char *gname)
522 static long ls = (-1L);
524 /* store ungoto information */
525 strcpy(WC->ugname, WC->wc_roomname);
528 /* move to the new room */
529 serv_printf("GOTO %s", gname);
532 serv_puts("GOTO _BASEROOM_");
538 extract(WC->wc_roomname, &buf[4], 0);
539 WC->room_flags = extract_int(&buf[4], 4);
540 /* highest_msg_read = extract_int(&buf[4],6);
541 maxmsgnum = extract_int(&buf[4],5);
542 is_mail = (char) extract_int(&buf[4],7); */
543 ls = extract_long(&buf[4], 6);
544 WC->wc_floor = extract_int(&buf[4], 10);
545 WC->wc_view = extract_int(&buf[4], 11);
546 WC->wc_default_view = extract_int(&buf[4], 12);
549 WC->is_room_aide = WC->is_aide;
551 WC->is_room_aide = (char) extract_int(&buf[4], 8);
553 remove_march(WC->wc_roomname);
554 if (!strcasecmp(gname, "_BASEROOM_"))
560 * Locate the room on the march list which we most want to go to. Each room
561 * is measured given a "weight" of preference based on various factors.
563 char *pop_march(int desired_floor)
565 static char TheRoom[128];
567 int TheOrder = 32767;
570 struct march *mptr = NULL;
572 strcpy(TheRoom, "_BASEROOM_");
573 if (WC->march == NULL)
576 for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
578 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
579 weight = weight + 10000;
580 if (mptr->march_floor == desired_floor)
581 weight = weight + 5000;
583 weight = weight + ((128 - (mptr->march_floor)) * 128);
584 weight = weight + (128 - (mptr->march_order));
586 if (weight > TheWeight) {
588 strcpy(TheRoom, mptr->march_name);
589 TheFloor = mptr->march_floor;
590 TheOrder = mptr->march_order;
598 /* Goto next room having unread messages.
599 * We want to skip over rooms that the user has already been to, and take the
600 * user back to the lobby when done. The room we end up in is placed in
601 * newroom - which is set to 0 (the lobby) initially.
602 * We start the search in the current room rather than the beginning to prevent
603 * two or more concurrent users from dragging each other back to the same room.
608 struct march *mptr, *mptr2;
611 /* First check to see if the march-mode list is already allocated.
612 * If it is, pop the first room off the list and go there.
615 if (WC->march == NULL) {
619 while (serv_gets(buf), strcmp(buf, "000")) {
620 mptr = (struct march *) malloc(sizeof(struct march));
622 extract(mptr->march_name, buf, 0);
623 mptr->march_floor = extract_int(buf, 2);
624 mptr->march_order = extract_int(buf, 3);
625 if (WC->march == NULL) {
629 while (mptr2->next != NULL)
634 /* add _BASEROOM_ to the end of the march list, so the user will end up
635 * in the system base room (usually the Lobby>) at the end of the loop
637 mptr = (struct march *) malloc(sizeof(struct march));
639 strcpy(mptr->march_name, "_BASEROOM_");
640 if (WC->march == NULL) {
644 while (mptr2->next != NULL)
649 * ...and remove the room we're currently in, so a <G>oto doesn't make us
650 * walk around in circles
652 remove_march(WC->wc_roomname);
654 if (WC->march != NULL) {
655 strcpy(next_room, pop_march(-1));
657 strcpy(next_room, "_BASEROOM_");
661 smart_goto(next_room);
665 void smart_goto(char *next_room) {
673 * mark all messages in current room as having been read
675 void slrp_highest(void)
680 serv_puts("SLRP HIGHEST");
683 wprintf("<EM>%s</EM><br />\n", &buf[4]);
690 * un-goto the previous room
696 if (!strcmp(WC->ugname, "")) {
697 smart_goto(WC->wc_roomname);
700 serv_printf("GOTO %s", WC->ugname);
703 smart_goto(WC->wc_roomname);
706 if (WC->uglsn >= 0L) {
707 serv_printf("SLRP %ld", WC->uglsn);
710 strcpy(buf, WC->ugname);
711 strcpy(WC->ugname, "");
720 * Set/clear/read the "self-service list subscribe" flag for a room
722 * Set 'newval' to 0 to clear, 1 to set, any other value to leave unchanged.
723 * Always returns the new value.
726 int self_service(int newval) {
727 int current_value = 0;
733 int flags, floor, order, view, flags2;
737 if (buf[0] != '2') return(0);
739 extract(name, &buf[4], 0);
740 extract(password, &buf[4], 1);
741 extract(dirname, &buf[4], 2);
742 flags = extract_int(&buf[4], 3);
743 floor = extract_int(&buf[4], 4);
744 order = extract_int(&buf[4], 5);
745 view = extract_int(&buf[4], 6);
746 flags2 = extract_int(&buf[4], 7);
748 if (flags2 & QR2_SELFLIST) {
756 flags2 = flags2 | QR2_SELFLIST;
758 else if (newval == 0) {
759 flags2 = flags2 & ~QR2_SELFLIST;
762 return(current_value);
765 if (newval != current_value) {
766 serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
767 name, password, dirname, flags,
768 floor, order, view, flags2);
782 * display the form for editing a room
784 void display_editroom(void)
789 char remote_room[SIZ];
792 char er_password[10];
794 char er_roomaide[26];
800 char *not_shared_with;
807 if (strlen(tab) == 0) tab = "admin";
814 strcpy(WC->ImportantMessage, &buf[4]);
818 extract(er_name, &buf[4], 0);
819 extract(er_password, &buf[4], 1);
820 extract(er_dirname, &buf[4], 2);
821 er_flags = extract_int(&buf[4], 3);
822 er_floor = extract_int(&buf[4], 4);
824 output_headers(1, 1, 1, 0, 0, 0, 0);
826 /* print the tabbed dialog */
827 wprintf("<br /><TABLE border=0 cellspacing=0 cellpadding=0 width=100%%>"
829 "<TD> </TD>\n");
831 if (!strcmp(tab, "admin")) {
832 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
835 wprintf("<TD BGCOLOR=\"#CCCCCC\"><A HREF=\"/display_editroom&tab=admin\">");
837 wprintf("Administration");
838 if (!strcmp(tab, "admin")) {
839 wprintf("</SPAN></TD>\n");
842 wprintf("</A></TD>\n");
845 wprintf("<TD> </TD>\n");
847 if (!strcmp(tab, "config")) {
848 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
851 wprintf("<TD BGCOLOR=\"#CCCCCC\"><A HREF=\"/display_editroom&tab=config\">");
853 wprintf("Configuration");
854 if (!strcmp(tab, "config")) {
855 wprintf("</SPAN></TD>\n");
858 wprintf("</A></TD>\n");
861 wprintf("<TD> </TD>\n");
863 if (!strcmp(tab, "expire")) {
864 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
867 wprintf("<TD BGCOLOR=\"#CCCCCC\"><A HREF=\"/display_editroom&tab=expire\">");
869 wprintf("Message expire policy");
870 if (!strcmp(tab, "expire")) {
871 wprintf("</SPAN></TD>\n");
874 wprintf("</A></TD>\n");
877 wprintf("<TD> </TD>\n");
879 if (!strcmp(tab, "sharing")) {
880 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
883 wprintf("<TD BGCOLOR=\"#CCCCCC\"><A HREF=\"/display_editroom&tab=sharing\">");
886 if (!strcmp(tab, "sharing")) {
887 wprintf("</SPAN></TD>\n");
890 wprintf("</A></TD>\n");
893 wprintf("<TD> </TD>\n");
895 if (!strcmp(tab, "listserv")) {
896 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
899 wprintf("<TD BGCOLOR=\"#CCCCCC\"><A HREF=\"/display_editroom&tab=listserv\">");
901 wprintf("Mailing list service");
902 if (!strcmp(tab, "listserv")) {
903 wprintf("</SPAN></TD>\n");
906 wprintf("</A></TD>\n");
909 wprintf("<TD> </TD>\n");
911 wprintf("</TR></TABLE>\n");
912 /* end tabbed dialog */
914 /* begin content of whatever tab is open now */
915 wprintf("<TABLE border=0 width=100%% bgcolor=\"#FFFFFF\">\n"
918 if (!strcmp(tab, "admin")) {
920 "<LI><A HREF=\"/confirm_delete_room\">\n"
921 "Delete this room</A>\n"
922 "<LI><A HREF=\"/display_editroompic\">\n"
923 "Set or change the graphic for this room's banner</A>\n"
924 "<LI><A HREF=\"/display_editinfo\">\n"
925 "Edit this room's Info file</A>\n"
929 if (!strcmp(tab, "config")) {
930 wprintf("<FORM METHOD=\"POST\" ACTION=\"/editroom\">\n");
932 wprintf("<UL><LI>Name of room: ");
933 wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\"19\">\n", er_name);
935 wprintf("<LI>Resides on floor: ");
936 wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
937 for (i = 0; i < 128; ++i)
938 if (strlen(floorlist[i]) > 0) {
941 wprintf("SELECTED ");
942 wprintf("VALUE=\"%d\">", i);
943 escputs(floorlist[i]);
944 wprintf("</OPTION>\n");
946 wprintf("</SELECT>\n");
948 wprintf("<LI>Type of room:<UL>\n");
950 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
951 if ((er_flags & QR_PRIVATE) == 0)
953 wprintf("> Public room\n");
955 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
956 if ((er_flags & QR_PRIVATE) &&
957 (er_flags & QR_GUESSNAME))
959 wprintf("> Private - guess name\n");
961 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
962 if ((er_flags & QR_PRIVATE) &&
963 (er_flags & QR_PASSWORDED))
965 wprintf("> Private - require password:\n");
966 wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n", er_password);
968 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
969 if ((er_flags & QR_PRIVATE)
970 && ((er_flags & QR_GUESSNAME) == 0)
971 && ((er_flags & QR_PASSWORDED) == 0))
973 wprintf("> Private - invitation only\n");
975 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
976 wprintf("> If private, cause current users to forget room\n");
980 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
981 if (er_flags & QR_PREFONLY)
983 wprintf("> Preferred users only\n");
985 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
986 if (er_flags & QR_READONLY)
988 wprintf("> Read-only room\n");
990 /* directory stuff */
991 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
992 if (er_flags & QR_DIRECTORY)
994 wprintf("> File directory room\n");
996 wprintf("<UL><LI>Directory name: ");
997 wprintf("<INPUT TYPE=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n", er_dirname);
999 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
1000 if (er_flags & QR_UPLOAD)
1001 wprintf("CHECKED ");
1002 wprintf("> Uploading allowed\n");
1004 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
1005 if (er_flags & QR_DOWNLOAD)
1006 wprintf("CHECKED ");
1007 wprintf("> Downloading allowed\n");
1009 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
1010 if (er_flags & QR_VISDIR)
1011 wprintf("CHECKED ");
1012 wprintf("> Visible directory</UL>\n");
1014 /* end of directory stuff */
1016 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
1017 if (er_flags & QR_NETWORK)
1018 wprintf("CHECKED ");
1019 wprintf("> Network shared room\n");
1021 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"permanent\" VALUE=\"yes\" ");
1022 if (er_flags & QR_PERMANENT)
1023 wprintf("CHECKED ");
1024 wprintf("> Permanent (does not auto-purge)\n");
1026 /* start of anon options */
1028 wprintf("<LI>Anonymous messages<UL>\n");
1030 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
1031 if (((er_flags & QR_ANONONLY) == 0)
1032 && ((er_flags & QR_ANONOPT) == 0))
1033 wprintf("CHECKED ");
1034 wprintf("> No anonymous messages\n");
1036 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
1037 if (er_flags & QR_ANONONLY)
1038 wprintf("CHECKED ");
1039 wprintf("> All messages are anonymous\n");
1041 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
1042 if (er_flags & QR_ANONOPT)
1043 wprintf("CHECKED ");
1044 wprintf("> Prompt user when entering messages</UL>\n");
1046 /* end of anon options */
1048 wprintf("<LI>Room aide: \n");
1051 if (buf[0] != '2') {
1052 wprintf("<EM>%s</EM>\n", &buf[4]);
1054 extract(er_roomaide, &buf[4], 0);
1055 wprintf("<INPUT TYPE=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
1058 wprintf("</UL><CENTER>\n");
1059 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"config\">\n"
1060 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">"
1062 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">"
1068 /* Sharing the room with other Citadel nodes... */
1069 if (!strcmp(tab, "sharing")) {
1071 shared_with = strdup("");
1072 not_shared_with = strdup("");
1074 /* Learn the current configuration */
1075 serv_puts("CONF getsys|application/x-citadel-ignet-config");
1077 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf, "000")) {
1078 extract(node, buf, 0);
1079 not_shared_with = realloc(not_shared_with,
1080 strlen(not_shared_with) + 32);
1081 strcat(not_shared_with, node);
1082 strcat(not_shared_with, "\n");
1087 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf, "000")) {
1088 extract(cmd, buf, 0);
1089 extract(node, buf, 1);
1090 extract(remote_room, buf, 2);
1091 if (!strcasecmp(cmd, "ignet_push_share")) {
1092 shared_with = realloc(shared_with,
1093 strlen(shared_with) + 32);
1094 strcat(shared_with, node);
1095 if (strlen(remote_room) > 0) {
1096 strcat(shared_with, "|");
1097 strcat(shared_with, remote_room);
1099 strcat(shared_with, "\n");
1103 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1104 extract_token(buf, shared_with, i, '\n');
1105 extract_token(node, buf, 0, '|');
1106 for (j=0; j<num_tokens(not_shared_with, '\n'); ++j) {
1107 extract_token(cmd, not_shared_with, j, '\n');
1108 if (!strcasecmp(node, cmd)) {
1109 remove_token(not_shared_with, j, '\n');
1114 /* Display the stuff */
1115 wprintf("<CENTER><br />"
1116 "<TABLE border=1 cellpadding=5><TR>"
1117 "<TD><B><I>Shared with</I></B></TD>"
1118 "<TD><B><I>Not shared with</I></B></TD></TR>\n"
1119 "<TR><TD VALIGN=TOP>\n");
1121 wprintf("<TABLE border=0 cellpadding=5><TR BGCOLOR=\"#CCCCCC\">"
1122 "<TD>Remote node name</TD>"
1123 "<TD>Remote room name</TD>"
1128 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1129 extract_token(buf, shared_with, i, '\n');
1130 extract_token(node, buf, 0, '|');
1131 extract_token(remote_room, buf, 1, '|');
1132 if (strlen(node) > 0) {
1133 wprintf("<FORM METHOD=\"POST\" "
1134 "ACTION=\"/netedit\">"
1135 "<TR><TD>%s</TD>\n", node);
1138 if (strlen(remote_room) > 0) {
1139 escputs(remote_room);
1145 wprintf("<INPUT TYPE=\"hidden\" NAME=\"line\" "
1146 "VALUE=\"ignet_push_share|");
1148 if (strlen(remote_room) > 0) {
1150 urlescputs(remote_room);
1153 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" "
1154 "VALUE=\"sharing\">\n");
1155 wprintf("<INPUT TYPE=\"hidden\" NAME=\"cmd\" "
1156 "VALUE=\"remove\">\n");
1157 wprintf("<INPUT TYPE=\"submit\" "
1158 "NAME=\"sc\" VALUE=\"Unshare\">");
1159 wprintf("</TD></TR></FORM>\n");
1163 wprintf("</TABLE>\n");
1164 wprintf("</TD><TD VALIGN=TOP>\n");
1165 wprintf("<TABLE border=0 cellpadding=5><TR BGCOLOR=\"#CCCCCC\">"
1166 "<TD>Remote node name</TD>"
1167 "<TD>Remote room name</TD>"
1172 for (i=0; i<num_tokens(not_shared_with, '\n'); ++i) {
1173 extract_token(node, not_shared_with, i, '\n');
1174 if (strlen(node) > 0) {
1175 wprintf("<FORM METHOD=\"POST\" "
1176 "ACTION=\"/netedit\">"
1180 "<INPUT TYPE=\"INPUT\" "
1184 wprintf("<INPUT TYPE=\"hidden\" "
1186 "VALUE=\"ignet_push_share|");
1189 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" "
1190 "VALUE=\"sharing\">\n");
1191 wprintf("<INPUT TYPE=\"hidden\" NAME=\"cmd\" "
1192 "VALUE=\"add\">\n");
1193 wprintf("<INPUT TYPE=\"submit\" "
1194 "NAME=\"sc\" VALUE=\"Share\">");
1195 wprintf("</TD></TR></FORM>\n");
1199 wprintf("</TABLE>\n");
1200 wprintf("</TD></TR>"
1201 "</TABLE></CENTER><br />\n"
1202 "<I><B>Notes:</B><UL><LI>When sharing a room, "
1203 "it must be shared from both ends. Adding a node to "
1204 "the 'shared' list sends messages out, but in order to"
1205 " receive messages, the other nodes must be configured"
1206 " to send messages out to your system as well.\n"
1207 "<LI>If the remote room name is blank, it is assumed "
1208 "that the room name is identical on the remote node."
1209 "<LI>If the remote room name is different, the remote "
1210 "node must also configure the name of the room here."
1216 /* Mailing list management */
1217 if (!strcmp(tab, "listserv")) {
1219 wprintf("<br /><center>"
1220 "<TABLE BORDER=0 WIDTH=100%% CELLPADDING=5>"
1221 "<TR><TD VALIGN=TOP>");
1223 wprintf("<i>The contents of this room are being "
1224 "mailed <b>as individual messages</b> "
1225 "to the following list recipients:"
1226 "</i><br /><br />\n");
1230 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf, "000")) {
1231 extract(cmd, buf, 0);
1232 if (!strcasecmp(cmd, "listrecp")) {
1233 extract(recp, buf, 1);
1236 wprintf(" <A HREF=\"/netedit&cmd=remove&line="
1239 wprintf("&tab=listserv\">(remove)</A><br />");
1243 wprintf("<br /><FORM METHOD=\"POST\" ACTION=\"/netedit\">\n"
1244 "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1245 "<INPUT TYPE=\"hidden\" NAME=\"prefix\" VALUE=\"listrecp|\">\n");
1246 wprintf("<INPUT TYPE=\"text\" NAME=\"line\">\n");
1247 wprintf("<INPUT TYPE=\"submit\" NAME=\"cmd\" VALUE=\"Add\">");
1248 wprintf("</FORM>\n");
1250 wprintf("</TD><TD VALIGN=TOP>\n");
1252 wprintf("<i>The contents of this room are being "
1253 "mailed <b>in digest form</b> "
1254 "to the following list recipients:"
1255 "</i><br /><br />\n");
1259 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf, "000")) {
1260 extract(cmd, buf, 0);
1261 if (!strcasecmp(cmd, "digestrecp")) {
1262 extract(recp, buf, 1);
1265 wprintf(" <A HREF=\"/netedit&cmd=remove&line="
1268 wprintf("&tab=listserv\">(remove)</A><br />");
1272 wprintf("<br /><FORM METHOD=\"POST\" ACTION=\"/netedit\">\n"
1273 "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1274 "<INPUT TYPE=\"hidden\" NAME=\"prefix\" VALUE=\"digestrecp|\">\n");
1275 wprintf("<INPUT TYPE=\"text\" NAME=\"line\">\n");
1276 wprintf("<INPUT TYPE=\"submit\" NAME=\"cmd\" VALUE=\"Add\">");
1277 wprintf("</FORM>\n");
1279 wprintf("</TD></TR></TABLE><hr />\n");
1281 if (self_service(999) == 1) {
1282 wprintf("This room is configured to allow "
1283 "self-service subscribe/unsubscribe requests."
1284 " <A HREF=\"/toggle_self_service?newval=0&"
1286 "Click to disable.</A><br />\n"
1287 "The URL for subscribe/unsubscribe is: "
1288 "<TT>http://%s/listsub</TT><br />\n",
1293 wprintf("This room is <i>not</i> configured to allow "
1294 "self-service subscribe/unsubscribe requests."
1295 " <A HREF=\"/toggle_self_service?newval=1&"
1297 "Click to enable.</A><br />\n"
1302 wprintf("</CENTER>\n");
1306 /* Mailing list management */
1307 if (!strcmp(tab, "expire")) {
1309 serv_puts("GPEX room");
1311 if (buf[0] == '2') {
1312 roompolicy = extract_int(&buf[4], 0);
1313 roomvalue = extract_int(&buf[4], 1);
1316 serv_puts("GPEX floor");
1318 if (buf[0] == '2') {
1319 floorpolicy = extract_int(&buf[4], 0);
1320 floorvalue = extract_int(&buf[4], 1);
1323 wprintf("<br /><FORM METHOD=\"POST\" ACTION=\"/set_room_policy\">\n");
1324 wprintf("<TABLE border=0 cellspacing=5>\n");
1325 wprintf("<TR><TD>Message expire policy for this room<br />(");
1326 escputs(WC->wc_roomname);
1327 wprintf(")</TD><TD>");
1328 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"0\" %s>",
1329 ((roompolicy == 0) ? "CHECKED" : "") );
1330 wprintf("Use the default policy for this floor<br />\n");
1331 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"1\" %s>",
1332 ((roompolicy == 1) ? "CHECKED" : "") );
1333 wprintf("Never automatically expire messages<br />\n");
1334 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"2\" %s>",
1335 ((roompolicy == 2) ? "CHECKED" : "") );
1336 wprintf("Expire by message count<br />\n");
1337 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"3\" %s>",
1338 ((roompolicy == 3) ? "CHECKED" : "") );
1339 wprintf("Expire by message age<br />");
1340 wprintf("Number of messages or days: ");
1341 wprintf("<INPUT TYPE=\"text\" NAME=\"roomvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">", roomvalue);
1342 wprintf("</TD></TR>\n");
1344 if (WC->axlevel >= 6) {
1345 wprintf("<TR><TD COLSPAN=2><hr /></TD></TR>\n");
1346 wprintf("<TR><TD>Message expire policy for this floor<br />(");
1347 escputs(floorlist[WC->wc_floor]);
1348 wprintf(")</TD><TD>");
1349 wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"0\" %s>",
1350 ((floorpolicy == 0) ? "CHECKED" : "") );
1351 wprintf("Use the system default<br />\n");
1352 wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"1\" %s>",
1353 ((floorpolicy == 1) ? "CHECKED" : "") );
1354 wprintf("Never automatically expire messages<br />\n");
1355 wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"2\" %s>",
1356 ((floorpolicy == 2) ? "CHECKED" : "") );
1357 wprintf("Expire by message count<br />\n");
1358 wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"3\" %s>",
1359 ((floorpolicy == 3) ? "CHECKED" : "") );
1360 wprintf("Expire by message age<br />");
1361 wprintf("Number of messages or days: ");
1362 wprintf("<INPUT TYPE=\"text\" NAME=\"floorvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">",
1366 wprintf("<CENTER>\n");
1367 wprintf("<TR><TD COLSPAN=2><hr /><CENTER>\n");
1368 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1370 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1371 wprintf("</CENTER></TD><TR>\n");
1373 wprintf("</TABLE>\n"
1374 "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"expire\">\n"
1381 /* end content of whatever tab is open now */
1382 wprintf("</TD></TR></TABLE>\n");
1389 * Toggle self-service list subscription
1391 void toggle_self_service(void) {
1394 newval = atoi(bstr("newval"));
1395 self_service(newval);
1402 * save new parameters for a room
1408 char er_password[10];
1409 char er_dirname[15];
1410 char er_roomaide[26];
1416 if (strcmp(bstr("sc"), "OK")) {
1417 strcpy(WC->ImportantMessage,
1418 "Cancelled. Changes were not saved.");
1425 if (buf[0] != '2') {
1426 strcpy(WC->ImportantMessage, &buf[4]);
1430 extract(er_name, &buf[4], 0);
1431 extract(er_password, &buf[4], 1);
1432 extract(er_dirname, &buf[4], 2);
1433 er_flags = extract_int(&buf[4], 3);
1435 strcpy(er_roomaide, bstr("er_roomaide"));
1436 if (strlen(er_roomaide) == 0) {
1439 if (buf[0] != '2') {
1440 strcpy(er_roomaide, "");
1442 extract(er_roomaide, &buf[4], 0);
1445 strcpy(buf, bstr("er_name"));
1447 if (strlen(buf) > 0)
1448 strcpy(er_name, buf);
1450 strcpy(buf, bstr("er_password"));
1452 if (strlen(buf) > 0)
1453 strcpy(er_password, buf);
1455 strcpy(buf, bstr("er_dirname"));
1457 if (strlen(buf) > 0)
1458 strcpy(er_dirname, buf);
1460 strcpy(buf, bstr("type"));
1461 er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
1463 if (!strcmp(buf, "invonly")) {
1464 er_flags |= (QR_PRIVATE);
1466 if (!strcmp(buf, "guessname")) {
1467 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
1469 if (!strcmp(buf, "passworded")) {
1470 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
1472 if (!strcmp(bstr("prefonly"), "yes")) {
1473 er_flags |= QR_PREFONLY;
1475 er_flags &= ~QR_PREFONLY;
1478 if (!strcmp(bstr("readonly"), "yes")) {
1479 er_flags |= QR_READONLY;
1481 er_flags &= ~QR_READONLY;
1484 if (!strcmp(bstr("permanent"), "yes")) {
1485 er_flags |= QR_PERMANENT;
1487 er_flags &= ~QR_PERMANENT;
1490 if (!strcmp(bstr("network"), "yes")) {
1491 er_flags |= QR_NETWORK;
1493 er_flags &= ~QR_NETWORK;
1496 if (!strcmp(bstr("directory"), "yes")) {
1497 er_flags |= QR_DIRECTORY;
1499 er_flags &= ~QR_DIRECTORY;
1502 if (!strcmp(bstr("ulallowed"), "yes")) {
1503 er_flags |= QR_UPLOAD;
1505 er_flags &= ~QR_UPLOAD;
1508 if (!strcmp(bstr("dlallowed"), "yes")) {
1509 er_flags |= QR_DOWNLOAD;
1511 er_flags &= ~QR_DOWNLOAD;
1514 if (!strcmp(bstr("visdir"), "yes")) {
1515 er_flags |= QR_VISDIR;
1517 er_flags &= ~QR_VISDIR;
1520 strcpy(buf, bstr("anon"));
1522 er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
1523 if (!strcmp(buf, "anononly"))
1524 er_flags |= QR_ANONONLY;
1525 if (!strcmp(buf, "anon2"))
1526 er_flags |= QR_ANONOPT;
1529 if (!strcmp(bstr("bump"), "yes"))
1532 er_floor = atoi(bstr("er_floor"));
1534 sprintf(buf, "SETR %s|%s|%s|%u|%d|%d",
1535 er_name, er_password, er_dirname, er_flags, bump, er_floor);
1538 if (buf[0] != '2') {
1539 strcpy(WC->ImportantMessage, &buf[4]);
1545 if (strlen(er_roomaide) > 0) {
1546 sprintf(buf, "SETA %s", er_roomaide);
1549 if (buf[0] != '2') {
1550 strcpy(WC->ImportantMessage, &buf[4]);
1551 display_main_menu();
1556 strcpy(WC->ImportantMessage, "Your changes have been saved.");
1562 * Invite, Kick, and show Who Knows a room
1564 void display_whok(void)
1566 char buf[SIZ], room[SIZ], username[SIZ];
1571 if (buf[0] != '2') {
1572 strcpy(WC->ImportantMessage, &buf[4]);
1573 display_main_menu();
1576 extract(room, &buf[4], 0);
1578 strcpy(username, bstr("username"));
1580 if(!strcmp(bstr("sc"), "Kick")) {
1581 sprintf(buf, "KICK %s", username);
1585 if (buf[0] != '2') {
1586 strcpy(WC->ImportantMessage, &buf[4]);
1588 sprintf(WC->ImportantMessage,
1589 "<B><I>User %s kicked out of room %s.</I></B>\n",
1592 } else if(!strcmp(bstr("sc"), "Invite")) {
1593 sprintf(buf, "INVT %s", username);
1597 if (buf[0] != '2') {
1598 strcpy(WC->ImportantMessage, &buf[4]);
1600 sprintf(WC->ImportantMessage,
1601 "<B><I>User %s invited to room %s.</I></B>\n",
1606 output_headers(1, 1, 1, 0, 0, 0, 0);
1607 stresc(buf, WC->wc_roomname, 1, 1);
1608 svprintf("BOXTITLE", WCS_STRING, "Access control list for %s", buf);
1609 do_template("beginbox");
1611 wprintf("<TABLE border=0 CELLSPACING=10><TR VALIGN=TOP>"
1612 "<TD>The users listed below have access to this room. "
1613 "To remove a user from the access list, select the user "
1614 "name from the list and click 'Kick'.<br /><br />");
1616 wprintf("<CENTER><FORM METHOD=\"POST\" ACTION=\"/display_whok\">\n");
1617 wprintf("<SELECT NAME=\"username\" SIZE=10>\n");
1620 if (buf[0] == '1') {
1621 while (serv_gets(buf), strcmp(buf, "000")) {
1622 extract(username, buf, 0);
1623 wprintf("<OPTION>");
1628 wprintf("</SELECT><br />\n");
1630 wprintf("<input type=submit name=sc value=\"Kick\">");
1631 wprintf("</FORM></CENTER>\n");
1634 "To grant another user access to this room, enter the "
1635 "user name in the box below and click 'Invite'.<br /><br />");
1637 wprintf("<CENTER><FORM METHOD=\"POST\" ACTION=\"/display_whok\">\n");
1638 wprintf("Invite: ");
1639 wprintf("<input type=text name=username><br />\n"
1640 "<input type=hidden name=sc value=\"Invite\">"
1641 "<input type=submit value=\"Invite\">"
1642 "</FORM></CENTER>\n");
1644 wprintf("</TD></TR></TABLE>\n");
1645 do_template("endbox");
1652 * display the form for entering a new room
1654 void display_entroom(void)
1659 serv_puts("CRE8 0");
1662 if (buf[0] != '2') {
1663 strcpy(WC->ImportantMessage, &buf[4]);
1664 display_main_menu();
1667 output_headers(1, 1, 0, 0, 0, 0, 0);
1668 svprintf("BOXTITLE", WCS_STRING, "Create a new room");
1669 do_template("beginbox");
1671 wprintf("<FORM METHOD=\"POST\" ACTION=\"/entroom\">\n");
1673 wprintf("<UL><LI>Name of room: ");
1674 wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" MAXLENGTH=\"127\">\n");
1676 wprintf("<LI>Resides on floor: ");
1678 wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
1679 for (i = 0; i < 128; ++i)
1680 if (strlen(floorlist[i]) > 0) {
1681 wprintf("<OPTION ");
1682 wprintf("VALUE=\"%d\">", i);
1683 escputs(floorlist[i]);
1684 wprintf("</OPTION>\n");
1686 wprintf("</SELECT>\n");
1688 wprintf("<LI>Type of room:<UL>\n");
1690 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
1691 wprintf("CHECKED > Public room\n");
1693 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
1694 wprintf("> Private - guess name\n");
1696 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
1697 wprintf("> Private - require password:\n");
1698 wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
1700 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
1701 wprintf("> Private - invitation only\n");
1703 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"personal\" ");
1704 wprintf("> Personal (mailbox for you only)\n");
1707 wprintf("<LI>Default view for room: "); /* FOO */
1708 wprintf("<SELECT NAME=\"er_view\" SIZE=\"1\">\n");
1709 for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
1710 wprintf("<OPTION %s VALUE=\"%d\">",
1711 ((i == 0) ? "SELECTED" : ""), i );
1712 escputs(viewdefs[i]);
1713 wprintf("</OPTION>\n");
1715 wprintf("</SELECT>\n");
1717 wprintf("<CENTER>\n");
1718 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1720 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1721 wprintf("</CENTER>\n");
1722 wprintf("</FORM>\n<hr />");
1723 serv_printf("MESG roomaccess");
1725 if (buf[0] == '1') {
1726 fmout(NULL, "CENTER");
1728 do_template("endbox");
1736 * support function for entroom() -- sets the default view
1738 void er_set_default_view(int newview) {
1752 if (buf[0] != '2') return;
1754 extract(rm_name, &buf[4], 0);
1755 extract(rm_pass, &buf[4], 1);
1756 extract(rm_dir, &buf[4], 2);
1757 rm_bits1 = extract_int(&buf[4], 3);
1758 rm_floor = extract_int(&buf[4], 4);
1759 rm_listorder = extract_int(&buf[4], 5);
1760 rm_bits2 = extract_int(&buf[4], 7);
1762 serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1763 rm_name, rm_pass, rm_dir, rm_bits1, rm_floor,
1764 rm_listorder, newview, rm_bits2
1779 char er_password[SIZ];
1784 if (strcmp(bstr("sc"), "OK")) {
1785 strcpy(WC->ImportantMessage,
1786 "Cancelled. No new room was created.");
1787 display_main_menu();
1790 strcpy(er_name, bstr("er_name"));
1791 strcpy(er_type, bstr("type"));
1792 strcpy(er_password, bstr("er_password"));
1793 er_floor = atoi(bstr("er_floor"));
1794 er_view = atoi(bstr("er_view"));
1797 if (!strcmp(er_type, "guessname"))
1799 if (!strcmp(er_type, "passworded"))
1801 if (!strcmp(er_type, "invonly"))
1803 if (!strcmp(er_type, "personal"))
1806 sprintf(buf, "CRE8 1|%s|%d|%s|%d|%d|%d",
1807 er_name, er_num_type, er_password, er_floor, 0, er_view);
1810 if (buf[0] != '2') {
1811 strcpy(WC->ImportantMessage, &buf[4]);
1812 display_main_menu();
1816 do_change_view(er_view); /* Now go there */
1821 * display the screen to enter a private room
1823 void display_private(char *rname, int req_pass)
1826 output_headers(1, 1, 0, 0, 0, 0, 0);
1828 svprintf("BOXTITLE", WCS_STRING, "Go to a hidden room");
1829 do_template("beginbox");
1831 wprintf("<CENTER>\n");
1832 wprintf("<br />If you know the name of a hidden (guess-name) or\n");
1833 wprintf("passworded room, you can enter that room by typing\n");
1834 wprintf("its name below. Once you gain access to a private\n");
1835 wprintf("room, it will appear in your regular room listings\n");
1836 wprintf("so you don't have to keep returning here.\n");
1837 wprintf("<br /><br />");
1839 wprintf("<FORM METHOD=\"GET\" ACTION=\"/goto_private\">\n");
1841 wprintf("<table border=\"0\" cellspacing=\"5\" "
1842 "cellpadding=\"5\" BGCOLOR=\"#EEEEEE\">\n"
1844 "Enter room name:</TD><TD>"
1845 "<INPUT TYPE=\"text\" NAME=\"gr_name\" "
1846 "VALUE=\"%s\" MAXLENGTH=\"19\">\n", rname);
1849 wprintf("</TD></TR><TR><TD>");
1850 wprintf("Enter room password:</TD><TD>");
1851 wprintf("<INPUT TYPE=\"password\" NAME=\"gr_pass\" MAXLENGTH=\"9\">\n");
1853 wprintf("</TD></TR></TABLE><br />\n");
1855 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">"
1857 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1858 wprintf("</FORM>\n");
1859 do_template("endbox");
1864 * goto a private room
1866 void goto_private(void)
1871 if (strcasecmp(bstr("sc"), "OK")) {
1872 display_main_menu();
1875 strcpy(hold_rm, WC->wc_roomname);
1876 strcpy(buf, "GOTO ");
1877 strcat(buf, bstr("gr_name"));
1879 strcat(buf, bstr("gr_pass"));
1883 if (buf[0] == '2') {
1884 smart_goto(bstr("gr_name"));
1887 if (!strncmp(buf, "540", 3)) {
1888 display_private(bstr("gr_name"), 1);
1891 output_headers(1, 1, 1, 0, 0, 0, 0);
1892 wprintf("%s\n", &buf[4]);
1899 * display the screen to zap a room
1901 void display_zap(void)
1903 output_headers(1, 1, 2, 0, 0, 0, 0);
1905 wprintf("<div id=\"banner\">\n");
1906 wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#770000\"><TR><TD>");
1907 wprintf("<SPAN CLASS=\"titlebar\">Zap (forget/unsubscribe) the current room</SPAN>\n");
1908 wprintf("</TD></TR></TABLE>\n");
1909 wprintf("</div>\n<div id=\"content\">\n");
1911 wprintf("If you select this option, <em>%s</em> will ", WC->wc_roomname);
1912 wprintf("disappear from your room list. Is this what you wish ");
1913 wprintf("to do?<br />\n");
1915 wprintf("<FORM METHOD=\"GET\" ACTION=\"/zap\">\n");
1916 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1918 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1919 wprintf("</FORM>\n");
1930 char final_destination[SIZ];
1932 /* If the forget-room routine fails for any reason, we fall back
1933 * to the current room; otherwise, we go to the Lobby
1935 strcpy(final_destination, WC->wc_roomname);
1937 if (!strcasecmp(bstr("sc"), "OK")) {
1938 serv_printf("GOTO %s", WC->wc_roomname);
1940 if (buf[0] == '2') {
1943 if (buf[0] == '2') {
1944 strcpy(final_destination, "_BASEROOM_");
1948 smart_goto(final_destination);
1955 * Confirm deletion of the current room
1957 void confirm_delete_room(void)
1961 serv_puts("KILL 0");
1963 if (buf[0] != '2') {
1964 strcpy(WC->ImportantMessage, &buf[4]);
1965 display_main_menu();
1968 output_headers(1, 1, 2, 0, 0, 0, 0);
1969 wprintf("<div id=\"banner\">\n");
1970 wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#770000\"><TR><TD>");
1971 wprintf("<SPAN CLASS=\"titlebar\">Confirm deletion of room</SPAN>\n");
1972 wprintf("</TD></TR></TABLE>\n");
1973 wprintf("</div>\n<div id=\"content\">\n");
1975 wprintf("<CENTER>");
1976 wprintf("<FORM METHOD=\"GET\" ACTION=\"/delete_room\">\n");
1978 wprintf("Are you sure you want to delete <FONT SIZE=+1>");
1979 escputs(WC->wc_roomname);
1980 wprintf("</FONT>?<br />\n");
1982 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Delete\">");
1983 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1985 wprintf("</FORM></CENTER>\n");
1991 * Delete the current room
1993 void delete_room(void)
1998 strcpy(sc, bstr("sc"));
2000 if (strcasecmp(sc, "Delete")) {
2001 strcpy(WC->ImportantMessage,
2002 "Cancelled. This room was not deleted.");
2003 display_main_menu();
2006 serv_puts("KILL 1");
2008 if (buf[0] != '2') {
2009 strcpy(WC->ImportantMessage, &buf[4]);
2010 display_main_menu();
2013 smart_goto("_BASEROOM_");
2020 * Perform changes to a room's network configuration
2022 void netedit(void) {
2031 if (strlen(bstr("line"))==0) {
2036 strcpy(line, bstr("prefix"));
2037 strcat(line, bstr("line"));
2038 strcat(line, bstr("suffix"));
2048 if (buf[0] != '1') {
2054 /* This loop works for add *or* remove. Spiffy, eh? */
2055 while (serv_gets(buf), strcmp(buf, "000")) {
2056 extract(cmpa0, buf, 0);
2057 extract(cmpa1, buf, 1);
2058 extract(cmpb0, line, 0);
2059 extract(cmpb1, line, 1);
2060 if ( (strcasecmp(cmpa0, cmpb0))
2061 || (strcasecmp(cmpa1, cmpb1)) ) {
2062 fprintf(fp, "%s\n", buf);
2069 if (buf[0] != '4') {
2075 while (fgets(buf, sizeof buf, fp) != NULL) {
2076 buf[strlen(buf)-1] = 0;
2080 if (!strcasecmp(bstr("cmd"), "add")) {
2092 * Convert a room name to a folder-ish-looking name.
2094 void room_to_folder(char *folder, char *room, int floor, int is_mailbox)
2099 * For mailboxes, just do it straight...
2102 sprintf(folder, "My folders|%s", room);
2106 * Otherwise, prefix the floor name as a "public folders" moniker
2109 sprintf(folder, "%s|%s", floorlist[floor], room);
2113 * Replace "\" characters with "|" for pseudo-folder-delimiting
2115 for (i=0; i<strlen(folder); ++i) {
2116 if (folder[i] == '\\') folder[i] = '|';
2124 * Back end for change_view()
2126 void do_change_view(int newview) {
2129 serv_printf("VIEW %d", newview);
2131 WC->wc_view = newview;
2132 smart_goto(WC->wc_roomname);
2138 * Change the view for this room
2140 void change_view(void) {
2143 view = atol(bstr("view"));
2144 do_change_view(view);
2149 * One big expanded tree list view --- like a folder list
2151 void do_folder_view(struct folder *fold, int max_folders, int num_floors) {
2153 int levels, oldlevels;
2156 int has_subfolders = 0;
2158 /* Include the menu expanding/collapsing code */
2159 wprintf("<script type=\"text/javascript\" src=\"/static/menuExpandable3.js\"></script>\n");
2161 /* BEGIN TREE MENU */
2162 wprintf("<div id=\"mainMenu\">\n");
2163 wprintf("<UL id=\"menuList\">\n");
2167 for (i=0; i<max_folders; ++i) {
2170 if ((i+1) < max_folders) {
2171 if ( (!strncasecmp(fold[i].name, fold[i+1].name, strlen(fold[i].name)))
2172 && (fold[i+1].name[strlen(fold[i].name)] == '|') ) {
2177 levels = num_tokens(fold[i].name, '|');
2179 if ( (levels < oldlevels) || ((levels==1)&&(i!=0)) ) {
2180 for (t=0; t<(oldlevels-levels); ++t) {
2185 if (has_subfolders) {
2187 if (levels == 1) wprintf(" class=\"menubar\"");
2189 wprintf("<A href=\"#\" id=\"actuator%d\" class=\"actuator\"></a>\n", actnum);
2195 if (fold[i].selectable) {
2196 wprintf("<A HREF=\"/dotgoto?room=");
2197 urlescputs(fold[i].room);
2202 wprintf("<SPAN CLASS=\"roomlist_floor\">");
2204 else if (fold[i].hasnewmsgs) {
2205 wprintf("<SPAN CLASS=\"roomlist_new\">");
2208 wprintf("<SPAN CLASS=\"roomlist_old\">");
2210 extract(buf, fold[i].name, levels-1);
2214 if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
2215 wprintf(" (INBOX)");
2218 if (fold[i].selectable) {
2223 if (has_subfolders) {
2224 wprintf("<UL id=\"menu%d\" class=\"%s\">\n",
2226 ( (levels == 1) ? "menu" : "submenu")
2232 wprintf("</UL></UL>\n");
2233 wprintf("<img src=\"/static/blank.gif\" onLoad = ' \n");
2234 for (i=0; i<actnum; ++i) {
2235 wprintf(" initializeMenu(\"menu%d\", \"actuator%d\");\n", i, i);
2238 wprintf("</DIV>\n");
2243 * Boxes and rooms and lists ... oh my!
2245 void do_rooms_view(struct folder *fold, int max_folders, int num_floors) {
2248 int levels, oldlevels;
2251 static int columns = 3;
2252 int boxes_per_column = 0;
2253 int current_column = 0;
2257 while (nf % columns != 0) ++nf;
2258 boxes_per_column = (nf / columns);
2259 if (boxes_per_column < 1) boxes_per_column = 1;
2261 /* Outer table (for columnization) */
2262 wprintf("<TABLE BORDER=0 WIDTH=96%% CELLPADDING=5>"
2263 "<tr><td valign=top>");
2267 for (i=0; i<max_folders; ++i) {
2269 levels = num_tokens(fold[i].name, '|');
2271 if ((levels == 1) && (oldlevels > 1)) {
2274 do_template("endbox");
2277 if ((num_boxes % boxes_per_column) == 0) {
2279 if (current_column < columns) {
2280 wprintf("</td><td valign=top>\n");
2287 /* Begin inner box */
2288 extract(buf, fold[i].name, levels-1);
2289 stresc(boxtitle, buf, 1, 0);
2290 svprintf("BOXTITLE", WCS_STRING, boxtitle);
2291 do_template("beginbox");
2299 if (levels>2) for (t=0; t<(levels-2); ++t) wprintf(" ");
2300 if (fold[i].selectable) {
2301 wprintf("<A HREF=\"/dotgoto?room=");
2302 urlescputs(fold[i].room);
2308 if (fold[i].hasnewmsgs) {
2309 wprintf("<SPAN CLASS=\"roomlist_new\">");
2312 wprintf("<SPAN CLASS=\"roomlist_old\">");
2314 extract(buf, fold[i].name, levels-1);
2317 if (fold[i].selectable) {
2323 if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
2324 wprintf(" (INBOX)");
2326 wprintf("<br />\n");
2329 /* End the final inner box */
2330 do_template("endbox");
2332 wprintf("</TD></TR></TABLE>\n");
2337 * Show the room list. (only should get called by
2338 * knrooms() because that's where output_headers() is called from)
2341 void list_all_rooms_by_floor(char *viewpref) {
2344 struct folder *fold = NULL;
2346 int max_folders = 0;
2347 int alloc_folders = 0;
2351 int num_floors = 1; /* add an extra one for private folders */
2353 /* Start with the mailboxes */
2356 fold = malloc(sizeof(struct folder));
2357 memset(fold, 0, sizeof(struct folder));
2358 strcpy(fold[0].name, "My folders");
2359 fold[0].is_mailbox = 1;
2361 /* Then add floors */
2364 if (buf[0]=='1') while(serv_gets(buf), strcmp(buf, "000")) {
2365 if (max_folders >= alloc_folders) {
2366 alloc_folders = max_folders + 100;
2367 fold = realloc(fold,
2368 alloc_folders * sizeof(struct folder));
2370 memset(&fold[max_folders], 0, sizeof(struct folder));
2371 extract(fold[max_folders].name, buf, 1);
2379 if (buf[0]=='1') while(serv_gets(buf), strcmp(buf, "000")) {
2380 if (max_folders >= alloc_folders) {
2381 alloc_folders = max_folders + 100;
2382 fold = realloc(fold,
2383 alloc_folders * sizeof(struct folder));
2385 memset(&fold[max_folders], 0, sizeof(struct folder));
2386 extract(fold[max_folders].room, buf, 0);
2387 ra_flags = extract_int(buf, 5);
2388 flags = extract_int(buf, 1);
2389 fold[max_folders].floor = extract_int(buf, 2);
2390 fold[max_folders].hasnewmsgs =
2391 ((ra_flags & UA_HASNEWMSGS) ? 1 : 0 );
2392 if (flags & QR_MAILBOX) {
2393 fold[max_folders].is_mailbox = 1;
2395 room_to_folder(fold[max_folders].name,
2396 fold[max_folders].room,
2397 fold[max_folders].floor,
2398 fold[max_folders].is_mailbox);
2399 fold[max_folders].selectable = 1;
2403 /* Bubble-sort the folder list */
2404 for (i=0; i<max_folders; ++i) {
2405 for (j=0; j<(max_folders-1)-i; ++j) {
2406 if (fold[j].is_mailbox == fold[j+1].is_mailbox) {
2407 swap = strcasecmp(fold[j].name, fold[j+1].name);
2410 if ( (fold[j+1].is_mailbox)
2411 && (!fold[j].is_mailbox)) {
2419 memcpy(&ftmp, &fold[j], sizeof(struct folder));
2420 memcpy(&fold[j], &fold[j+1],
2421 sizeof(struct folder));
2422 memcpy(&fold[j+1], &ftmp,
2423 sizeof(struct folder));
2428 /* test only hackish view
2429 wprintf("<table><TR><TD>A Table</TD></TR></table>\n");
2430 for (i=0; i<max_folders; ++i) {
2431 escputs(fold[i].name);
2432 wprintf("<br />\n");
2436 if (!strcasecmp(viewpref, "folders")) {
2437 do_folder_view(fold, max_folders, num_floors);
2440 do_rooms_view(fold, max_folders, num_floors);
2448 /* Do either a known rooms list or a folders list, depending on the
2452 char listviewpref[SIZ];
2454 output_headers(1, 1, 2, 0, 0, 0, 0);
2457 /* Determine whether the user is trying to change views */
2458 if (bstr("view") != NULL) {
2459 if (strlen(bstr("view")) > 0) {
2460 set_preference("roomlistview", bstr("view"));
2464 get_preference("roomlistview", listviewpref);
2466 if ( (strcasecmp(listviewpref, "folders"))
2467 && (strcasecmp(listviewpref, "table")) ) {
2468 strcpy(listviewpref, "rooms");
2472 wprintf("<div id=\"banner\">\n"
2473 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
2474 "<SPAN CLASS=\"titlebar\">"
2476 if (!strcasecmp(listviewpref, "rooms")) {
2477 wprintf("Room list");
2479 if (!strcasecmp(listviewpref, "folders")) {
2480 wprintf("Folder list");
2482 if (!strcasecmp(listviewpref, "table")) {
2483 wprintf("Room list");
2485 wprintf("</SPAN></TD>\n");
2487 /* offer the ability to switch views */
2488 wprintf("<TD ALIGN=RIGHT><FORM NAME=\"roomlistomatic\">\n"
2489 "<SELECT NAME=\"newview\" SIZE=\"1\" "
2490 "OnChange=\"location.href=roomlistomatic.newview.options"
2491 "[selectedIndex].value\">\n");
2493 wprintf("<OPTION %s VALUE=\"/knrooms&view=rooms\">"
2496 ( !strcasecmp(listviewpref, "rooms") ? "SELECTED" : "" )
2499 wprintf("<OPTION %s VALUE=\"/knrooms&view=folders\">"
2500 "View as folder list"
2502 ( !strcasecmp(listviewpref, "folders") ? "SELECTED" : "" )
2505 wprintf("</SELECT><br />");
2507 wprintf("</FORM></TD></TR></TABLE>\n");
2509 "<div id=\"content\">\n");
2511 /* Display the room list in the user's preferred format */
2512 list_all_rooms_by_floor(listviewpref);
2518 * Set the message expire policy for this room and/or floor
2520 void set_room_policy(void) {
2523 if (strcmp(bstr("sc"), "OK")) {
2524 strcpy(WC->ImportantMessage,
2525 "Cancelled. Changes were not saved.");
2530 serv_printf("SPEX room|%d|%d", atoi(bstr("roompolicy")), atoi(bstr("roomvalue")));
2532 strcpy(WC->ImportantMessage, &buf[4]);
2534 if (WC->axlevel >= 6) {
2535 strcat(WC->ImportantMessage, "<br />\n");
2536 serv_printf("SPEX floor|%d|%d", atoi(bstr("floorpolicy")), atoi(bstr("floorvalue")));
2538 strcat(WC->ImportantMessage, &buf[4]);