#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "bbs.h"
#include "lua/lua.h"
#include "lua/lualib.h"
#include "lua/lauxlib.h"

#define MENU_SUBMENU            1
#define MENU_LOGOFF             2
#define MENU_PREVMENU           3
#define MENU_AUTOMESSAGE        4
#define MENU_TEXTFILES          5
#define MENU_CHATSYSTEM         6
#define MENU_BBSLIST            7
#define MENU_LISTUSERS          8
#define MENU_BULLETINS          9
#define MENU_LAST10             10
#define MENU_SETTINGS           11
#define MENU_DOOR               12
#define MENU_MAILSCAN           13
#define MENU_READMAIL           14
#define MENU_POSTMESSAGE        15
#define MENU_CHOOSEMAILCONF     16
#define MENU_CHOOSEMAILAREA     17
#define MENU_SENDEMAIL          18
#define MENU_LISTEMAIL          19
#define MENU_NEXTMAILCONF       20
#define MENU_PREVMAILCONF       21
#define MENU_NEXTMAILAREA       22
#define MENU_PREVMAILAREA       23
#define MENU_BLUEWAVEDOWN       24
#define MENU_BLUEWAVEUP         25
#define MENU_CHOOSEFILEDIR      26
#define MENU_CHOOSEFILESUB      27
#define MENU_LISTFILES          28
#define MENU_UPLOAD             29
#define MENU_DOWNLOAD           30
#define MENU_CLEARTAGGEDFILES   31
#define MENU_NEXTFILEDIR        32
#define MENU_PREVFILEDIR        33
#define MENU_NEXTFILESUB        34
#define MENU_PREVFILESUB        35
#define MENU_LISTMESSAGES       36
#define MENU_DOSCRIPT           37
#define MENU_SENDNODEMSG        38
#define MENU_SUBUNSUBCONF		39
#define MENU_RESETPOINTERS      40
#define MENU_RESETALLPOINTERS   41
#define MENU_FILESCAN           42
#define MENU_FULLMAILSCAN       43
#define MENU_FILESEARCH			44
#define MENU_DISPTXTFILE		45
#define MENU_DISPTXTFILEPAUSE	46
#define MENU_GENWWWURLS         47
#define MENU_NLBROWSER          48
#define MENU_SENDFEEDBACK       49
#define MENU_BLOGDISPLAY        50
#define MENU_BLOGWRITE          51

extern struct bbs_config conf;
extern struct user_record *gUser;
extern int mynode;

struct menu_item {
    char hotkey;
    int *command;
    char **data;
    int command_count;
    int seclevel;
};

int menu_system(char *menufile) {
    FILE *fptr;
    char buffer[PATH_MAX];
    int menu_items = 0;
    struct menu_item **menu;
    char *lua_script;
    int do_lua_menu;
    char *ansi_file;
    int i;
    int j;
    int k;
    int m;
    struct stat s;
    char *lRet;
	lua_State *L;
    int result;
    int doquit = 0;
    char c;
    int clearscreen = 0;
	char confirm;
    char *msg;

    dolog("%s is loading menu: %s", gUser->loginname, menufile);
	broadcast("USER: %s; NODE:%d; STATUS: Browsing menu %s.", gUser->loginname, mynode, menufile);


    if (menufile[0] == '/') {
        snprintf(buffer, PATH_MAX, "%s.mnu", menufile);
    } else {
        snprintf(buffer, PATH_MAX, "%s/%s.mnu", conf.menu_path, menufile);
    }
    fptr = fopen(buffer, "r");
    
    if (!fptr) {
        s_printf("Error opening menu file! %s\r\n", menufile);
        return 0;
    }

    lua_script = NULL;
    ansi_file = NULL;


    fgets(buffer, 256, fptr);
    while (!feof(fptr)) {


        chomp(buffer);

        if (strncasecmp(buffer, "HOTKEY", 6) == 0) {
            menu_items++;
            if (menu_items == 1) {
                menu = (struct menu_item **)malloc(sizeof(struct menu_item *));
            } else {
                menu = (struct menu_item **)realloc(menu, sizeof(struct menu_item *) * (menu_items));
            }
            menu[menu_items-1] = (struct menu_item *)malloc(sizeof(struct menu_item));
            menu[menu_items-1]->hotkey = buffer[7];
            menu[menu_items-1]->command = NULL;
            menu[menu_items-1]->data = NULL;
            menu[menu_items-1]->command_count = 0;
            menu[menu_items-1]->seclevel = 0;
        } else if (strncasecmp(buffer, "COMMAND", 7) == 0 && menu_items > 0) {
            if (menu[menu_items-1]->command_count == 0) {
                menu[menu_items-1]->command = (int *)malloc(sizeof(int));
                menu[menu_items-1]->data = (char **)malloc(sizeof(char *));
            } else {
                menu[menu_items-1]->command = (int *)realloc(menu[menu_items-1]->command, sizeof(int) * (menu[menu_items-1]->command_count + 1));
                menu[menu_items-1]->data = (char **)realloc(menu[menu_items-1]->data, sizeof(char *) * (menu[menu_items-1]->command_count + 1));
            }
            menu[menu_items-1]->command_count++;
            menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = 0;
            menu[menu_items-1]->data[menu[menu_items -1]->command_count - 1] = NULL;
            if (strncasecmp(&buffer[8], "SUBMENU", 7) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SUBMENU;
            } else if (strncasecmp(&buffer[8], "LOGOFF", 6) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LOGOFF;
            } else if (strncasecmp(&buffer[8], "PREVMENU", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_PREVMENU;
            } else if (strncasecmp(&buffer[8], "AUTOMESSAGE", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_AUTOMESSAGE;
            } else if (strncasecmp(&buffer[8], "TEXTFILES", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_TEXTFILES;
            } else if (strncasecmp(&buffer[8], "CHATSYSTEM", 10) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CHATSYSTEM;
            } else if (strncasecmp(&buffer[8], "BBSLIST", 7) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BBSLIST;
            } else if (strncasecmp(&buffer[8], "LISTUSERS", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LISTUSERS;
            } else if (strncasecmp(&buffer[8], "BULLETINS", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BULLETINS;
            } else if (strncasecmp(&buffer[8], "LAST10CALLERS", 13) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LAST10;
            } else if (strncasecmp(&buffer[8], "SETTINGS", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SETTINGS;
            } else if (strncasecmp(&buffer[8], "RUNDOOR", 7) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_DOOR;
            } else if (strncasecmp(&buffer[8], "MAILSCAN", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_MAILSCAN;
            } else if (strncasecmp(&buffer[8], "READMAIL", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_READMAIL;
            } else if (strncasecmp(&buffer[8], "POSTMESSAGE", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_POSTMESSAGE;
            } else if (strncasecmp(&buffer[8], "CHOOSEMAILCONF", 14) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CHOOSEMAILCONF;
            } else if (strncasecmp(&buffer[8], "CHOOSEMAILAREA", 14) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CHOOSEMAILAREA;
            } else if (strncasecmp(&buffer[8], "SENDEMAIL", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SENDEMAIL;
            } else if (strncasecmp(&buffer[8], "LISTEMAIL", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LISTEMAIL;
            } else if (strncasecmp(&buffer[8], "NEXTMAILCONF", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_NEXTMAILCONF;
            } else if (strncasecmp(&buffer[8], "PREVMAILCONF", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_PREVMAILCONF;
            } else if (strncasecmp(&buffer[8], "NEXTMAILAREA", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_NEXTMAILAREA;
            } else if (strncasecmp(&buffer[8], "PREVMAILAREA", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_PREVMAILAREA;
            } else if (strncasecmp(&buffer[8], "BLUEWAVEDOWNLOAD", 16) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BLUEWAVEDOWN;
            } else if (strncasecmp(&buffer[8], "BLUEWAVEUPLOAD", 14) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BLUEWAVEUP;
            } else if (strncasecmp(&buffer[8], "CHOOSEFILEDIR", 13) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CHOOSEFILEDIR;
            } else if (strncasecmp(&buffer[8], "CHOOSEFILESUB", 13) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CHOOSEFILESUB;
            } else if (strncasecmp(&buffer[8], "LISTFILES", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LISTFILES;
            } else if (strncasecmp(&buffer[8], "UPLOAD", 6) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_UPLOAD;
            } else if (strncasecmp(&buffer[8], "DOWNLOAD", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_DOWNLOAD;
            } else if (strncasecmp(&buffer[8], "CLEARTAGGED", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_CLEARTAGGEDFILES;
            } else if (strncasecmp(&buffer[8], "NEXTFILEDIR", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_NEXTFILEDIR;
            } else if (strncasecmp(&buffer[8], "PREVFILEDIR", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_PREVFILEDIR;
            } else if (strncasecmp(&buffer[8], "NEXTFILESUB", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_NEXTFILESUB;
            } else if (strncasecmp(&buffer[8], "PREVFILESUB", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_PREVFILESUB;
            } else if (strncasecmp(&buffer[8], "LISTMESSAGES", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_LISTMESSAGES;
            } else if (strncasecmp(&buffer[8], "DOSCRIPT", 8) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_DOSCRIPT;
            } else if (strncasecmp(&buffer[8], "SENDNODEMSG", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SENDNODEMSG;
            } else if (strncasecmp(&buffer[8], "SUBUNSUBCONF", 12) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SUBUNSUBCONF;
			} else if (strncasecmp(&buffer[8], "RESETMSGPTRS", 12) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_RESETPOINTERS;
			} else if (strncasecmp(&buffer[8], "RESETALLMSGPTRS", 15) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_RESETALLPOINTERS;
			} else if (strncasecmp(&buffer[8], "FILESCAN", 8) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_FILESCAN;
			} else if (strncasecmp(&buffer[8], "FULLMAILSCAN", 12) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_FULLMAILSCAN;
			} else if (strncasecmp(&buffer[8], "FILESEARCH", 10) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_FILESEARCH;
			} else if (strncasecmp(&buffer[8], "DISPLAYTXTFILE", 14) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_DISPTXTFILE;
			} else if (strncasecmp(&buffer[8], "DISPLAYTXTPAUSE", 15) == 0) {
				menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_DISPTXTFILEPAUSE;
			} else if (strncasecmp(&buffer[8], "GENWWWURLS", 10) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_GENWWWURLS;
            } else if (strncasecmp(&buffer[8], "NLBROWSER", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_NLBROWSER;
            } else if (strncasecmp(&buffer[8], "SENDFEEDBACK", 12) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_SENDFEEDBACK;
            } else if (strncasecmp(&buffer[8], "BLOGDISPLAY", 11) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BLOGDISPLAY;
            } else if (strncasecmp(&buffer[8], "BLOGWRITE", 9) == 0) {
                menu[menu_items-1]->command[menu[menu_items -1]->command_count - 1] = MENU_BLOGWRITE;
            }
        } else if (strncasecmp(buffer, "SECLEVEL", 8) == 0) {
            menu[menu_items-1]->seclevel = atoi(&buffer[9]);
        } else if (strncasecmp(buffer, "DATA", 4) == 0) {
            if (menu[menu_items-1]->data[menu[menu_items -1]->command_count - 1] != NULL) {
                free(menu[menu_items-1]->data[menu[menu_items -1]->command_count - 1]);
            }
            menu[menu_items-1]->data[menu[menu_items -1]->command_count - 1] = strdup(&buffer[5]);
        } else if (strncasecmp(buffer, "LUASCRIPT", 9) == 0) {
            if (lua_script != NULL) {
                free(lua_script);
            }
            lua_script = strdup(&buffer[10]);
        } else if (strncasecmp(buffer, "ANSIFILE", 8) == 0) {
            if (ansi_file != NULL) {
                free(ansi_file);
            }
            ansi_file = strdup(&buffer[9]);
        } else if (strncasecmp(buffer, "CLEARSCREEN", 11) == 0) {
			clearscreen = 1;
		}

        fgets(buffer, 256, fptr);
    }
    fclose(fptr);

    do_lua_menu = 0;

    if (lua_script != NULL) {
        if (conf.script_path != NULL && lua_script[0] != '/') {
            snprintf(buffer, PATH_MAX, "%s/%s.lua", conf.script_path, lua_script);
            do_lua_menu = 1;
        } else if (lua_script[0] == '/') {
            snprintf(buffer, PATH_MAX, "%s.lua", lua_script);
            do_lua_menu = 1;
        } 

        if (do_lua_menu) {
            if (stat(buffer, &s) == 0) {
                L = luaL_newstate();
                luaL_openlibs(L);
                lua_push_cfunctions(L);
                luaL_loadfile(L, buffer);
                do_lua_menu = 1;
                result = lua_pcall(L, 0, 1, 0);
                if (result) {
                    dolog("Failed to run script: %s", lua_tostring(L, -1));
                    do_lua_menu = 0;
                }
            } else {
                do_lua_menu = 0;
            }
        }
    }


	while (!doquit) {
        if (gUser->nodemsgs) {
            snprintf(buffer, PATH_MAX, "%s/node%d/nodemsg.txt", conf.bbs_path, mynode);

            if (stat(buffer, &s) == 0) {
                fptr = fopen(buffer, "r");
                if (fptr) {
                    fgets(buffer, PATH_MAX, fptr);
                    while (!feof(fptr)) {
                        chomp(buffer);
                        s_printf("\r\n%s\r\n", buffer);
                        fgets(buffer, PATH_MAX, fptr);
                    }
                    fclose(fptr);
                    snprintf(buffer, PATH_MAX, "%s/node%d/nodemsg.txt", conf.bbs_path, mynode);
                    unlink(buffer);

                    s_printf(get_string(6));
                    c = s_getc();
                }
            }
        }
        
        if (clearscreen) {
			s_printf("\e[2J\e[1;1H");
		}
        
		if (do_lua_menu == 0) {
            if (ansi_file != NULL) {
			    s_displayansi(ansi_file);
            }
			s_printf(get_string(142), gUser->timeleft);
			c = s_getc();
		} else {
			lua_getglobal(L, "menu");
			result = lua_pcall(L, 0, 1, 0);
			if (result) {
				dolog("Failed to run script: %s", lua_tostring(L, -1));
				do_lua_menu = 0;
				lua_close(L);
				continue;
			}
			lRet = (char *)lua_tostring(L, -1);
            c = lRet[0];
			lua_pop(L, 1);
		}

        for (i=0;i<menu_items;i++) {
            if (tolower(menu[i]->hotkey) == tolower(c)) {
                if (menu[i]->seclevel <= gUser->sec_level) {
                    for (j=0; j<menu[i]->command_count;j++) {
                        switch(menu[i]->command[j]) {
                            case MENU_SUBMENU:
                                doquit = menu_system(menu[i]->data[j]);
                                if (doquit == 1) {
                                    // free menus
                                    if (do_lua_menu) {
                                        lua_close(L);
                                    }
                                    if (lua_script != NULL) {
                                        free(lua_script);
                                    }
                                    if (ansi_file != NULL) {
                                        free(ansi_file);
                                    }
                                    for (i=0;i<menu_items;i++) {
                                        for (j=0;j<menu[i]->command_count;j++) {
                                            if (menu[i]->data[j] != NULL) {
                                                free(menu[i]->data[j]);
                                            }
                                        }
                                        free(menu[i]->data);
                                        free(menu[i]->command);
                                        free(menu[i]);
                                    }
                                    free(menu);
                                    return doquit;
                                }
                                break;
                            case MENU_LOGOFF:
                                if (do_lua_menu) {
                                    lua_close(L);
                                }              
                                if (lua_script != NULL) {
                                    free(lua_script);
                                }
                                if (ansi_file != NULL) {
                                    free(ansi_file);
                                }
                                for (i=0;i<menu_items;i++) {
                                    for (j=0;j<menu[i]->command_count;j++) {
                                        if (menu[i]->data[j] != NULL) {
                                            free(menu[i]->data[j]);
                                        }
                                    }
                                    free(menu[i]->data);
                                    free(menu[i]->command);
                                    free(menu[i]);
                                }
                                free(menu);                              
                                return 1;
                            case MENU_PREVMENU:
                                if (do_lua_menu) {
                                    lua_close(L);
                                }                    
                                if (lua_script != NULL) {
                                    free(lua_script);
                                }
                                if (ansi_file != NULL) {
                                    free(ansi_file);
                                }
                                for (i=0;i<menu_items;i++) {
                                    for (j=0;j<menu[i]->command_count;j++) {
                                        if (menu[i]->data[j] != NULL) {
                                            free(menu[i]->data[j]);
                                        }
                                    }
                                    free(menu[i]->data);
                                    free(menu[i]->command);
                                    free(menu[i]);
                                }
                                free(menu);                                                      
                                return 0;
                            case MENU_AUTOMESSAGE:
                                broadcast("USER: %s; NODE:%d; STATUS: Viewing/Changing Automessage.", gUser->loginname, mynode);
                                automessage();
                                break;
                            case MENU_TEXTFILES:
                                broadcast("USER: %s; NODE:%d; STATUS: Browsing Textfiles.", gUser->loginname, mynode);
                                display_textfiles();
                                break;
                            case MENU_CHATSYSTEM:
                                broadcast("USER: %s; NODE:%d; STATUS: In Chat System.", gUser->loginname, mynode);
                                chat_system(gUser);
                                break;
                            case MENU_BBSLIST:
                                broadcast("USER: %s; NODE:%d; STATUS: Browsing BBS List.", gUser->loginname, mynode);
                                bbs_list(gUser);
                                break;
                            case MENU_LISTUSERS:
                                broadcast("USER: %s; NODE:%d; STATUS: Browsing User List.", gUser->loginname, mynode);
                                list_users(gUser);
                                break;
                            case MENU_BULLETINS:
                                broadcast("USER: %s; NODE:%d; STATUS: Reading Bulletins.", gUser->loginname, mynode);
                                display_bulletins();
                                break;
                            case MENU_LAST10:
                                broadcast("USER: %s; NODE:%d; STATUS: Viewing Last 10 Callers.", gUser->loginname, mynode);
                                display_last10_callers(gUser);
                                break;
                            case MENU_SETTINGS:
                                settings_menu(gUser);
                                break;
                            case MENU_DOOR:
                                {
                                    for (m=0;m<conf.door_count;m++) {
                                        if (strcasecmp(menu[i]->data[j], conf.doors[m]->name) == 0) {
                                            dolog("%s launched door %s, on node %d", gUser->loginname, conf.doors[m]->name, mynode);
                                            broadcast("USER: %s; NODE:%d; STATUS: Executing Door %s.", gUser->loginname, mynode, conf.doors[m]->name);
                                            rundoor(gUser, conf.doors[m]->command, conf.doors[m]->stdio, conf.doors[m]->codepage);
                                            dolog("%s returned from door %s, on node %d", gUser->loginname, conf.doors[m]->name, mynode);
                                            break;
                                        }
                                    }
                                }
                                break;
                            case MENU_MAILSCAN:
                                broadcast("USER: %s; NODE:%d; STATUS: Performing Mail Scan.", gUser->loginname, mynode);
                                mail_scan(gUser);
                                break;
                            case MENU_READMAIL:
                                broadcast("USER: %s; NODE:%d; STATUS: Reading Mail.", gUser->loginname, mynode);
                                read_mail(gUser);
                                break;
                            case MENU_POSTMESSAGE:
                                broadcast("USER: %s; NODE:%d; STATUS: Posting a Message.", gUser->loginname, mynode);
                                post_message(gUser);
                                break;
                            case MENU_CHOOSEMAILCONF:
                                broadcast("USER: %s; NODE:%d; STATUS: Choosing Mail Conference.", gUser->loginname, mynode);
                                choose_conference();
                                break;
                            case MENU_CHOOSEMAILAREA:
                                broadcast("USER: %s; NODE:%d; STATUS: Choosing Mail Area.", gUser->loginname, mynode);
                                choose_area();
                                break;
                            case MENU_SENDEMAIL:
                                broadcast("USER: %s; NODE:%d; STATUS: Sending an Email.", gUser->loginname, mynode);
                                send_email(gUser);
                                break;
                            case MENU_LISTEMAIL:
                                broadcast("USER: %s; NODE:%d; STATUS: Browsing their Emails.", gUser->loginname, mynode);
                                list_emails(gUser);
                                break;
                            case MENU_NEXTMAILCONF:
                                next_mail_conf(gUser);
                                break;
                            case MENU_PREVMAILCONF:
                                prev_mail_conf(gUser);
                                break;
                            case MENU_NEXTMAILAREA:
                                next_mail_area(gUser);
                                break;
                            case MENU_PREVMAILAREA:
                                prev_mail_area(gUser);
                                break;
                            case MENU_BLUEWAVEDOWN:
                                broadcast("USER: %s; NODE:%d; STATUS: Downloading Bluewave Packet.", gUser->loginname, mynode);
                                bwave_create_packet();
                                break;
                            case MENU_BLUEWAVEUP:
                                broadcast("USER: %s; NODE:%d; STATUS: Uploading Bluewave Packet.", gUser->loginname, mynode);
                                bwave_upload_reply();
                                break;
                            case MENU_CHOOSEFILEDIR:
                                broadcast("USER: %s; NODE:%d; STATUS: Choosing a file directory.", gUser->loginname, mynode);
                                choose_directory();
                                break;
                            case MENU_CHOOSEFILESUB:
                                broadcast("USER: %s; NODE:%d; STATUS: Choosing a file sub-directory.", gUser->loginname, mynode);
                                choose_subdir();
                                break;
                            case MENU_LISTFILES:
                                broadcast("USER: %s; NODE:%d; STATUS: Browsing Files.", gUser->loginname, mynode);
                                list_files(gUser);
                                break;
                            case MENU_UPLOAD:
                                if (gUser->sec_level >= conf.file_directories[gUser->cur_file_dir]->file_subs[gUser->cur_file_sub]->upload_sec_level) {
                                    broadcast("USER: %s; NODE:%d; STATUS: Uploading a File.", gUser->loginname, mynode);
                                    upload(gUser);
                                } else {
                                    s_printf(get_string(84));
                                }
                                break;
                            case MENU_DOWNLOAD:
                                broadcast("USER: %s; NODE:%d; STATUS: Downloading Files.", gUser->loginname, mynode);
                                download(gUser);
                                break;
                            case MENU_CLEARTAGGEDFILES:
                                clear_tagged_files();
                                break;
                            case MENU_NEXTFILEDIR:
                                next_file_dir(gUser);
                                break;
                            case MENU_PREVFILEDIR:
                                prev_file_dir(gUser);
                                break;
                            case MENU_NEXTFILESUB:
                                next_file_sub(gUser);
                                break;
                            case MENU_PREVFILESUB:
                                prev_file_sub(gUser);
                                break; 
                            case MENU_LISTMESSAGES:
                                list_messages(gUser);
                                break;
                            case MENU_DOSCRIPT:
                                broadcast("USER: %s; NODE:%d; STATUS: Executing a script %s.", gUser->loginname, mynode, menu[i]->data[j]);
                                do_lua_script(menu[i]->data[j]);
                                break;
                            case MENU_SENDNODEMSG:
                                broadcast("USER: %s; NODE:%d; STATUS: Sending a node Message.", gUser->loginname, mynode);
                                send_node_msg();
                                break;
                            case MENU_SUBUNSUBCONF:
                                broadcast("USER: %s; NODE:%d; STATUS: Subscribing to conferences.", gUser->loginname, mynode);
                                msg_conf_sub_bases();
                                break;
                            case MENU_RESETPOINTERS:
                                s_printf(get_string(229));
                                s_readstring(buffer, 10);
                                if (tolower(buffer[0]) == 'r') {
                                    k = -1;
                                    m = 1;
                                } else if (tolower(buffer[0]) == 'u') {
                                    k = -1;
                                    m = 0;
                                } else if (buffer[0] < '0' || buffer[0] > '9') {
                                    s_printf(get_string(39));
                                    break;
                                } else {
                                    k = atoi(buffer) - 1;
                                }

                                msgbase_reset_pointers(gUser->cur_mail_conf, gUser->cur_mail_area, m, k);

                                break;
                            case MENU_RESETALLPOINTERS:
                                s_printf(get_string(230));
                                confirm = s_getc();
                                if (confirm == 'r' || confirm == 'R') {
                                    m = 1;
                                } else if (confirm == 'u' || confirm == 'U') {
                                    m = 0;
                                } else {
                                    s_printf(get_string(39));
                                    break;
                                }                        
                                msgbase_reset_all_pointers(m);
                                break;
                            case MENU_FILESCAN:
                                broadcast("USER: %s; NODE:%d; STATUS: Doing a filescan.", gUser->loginname, mynode);
                                file_scan();
                                break;
                            case MENU_FULLMAILSCAN:
                                if (menu[i]->data[j] != NULL) {
                                    if (strcasecmp(menu[i]->data[j], "PERSONAL") == 0) {
                                        broadcast("USER: %s; NODE:%d; STATUS: Scanning for personal mail.", gUser->loginname, mynode);
                                        full_mail_scan_personal(gUser);
                                    } else {
                                        broadcast("USER: %s; NODE:%d; STATUS: Scanning all mail.", gUser->loginname, mynode);
                                        full_mail_scan(gUser);
                                    }
                                } else {
                                    full_mail_scan(gUser);
                                }
                                break;
                            case MENU_FILESEARCH:
                                broadcast("USER: %s; NODE:%d; STATUS: Executing a filesearch.", gUser->loginname, mynode);
                                file_search();
                                break;
                            case MENU_DISPTXTFILE:
                                if (menu[i]->data[j] != NULL) {
                                    broadcast("USER: %s; NODE:%d; STATUS: Displaying Text File: %s.", gUser->loginname, mynode, menu[i]->data[j]);
                                    s_displayansi_pause(menu[i]->data[j], 0);
                                }
                                break;
                            case MENU_DISPTXTFILEPAUSE:
                                if (menu[i]->data[j] != NULL) {
                                    broadcast("USER: %s; NODE:%d; STATUS: Displaying Text File: %s.", gUser->loginname, mynode, menu[i]->data[j]);
                                    s_displayansi_pause(menu[i]->data[j], 1);
                                }
                                s_printf(get_string(6));
                                s_getc();
                                break;
                            case MENU_GENWWWURLS:
                                genurls();
                                break;
                            case MENU_NLBROWSER:
                                broadcast("USER: %s; NODE:%d; STATUS: Executing a filesearch.", gUser->loginname, mynode);
                                nl_browser();
                                break;
                            case MENU_SENDFEEDBACK:
                                if (check_user(conf.sysop_name)) {
                                    break;
                                }
                                broadcast("USER: %s; NODE:%d; STATUS: Sending feedback to Sysop.", gUser->loginname, mynode);
                                msg = external_editor(gUser, conf.sysop_name, gUser->loginname, NULL, 0, NULL, "Feedback", 1, 0);
                                if (msg != NULL) {
                                    commit_email(conf.sysop_name, "Feedback", msg);
                                    free(msg);
                                }
                                break;
                            case MENU_BLOGDISPLAY:
                                broadcast("USER: %s; NODE:%d; STATUS: Displaying Blog.", gUser->loginname, mynode);
                                blog_display();
                                break;
                            case MENU_BLOGWRITE:
                                broadcast("USER: %s; NODE:%d; STATUS: Writing a Blog Entry.", gUser->loginname, mynode);
                                blog_write();
                                break;
                            default:
                                break;     
                        }
                    }
                    break;
                }
            }
        }
    }

    // free menus;
    return doquit;
}