diff --git a/Makefile b/Makefile index 23f19ed..d3b2b7e 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ CC=cc CFLAGS=-I/usr/local/include DEPS = bbs.h +JAMLIB = /usr/local/lib/libjam.a + OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) magicka: $(OBJ) - $(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 + $(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) .PHONY: clean diff --git a/bbs.c b/bbs.c index e5cdc0b..90b18f4 100644 --- a/bbs.c +++ b/bbs.c @@ -47,6 +47,12 @@ static int mail_area_handler(void* user, const char* section, const char* name, if (strcasecmp(section, "main") == 0) { if (strcasecmp(name, "visible sec level")) { mc->sec_level = atoi(value); + } else if (strcasecmp(name, "networked")) { + if (strcasecmp(value, "true") == 0) { + mc->networked = 1; + } else { + mc->networked = 0; + } } } else { // check if it's partially filled in diff --git a/bbs.h b/bbs.h index 3c0573f..d174969 100644 --- a/bbs.h +++ b/bbs.h @@ -17,6 +17,7 @@ struct mail_area { struct mail_conference { char *name; char *path; + int networked; int sec_level; int mail_area_count; struct mail_area **mail_areas; diff --git a/jamlib-1.4.7/include/jamlib/jam.h b/jamlib-1.4.7/include/jamlib/jam.h index c7c0b4c..42d4179 100644 --- a/jamlib-1.4.7/include/jamlib/jam.h +++ b/jamlib-1.4.7/include/jamlib/jam.h @@ -49,7 +49,7 @@ #if !(((defined(__FreeBSD__) && __FreeBSD_version >= 440000)) || defined(NeXTBSD)) typedef unsigned short ushort; /* must be 16 bits wide */ #endif -typedef unsigned long ulong; /* must be 32 bits wide */ +typedef uint32_t ulong; /* must be 32 bits wide */ #endif typedef unsigned char uchar; /* must be 8 bits wide */ diff --git a/jamlib-1.4.7/src/message.c b/jamlib-1.4.7/src/message.c index bf4a69c..dbc2306 100644 --- a/jamlib-1.4.7/src/message.c +++ b/jamlib-1.4.7/src/message.c @@ -103,10 +103,13 @@ int JAM_ReadMsgHeader( s_JamBase* Base_PS, char* Roof_PC; int BufSize_I = Header_PS->SubfieldLen; - Buf_PC = (void*) malloc( BufSize_I ); - if ( !Buf_PC ) - return JAM_NO_MEMORY; + + Buf_PC = (void*) malloc( BufSize_I ); + if ( !Buf_PC ) { + return JAM_NO_MEMORY; + } + /* read all subfields */ if ( 1 > fread( Buf_PC, BufSize_I, 1, Base_PS->HdrFile_PS ) ) { Base_PS->Errno_I = errno; diff --git a/jamlib-1.4.7/src/subpack.c b/jamlib-1.4.7/src/subpack.c index acf075f..61785ae 100644 --- a/jamlib-1.4.7/src/subpack.c +++ b/jamlib-1.4.7/src/subpack.c @@ -156,9 +156,9 @@ int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS ) SubPack_PS->NumAlloc *= 2; Fields_PPS = (s_JamSubfield**) realloc( SubPack_PS->Fields, SubPack_PS->NumAlloc * sizeof( s_JamSubfield* ) ); - if ( !Fields_PPS ) + if ( !Fields_PPS ) { return JAM_NO_MEMORY; - + } SubPack_PS->Fields=Fields_PPS; } @@ -168,8 +168,9 @@ int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS ) /* allocate a new subfield */ NewField_PS = (s_JamSubfield*) malloc( sizeof( s_JamSubfield ) ); - if ( !NewField_PS ) - return JAM_NO_MEMORY; + if ( !NewField_PS ) { + return JAM_NO_MEMORY; + } /* allocate a new buffer */ if ( Field_PS->DatLen ) { diff --git a/localmail.ini b/localmail.ini index 3b2ac57..7a8fc62 100644 --- a/localmail.ini +++ b/localmail.ini @@ -1,5 +1,6 @@ [main] Visible Sec Level = 10 +Networked = false [General] Read Sec Level = 10 diff --git a/mail_menu.c b/mail_menu.c index 41acd28..b99dba1 100644 --- a/mail_menu.c +++ b/mail_menu.c @@ -1,15 +1,200 @@ #include #include #include +#include +#include +#include +#include #include "bbs.h" extern struct bbs_config conf; +s_JamBase *open_jam_base(char *path) { + int ret; + s_JamBase *jb; + + ret = JAM_OpenMB((uchar *)path, &jb); + + if (ret != 0) { + if (ret == JAM_IO_ERROR) { + free(jb); + ret = JAM_CreateMB((uchar *)path, 1, &jb); + if (ret != 0) { + free(jb); + return NULL; + } + } + } + return jb; +} + +char *editor(int socket, char *quote) { + int lines = 0; + char linebuffer[80]; + char prompt[12]; + int doquit = 0; + char **content = NULL; + int i; + char *msg; + int size = 0; + + s_putstring(socket, "\r\nMagicka Internal Editor, Type /S to Save, /A to abort and /? for help\r\n"); + s_putstring(socket, "-------------------------------------------------------------------------------"); + + while(!doquit) { + sprintf(prompt, "\r\n[%3d]: ", lines); + s_putstring(socket, prompt); + s_readstring(socket, linebuffer, 70); + if (linebuffer[0] == '/') { + if (toupper(linebuffer[1]) == 'S') { + for (i=0;i 0) { + free(content); + } + return NULL; + } + } else { + if (lines == 0) { + content = (char **)malloc(sizeof(char *)); + } else { + content = (char **)realloc(content, sizeof(char *) * (lines + 1)); + } + + content[lines] = strdup(linebuffer); + + lines++; + } + } + return NULL; +} + +void read_message(int socket, struct user_record *user, int mailno) { + s_JamBase *jb; + s_JamBaseHeader jbh; + s_JamMsgHeader jmh; + s_JamSubPacket* jsp; + s_JamSubfield jsf; + char buffer[256]; + int z; + + char *subject = NULL; + char *from = NULL; + char *to = NULL; + char *body = NULL; + int lines = 0; + + + jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + if (!jb) { + printf("Error opening JAM base.. %s\n", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + return; + } + + z = JAM_ReadMsgHeader(jb, mailno, &jmh, &jsp); + if (z != 0) { + return; + } + + for (z=0;zNumFields;z++) { + if (jsp->Fields[z]->LoID == JAMSFLD_SUBJECT) { + subject = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(subject, 0, jsp->Fields[z]->DatLen + 1); + memcpy(subject, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + if (jsp->Fields[z]->LoID == JAMSFLD_SENDERNAME) { + from = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(from, 0, jsp->Fields[z]->DatLen + 1); + memcpy(from, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + if (jsp->Fields[z]->LoID == JAMSFLD_RECVRNAME) { + to = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(to, 0, jsp->Fields[z]->DatLen + 1); + memcpy(to, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + } + sprintf(buffer, "\e[2JFrom : %s\r\n", from); + s_putstring(socket, buffer); + sprintf(buffer, "To : %s\r\n", to); + s_putstring(socket, buffer); + sprintf(buffer, "Subject : %s\r\n", subject); + s_putstring(socket, buffer); + s_putstring(socket, "-------------------------------------------------------------------------------\r\n"); + + body = (char *)malloc(jmh.TxtLen); + + JAM_ReadMsgText(jb, jmh.TxtOffset, jmh.TxtLen, (uchar *)body); + + JAM_CloseMB(jb); + + for (z=0;zcur_mail_conf]->networked == 0 && strcasecmp(buffer, "ALL") != 0) { + if (check_user(buffer)) { + s_putstring(socket, "\r\n\r\nInvalid Username\r\n"); + break; + } + } + + to = strdup(buffer); + s_putstring(socket, "\r\nSUBJECT: "); + s_readstring(socket, buffer, 25); + subject = strdup(buffer); + + // post a message + msg = editor(socket, NULL); + + if (msg != NULL) { + jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + if (!jb) { + printf("Error opening JAM base.. %s\n", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + free(msg); + free(to); + free(subject); + break; + } + + JAM_ClearMsgHeader( &jmh ); + jmh.DateWritten = time(NULL); + + jsp = JAM_NewSubPacket(); + jsf.LoID = JAMSFLD_SENDERNAME; + jsf.HiID = 0; + jsf.DatLen = strlen(user->loginname); + jsf.Buffer = (uchar *)user->loginname; + JAM_PutSubfield(jsp, &jsf); + + jsf.LoID = JAMSFLD_RECVRNAME; + jsf.HiID = 0; + jsf.DatLen = strlen(to); + jsf.Buffer = (uchar *)to; + JAM_PutSubfield(jsp, &jsf); + + jsf.LoID = JAMSFLD_SUBJECT; + jsf.HiID = 0; + jsf.DatLen = strlen(subject); + jsf.Buffer = (uchar *)subject; + JAM_PutSubfield(jsp, &jsf); + + + while (1) { + z = JAM_LockMB(jb, 100); + if (z == 0) { + break; + } else if (z == JAM_LOCK_FAILED) { + sleep(1); + } else { + free(msg); + free(to); + free(subject); + printf("Failed to lock msg base!\n"); + break; + } + } + if (z != 0) { + JAM_CloseMB(jb); + break; + } + + if (JAM_AddMessage(jb, &jmh, jsp, (uchar *)msg, strlen(msg))) { + printf("Failed to add message\n"); + } + + JAM_UnlockMB(jb); + + JAM_DelSubPacket(jsp); + free(msg); + JAM_CloseMB(jb); + } + free(to); + free(subject); + } + break; + case 'l': + { + s_putstring(socket, "\r\n"); + // list mail in message base + jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + if (!jb) { + printf("Error opening JAM base.. %s\n", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path); + break; + } else { + JAM_ReadMBHeader(jb, &jbh); + + sprintf(buffer, "Start at message [0-%d] ? ", jbh.ActiveMsgs - 1); + s_putstring(socket, buffer); + + s_readstring(socket, buffer, 6); + i = atoi(buffer); + closed = 0; + s_putstring(socket, "\r\n"); + for (j=i;jNumFields;z++) { + if (jsp->Fields[z]->LoID == JAMSFLD_SUBJECT) { + subject = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(subject, 0, jsp->Fields[z]->DatLen + 1); + memcpy(subject, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + if (jsp->Fields[z]->LoID == JAMSFLD_SENDERNAME) { + from = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(from, 0, jsp->Fields[z]->DatLen + 1); + memcpy(from, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + if (jsp->Fields[z]->LoID == JAMSFLD_RECVRNAME) { + to = (char *)malloc(jsp->Fields[z]->DatLen + 1); + memset(to, 0, jsp->Fields[z]->DatLen + 1); + memcpy(to, jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen); + } + + } + + localtime_r((time_t *)&jmh.DateWritten, &msg_date); + + sprintf(buffer, "[%4d] %-25s %-15s %-15s %02d:%02d %02d-%02d-%02d\r\n", j, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100); + s_putstring(socket, buffer); + JAM_DelSubPacket(jsp); + if (subject != NULL) { + free(subject); + } + if (from != NULL) { + free(from); + } + if (to != NULL) { + free(to); + } + + if ((j - i) != 0 && (j - i) % 22 == 0) { + sprintf(buffer, "(#) Read Message # (Q) Quit (ENTER) Continue\r\n"); + s_putstring(socket, buffer); + s_readstring(socket, buffer, 6); + + if (tolower(buffer[0]) == 'q') { + break; + } else if (strlen(buffer) > 0) { + z = atoi(buffer); + if (z >= 0 && z <= jbh.ActiveMsgs) { + JAM_CloseMB(jb); + closed = 1; + read_message(socket, user, z); + break; + } + } + } + + } + sprintf(buffer, "(#) Read Message # (Q) Quit (ENTER) Continue\r\n"); + s_putstring(socket, buffer); + s_readstring(socket, buffer, 6); + + if (tolower(buffer[0]) == 'q') { + break; + } else if (strlen(buffer) > 0) { + z = atoi(buffer); + if (z >= 0 && z <= jbh.ActiveMsgs) { + JAM_CloseMB(jb); + closed = 1; + read_message(socket, user, z); + break; + } + } + } + if (closed == 0) { + JAM_CloseMB(jb); + } + } + break; + case 'c': + { + s_putstring(socket, "\r\n\r\nMail Conferences:\r\n\r\n"); + for (i=0;iname); + s_putstring(socket, buffer); + + if (i != 0 && i % 22 == 0) { + s_putstring(socket, "Press any key to continue...\r\n"); + c = s_getc(socket); + } + } + s_putstring(socket, "Enter the conference number: "); + s_readstring(socket, buffer, 5); + if (tolower(buffer[0]) != 'q') { + j = atoi(buffer); + if (j < 0 || j >= conf.mail_conference_count) { + s_putstring(socket, "\r\nInvalid conference number!\r\n"); + } else { + s_putstring(socket, "\r\n"); + user->cur_mail_conf = j; + user->cur_mail_area = 0; + } + } + } + break; + case 'a': + { + s_putstring(socket, "\r\n\r\nMail Areas:\r\n\r\n"); + for (i=0;icur_mail_conf]->mail_area_count;i++) { + sprintf(buffer, " %d. %s\r\n", i, conf.mail_conferences[user->cur_mail_conf]->mail_areas[i]->name); + s_putstring(socket, buffer); + + if (i != 0 && i % 22 == 0) { + s_putstring(socket, "Press any key to continue...\r\n"); + c = s_getc(socket); + } + } + s_putstring(socket, "Enter the area number: "); + s_readstring(socket, buffer, 5); + if (tolower(buffer[0]) != 'q') { + j = atoi(buffer); + if (j < 0 || j >= conf.mail_conferences[user->cur_mail_conf]->mail_area_count) { + s_putstring(socket, "\r\nInvalid area number!\r\n"); + } else { + s_putstring(socket, "\r\n"); + user->cur_mail_area = j; + } + } + } + break; case 'q': { domail = 1;