diff --git a/.gitignore b/.gitignore index 9378e53..3e334c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o *.sq3 *.core +magicka diff --git a/Makefile b/Makefile index 1f09d84..23f19ed 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC=cc CFLAGS=-I/usr/local/include DEPS = bbs.h -OBJ = inih/ini.o bbs.o main.o users.o main_menu.o +OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/bbs.c b/bbs.c index 0924e6a..e5cdc0b 100644 --- a/bbs.c +++ b/bbs.c @@ -38,6 +38,51 @@ void timer_handler(int signum) { } } +static int mail_area_handler(void* user, const char* section, const char* name, + const char* value) +{ + struct mail_conference *mc = (struct mail_conference *)user; + int i; + + if (strcasecmp(section, "main") == 0) { + if (strcasecmp(name, "visible sec level")) { + mc->sec_level = atoi(value); + } + } else { + // check if it's partially filled in + for (i=0;imail_area_count;i++) { + if (strcasecmp(mc->mail_areas[i]->name, section) == 0) { + if (strcasecmp(name, "read sec level") == 0) { + mc->mail_areas[i]->read_sec_level = atoi(value); + } else if (strcasecmp(name, "write sec level") == 0) { + mc->mail_areas[i]->write_sec_level = atoi(value); + } else if (strcasecmp(name, "path") == 0) { + mc->mail_areas[i]->path = strdup(value); + } + return 1; + } + } + if (mc->mail_area_count == 0) { + mc->mail_areas = (struct mail_area **)malloc(sizeof(struct mail_area *)); + } else { + mc->mail_areas = (struct mail_area **)realloc(mc->mail_areas, sizeof(struct mail_area *) * (mc->mail_area_count + 1)); + } + + mc->mail_areas[mc->mail_area_count] = (struct mail_area *)malloc(sizeof(struct mail_area)); + + mc->mail_areas[mc->mail_area_count]->name = strdup(section); + if (strcasecmp(name, "read sec level") == 0) { + mc->mail_areas[mc->mail_area_count]->read_sec_level = atoi(value); + } else if (strcasecmp(name, "write sec level") == 0) { + mc->mail_areas[mc->mail_area_count]->write_sec_level = atoi(value); + } else if (strcasecmp(name, "path") == 0) { + mc->mail_areas[mc->mail_area_count]->path = strdup(value); + } + mc->mail_area_count++; + } + return 1; +} + static int handler(void* user, const char* section, const char* name, const char* value) { @@ -59,6 +104,18 @@ static int handler(void* user, const char* section, const char* name, } else if (strcasecmp(name, "bbs path") == 0) { conf->bbs_path = strdup(value); } + } else if (strcasecmp(section, "mail conferences") == 0) { + if (conf->mail_conference_count == 0) { + conf->mail_conferences = (struct mail_conference **)malloc(sizeof(struct mail_conference *)); + } else { + conf->mail_conferences = (struct mail_conference **)realloc(conf->mail_conferences, sizeof(struct mail_conference *) * (conf->mail_conference_count + 1)); + } + + conf->mail_conferences[conf->mail_conference_count] = (struct mail_conference *)malloc(sizeof(struct mail_conference)); + conf->mail_conferences[conf->mail_conference_count]->name = strdup(name); + conf->mail_conferences[conf->mail_conference_count]->path = strdup(value); + conf->mail_conferences[conf->mail_conference_count]->mail_area_count = 0; + conf->mail_conference_count++; } return 1; @@ -210,13 +267,19 @@ void runbbs(int socket, char *config_path) { sprintf(buffer, "Magicka BBS v%d.%d (%s) Loading...\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_STR); s_putstring(socket, buffer); - + conf.mail_conference_count = 0; // Load BBS data if (ini_parse(config_path, handler, &conf) <0) { printf("Unable to load configuration ini (%s)!\n", config_path); exit(-1); } - + // Load mail Areas + for (i=0;ipath, mail_area_handler, conf.mail_conferences[i]) <0) { + printf("Unable to load configuration ini (%s)!\n", conf.mail_conferences[i]->path); + exit(-1); + } + } // find out which node we are diff --git a/bbs.h b/bbs.h index fc7ca00..3c0573f 100644 --- a/bbs.h +++ b/bbs.h @@ -7,6 +7,21 @@ #define VERSION_MINOR 1 #define VERSION_STR "dev" +struct mail_area { + char *name; + char *path; + int read_sec_level; + int write_sec_level; +}; + +struct mail_conference { + char *name; + char *path; + int sec_level; + int mail_area_count; + struct mail_area **mail_areas; +}; + struct bbs_config { char *bbs_name; char *sysop_name; @@ -15,7 +30,8 @@ struct bbs_config { char *bbs_path; int nodes; int newuserlvl; - + int mail_conference_count; + struct mail_conference **mail_conferences; }; struct sec_level_t { @@ -34,6 +50,10 @@ struct user_record { struct sec_level_t *sec_info; time_t laston; int timeleft; + int cur_mail_conf; + int cur_mail_area; + int cur_file_dir; + int cur_file_sub; }; @@ -54,4 +74,6 @@ extern struct user_record *check_user_pass(int socket, char *loginname, char *pa extern void main_menu(int socket, struct user_record *user); + +extern int mail_menu(int socket, struct user_record *user); #endif diff --git a/bbs.ini b/bbs.ini index b113429..2783b9d 100644 --- a/bbs.ini +++ b/bbs.ini @@ -7,3 +7,6 @@ New User Level = 10 [paths] ANSI Path = /home/andrew/MagickaBBS/ansis BBS Path = /home/andrew/MagickaBBS + +[mail conferences] +Local Mail = localmail.ini diff --git a/localmail.ini b/localmail.ini new file mode 100644 index 0000000..3b2ac57 --- /dev/null +++ b/localmail.ini @@ -0,0 +1,12 @@ +[main] +Visible Sec Level = 10 + +[General] +Read Sec Level = 10 +Write Sec Level = 10 +Path = /home/andrew/MagickaBBS/msgs/general + +[Testing] +Read Sec Level = 10 +Write Sec Level = 10 +Path = /home/andrew/MagickaBBS/msgs/testing diff --git a/mail_menu.c b/mail_menu.c new file mode 100644 index 0000000..41acd28 --- /dev/null +++ b/mail_menu.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include "bbs.h" + +extern struct bbs_config conf; + +int mail_menu(int socket, struct user_record *user) { + int doquit = 0; + int domail = 0; + char c; + char prompt[128]; + + while (!domail) { + s_displayansi(socket, "mailmenu"); + + + sprintf(prompt, "\r\nConf: (%d) %s\r\nArea: (%d) %s\r\nTL: %dm :> ", user->cur_mail_conf, conf.mail_conferences[user->cur_mail_conf]->name, user->cur_mail_area, conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->name, user->timeleft); + s_putstring(socket, prompt); + + c = s_getc(socket); + + switch(tolower(c)) { + case 'q': + { + domail = 1; + } + break; + case 'g': + { + s_putstring(socket, "\r\nAre you sure you want to log off? (Y/N)"); + c = s_getc(socket); + if (tolower(c) == 'y') { + domail = 1; + doquit = 1; + } + } + break; + + } + } + + return doquit; +} diff --git a/main_menu.c b/main_menu.c index d33563f..71923a0 100644 --- a/main_menu.c +++ b/main_menu.c @@ -20,6 +20,11 @@ void main_menu(int socket, struct user_record *user) { c = s_getc(socket); switch(tolower(c)) { + case 'm': + { + doquit = mail_menu(socket, user); + } + break; case 'g': { s_putstring(socket, "\r\nAre you sure you want to log off? (Y/N)"); diff --git a/users.c b/users.c index 1e31b2b..0cdfdc3 100644 --- a/users.c +++ b/users.c @@ -28,7 +28,7 @@ int save_user(struct user_record *user) { int rc; char *update_sql = "UPDATE users SET password=?, firstname=?," - "lastname=?, email=?, location=?, sec_level=?, last_on=?, time_left=? where loginname LIKE ?"; + "lastname=?, email=?, location=?, sec_level=?, last_on=?, time_left=?, cur_mail_conf=?, cur_mail_area=?, cur_file_dir=?, cur_file_sub=? where loginname LIKE ?"; char *err_msg = 0; sprintf(buffer, "%s/users.sq3", conf.bbs_path); @@ -53,7 +53,11 @@ int save_user(struct user_record *user) { sqlite3_bind_int(res, 6, user->sec_level); sqlite3_bind_int(res, 7, user->laston); sqlite3_bind_int(res, 8, user->timeleft); - sqlite3_bind_text(res, 9, user->loginname, -1, 0); + sqlite3_bind_int(res, 9, user->cur_mail_conf); + sqlite3_bind_int(res, 10, user->cur_mail_area); + sqlite3_bind_int(res, 11, user->cur_file_dir); + sqlite3_bind_int(res, 12, user->cur_file_sub); + sqlite3_bind_text(res, 13, user->loginname, -1, 0); } else { fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(db)); } @@ -87,10 +91,14 @@ int inst_user(struct user_record *user) { "location TEXT," "sec_level INTEGER," "last_on INTEGER," - "time_left INTEGER);"; + "time_left INTEGER," + "cur_mail_conf INTEGER," + "cur_mail_area INTEGER," + "cur_file_sub INTEGER," + "cur_file_dir INTEGER);"; char *insert_sql = "INSERT INTO users (loginname, password, firstname," - "lastname, email, location, sec_level, last_on, time_left) VALUES(?,?, ?, ?, ?, ?, ?, ?, ?)"; + "lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub) VALUES(?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; char *err_msg = 0; sprintf(buffer, "%s/users.sq3", conf.bbs_path); @@ -127,6 +135,11 @@ int inst_user(struct user_record *user) { sqlite3_bind_int(res, 7, user->sec_level); sqlite3_bind_int(res, 8, user->laston); sqlite3_bind_int(res, 9, user->timeleft); + sqlite3_bind_int(res, 10, user->cur_mail_conf); + sqlite3_bind_int(res, 11, user->cur_mail_area); + sqlite3_bind_int(res, 12, user->cur_file_dir); + sqlite3_bind_int(res, 13, user->cur_file_sub); + } else { fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(db)); } @@ -186,6 +199,10 @@ struct user_record *check_user_pass(int socket, char *loginname, char *password) user->sec_level = sqlite3_column_int(res, 7); user->laston = (time_t)sqlite3_column_int(res, 8); user->timeleft = sqlite3_column_int(res, 9); + user->cur_mail_conf = sqlite3_column_int(res, 10); + user->cur_mail_area = sqlite3_column_int(res, 11); + user->cur_file_dir = sqlite3_column_int(res, 12); + user->cur_file_sub = sqlite3_column_int(res, 13); if (strcmp(password, user->password) != 0) { free(user);