This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/src/mail_menu.c

3485 lines
100 KiB
C
Raw Normal View History

2016-03-22 13:07:42 +10:00
#include <stdio.h>
#include <string.h>
#include <ctype.h>
2016-03-22 18:19:06 +10:00
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
2016-04-07 14:43:23 +10:00
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/file.h>
2016-04-23 14:10:42 +10:00
#include <fcntl.h>
2016-03-25 18:24:24 +10:00
#include "jamlib/jam.h"
2016-03-22 13:07:42 +10:00
#include "bbs.h"
#include "lua/lua.h"
#include "lua/lualib.h"
#include "lua/lauxlib.h"
2018-05-22 21:02:22 +10:00
#include "libuuid/uuid.h"
2017-10-20 07:27:58 +10:00
#ifdef __sun
#include "os/sunos.h"
#endif
extern struct bbs_config conf;
extern struct user_record *gUser;
2016-04-07 14:43:23 +10:00
extern int mynode;
2016-03-30 12:59:00 +10:00
2017-04-21 20:31:41 +10:00
time_t utc_to_local(time_t utc) {
time_t local;
struct tm date_time;
localtime_r(&utc, &date_time);
2017-10-20 07:27:58 +10:00
#ifdef __sun
local = utc + gmtoff(utc);
#else
2017-04-21 20:45:47 +10:00
local = utc + date_time.tm_gmtoff;
2017-10-20 07:27:58 +10:00
#endif
2017-04-21 20:31:41 +10:00
return local;
}
2016-03-22 18:19:06 +10:00
s_JamBase *open_jam_base(char *path) {
int ret;
s_JamBase *jb;
2016-03-25 18:28:09 +10:00
ret = JAM_OpenMB((char *)path, &jb);
2016-03-22 18:19:06 +10:00
if (ret != 0) {
if (ret == JAM_IO_ERROR) {
free(jb);
2016-03-25 18:28:09 +10:00
ret = JAM_CreateMB((char *)path, 1, &jb);
2016-03-22 18:19:06 +10:00
if (ret != 0) {
free(jb);
return NULL;
}
2016-03-30 12:59:00 +10:00
} else {
free(jb);
dolog("Got %d", ret);
2016-03-30 12:59:00 +10:00
return NULL;
2016-03-22 18:19:06 +10:00
}
}
return jb;
}
unsigned long generate_msgid() {
char buffer[1024];
2017-03-21 10:47:51 +10:00
time_t unixtime;
unsigned long msgid;
unsigned long lastid;
FILE *fptr;
snprintf(buffer, 1024, "%s/msgserial", conf.bbs_path);
2017-03-21 10:47:51 +10:00
unixtime = time(NULL);
2016-12-04 18:06:20 +10:00
fptr = fopen(buffer, "r+");
if (fptr) {
flock(fileno(fptr), LOCK_EX);
fread(&lastid, sizeof(unsigned long), 1, fptr);
2017-03-21 10:47:51 +10:00
if (unixtime > lastid) {
lastid = unixtime;
} else {
lastid++;
}
rewind(fptr);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
fptr = fopen(buffer, "w");
if (fptr) {
2017-03-21 10:47:51 +10:00
lastid = unixtime;
flock(fileno(fptr), LOCK_EX);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
2017-04-22 18:32:36 +10:00
lastid = unixtime;
dolog("Unable to open message id log");
}
}
2017-04-22 18:34:19 +10:00
sprintf(buffer, "%lX", lastid);
2017-04-22 18:32:36 +10:00
return strtoul(&buffer[strlen(buffer) - 8], NULL, 16);
}
2016-03-30 12:59:00 +10:00
void free_message_headers(struct msg_headers *msghs) {
int i;
for (i = 0; i < msghs->msg_count; i++) {
2016-03-30 12:59:00 +10:00
free(msghs->msgs[i]->msg_h);
if (msghs->msgs[i]->from != NULL) {
free(msghs->msgs[i]->from);
}
if (msghs->msgs[i]->to != NULL) {
free(msghs->msgs[i]->to);
}
if (msghs->msgs[i]->from != NULL) {
free(msghs->msgs[i]->subject);
}
if (msghs->msgs[i]->oaddress != NULL) {
free(msghs->msgs[i]->oaddress);
}
if (msghs->msgs[i]->daddress != NULL) {
free(msghs->msgs[i]->daddress);
}
if (msghs->msgs[i]->msgid != NULL) {
free(msghs->msgs[i]->msgid);
}
if (msghs->msgs[i]->replyid != NULL) {
free(msghs->msgs[i]->replyid);
}
2018-02-10 16:01:30 +10:00
free(msghs->msgs[i]);
}
if (msghs->msg_count > 0) {
free(msghs->msgs);
}
2016-03-30 12:59:00 +10:00
free(msghs);
}
2016-08-20 13:52:02 +10:00
int msg_is_to(struct user_record *user, char *addressed_to, char *address, int type, int rn, int msgconf) {
char *myname;
struct fido_addr *dest;
int j;
2018-05-22 21:02:22 +10:00
int magi_dest;
if (rn) {
myname = str3dup(user->firstname, " ", user->lastname);
} else {
2016-08-20 13:52:02 +10:00
myname = strdup(user->loginname);
}
2018-02-18 14:11:34 +10:00
if (type == NETWORK_FIDO && address != NULL) {
if (strcasecmp(myname, addressed_to) == 0) {
dest = parse_fido_addr(address);
if (conf.mail_conferences[msgconf]->fidoaddr->zone == dest->zone &&
conf.mail_conferences[msgconf]->fidoaddr->net == dest->net &&
conf.mail_conferences[msgconf]->fidoaddr->node == dest->node &&
conf.mail_conferences[msgconf]->fidoaddr->point == dest->point) {
free(dest);
free(myname);
return 1;
}
free(dest);
}
free(myname);
return 0;
2018-05-22 21:02:22 +10:00
} else if (type == NETWORK_MAGI && address != NULL) {
if (strcasecmp(myname, addressed_to) == 0) {
magi_dest = atoi(address);
if (magi_dest == conf.mail_conferences[msgconf]->maginode) {
free(myname);
return 1;
}
}
free(myname);
return 0;
} else {
if (strcasecmp(myname, addressed_to) == 0) {
free(myname);
return 1;
}
free(myname);
return 0;
}
}
2016-08-20 13:52:02 +10:00
int msg_is_from(struct user_record *user, char *addressed_from, char *address, int type, int rn, int msgconf) {
char *myname;
struct fido_addr *orig;
int j;
2018-05-22 21:02:22 +10:00
int magi_orig;
if (rn) {
myname = str3dup(user->firstname, " ", user->lastname);
} else {
2016-08-20 13:52:02 +10:00
myname = strdup(user->loginname);
}
2018-05-22 21:02:22 +10:00
if (type == NETWORK_FIDO && address != NULL) {
if (strcasecmp(myname, addressed_from) == 0) {
orig = parse_fido_addr(address);
if (conf.mail_conferences[msgconf]->fidoaddr->zone == orig->zone &&
conf.mail_conferences[msgconf]->fidoaddr->net == orig->net &&
conf.mail_conferences[msgconf]->fidoaddr->node == orig->node &&
conf.mail_conferences[msgconf]->fidoaddr->point == orig->point) {
free(orig);
free(myname);
return 1;
}
free(orig);
}
free(myname);
return 0;
2018-05-22 21:02:22 +10:00
} else if (type == NETWORK_MAGI && address != NULL) {
if (strcasecmp(myname, addressed_from) == 0) {
magi_orig = atoi(address);
if (magi_orig == conf.mail_conferences[msgconf]->maginode) {
free(myname);
return 1;
}
}
free(myname);
return 0;
} else {
if (strcasecmp(myname, addressed_from) == 0) {
free(myname);
return 1;
}
free(myname);
return 0;
}
}
2018-02-18 13:51:39 +10:00
struct msg_headers *read_message_headers(int msgconf, int msgarea, struct user_record *user, int personal) {
2016-03-30 12:59:00 +10:00
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
2016-03-30 12:59:00 +10:00
struct jam_msg *jamm;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct ptr_vector vec;
int to_us;
2016-03-30 12:59:00 +10:00
int i;
int z;
int j;
2016-03-30 13:04:11 +10:00
int k;
2016-03-30 12:59:00 +10:00
struct fido_addr *dest;
struct msg_headers *msghs = NULL;
jb = open_jam_base(conf.mail_conferences[msgconf]->mail_areas[msgarea]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[msgconf]->mail_areas[msgarea]->path);
2016-03-30 12:59:00 +10:00
return NULL;
}
JAM_ReadMBHeader(jb, &jbh);
if (jbh.ActiveMsgs > 0) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
init_ptr_vector(&vec);
msghs = (struct msg_headers *)malloz(sizeof(struct msg_headers));
2016-03-30 12:59:00 +10:00
msghs->msg_count = 0;
2016-03-30 13:04:11 +10:00
k = 0;
for (i = 0; k < jbh.ActiveMsgs; i++) {
2016-03-30 12:59:00 +10:00
memset(&jmh, 0, sizeof(s_JamMsgHeader));
z = JAM_ReadMsgHeader(jb, i, &jmh, &jsp);
2016-03-30 12:59:00 +10:00
if (z != 0) {
dolog("Failed to read msg header: %d Erro %d", z, JAM_Errno(jb));
2016-03-30 12:59:00 +10:00
continue;
}
if (jmh.Attribute & JAM_MSG_DELETED) {
2016-03-30 12:59:00 +10:00
JAM_DelSubPacket(jsp);
continue;
}
jamm = (struct jam_msg *)malloz(sizeof(struct jam_msg));
2016-03-30 12:59:00 +10:00
jamm->msg_no = i;
jamm->msg_h = (s_JamMsgHeader *)malloz(sizeof(s_JamMsgHeader));
2016-03-30 12:59:00 +10:00
memcpy(jamm->msg_h, &jmh, sizeof(s_JamMsgHeader));
jamm->from = NULL;
jamm->to = NULL;
jamm->subject = NULL;
jamm->oaddress = NULL;
jamm->daddress = NULL;
jamm->msgid = NULL;
jamm->replyid = NULL;
for (z = 0; z < jsp->NumFields; z++) {
2016-03-30 12:59:00 +10:00
if (jsp->Fields[z]->LoID == JAMSFLD_SUBJECT) {
jamm->subject = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_SENDERNAME) {
jamm->from = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_RECVRNAME) {
jamm->to = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_DADDRESS) {
jamm->daddress = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_OADDRESS) {
jamm->oaddress = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_MSGID) {
jamm->msgid = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
} else if (jsp->Fields[z]->LoID == JAMSFLD_REPLYID) {
jamm->replyid = strndup(jsp->Fields[z]->Buffer, jsp->Fields[z]->DatLen);
}
2016-03-30 12:59:00 +10:00
}
JAM_DelSubPacket(jsp);
2016-08-31 16:20:36 +10:00
if (jamm->subject == NULL) {
jamm->subject = strdup("(No Subject)");
}
2018-01-22 12:48:43 +10:00
if (jamm->from == NULL) {
jamm->from = strdup("(No Sender)");
}
if (jamm->to == NULL) {
jamm->to = strdup("(No Recipient)");
}
if (jmh.Attribute & JAM_MSG_PRIVATE) {
2016-08-20 13:59:37 +10:00
if (!msg_is_to(user, jamm->to, jamm->daddress, conf.mail_conferences[msgconf]->nettype, conf.mail_conferences[msgconf]->realnames, msgconf) &&
!msg_is_from(user, jamm->from, jamm->oaddress, conf.mail_conferences[msgconf]->nettype, conf.mail_conferences[msgconf]->realnames, msgconf) &&
!msg_is_to(user, jamm->to, jamm->daddress, conf.mail_conferences[msgconf]->nettype, !conf.mail_conferences[msgconf]->realnames, msgconf) &&
!msg_is_from(user, jamm->from, jamm->oaddress, conf.mail_conferences[msgconf]->nettype, !conf.mail_conferences[msgconf]->realnames, msgconf)) {
if (jamm->subject != NULL) {
free(jamm->subject);
}
if (jamm->from != NULL) {
free(jamm->from);
}
if (jamm->to != NULL) {
free(jamm->to);
}
if (jamm->oaddress != NULL) {
free(jamm->oaddress);
}
if (jamm->daddress != NULL) {
free(jamm->daddress);
}
if (jamm->msgid != NULL) {
free(jamm->msgid);
}
if (jamm->replyid != NULL) {
free(jamm->replyid);
}
free(jamm->msg_h);
free(jamm);
k++;
continue;
2016-03-30 12:59:00 +10:00
}
2018-02-18 13:51:39 +10:00
} else if (personal) {
if (!msg_is_to(user, jamm->to, jamm->daddress, conf.mail_conferences[msgconf]->nettype, conf.mail_conferences[msgconf]->realnames, msgconf) &&
!msg_is_to(user, jamm->to, jamm->daddress, conf.mail_conferences[msgconf]->nettype, !conf.mail_conferences[msgconf]->realnames, msgconf)) {
if (jamm->subject != NULL) {
free(jamm->subject);
}
if (jamm->from != NULL) {
free(jamm->from);
}
if (jamm->to != NULL) {
free(jamm->to);
}
if (jamm->oaddress != NULL) {
free(jamm->oaddress);
}
if (jamm->daddress != NULL) {
free(jamm->daddress);
}
if (jamm->msgid != NULL) {
free(jamm->msgid);
}
if (jamm->replyid != NULL) {
free(jamm->replyid);
}
free(jamm->msg_h);
free(jamm);
k++;
continue;
}
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_append(&vec, jamm);
k++;
2016-03-30 12:59:00 +10:00
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
msghs->msg_count = ptr_vector_len(&vec);
msghs->msgs = (struct jam_msg **)consume_ptr_vector(&vec);
2016-03-30 12:59:00 +10:00
} else {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2016-03-30 12:59:00 +10:00
return NULL;
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2016-03-30 12:59:00 +10:00
return msghs;
}
2018-01-13 19:17:22 +10:00
char *external_editor(struct user_record *user, char *to, char *from, char *quote, int qlen, char *qfrom, char *subject, int email, int sig) {
2016-04-07 14:43:23 +10:00
char c;
FILE *fptr;
char *body = NULL;
char buffer[256];
int len;
2016-04-07 14:43:23 +10:00
int totlen;
char *body2 = NULL;
char *tagline;
int i;
int j;
struct stat s;
struct utsname name;
if (conf.external_editor_cmd != NULL && user->exteditor != 0) {
if (user->exteditor == 2) {
s_printf(get_string(85));
c = s_getc();
} else {
c = 'y';
}
2016-04-07 14:43:23 +10:00
if (tolower(c) == 'y') {
sprintf(buffer, "%s/node%d", conf.bbs_path, mynode);
if (stat(buffer, &s) != 0) {
mkdir(buffer, 0755);
}
2016-04-07 14:43:23 +10:00
sprintf(buffer, "%s/node%d/MSGTMP", conf.bbs_path, mynode);
2016-04-07 14:43:23 +10:00
if (stat(buffer, &s) == 0) {
remove(buffer);
}
2016-04-07 14:43:23 +10:00
// write msgtemp
if (quote != NULL) {
fptr = fopen(buffer, "w");
for (i = 0; i < qlen; i++) {
2016-04-09 12:44:25 +10:00
if (quote[i] == '\r') {
fprintf(fptr, "\r\n");
} else if (quote[i] == 0x1) {
continue;
2016-04-09 12:54:50 +10:00
} else if (quote[i] == '\e' && quote[i + 1] == '[') {
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL)
i++;
2016-12-07 18:30:47 +10:00
} else if (quote[i] != '\n') {
2016-04-09 12:44:25 +10:00
fprintf(fptr, "%c", quote[i]);
}
}
2016-04-07 14:43:23 +10:00
fclose(fptr);
}
sprintf(buffer, "%s/node%d/MSGINF", conf.bbs_path, mynode);
fptr = fopen(buffer, "w");
fprintf(fptr, "%s\r\n", user->loginname);
2016-04-09 11:57:01 +10:00
if (qfrom != NULL) {
fprintf(fptr, "%s\r\n", qfrom);
} else {
fprintf(fptr, "%s\r\n", to);
}
2016-04-07 14:43:23 +10:00
fprintf(fptr, "%s\r\n", subject);
fprintf(fptr, "0\r\n");
if (email == 1) {
fprintf(fptr, "E-Mail\r\n");
fprintf(fptr, "YES\r\n");
} else {
2018-01-13 19:17:22 +10:00
if (!sig) {
fprintf(fptr, "%s\r\n", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->name);
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
2018-01-13 19:17:22 +10:00
fprintf(fptr, "YES\r\n");
} else {
fprintf(fptr, "NO\r\n");
}
2016-04-07 14:43:23 +10:00
} else {
2018-01-13 19:17:22 +10:00
fprintf(fptr, "None\r\n");
fprintf(fptr, "NO\r\n");
2016-04-07 14:43:23 +10:00
}
}
fclose(fptr);
2017-04-23 12:14:14 +10:00
rundoor(user, conf.external_editor_cmd, conf.external_editor_stdio, conf.external_editor_codepage);
2016-04-07 14:43:23 +10:00
// readin msgtmp
sprintf(buffer, "%s/node%d/MSGTMP", conf.bbs_path, mynode);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
body = file2str(buffer);
2018-10-12 11:11:44 +10:00
if (body == NULL) {
return NULL;
}
totlen = strlen(body);
if (email == 1) {
2016-04-07 14:43:23 +10:00
tagline = conf.default_tagline;
} else {
if (conf.mail_conferences[user->cur_mail_conf]->tagline != NULL) {
tagline = conf.mail_conferences[user->cur_mail_conf]->tagline;
} else {
tagline = conf.default_tagline;
}
}
2018-01-13 19:17:22 +10:00
if (!sig) {
uname(&name);
2018-01-13 19:17:22 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO && !email) {
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point == 0) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2018-01-13 19:17:22 +10:00
} else {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d.%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2018-01-13 19:17:22 +10:00
}
2018-05-22 21:02:22 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_MAGI && !email) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->maginode);
2018-06-24 10:28:18 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_QWK && !email) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%s)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.bwave_name);
} else {
2018-05-22 21:02:22 +10:00
snprintf(buffer, 256, "\r");
2018-01-13 19:17:22 +10:00
}
if (user->autosig) {
body2 = (char *)malloz(totlen + 3 + strlen(buffer) + strlen(user->signature));
2018-01-13 19:17:22 +10:00
} else {
body2 = (char *)malloz(totlen + 2 + strlen(buffer));
}
} else {
body2 = (char *)malloz(totlen + 1);
}
2016-04-07 14:43:23 +10:00
j = 0;
for (i = 0; i < totlen; i++) {
2016-04-07 14:43:23 +10:00
if (body[i] == '\n') {
continue;
2016-04-10 19:30:43 +10:00
} else if (body[i] == '\0') {
continue;
2016-04-07 14:43:23 +10:00
}
body2[j++] = body[i];
body2[j] = '\0';
2016-04-07 14:43:23 +10:00
}
2018-01-13 19:17:22 +10:00
if (!sig) {
if (user->autosig) {
strlcat(body2, "\r", totlen + 1);
strlcat(body2, user->signature, totlen + 1);
2018-01-13 19:17:22 +10:00
}
strlcat(body2, buffer, totlen + 1);
2018-01-13 19:17:22 +10:00
}
2016-04-07 16:41:10 +10:00
free(body);
2016-04-07 14:43:23 +10:00
return body2;
}
}
2018-01-13 19:17:22 +10:00
return editor(user, quote, qlen, qfrom, email, sig);
2016-04-07 14:43:23 +10:00
}
2018-01-13 19:17:22 +10:00
char *editor(struct user_record *user, char *quote, int quotelen, char *from, int email, int sig) {
char buffer[256];
2016-03-22 18:19:06 +10:00
char linebuffer[80];
int doquit = 0;
2016-03-22 18:19:06 +10:00
int i;
char *msg;
int size = 0;
int lineat = 0;
int qfrom, qto;
2016-03-23 10:14:31 +10:00
int z;
2016-03-27 13:17:25 +10:00
char *tagline;
struct utsname name;
2016-04-13 22:35:49 +10:00
char next_line_buffer[80];
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct ptr_vector content;
struct ptr_vector quotecontent;
2016-04-13 22:35:49 +10:00
memset(next_line_buffer, 0, 80);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
init_ptr_vector(&quotecontent);
init_ptr_vector(&content);
2016-04-07 14:43:23 +10:00
if (quote != NULL) {
for (i = 0; i < quotelen; i++) {
2016-04-13 22:35:49 +10:00
if (quote[i] == '\r' || lineat == 67) {
char prefix[] = {from[0], '>', '\0'};
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_append(&quotecontent, str3dup(prefix, " ", linebuffer));
lineat = 0;
2016-03-23 10:14:31 +10:00
linebuffer[0] = '\0';
2016-04-07 12:42:25 +10:00
if (quote[i] != '\r') {
i--;
}
} else {
if (quote[i] == 27) {
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL)
i++;
continue;
}
linebuffer[lineat++] = quote[i];
linebuffer[lineat] = '\0';
}
}
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
s_printf(get_string(86));
s_printf(get_string(87));
while (!doquit) {
s_printf(get_string(88), ptr_vector_len(&content), "");
strlcpy(linebuffer, next_line_buffer, sizeof(linebuffer));
2018-02-20 15:02:39 +10:00
s_readstring_inject(linebuffer, 70, next_line_buffer);
2016-04-13 22:35:49 +10:00
memset(next_line_buffer, 0, 70);
if (strlen(linebuffer) == 70 && linebuffer[69] != ' ') {
for (i = strlen(linebuffer) - 1; i > 15; i--) {
2016-04-13 22:35:49 +10:00
if (linebuffer[i] == ' ') {
linebuffer[i] = '\0';
strlcpy(next_line_buffer, &linebuffer[i + 1], sizeof next_line_buffer);
s_printf("\e[%dD\e[0K", 70 - i);
2016-04-13 22:35:49 +10:00
break;
}
}
}
2016-04-13 22:35:49 +10:00
if (linebuffer[0] == '/' && strlen(linebuffer) == 2) {
2016-03-22 18:19:06 +10:00
if (toupper(linebuffer[1]) == 'S') {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (i = 0; i < ptr_vector_len(&content); i++) {
size += strlen(ptr_vector_get(&content, i)) + 1;
2016-03-22 18:19:06 +10:00
}
size++;
2016-03-27 13:17:25 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->tagline != NULL) {
tagline = conf.mail_conferences[user->cur_mail_conf]->tagline;
} else {
tagline = conf.default_tagline;
}
2018-01-13 19:17:22 +10:00
if (!sig) {
uname(&name);
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO && !email) {
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point == 0) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2018-01-13 19:17:22 +10:00
} else {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d.%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2018-01-13 19:17:22 +10:00
}
2018-05-22 21:02:22 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_MAGI && !email) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.mail_conferences[user->cur_mail_conf]->maginode);
2018-06-24 10:28:18 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_QWK && !email) {
snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%s)\r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline, conf.bwave_name);
} else {
2018-05-22 21:02:22 +10:00
snprintf(buffer, 256, "\r");
2018-01-13 19:17:22 +10:00
}
if (user->autosig) {
size += 3;
size += strlen(buffer) + strlen(user->signature);
} else {
size += 2;
size += strlen(buffer);
}
} else {
2018-01-13 19:17:22 +10:00
size += 1;
}
msg = (char *)malloz(size);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (i = 0; i < ptr_vector_len(&content); i++) {
strlcat(msg, ptr_vector_get(&content, i), size);
strlcat(msg, "\r", size);
2016-03-22 18:19:06 +10:00
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&content, free);
destroy_ptr_vector(&content);
2018-01-13 19:17:22 +10:00
if (!sig) {
if (user->autosig) {
strlcat(msg, "\r", size);
strlcat(msg, user->signature, size);
2018-01-13 19:17:22 +10:00
}
strlcat(msg, buffer, size);
2018-01-13 19:17:22 +10:00
}
if (quote != NULL) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
2016-03-22 18:19:06 +10:00
return msg;
} else if (toupper(linebuffer[1]) == 'A') {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&content, free);
destroy_ptr_vector(&content);
if (quote != NULL) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
2016-03-22 18:19:06 +10:00
return NULL;
} else if (toupper(linebuffer[1]) == 'Q') {
if (quote == NULL) {
s_printf(get_string(89));
} else {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
s_printf("\r\n");
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (i = 0; i < ptr_vector_len(&quotecontent); i++) {
s_printf(get_string(88), i, ptr_vector_get(&quotecontent, i));
}
s_printf(get_string(90));
s_readstring(buffer, 5);
qfrom = atoi(buffer);
s_printf(get_string(91));
s_readstring(buffer, 5);
qto = atoi(buffer);
s_printf("\r\n");
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
if (qto > ptr_vector_len(&quotecontent)) {
qto = ptr_vector_len(&quotecontent);
}
if (qfrom < 0) {
qfrom = 0;
}
if (qfrom > qto) {
s_printf(get_string(92));
}
for (i = qfrom; i <= qto; i++) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
char *copy = strdup(ptr_vector_get(&quotecontent, i));
ptr_vector_append(&content, copy);
}
s_printf(get_string(86));
s_printf(get_string(87));
2016-03-23 10:14:31 +10:00
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (i = 0; i < ptr_vector_len(&content); i++) {
s_printf(get_string(88), i, ptr_vector_get(&content, i));
}
}
} else if (toupper(linebuffer[1]) == 'L') {
s_printf(get_string(86));
s_printf(get_string(87));
2016-03-23 10:14:31 +10:00
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (i = 0; i < ptr_vector_len(&content); i++) {
s_printf(get_string(88), i, ptr_vector_get(&content, i));
}
} else if (linebuffer[1] == '?') {
s_printf(get_string(93));
s_printf(get_string(94));
s_printf(get_string(95));
s_printf(get_string(96));
s_printf(get_string(97));
s_printf(get_string(98));
s_printf(get_string(99));
s_printf(get_string(100));
2016-03-23 10:14:31 +10:00
} else if (toupper(linebuffer[1]) == 'D') {
s_printf(get_string(101));
s_readstring(buffer, 6);
2016-03-23 10:14:31 +10:00
if (strlen(buffer) == 0) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
free(ptr_vector_del(&content, i));
2016-03-23 10:14:31 +10:00
}
}
} else if (toupper(linebuffer[1]) == 'E') {
s_printf(get_string(102));
s_readstring(buffer, 6);
2016-03-23 10:14:31 +10:00
if (strlen(buffer) == 0) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
s_printf(get_string(88), z, ptr_vector_get(&content, z));
s_printf(get_string(103), z);
s_readstring(linebuffer, 70);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
free(ptr_vector_get(&content, z));
ptr_vector_put(&content, strdup(linebuffer), z);
2016-03-23 10:14:31 +10:00
}
}
} else if (toupper(linebuffer[1]) == 'I') {
s_printf(get_string(104));
s_readstring(buffer, 6);
2016-03-23 10:14:31 +10:00
if (strlen(buffer) == 0) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
2016-03-23 10:14:31 +10:00
} else {
s_printf(get_string(103), z);
s_readstring(linebuffer, 70);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_ins(&content, strdup(linebuffer), z);
2016-03-23 10:14:31 +10:00
}
}
2016-03-22 18:19:06 +10:00
}
} else {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_append(&content, strdup(linebuffer));
2016-03-22 18:19:06 +10:00
}
}
if (quote != NULL) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
2016-03-22 18:19:06 +10:00
return NULL;
}
struct character_t {
char c;
int fg;
int bg;
};
void unmangle_ansi(char *body, int len, char **body_out, int *body_len) {
// count lines
int line_count = 1;
int line_at = 1;
int char_at = 1;
int fg = 0x07;
int bg = 0x00;
int state = 0;
int save_char_at = 0;
int save_line_at = 0;
int params[16];
int param_count = 0;
int bold = 0;
char *out;
int out_len;
int out_max;
char buffer[1024];
int buf_at;
int i, j, k;
struct character_t ***fake_screen;
int ansi;
2017-09-18 10:54:11 +10:00
int tab;
2017-09-09 22:18:23 +10:00
line_at = 1;
char_at = 1;
for (i = 0; i < len; i++) {
2017-09-09 22:18:23 +10:00
if (state == 0) {
if (body[i] == 27) {
state = 1;
continue;
} else {
if (body[i] == '\r') {
char_at = 1;
line_at++;
2017-09-18 10:54:11 +10:00
} else if (body[i] == '\t') {
char_at += 8;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
} else {
2016-12-06 20:11:41 +10:00
char_at++;
2017-09-09 22:18:23 +10:00
while (char_at > 80) {
line_at++;
char_at -= 80;
}
2016-12-06 20:11:41 +10:00
}
2017-09-09 22:18:23 +10:00
if (line_at > line_count) {
line_count = line_at;
2016-12-06 20:11:41 +10:00
}
2017-09-09 22:18:23 +10:00
}
} else if (state == 1) {
if (body[i] == '[') {
state = 2;
continue;
2018-09-02 18:23:47 +10:00
} else {
state = 0;
continue;
2017-09-09 22:18:23 +10:00
}
} else if (state == 2) {
param_count = 0;
for (j = 0; j < 16; j++) {
2017-09-09 22:18:23 +10:00
params[j] = 0;
}
state = 3;
}
if (state == 3) {
if (body[i] == ';') {
if (param_count < 15) {
param_count++;
2016-12-06 20:11:41 +10:00
}
2017-09-09 22:18:23 +10:00
continue;
} else if (body[i] >= '0' && body[i] <= '9') {
if (!param_count) param_count = 1;
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
2017-09-09 22:18:23 +10:00
continue;
} else {
state = 4;
}
}
2017-09-09 22:18:23 +10:00
if (state == 4) {
switch (body[i]) {
2017-09-09 22:18:23 +10:00
case 'H':
case 'f':
if (params[0]) params[0]--;
if (params[1]) params[1]--;
line_at = params[0] + 1;
char_at = params[1] + 1;
2017-09-09 22:18:23 +10:00
if (char_at > 80) {
char_at = 80;
}
2017-09-09 22:18:23 +10:00
if (line_at > line_count) {
line_count = line_at;
}
2017-09-09 22:18:23 +10:00
state = 0;
break;
case 'A':
if (param_count > 0) {
line_at = line_at - params[0];
} else {
line_at--;
}
if (line_at < 1) {
line_at = 1;
}
state = 0;
break;
case 'B':
if (param_count > 0) {
line_at = line_at + params[0];
} else {
line_at++;
}
if (line_at > line_count) {
line_count = line_at;
}
state = 0;
break;
case 'C':
if (param_count > 0) {
char_at = char_at + params[0];
} else {
char_at++;
2017-09-09 22:18:23 +10:00
}
if (char_at > 80) {
char_at = 80;
}
state = 0;
break;
case 'D':
if (param_count > 0) {
char_at = char_at - params[0];
} else {
char_at--;
2017-09-09 22:18:23 +10:00
}
if (char_at < 1) {
char_at = 1;
}
state = 0;
break;
case 's':
save_char_at = char_at;
save_line_at = line_at;
state = 0;
break;
case 'u':
char_at = save_char_at;
line_at = save_line_at;
state = 0;
break;
default:
state = 0;
break;
}
}
}
fake_screen = (struct character_t ***)malloz(sizeof(struct character_t **) * line_count);
for (i = 0; i < line_count; i++) {
fake_screen[i] = (struct character_t **)malloz(sizeof(struct character_t *) * 80);
for (j = 0; j < 80; j++) {
fake_screen[i][j] = (struct character_t *)malloz(sizeof(struct character_t));
fake_screen[i][j]->c = ' ';
fake_screen[i][j]->fg = fg;
fake_screen[i][j]->bg = bg;
}
}
line_at = 1;
char_at = 1;
for (i = 0; i < len; i++) {
if (state == 0) {
if (body[i] == 27) {
state = 1;
continue;
} else {
if (body[i] == '\r') {
char_at = 1;
line_at++;
2017-09-18 10:54:11 +10:00
} else if (body[i] == '\t') {
for (tab = 0; tab < 8; tab++) {
if (line_at > line_count) line_at = line_count;
fake_screen[line_at - 1][char_at - 1]->c = ' ';
fake_screen[line_at - 1][char_at - 1]->fg = fg;
fake_screen[line_at - 1][char_at - 1]->bg = bg;
2017-09-18 10:54:11 +10:00
char_at++;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
2017-09-18 10:54:11 +10:00
}
} else {
2017-09-09 22:18:23 +10:00
if (line_at > line_count) line_at = line_count;
fake_screen[line_at - 1][char_at - 1]->c = body[i];
fake_screen[line_at - 1][char_at - 1]->fg = fg;
fake_screen[line_at - 1][char_at - 1]->bg = bg;
char_at++;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
}
}
} else if (state == 1) {
if (body[i] == '[') {
state = 2;
continue;
2018-09-02 18:27:22 +10:00
} else {
state = 0;
continue;
}
} else if (state == 2) {
param_count = 0;
for (j = 0; j < 16; j++) {
params[j] = 0;
}
state = 3;
}
if (state == 3) {
if (body[i] == ';') {
if (param_count < 15) {
param_count++;
}
continue;
} else if (body[i] >= '0' && body[i] <= '9') {
if (!param_count) param_count = 1;
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
continue;
} else {
state = 4;
}
}
if (state == 4) {
switch (body[i]) {
case 'H':
case 'f':
if (params[0]) params[0]--;
if (params[1]) params[1]--;
line_at = params[0] + 1;
char_at = params[1] + 1;
state = 0;
break;
case 'A':
if (param_count > 0) {
line_at = line_at - params[0];
} else {
line_at--;
}
if (line_at < 1) {
line_at = 1;
}
state = 0;
break;
case 'B':
if (param_count > 0) {
line_at = line_at + params[0];
} else {
line_at++;
}
2017-09-09 22:18:23 +10:00
if (line_at > line_count) {
line_at = line_count;
}
state = 0;
break;
case 'C':
if (param_count > 0) {
char_at = char_at + params[0];
} else {
char_at++;
}
if (char_at > 80) {
char_at = 80;
}
state = 0;
break;
case 'D':
if (param_count > 0) {
char_at = char_at - params[0];
} else {
char_at--;
}
if (char_at < 1) {
char_at = 1;
}
state = 0;
break;
case 's':
save_char_at = char_at;
save_line_at = line_at;
state = 0;
break;
case 'u':
char_at = save_char_at;
line_at = save_line_at;
state = 0;
break;
case 'm':
for (j = 0; j < param_count; j++) {
switch (params[j]) {
case 0:
fg = 0x07;
bg = 0x00;
bold = 0;
break;
case 1:
bold = 1;
if (fg < 0x08) {
fg += 0x08;
}
break;
case 2:
bold = 0;
if (fg > 0x07) {
fg -= 0x08;
}
break;
case 30:
if (bold) {
fg = 0x08;
} else {
fg = 0x00;
}
break;
case 31:
if (bold) {
fg = 0x0C;
} else {
fg = 0x04;
}
break;
case 32:
if (bold) {
fg = 0x0A;
} else {
fg = 0x02;
}
break;
case 33:
if (bold) {
fg = 0x0E;
} else {
fg = 0x06;
}
break;
case 34:
if (bold) {
fg = 0x09;
} else {
fg = 0x01;
}
break;
case 35:
if (bold) {
fg = 0x0D;
} else {
fg = 0x05;
}
break;
case 36:
if (bold) {
fg = 0x0B;
} else {
fg = 0x03;
}
break;
case 37:
if (bold) {
fg = 0x0F;
} else {
fg = 0x07;
}
break;
case 40:
bg = 0x00;
break;
case 41:
bg = 0x04;
break;
case 42:
bg = 0x02;
break;
case 43:
bg = 0x06;
break;
case 44:
bg = 0x01;
break;
case 45:
bg = 0x05;
break;
case 46:
bg = 0x03;
break;
case 47:
bg = 0x07;
break;
}
}
state = 0;
break;
case 'K':
if (params[0] == 0) {
for (k = char_at - 1; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
} else if (params[0] == 1) {
for (k = 0; k < char_at; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
} else if (params[0] == 2) {
for (k = 0; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
}
state = 0;
break;
case 'J':
if (params[0] == 0) {
for (k = char_at - 1; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
for (k = line_at; k < line_count; k++) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
} else if (params[0] == 1) {
for (k = 0; k < char_at; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
for (k = line_at - 2; k >= 0; k--) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
} else if (params[0] == 2) {
for (k = 0; k < line_count; k++) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
}
state = 0;
break;
default:
// bad ansi
state = 0;
break;
}
}
}
2016-12-06 20:11:41 +10:00
fg = 0x07;
bg = 0x00;
out_max = 256;
out_len = 0;
out = (char *)malloz(256);
for (i = 0; i < line_count; i++) {
buf_at = 0;
for (j = 0; j < 79; j++) {
if (fake_screen[i][j]->fg != fg || fake_screen[i][j]->bg != bg) {
buffer[buf_at++] = 27;
buffer[buf_at++] = '[';
fg = fake_screen[i][j]->fg;
if (fg < 0x08) {
buffer[buf_at++] = '0';
buffer[buf_at++] = ';';
buffer[buf_at++] = '3';
switch (fg) {
case 0x00:
buffer[buf_at++] = '0';
break;
case 0x04:
buffer[buf_at++] = '1';
break;
case 0x02:
buffer[buf_at++] = '2';
break;
case 0x06:
buffer[buf_at++] = '3';
break;
case 0x01:
buffer[buf_at++] = '4';
break;
case 0x05:
buffer[buf_at++] = '5';
break;
case 0x03:
buffer[buf_at++] = '6';
break;
case 0x07:
buffer[buf_at++] = '7';
break;
}
} else {
buffer[buf_at++] = '1';
buffer[buf_at++] = ';';
buffer[buf_at++] = '3';
switch (fg) {
case 0x08:
buffer[buf_at++] = '0';
break;
case 0x0C:
buffer[buf_at++] = '1';
break;
case 0x0A:
buffer[buf_at++] = '2';
break;
case 0x0E:
buffer[buf_at++] = '3';
break;
case 0x09:
buffer[buf_at++] = '4';
break;
case 0x0D:
buffer[buf_at++] = '5';
break;
case 0x0B:
buffer[buf_at++] = '6';
break;
case 0x0F:
buffer[buf_at++] = '7';
break;
}
}
bg = fake_screen[i][j]->bg;
buffer[buf_at++] = ';';
buffer[buf_at++] = '4';
switch (bg) {
case 0x00:
buffer[buf_at++] = '0';
break;
case 0x04:
buffer[buf_at++] = '1';
break;
case 0x02:
buffer[buf_at++] = '2';
break;
case 0x06:
buffer[buf_at++] = '3';
break;
case 0x01:
buffer[buf_at++] = '4';
break;
case 0x05:
buffer[buf_at++] = '5';
break;
case 0x03:
buffer[buf_at++] = '6';
break;
case 0x07:
buffer[buf_at++] = '7';
break;
}
buffer[buf_at++] = 'm';
}
buffer[buf_at++] = fake_screen[i][j]->c;
}
while (buf_at > 0 && buffer[buf_at - 1] == ' ') {
buf_at--;
}
buffer[buf_at++] = '\r';
while (buf_at + out_len > out_max) {
out_max += 256;
out = (char *)realloc(out, out_max);
}
memcpy(&out[out_len], buffer, buf_at);
out_len += buf_at;
}
for (i = 0; i < line_count; i++) {
for (j = 0; j < 80; j++) {
free(fake_screen[i][j]);
}
free(fake_screen[i]);
}
free(fake_screen);
while (out[out_len - 2] == '\r') {
out_len--;
}
*body_out = out;
*body_len = out_len;
}
2017-10-13 13:03:06 +10:00
int read_message(struct user_record *user, struct msg_headers *msghs, int mailno, int newscan) {
2016-03-22 18:19:06 +10:00
s_JamBase *jb;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
2016-03-22 18:19:06 +10:00
s_JamSubfield jsf;
2016-03-26 16:06:59 +10:00
s_JamLastRead jlr;
2016-03-22 18:19:06 +10:00
char buffer[256];
2016-04-04 10:53:23 +10:00
int z, z2;
2016-03-23 10:14:31 +10:00
struct tm msg_date;
2016-03-22 18:19:06 +10:00
char *subject = NULL;
char *from = NULL;
char *to = NULL;
2016-03-22 18:19:06 +10:00
char *body = NULL;
2016-04-04 10:53:23 +10:00
char *body2 = NULL;
2016-03-22 18:19:06 +10:00
int lines = 0;
char c;
char *replybody;
2016-03-24 17:23:42 +10:00
struct fido_addr *from_addr = NULL;
int i, j;
2016-03-30 12:59:00 +10:00
int doquit = 0;
2016-04-04 10:53:23 +10:00
int skip_line = 0;
int chars = 0;
2016-04-22 14:36:53 +10:00
int ansi;
2016-04-23 14:10:42 +10:00
int sem_fd;
int start_line;
int should_break;
int position;
int y;
uuid_t magi_msgid;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct ptr_vector msg_lines;
2018-05-22 21:02:22 +10:00
init_ptr_vector(&msg_lines);
2016-03-22 18:19:06 +10:00
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
2017-10-13 13:03:06 +10:00
return 0;
2016-03-22 18:19:06 +10:00
}
2017-10-13 13:03:06 +10:00
while (doquit == 0) {
2016-03-30 12:59:00 +10:00
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.UserCRC = JAM_Crc32(user->loginname, strlen(user->loginname));
jlr.UserID = user->id;
2016-08-21 09:39:36 +10:00
jlr.HighReadMsg = msghs->msgs[mailno]->msg_h->MsgNum;
2016-03-28 21:10:07 +10:00
}
2016-08-21 09:39:36 +10:00
jlr.LastReadMsg = msghs->msgs[mailno]->msg_h->MsgNum;
if (jlr.HighReadMsg < msghs->msgs[mailno]->msg_h->MsgNum) {
jlr.HighReadMsg = msghs->msgs[mailno]->msg_h->MsgNum;
2016-03-28 21:10:07 +10:00
}
2016-03-30 12:59:00 +10:00
if (msghs->msgs[mailno]->oaddress != NULL && conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
from_addr = parse_fido_addr(msghs->msgs[mailno]->oaddress);
s_printf(get_string(105), msghs->msgs[mailno]->from, from_addr->zone, from_addr->net, from_addr->node, from_addr->point);
2016-03-30 12:59:00 +10:00
free(from_addr);
2018-05-22 21:02:22 +10:00
} else if (msghs->msgs[mailno]->oaddress != NULL && conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_MAGI) {
s_printf(get_string(288), msghs->msgs[mailno]->from, atoi(msghs->msgs[mailno]->oaddress));
2018-06-24 10:28:18 +10:00
} else if (msghs->msgs[mailno]->oaddress != NULL && conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_QWK) {
s_printf(get_string(289), msghs->msgs[mailno]->from, msghs->msgs[mailno]->oaddress);
2016-03-30 12:59:00 +10:00
} else {
s_printf(get_string(106), msghs->msgs[mailno]->from);
2016-03-28 21:10:07 +10:00
}
s_printf(get_string(107), msghs->msgs[mailno]->to, conf.mail_conferences[user->cur_mail_conf]->name);
s_printf(get_string(108), msghs->msgs[mailno]->subject, conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->name);
2017-04-21 20:31:41 +10:00
gmtime_r((time_t *)&msghs->msgs[mailno]->msg_h->DateWritten, &msg_date);
sprintf(buffer, "%s", asctime(&msg_date));
2016-03-30 12:59:00 +10:00
buffer[strlen(buffer) - 1] = '\0';
s_printf(get_string(109), buffer, mailno + 1, msghs->msg_count);
2018-05-22 08:55:44 +10:00
s_printf(get_string(110), (msghs->msgs[mailno]->msg_h->Attribute & JAM_MSG_SENT ? "SENT" : ""), (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[mailno]->msg_h->MsgNum) ? "FLAGGED" : ""));
s_printf(get_string(111));
2016-03-22 18:19:06 +10:00
body = (char *)malloz(msghs->msgs[mailno]->msg_h->TxtLen);
2016-03-30 12:59:00 +10:00
JAM_ReadMsgText(jb, msghs->msgs[mailno]->msg_h->TxtOffset, msghs->msgs[mailno]->msg_h->TxtLen, (char *)body);
2017-10-13 13:03:06 +10:00
if (!newscan) {
JAM_WriteLastRead(jb, user->id, &jlr);
}
2016-03-22 18:19:06 +10:00
2017-03-20 21:06:52 +10:00
z2 = msghs->msgs[mailno]->msg_h->TxtLen;
2016-04-08 13:09:39 +10:00
lines = 0;
chars = 0;
body2 = body;
z = z2;
unmangle_ansi(body2, z, &body, &z2);
free(body2);
start_line = 0;
// count the number of lines...
for (z = 0; z < z2; z++) {
if (body[z] == '\r' || chars == 80) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
char *msg_line = (char *)malloz(z - start_line + 1);
ptr_vector_append(&msg_lines, msg_line);
if (z == start_line) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
msg_line[0] = '\0';
} else {
strlcpy(msg_line, &body[start_line], z - start_line + 1);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
msg_line[z - start_line] = '\0';
}
if (body[z] == '\r') {
start_line = z + 1;
} else {
start_line = z;
}
chars = 0;
} else {
if (body[z] == 27) {
ansi = z;
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", body[z]) == NULL)
z++;
if (body[z] == 'm') {
// do nothing
} else {
y = ansi;
for (j = z + 1; j < z2; j++) {
body[y] = body[j];
y++;
}
z2 = z2 - (z2 - y);
z = ansi - 1;
}
} else {
chars++;
}
}
}
lines = 0;
position = 0;
should_break = 0;
while (!should_break) {
s_printf("\e[7;1H");
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
for (z = position; z < ptr_vector_len(&msg_lines); z++) {
s_printf("%s\e[K\r\n", ptr_vector_get(&msg_lines, z));
if (z - position >= 15) {
break;
}
}
s_printf(get_string(187));
2017-10-13 13:03:06 +10:00
if (newscan) {
2017-10-13 13:17:25 +10:00
s_printf(get_string(234));
2017-10-13 13:03:06 +10:00
} else {
2017-10-13 13:15:46 +10:00
s_printf(get_string(186));
2017-10-13 13:03:06 +10:00
}
c = s_getc();
if (tolower(c) == 'r') {
should_break = 1;
} else if (tolower(c) == 'q') {
should_break = 1;
2017-10-13 13:03:06 +10:00
} else if (tolower(c) == 'j' && newscan == 1) {
should_break = 1;
2018-05-22 08:55:44 +10:00
} else if (tolower(c) == 'f') {
should_break = 1;
} else if (c == '\e') {
c = s_getc();
if (c == 91) {
c = s_getc();
if (c == 65) {
position--;
if (position < 0) {
position = 0;
}
} else if (c == 66) {
position++;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
if (position + 15 >= ptr_vector_len(&msg_lines)) {
position--;
}
} else if (c == 67) {
c = ' ';
should_break = 1;
} else if (c == 68) {
c = 'b';
should_break = 1;
}
}
}
}
2016-03-30 12:59:00 +10:00
if (tolower(c) == 'r') {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2018-02-23 14:27:36 +10:00
jb = NULL;
2016-03-30 12:59:00 +10:00
if (user->sec_level < conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->write_sec_level) {
s_printf(get_string(113));
2018-05-16 13:44:04 +10:00
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
2016-03-28 14:46:48 +10:00
} else {
2016-04-01 08:55:25 +10:00
if (msghs->msgs[mailno]->subject != NULL) {
2016-04-09 11:57:01 +10:00
if (strncasecmp(msghs->msgs[mailno]->subject, "RE:", 3) != 0) {
snprintf(buffer, 256, "RE: %s", msghs->msgs[mailno]->subject);
} else {
snprintf(buffer, 256, "%s", msghs->msgs[mailno]->subject);
}
2016-03-30 12:59:00 +10:00
}
subject = strdup(buffer);
2018-05-09 13:19:49 +10:00
s_printf(get_string(114));
s_readstring_inject(buffer, 32, msghs->msgs[mailno]->from);
to = strdup(buffer);
s_printf(get_string(115));
2018-05-09 13:19:49 +10:00
s_readstring_inject(buffer, 64, subject);
free(subject);
subject = strdup(buffer);
s_printf("\r\n");
2016-03-30 12:59:00 +10:00
if (msghs->msgs[mailno]->from != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->from, sizeof buffer);
2016-03-30 12:59:00 +10:00
}
if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) {
from = strdup(user->loginname);
2016-03-30 12:59:00 +10:00
} else {
from = str3dup(user->firstname, " ", user->lastname);
}
2017-03-20 21:06:52 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
2018-05-09 13:19:49 +10:00
free(to);
to = strdup("ALL");
2016-03-30 12:59:00 +10:00
}
2018-01-13 19:17:22 +10:00
replybody = external_editor(user, to, from, body, z2, msghs->msgs[mailno]->from, subject, 0, 0);
2016-03-30 12:59:00 +10:00
if (replybody != NULL) {
2016-03-30 12:59:00 +10:00
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
2016-03-30 12:59:00 +10:00
free(replybody);
free(body);
free(subject);
free(to);
free(from);
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
2017-10-13 13:03:06 +10:00
return 0;
2016-03-30 12:59:00 +10:00
}
JAM_ClearMsgHeader(&jmh);
2017-04-21 20:31:41 +10:00
jmh.DateWritten = utc_to_local(time(NULL));
jmh.Attribute |= JAM_MSG_LOCAL;
2016-03-30 12:59:00 +10:00
jsp = JAM_NewSubPacket();
jsf.LoID = JAMSFLD_SENDERNAME;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(from);
jsf.Buffer = (char *)from;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_RECVRNAME;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(to);
jsf.Buffer = (char *)to;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_SUBJECT;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(subject);
jsf.Buffer = (char *)subject;
JAM_PutSubfield(jsp, &jsf);
2016-03-29 21:53:42 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_ECHOMAIL_AREA || conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
jmh.Attribute |= JAM_MSG_TYPEECHO;
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
2016-03-30 12:59:00 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point) {
sprintf(buffer, "%d:%d/%d.%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2016-03-30 12:59:00 +10:00
} else {
sprintf(buffer, "%d:%d/%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2016-03-30 12:59:00 +10:00
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
sprintf(buffer, "%d:%d/%d.%d %08lx", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point,
generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
2016-04-15 12:34:58 +10:00
if (msghs->msgs[mailno]->msgid != NULL) {
2017-10-16 11:50:40 +10:00
sprintf(buffer, "%s", msghs->msgs[mailno]->msgid);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
2016-03-30 12:59:00 +10:00
}
2018-05-22 21:02:22 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_MAGI) {
sprintf(buffer, "%d", conf.mail_conferences[user->cur_mail_conf]->maginode);
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
uuid_generate(magi_msgid);
uuid_unparse_lower(magi_msgid, buffer);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
2018-05-22 21:02:22 +10:00
if (msghs->msgs[mailno]->msgid != NULL) {
sprintf(buffer, "%s", msghs->msgs[mailno]->msgid);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
}
2018-06-24 10:28:18 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_QWK) {
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2018-06-24 10:28:18 +10:00
jsf.DatLen = strlen(conf.bwave_name);
jsf.Buffer = (char *)conf.bwave_name;
JAM_PutSubfield(jsp, &jsf);
2016-03-29 21:53:42 +10:00
}
2016-03-30 12:59:00 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
jmh.Attribute |= JAM_MSG_TYPENET;
jmh.Attribute |= JAM_MSG_PRIVATE;
2016-03-30 12:59:00 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point) {
sprintf(buffer, "%d:%d/%d.%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2016-03-25 15:58:08 +10:00
} else {
2016-03-30 12:59:00 +10:00
sprintf(buffer, "%d:%d/%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2016-03-25 15:58:08 +10:00
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2016-03-24 17:23:42 +10:00
jsf.DatLen = strlen(buffer);
2016-03-25 18:28:09 +10:00
jsf.Buffer = (char *)buffer;
2016-03-30 12:59:00 +10:00
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
2016-03-30 12:59:00 +10:00
from_addr = parse_fido_addr(msghs->msgs[mailno]->oaddress);
if (from_addr != NULL) {
if (from_addr->point) {
sprintf(buffer, "%d:%d/%d.%d", from_addr->zone,
from_addr->net,
from_addr->node,
from_addr->point);
2016-03-30 12:59:00 +10:00
} else {
sprintf(buffer, "%d:%d/%d", from_addr->zone,
from_addr->net,
from_addr->node);
2016-03-30 12:59:00 +10:00
}
jsf.LoID = JAMSFLD_DADDRESS;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
free(from_addr);
}
sprintf(buffer, "%d:%d/%d.%d %08lx", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point,
generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2016-03-30 12:59:00 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
2016-03-30 13:46:09 +10:00
if (msghs->msgs[mailno]->msgid != NULL) {
2017-10-16 11:50:40 +10:00
sprintf(buffer, "%s", msghs->msgs[mailno]->msgid);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
2016-03-30 12:59:00 +10:00
}
}
2016-03-28 21:10:07 +10:00
}
2016-03-30 12:59:00 +10:00
while (1) {
z = JAM_LockMB(jb, 100);
if (z == 0) {
break;
} else if (z == JAM_LOCK_FAILED) {
sleep(1);
} else {
free(replybody);
free(body);
free(subject);
free(to);
free(from);
dolog("Failed to lock msg base!");
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
2017-10-13 13:03:06 +10:00
return 0;
2016-03-29 21:53:42 +10:00
}
}
2016-03-30 12:59:00 +10:00
if (JAM_AddMessage(jb, &jmh, jsp, (char *)replybody, strlen(replybody))) {
dolog("Failed to add message");
2016-04-23 14:10:42 +10:00
} else {
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
if (conf.netmail_sem != NULL) {
sem_fd = open(conf.netmail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
2016-04-23 14:10:42 +10:00
close(sem_fd);
}
} else if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_ECHOMAIL_AREA || conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
2016-04-23 14:10:42 +10:00
if (conf.echomail_sem != NULL) {
sem_fd = open(conf.echomail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
2016-04-23 14:10:42 +10:00
close(sem_fd);
}
2016-04-23 14:10:42 +10:00
}
2016-03-30 12:59:00 +10:00
}
2016-03-30 12:59:00 +10:00
JAM_UnlockMB(jb);
2016-03-30 12:59:00 +10:00
JAM_DelSubPacket(jsp);
free(replybody);
// JAM_CloseMB(jb);
// doquit = 1;
2017-04-29 20:17:58 +10:00
} else {
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
}
}
2016-03-30 12:59:00 +10:00
free(body);
2016-03-22 18:19:06 +10:00
2016-03-30 12:59:00 +10:00
if (from != NULL) {
free(from);
}
2016-03-30 12:59:00 +10:00
if (to != NULL) {
free(to);
}
2016-03-30 12:59:00 +10:00
if (subject != NULL) {
free(subject);
}
2017-10-13 13:03:06 +10:00
} else if (tolower(c) == 'j' && newscan == 1) {
free(body);
2017-10-13 15:41:43 +10:00
doquit = 1;
2016-03-30 12:59:00 +10:00
} else if (tolower(c) == 'q') {
free(body);
2017-10-13 15:41:43 +10:00
doquit = 2;
2016-03-30 12:59:00 +10:00
} else if (c == ' ') {
mailno++;
if (mailno >= msghs->msg_count) {
s_printf(get_string(118));
2016-03-30 12:59:00 +10:00
doquit = 1;
}
free(body);
2016-04-22 21:48:52 +10:00
} else if (tolower(c) == 'b') {
if (mailno > 0) {
mailno--;
}
free(body);
2018-05-22 08:55:44 +10:00
} else if (tolower(c) == 'f') {
msgbase_flag_unflag(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[mailno]->msg_h->MsgNum);
free(body);
} else {
free(body);
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
2016-03-29 21:53:42 +10:00
}
2018-02-23 14:27:36 +10:00
if (jb != NULL) {
JAM_CloseMB(jb);
free(jb);
}
2017-10-13 13:03:06 +10:00
if (doquit == 2) {
return 1;
}
2017-10-13 13:03:06 +10:00
return 0;
2016-03-22 18:19:06 +10:00
}
2017-10-13 13:03:06 +10:00
int read_new_msgs(struct user_record *user, struct msg_headers *msghs) {
2017-10-12 20:24:55 +10:00
s_JamBase *jb;
s_JamLastRead jlr;
int all_unread;
int i;
int k;
char buffer[7];
2017-10-13 13:03:06 +10:00
int res;
2017-10-12 20:24:55 +10:00
// list mail in message base
if (msghs != NULL && msghs->msg_count > 0) {
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
2017-10-13 13:03:06 +10:00
return 0;
2017-10-12 20:24:55 +10:00
} else {
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
2018-02-23 14:27:36 +10:00
}
if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
2017-10-12 20:24:55 +10:00
all_unread = 1;
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-10-12 20:24:55 +10:00
if (all_unread == 0) {
k = jlr.HighReadMsg;
for (i = 0; i < msghs->msg_count; i++) {
2017-10-12 20:24:55 +10:00
if (msghs->msgs[i]->msg_h->MsgNum == k) {
i += 2;
2017-10-12 20:24:55 +10:00
break;
}
2018-02-23 14:27:36 +10:00
if (msghs->msgs[i]->msg_h->MsgNum > k) {
i++;
break;
}
2017-10-12 20:24:55 +10:00
}
2017-10-12 20:24:55 +10:00
} else {
i = 1;
}
if (i > 0 && i <= msghs->msg_count) {
2017-10-13 13:20:42 +10:00
res = read_message(user, msghs, i - 1, 1);
s_printf("\r\n");
return res;
2017-10-12 20:24:55 +10:00
}
}
2017-10-13 13:03:06 +10:00
}
return 0;
2017-10-12 20:24:55 +10:00
}
2017-04-12 17:27:59 +10:00
void read_mail(struct user_record *user) {
struct msg_headers *msghs;
s_JamBase *jb;
s_JamLastRead jlr;
int all_unread;
int i;
int k;
char buffer[7];
s_printf("\r\n");
// list mail in message base
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
2017-04-12 17:27:59 +10:00
if (msghs != NULL && msghs->msg_count > 0) {
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
2017-04-12 22:34:08 +10:00
return;
2017-04-12 17:27:59 +10:00
} else {
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
2017-09-21 16:13:17 +10:00
} else if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
all_unread = 1;
2017-04-12 17:27:59 +10:00
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-04-12 17:27:59 +10:00
s_printf(get_string(120), msghs->msg_count);
s_readstring(buffer, 6);
if (tolower(buffer[0]) == 'n') {
if (all_unread == 0) {
k = jlr.HighReadMsg;
for (i = 0; i < msghs->msg_count; i++) {
2017-04-12 17:27:59 +10:00
if (msghs->msgs[i]->msg_h->MsgNum == k) {
break;
}
}
i += 2;
} else {
i = 1;
}
} else {
i = atoi(buffer);
}
if (i > 0 && i <= msghs->msg_count) {
2017-10-13 13:03:06 +10:00
read_message(user, msghs, i - 1, 0);
2017-04-12 17:27:59 +10:00
}
}
}
if (msghs != NULL) {
free_message_headers(msghs);
}
}
void post_message(struct user_record *user) {
char *subject;
char *from;
char *to;
char *msg;
int closed;
struct fido_addr *from_addr = NULL;
char buffer[256];
char buffer2[256];
2017-04-12 22:34:08 +10:00
int z;
int sem_fd;
2018-02-06 08:05:02 +10:00
char *bbsname;
2018-05-22 21:02:22 +10:00
uuid_t magi_msgid;
2017-04-12 17:27:59 +10:00
s_JamBase *jb;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
2017-04-12 17:27:59 +10:00
s_JamSubfield jsf;
s_JamLastRead jlr;
if (user->sec_level < conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->write_sec_level) {
s_printf(get_string(113));
return;
}
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
sprintf(buffer, "ALL");
} else {
s_printf(get_string(54));
2018-05-09 13:19:49 +10:00
s_readstring(buffer, 32);
2017-04-12 17:27:59 +10:00
}
if (strlen(buffer) == 0) {
strlcpy(buffer, "ALL", sizeof(buffer));
2017-04-12 17:27:59 +10:00
}
2018-05-22 21:02:22 +10:00
2017-04-12 17:27:59 +10:00
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
s_printf(get_string(121));
s_readstring(buffer2, 32);
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
from_addr = parse_fido_addr(buffer2);
if (!from_addr) {
s_printf(get_string(122));
return;
} else {
if (from_addr->zone == 0 && from_addr->net == 0 && from_addr->node == 0 && from_addr->point == 0) {
free(from_addr);
s_printf(get_string(122));
return;
}
2018-02-06 08:05:02 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->domain != NULL) {
bbsname = nl_get_bbsname(from_addr, conf.mail_conferences[gUser->cur_mail_conf]->domain);
} else {
bbsname = strdup("Unknown");
}
s_printf(get_string(123), from_addr->zone, from_addr->net, from_addr->node, from_addr->point, bbsname);
free(bbsname);
2017-04-12 17:27:59 +10:00
}
}
}
to = strdup(buffer);
s_printf(get_string(56));
s_readstring(buffer, 25);
if (strlen(buffer) == 0) {
s_printf(get_string(39));
free(to);
if (from_addr != NULL) {
free(from_addr);
}
return;
}
subject = strdup(buffer);
// post a message
if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) {
from = strdup(user->loginname);
} else {
from = str3dup(user->firstname, " ", user->lastname);
2017-04-12 17:27:59 +10:00
}
2018-01-13 19:17:22 +10:00
msg = external_editor(user, to, from, NULL, 0, NULL, subject, 0, 0);
2017-04-12 17:27:59 +10:00
free(from);
if (msg != NULL) {
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
free(msg);
free(to);
free(subject);
return;
}
JAM_ClearMsgHeader(&jmh);
2017-04-21 20:31:41 +10:00
jmh.DateWritten = (uint32_t)utc_to_local(time(NULL));
2017-04-12 17:27:59 +10:00
jmh.Attribute |= JAM_MSG_LOCAL;
if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) {
strlcpy(buffer, user->loginname, sizeof(buffer));
2017-04-12 17:27:59 +10:00
} else {
snprintf(buffer, sizeof buffer, "%s %s", user->firstname, user->lastname);
2017-04-12 17:27:59 +10:00
}
jsp = JAM_NewSubPacket();
jsf.LoID = JAMSFLD_SENDERNAME;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_RECVRNAME;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(to);
jsf.Buffer = (char *)to;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_SUBJECT;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(subject);
jsf.Buffer = (char *)subject;
JAM_PutSubfield(jsp, &jsf);
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_ECHOMAIL_AREA || conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
jmh.Attribute |= JAM_MSG_TYPEECHO;
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point) {
sprintf(buffer, "%d:%d/%d.%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2017-04-12 17:27:59 +10:00
} else {
sprintf(buffer, "%d:%d/%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2017-04-12 17:27:59 +10:00
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
sprintf(buffer, "%d:%d/%d.%d %08lx", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point,
generate_msgid());
2017-04-12 17:27:59 +10:00
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
2018-05-22 21:02:22 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_MAGI) {
sprintf(buffer, "%d", conf.mail_conferences[user->cur_mail_conf]->maginode);
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
uuid_generate(magi_msgid);
uuid_unparse_lower(magi_msgid, buffer);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2018-05-22 21:02:22 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
2018-06-24 10:28:18 +10:00
} else if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_QWK) {
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2018-06-24 10:28:18 +10:00
jsf.DatLen = strlen(conf.bwave_name);
jsf.Buffer = (char *)conf.bwave_name;
JAM_PutSubfield(jsp, &jsf);
}
} else if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
2017-04-12 17:27:59 +10:00
jmh.Attribute |= JAM_MSG_TYPENET;
jmh.Attribute |= JAM_MSG_PRIVATE;
if (conf.mail_conferences[user->cur_mail_conf]->nettype == NETWORK_FIDO) {
if (conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point) {
sprintf(buffer, "%d:%d/%d.%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point);
2017-04-12 17:27:59 +10:00
} else {
sprintf(buffer, "%d:%d/%d", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node);
2017-04-12 17:27:59 +10:00
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
if (from_addr != NULL) {
if (from_addr->point) {
sprintf(buffer, "%d:%d/%d.%d", from_addr->zone,
from_addr->net,
from_addr->node,
from_addr->point);
2017-04-12 17:27:59 +10:00
} else {
sprintf(buffer, "%d:%d/%d", from_addr->zone,
from_addr->net,
from_addr->node);
2017-04-12 17:27:59 +10:00
}
jsf.LoID = JAMSFLD_DADDRESS;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
free(from_addr);
from_addr = NULL;
}
sprintf(buffer, "%d:%d/%d.%d %08lx", conf.mail_conferences[user->cur_mail_conf]->fidoaddr->zone,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->net,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->node,
conf.mail_conferences[user->cur_mail_conf]->fidoaddr->point,
generate_msgid());
2017-04-12 17:27:59 +10:00
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
2017-04-12 17:27:59 +10:00
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
}
2017-04-12 17:27:59 +10:00
}
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);
dolog("Failed to lock msg base!");
break;
}
}
if (z != 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-04-12 22:34:08 +10:00
return;
2017-04-12 17:27:59 +10:00
}
if (JAM_AddMessage(jb, &jmh, jsp, (char *)msg, strlen(msg))) {
dolog("Failed to add message");
} else {
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
if (conf.netmail_sem != NULL) {
sem_fd = open(conf.netmail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
2017-04-12 17:27:59 +10:00
close(sem_fd);
}
} else if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_ECHOMAIL_AREA || conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
if (conf.echomail_sem != NULL) {
sem_fd = open(conf.echomail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
2017-04-12 17:27:59 +10:00
close(sem_fd);
}
}
}
JAM_UnlockMB(jb);
JAM_DelSubPacket(jsp);
free(msg);
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-04-12 17:27:59 +10:00
}
free(to);
free(subject);
}
2017-04-12 22:34:08 +10:00
void list_messages(struct user_record *user) {
2016-03-30 12:59:00 +10:00
struct msg_headers *msghs;
2016-03-22 18:19:06 +10:00
s_JamBase *jb;
2017-04-12 22:34:08 +10:00
int all_unread;
2016-03-26 16:06:59 +10:00
s_JamLastRead jlr;
2017-04-12 22:34:08 +10:00
char buffer[256];
int i;
int k;
int j;
int start;
2016-03-22 18:19:06 +10:00
int closed;
int redraw;
2017-04-12 22:34:08 +10:00
struct tm msg_date;
char c;
2017-04-12 22:34:08 +10:00
s_printf("\r\n");
// list mail in message base
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
2017-04-12 22:34:08 +10:00
if (msghs != NULL && msghs->msg_count > 0) {
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
return;
} else {
2017-04-12 22:34:08 +10:00
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
2017-09-21 16:13:17 +10:00
} else if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
all_unread = 1;
}
2017-04-12 22:34:08 +10:00
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-04-12 22:34:08 +10:00
s_printf(get_string(125), msghs->msg_count);
2017-04-12 22:34:08 +10:00
s_readstring(buffer, 6);
if (tolower(buffer[0]) == 'n') {
if (all_unread == 0) {
k = jlr.HighReadMsg;
for (i = 0; i < msghs->msg_count; i++) {
2017-04-12 22:34:08 +10:00
if (msghs->msgs[i]->msg_h->MsgNum == k) {
break;
2016-03-31 20:47:52 +10:00
}
2017-04-12 22:34:08 +10:00
}
if (i == msghs->msg_count - 1) {
i = 1;
2016-03-30 12:59:00 +10:00
} else {
i += 2;
2016-03-22 18:19:06 +10:00
}
2017-04-12 22:34:08 +10:00
} else {
i = 1;
}
2017-04-12 22:34:08 +10:00
} else {
i = atoi(buffer);
if (i <= 0) {
i = 1;
2016-03-22 18:19:06 +10:00
}
2017-04-12 22:34:08 +10:00
}
closed = 0;
redraw = 1;
start = i - 1;
2017-04-12 22:34:08 +10:00
while (!closed) {
if (redraw) {
s_printf(get_string(126));
for (j = start; j < start + 22 && j < msghs->msg_count; j++) {
2017-04-21 20:31:41 +10:00
gmtime_r((time_t *)&msghs->msgs[j]->msg_h->DateWritten, &msg_date);
if (j == i - 1) {
2018-05-22 08:55:44 +10:00
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[j]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
s_printf(get_string(286), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(286), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2018-05-22 08:55:44 +10:00
} else if (msghs->msgs[j]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(188), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(188), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:11:59 +10:00
if (conf.date_style == 1) {
2017-10-03 12:09:50 +10:00
s_printf(get_string(189), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(189), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2017-04-12 22:34:08 +10:00
}
2016-03-22 18:19:06 +10:00
} else {
2018-05-22 08:55:44 +10:00
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[j]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
s_printf(get_string(287), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(287), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2018-05-22 08:55:44 +10:00
} else if (msghs->msgs[j]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(127), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(127), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(128), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(128), j + 1, msghs->msgs[j]->subject, msghs->msgs[j]->from, msghs->msgs[j]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2017-04-12 22:34:08 +10:00
}
}
}
2017-04-12 22:34:08 +10:00
s_printf(get_string(190));
s_printf("\e[%d;5H", i - start + 1);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
closed = 1;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
i++;
if (i > start + 22) {
start += 22;
if (start > msghs->msg_count) {
start = msghs->msg_count - 22;
}
redraw = 1;
}
if (i - 1 == msghs->msg_count) {
2017-04-12 22:34:08 +10:00
i--;
s_printf("\e[%d;5H", i - start + 1);
} else if (!redraw) {
s_printf("\e[%d;1H", i - start);
gmtime_r((time_t *)&msghs->msgs[i - 2]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 2]->msg_h->MsgNum)) {
2018-05-22 08:55:44 +10:00
if (conf.date_style == 1) {
s_printf(get_string(287), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2018-05-22 08:55:44 +10:00
} else {
s_printf(get_string(287), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 2]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(127), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(127), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(128), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(128), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
}
2017-04-12 22:34:08 +10:00
s_printf("\e[%d;1H", i - start + 1);
gmtime_r((time_t *)&msghs->msgs[i - 1]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum)) {
2018-05-22 08:55:44 +10:00
if (conf.date_style == 1) {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2018-05-22 08:55:44 +10:00
} else {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 1]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
}
2017-04-12 22:34:08 +10:00
s_printf("\e[%d;5H", i - start + 1);
}
} else if (c == 65) {
// up
i--;
if (i - 1 < start) {
start -= 22;
2017-04-12 22:34:08 +10:00
if (start < 0) {
start = 0;
}
redraw = 1;
}
if (i <= 1) {
start = 0;
i = 1;
redraw = 1;
} else if (!redraw) {
s_printf("\e[%d;1H", i - start + 2);
2017-04-21 20:31:41 +10:00
gmtime_r((time_t *)&msghs->msgs[i]->msg_h->DateWritten, &msg_date);
2018-05-22 08:55:44 +10:00
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
2018-05-22 09:02:35 +10:00
s_printf(get_string(287), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2018-05-22 08:55:44 +10:00
} else {
2018-05-22 09:02:35 +10:00
s_printf(get_string(287), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2018-05-22 08:55:44 +10:00
} else if (msghs->msgs[i]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(127), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(127), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(128), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(128), i + 1, msghs->msgs[i]->subject, msghs->msgs[i]->from, msghs->msgs[i]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
}
2017-04-12 22:34:08 +10:00
s_printf("\e[%d;1H", i - start + 1);
gmtime_r((time_t *)&msghs->msgs[i - 1]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum)) {
2018-05-22 08:55:44 +10:00
if (conf.date_style == 1) {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2018-05-22 08:55:44 +10:00
} else {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 1]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
2017-04-12 22:34:08 +10:00
} else {
2017-10-03 12:09:50 +10:00
if (conf.date_style == 1) {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
} else {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
2017-10-03 12:09:50 +10:00
}
}
s_printf("\e[%d;5H", i - start + 1);
}
2017-09-09 17:57:55 +10:00
} else if (c == 75) {
// END KEY
i = msghs->msg_count;
start = i - 22;
if (start < 0) {
start = 0;
}
redraw = 1;
2017-09-09 17:57:55 +10:00
} else if (c == 72) {
// HOME KEY
i = 1;
start = 0;
redraw = 1;
2018-01-20 12:46:50 +10:00
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
i = i - 22;
if (i <= 0) {
i = 1;
}
start = i - 1;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
i = i + 22;
if (i > msghs->msg_count) {
i = msghs->msg_count;
}
start = i - 1;
redraw = 1;
}
}
2017-04-12 22:34:08 +10:00
} else if (c == 13) {
redraw = 1;
2017-10-13 13:03:06 +10:00
read_message(user, msghs, i - 1, 0);
free_message_headers(msghs);
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
jb = open_jam_base(conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (!jb) {
dolog("Error opening JAM base.. %s", conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->path);
if (msghs != NULL) {
free_message_headers(msghs);
}
return;
} else {
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
}
2018-05-22 08:55:44 +10:00
} else if (tolower(c) == 'f') {
redraw = 1;
msgbase_flag_unflag(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum);
}
2017-04-12 22:34:08 +10:00
}
}
if (msghs != NULL) {
free_message_headers(msghs);
}
} else {
s_printf(get_string(130));
}
}
struct conf_tmp_t {
struct mail_conference *conference;
int index;
};
void choose_conference() {
2017-04-12 22:34:08 +10:00
int i;
int list_tmp = 0;
struct conf_tmp_t **conf_tmp;
int redraw = 1;
int start = 0;
int selected = 0;
2017-04-12 22:34:08 +10:00
char c;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct ptr_vector vec;
2017-04-12 22:34:08 +10:00
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
init_ptr_vector(&vec);
for (i = 0; i < conf.mail_conference_count; i++) {
if (conf.mail_conferences[i]->sec_level <= gUser->sec_level) {
struct conf_tmp_t *c = (struct conf_tmp_t *)malloz(sizeof(struct conf_tmp_t));
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
c->conference = conf.mail_conferences[i];
c->index = i;
ptr_vector_append(&vec, c);
2017-04-12 22:34:08 +10:00
}
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
list_tmp = ptr_vector_len(&vec);
conf_tmp = (struct conf_tmp_t **)consume_ptr_vector(&vec);
while (1) {
if (redraw) {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(247));
s_printf(get_string(248));
for (i = start; i < start + 22 && i < list_tmp; i++) {
if (i == selected) {
s_printf(get_string(249), i - start + 2, conf_tmp[i]->index, conf_tmp[i]->conference->name);
} else {
s_printf(get_string(250), i - start + 2, conf_tmp[i]->index, conf_tmp[i]->conference->name);
}
}
2018-01-18 08:58:32 +10:00
s_printf("\e[%d;5H", selected - start + 2);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
break;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
2018-01-18 08:58:32 +10:00
if (selected + 1 >= start + 22) {
start += 22;
if (start >= list_tmp) {
start = list_tmp - 22;
}
redraw = 1;
}
selected++;
if (selected >= list_tmp) {
selected = list_tmp - 1;
} else {
if (!redraw) {
s_printf(get_string(250), selected - start + 1, conf_tmp[selected - 1]->index, conf_tmp[selected - 1]->conference->name);
s_printf(get_string(249), selected - start + 2, conf_tmp[selected]->index, conf_tmp[selected]->conference->name);
2018-01-18 08:58:32 +10:00
s_printf("\e[%d;5H", selected - start + 2);
}
}
} else if (c == 65) {
// up
if (selected - 1 < start) {
start -= 22;
if (start < 0) {
start = 0;
}
redraw = 1;
}
selected--;
if (selected < 0) {
selected = 0;
} else {
if (!redraw) {
s_printf(get_string(249), selected - start + 2, conf_tmp[selected]->index, conf_tmp[selected]->conference->name);
s_printf(get_string(250), selected - start + 3, conf_tmp[selected + 1]->index, conf_tmp[selected + 1]->conference->name);
2018-01-18 08:58:32 +10:00
s_printf("\e[%d;5H", selected - start + 2);
}
}
2018-01-20 12:46:50 +10:00
} else if (c == 75) {
// END KEY
selected = list_tmp - 1;
start = list_tmp - 22;
if (start < 0) {
start = 0;
}
redraw = 1;
} else if (c == 72) {
// HOME KEY
selected = 0;
start = 0;
redraw = 1;
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
selected = selected - 22;
if (selected < 0) {
selected = 0;
}
start = selected;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
selected = selected + 22;
if (selected >= list_tmp) {
selected = list_tmp - 1;
2018-01-20 12:46:50 +10:00
}
start = selected;
redraw = 1;
}
}
} else if (c == 13) {
gUser->cur_mail_conf = conf_tmp[selected]->index;
gUser->cur_mail_area = 0;
break;
2017-04-12 22:34:08 +10:00
}
}
for (i = 0; i < list_tmp; i++) {
free(conf_tmp[i]);
}
free(conf_tmp);
}
struct area_tmp_t {
struct mail_area *area;
int index;
};
void choose_area() {
int i;
int list_tmp = 0;
struct area_tmp_t **area_tmp;
int redraw = 1;
int start = 0;
int selected = 0;
char c;
int offset = 2;
int height = 22;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct ptr_vector vec;
if (conf.mail_conferences[gUser->cur_mail_conf]->header != NULL) {
offset = 8;
height = 13;
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
init_ptr_vector(&vec);
for (i = 0; i < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; i++) {
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[i]->read_sec_level <= gUser->sec_level) {
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
struct area_tmp_t *area = (struct area_tmp_t *)malloz(sizeof(struct area_tmp_t));
area_tmp[list_tmp]->area = conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[i];
area_tmp[list_tmp]->index = i;
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
ptr_vector_append(&vec, area);
2017-04-12 22:34:08 +10:00
}
}
More use of ptr_vector; avoid unnecessary copies. Recast more code in terms of the ptr_vector abstraction. The mail_menu.c code also made a lot of unnecessary copies of strings. For example, there was this code sequence: for (i = z; i < lines - 1; i++) { free(content[i]); content[i] = strdup(content[i + 1]); } free(content[i]); lines--; content = (char **)realloc(content, sizeof(char *) * lines); Here, `content` represents an array of lines of text. This code is removing an element from somewhere in that array (possibly in the middle), and then shifting the remaining elements over one position. But observe the calls to `free` and `strdup` in the loop body: the content is already dynamically allocated. We free whatever was in the selected position, and then make *another copy* of the data in the next position to put into the now-available slot in the array: repeat for the remainder of the array's elements. Instead, we could change this code to just shift things down: free(content[z]); for (i = z; i < (lines - 1); ++i) content[i] = content[i + 1]; --lines; ncontent = realloc(content, sizeof(char *) * lines); assert(ncontent == NULL); content = ncontent; However, the ptr_vector abstraction provides us a function, `ptr_vector_del` that deletes an element from the array and returns the pointer, so we can rewrite this as simply: free(ptr_vector_del(&content, z)); No additional malloc()/free() required, which means less pressure on the memory allocator and less copying of data. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
list_tmp = ptr_vector_len(&vec);
area_tmp = (struct area_tmp_t **)consume_ptr_vector(&vec);
while (1) {
if (redraw) {
if (conf.mail_conferences[gUser->cur_mail_conf]->header != NULL) {
s_printf("\e[2J\e[1;1H");
s_displayansi(conf.mail_conferences[gUser->cur_mail_conf]->header);
s_printf("\e[7;1H");
} else {
s_printf("\e[2J\e[1;1H");
}
s_printf(get_string(251), conf.mail_conferences[gUser->cur_mail_conf]->name);
s_printf(get_string(248));
for (i = start; i < start + height && i < list_tmp; i++) {
if (i == selected) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
s_printf(get_string(259), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
} else {
s_printf(get_string(249), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
}
} else {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
s_printf(get_string(260), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
} else {
s_printf(get_string(250), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
}
}
}
s_printf("\e[%d;5H", selected - start + offset);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
break;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
if (selected + 1 >= start + height) {
start += height;
if (start >= list_tmp) {
start = list_tmp - height;
}
redraw = 1;
}
selected++;
if (selected >= list_tmp) {
selected = list_tmp - 1;
} else {
if (!redraw) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected - 1]->index)) {
s_printf(get_string(260), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
} else {
s_printf(get_string(250), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
}
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
} else {
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
}
s_printf("\e[%d;5H", selected - start + offset);
}
}
} else if (c == 65) {
// up
if (selected - 1 < start) {
start -= height;
if (start < 0) {
start = 0;
}
redraw = 1;
}
selected--;
if (selected < 0) {
selected = 0;
} else {
if (!redraw) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
} else {
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
}
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected + 1]->index)) {
s_printf(get_string(260), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
} else {
s_printf(get_string(250), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
}
s_printf("\e[%d;5H", selected - start + offset);
}
}
2018-01-20 12:46:50 +10:00
} else if (c == 75) {
// END KEY
selected = list_tmp - 1;
start = list_tmp - height;
2018-01-20 12:46:50 +10:00
if (start < 0) {
start = 0;
}
redraw = 1;
} else if (c == 72) {
// HOME KEY
selected = 0;
start = 0;
redraw = 1;
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
selected = selected - height;
2018-01-20 12:46:50 +10:00
if (selected < 0) {
selected = 0;
}
start = selected;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
selected = selected + height;
2018-01-20 12:46:50 +10:00
if (selected >= list_tmp) {
selected = list_tmp - 1;
2018-01-20 12:46:50 +10:00
}
start = selected;
redraw = 1;
}
}
} else if (c == 13) {
gUser->cur_mail_area = area_tmp[selected]->index;
break;
}
}
for (i = 0; i < list_tmp; i++) {
free(area_tmp[i]);
}
free(area_tmp);
2017-04-12 22:34:08 +10:00
}
void next_mail_conf(struct user_record *user) {
int i;
for (i = user->cur_mail_conf; i < conf.mail_conference_count; i++) {
2017-04-12 22:34:08 +10:00
if (i + 1 == conf.mail_conference_count) {
i = -1;
}
if (conf.mail_conferences[i + 1]->sec_level <= user->sec_level) {
2017-04-12 22:34:08 +10:00
user->cur_mail_conf = i + 1;
user->cur_mail_area = 0;
break;
}
}
}
void prev_mail_conf(struct user_record *user) {
int i;
for (i = user->cur_mail_conf; i >= 0; i--) {
2017-04-12 22:34:08 +10:00
if (i - 1 == -1) {
i = conf.mail_conference_count;
}
if (conf.mail_conferences[i - 1]->sec_level <= user->sec_level) {
2017-04-12 22:34:08 +10:00
user->cur_mail_conf = i - 1;
user->cur_mail_area = 0;
break;
}
}
}
void next_mail_area(struct user_record *user) {
int i;
for (i = user->cur_mail_area; i < conf.mail_conferences[user->cur_mail_conf]->mail_area_count; i++) {
2017-04-12 22:34:08 +10:00
if (i + 1 == conf.mail_conferences[user->cur_mail_conf]->mail_area_count) {
i = -1;
}
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[i + 1]->read_sec_level <= user->sec_level) {
2017-04-12 22:34:08 +10:00
user->cur_mail_area = i + 1;
break;
}
}
}
void prev_mail_area(struct user_record *user) {
int i;
for (i = user->cur_mail_area; i >= 0; i--) {
2017-04-12 22:34:08 +10:00
if (i - 1 == -1) {
i = conf.mail_conferences[user->cur_mail_conf]->mail_area_count;
}
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[i - 1]->read_sec_level <= user->sec_level) {
2017-04-12 22:34:08 +10:00
user->cur_mail_area = i - 1;
break;
}
}
2016-03-22 13:07:42 +10:00
}
2016-03-23 10:14:31 +10:00
2018-02-18 13:51:39 +10:00
void do_mail_scan(struct user_record *user, int oldscan, int personal) {
2016-03-26 16:06:59 +10:00
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamLastRead jlr;
struct msg_headers *msghs;
2016-03-26 16:06:59 +10:00
char c;
int i;
int j;
int lines = 0;
2017-10-12 20:24:55 +10:00
int orig_conf;
int orig_area;
2017-10-13 13:03:06 +10:00
int res = 0;
2018-02-23 14:27:36 +10:00
char ch;
int unread_count;
int k;
2018-02-18 13:51:39 +10:00
if (personal) {
s_printf(get_string(276));
} else {
s_printf(get_string(139));
}
c = s_getc();
2017-10-10 11:16:34 +10:00
if (tolower(c) == 'y' || tolower(c) == 's') {
for (i = 0; i < conf.mail_conference_count; i++) {
2016-03-26 16:06:59 +10:00
if (conf.mail_conferences[i]->sec_level > user->sec_level) {
continue;
}
2018-02-23 14:27:36 +10:00
if (oldscan) {
s_printf(get_string(140), i, conf.mail_conferences[i]->name);
lines += 2;
2018-02-23 14:27:36 +10:00
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
}
for (j = 0; j < conf.mail_conferences[i]->mail_area_count; j++) {
2016-03-26 16:06:59 +10:00
if (conf.mail_conferences[i]->mail_areas[j]->read_sec_level > user->sec_level) {
continue;
}
2017-10-10 11:16:34 +10:00
if (tolower(c) == 's' && !msgbase_is_subscribed(i, j)) {
continue;
}
jb = open_jam_base(conf.mail_conferences[i]->mail_areas[j]->path);
if (!jb) {
dolog("Unable to open message base");
continue;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
continue;
}
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
if (jbh.ActiveMsgs == 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
continue;
}
if (conf.mail_conferences[i]->mail_areas[j]->type == TYPE_NETMAIL_AREA) {
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
2017-10-12 20:24:55 +10:00
if (oldscan) {
s_printf(get_string(141), j, conf.mail_conferences[i]->mail_areas[j]->name, msghs->msg_count);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
2018-02-23 14:27:36 +10:00
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, conf.mail_conferences[i]->name);
s_printf(get_string(278), j, conf.mail_conferences[i]->mail_areas[j]->name, msghs->msg_count);
2018-02-27 13:24:24 +10:00
s_printf(get_string(279));
2018-02-23 14:27:36 +10:00
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
2018-02-23 14:27:36 +10:00
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = i;
user->cur_mail_area = j;
2018-02-23 14:27:36 +10:00
res = read_new_msgs(user, msghs);
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
}
free_message_headers(msghs);
}
} else {
2017-10-12 20:24:55 +10:00
if (oldscan) {
s_printf(get_string(141), j, conf.mail_conferences[i]->mail_areas[j]->name, jbh.ActiveMsgs);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(i, j, user, personal);
2017-10-12 20:24:55 +10:00
if (msghs != NULL) {
2018-02-23 14:27:36 +10:00
if (msghs->msg_count > 0) {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, conf.mail_conferences[i]->name);
s_printf(get_string(278), j, conf.mail_conferences[i]->mail_areas[j]->name, msghs->msg_count);
2018-02-27 13:24:24 +10:00
s_printf(get_string(279));
2018-02-23 14:27:36 +10:00
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
2018-02-23 14:27:36 +10:00
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = i;
user->cur_mail_area = j;
2018-02-23 14:27:36 +10:00
res = read_new_msgs(user, msghs);
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
2017-10-12 20:24:55 +10:00
}
free_message_headers(msghs);
}
}
}
} else {
2016-08-21 09:39:36 +10:00
if (jlr.HighReadMsg < jbh.ActiveMsgs) {
2018-02-23 14:27:36 +10:00
if (conf.mail_conferences[i]->mail_areas[j]->type == TYPE_NETMAIL_AREA) {
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
2018-02-23 14:27:36 +10:00
unread_count = 0;
for (k = msghs->msg_count - 1; k >= 0; k--) {
2018-02-23 14:43:26 +10:00
if (msghs->msgs[k]->msg_no < jlr.HighReadMsg) {
2018-02-23 14:27:36 +10:00
break;
}
unread_count++;
}
2018-02-23 14:31:31 +10:00
if (unread_count > 0) {
2017-10-12 20:24:55 +10:00
if (oldscan) {
2018-02-23 14:27:36 +10:00
s_printf(get_string(141), j, conf.mail_conferences[i]->mail_areas[j]->name, unread_count);
2017-10-12 20:24:55 +10:00
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
2018-02-23 14:27:36 +10:00
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, conf.mail_conferences[i]->name);
s_printf(get_string(278), j, conf.mail_conferences[i]->mail_areas[j]->name, unread_count);
2018-02-27 13:24:24 +10:00
s_printf(get_string(279));
2018-02-23 14:27:36 +10:00
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
2018-02-23 14:27:36 +10:00
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = i;
user->cur_mail_area = j;
2018-02-23 14:27:36 +10:00
res = read_new_msgs(user, msghs);
2018-02-23 14:27:36 +10:00
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
}
}
free_message_headers(msghs);
}
} else {
2017-10-12 20:24:55 +10:00
if (oldscan) {
s_printf(get_string(141), j, conf.mail_conferences[i]->mail_areas[j]->name, jbh.ActiveMsgs - jlr.HighReadMsg);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
2018-02-18 13:51:39 +10:00
msghs = read_message_headers(i, j, user, personal);
2017-10-12 20:24:55 +10:00
if (msghs != NULL) {
if (msghs->msg_count > 0) {
2018-02-23 14:27:36 +10:00
unread_count = 0;
for (k = msghs->msg_count - 1; k >= 0; k--) {
2018-02-23 14:43:26 +10:00
if (msghs->msgs[k]->msg_no < jlr.HighReadMsg) {
2018-02-23 14:27:36 +10:00
break;
}
unread_count++;
2018-02-23 14:34:42 +10:00
}
if (unread_count > 0) {
2018-02-23 14:34:42 +10:00
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, conf.mail_conferences[i]->name);
s_printf(get_string(278), j, conf.mail_conferences[i]->mail_areas[j]->name, unread_count);
2018-02-23 14:34:42 +10:00
s_printf(get_string(279));
2018-02-23 14:34:42 +10:00
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
2018-02-23 14:34:42 +10:00
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
2018-02-23 14:34:42 +10:00
user->cur_mail_conf = i;
user->cur_mail_area = j;
2018-02-23 14:34:42 +10:00
res = read_new_msgs(user, msghs);
2018-02-23 14:34:42 +10:00
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
2018-02-23 14:27:36 +10:00
}
2017-10-12 20:24:55 +10:00
}
free_message_headers(msghs);
}
}
}
} else {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
continue;
}
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-10-13 13:03:06 +10:00
if (res) {
break;
}
2016-03-26 16:06:59 +10:00
}
2017-10-13 13:03:06 +10:00
if (res) {
break;
}
2016-03-26 16:06:59 +10:00
}
s_printf(get_string(6));
s_getc();
2016-03-26 16:06:59 +10:00
}
}
2017-09-21 10:21:51 +10:00
2018-02-18 13:51:39 +10:00
void full_mail_scan_personal(struct user_record *user) {
do_mail_scan(user, 0, 1);
}
2017-10-12 20:24:55 +10:00
void full_mail_scan(struct user_record *user) {
2018-02-18 13:51:39 +10:00
do_mail_scan(user, 0, 0);
2017-10-12 20:24:55 +10:00
}
void mail_scan(struct user_record *user) {
2018-02-18 13:51:39 +10:00
do_mail_scan(user, 1, 0);
2017-10-12 20:24:55 +10:00
}
2017-09-21 10:21:51 +10:00
void msg_conf_sub_bases() {
int i;
int lines = 0;
char buffer[10];
int toggle_area;
int done = 0;
2017-10-13 16:55:33 +10:00
int j;
2017-09-21 10:59:07 +10:00
s_printf("\e[1;1H\e[2J");
2017-09-21 10:21:51 +10:00
do {
for (i = 0; i < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; i++) {
2017-09-21 10:21:51 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[i]->read_sec_level <= gUser->sec_level) {
s_printf(get_string(226), i, (msgbase_is_subscribed(gUser->cur_mail_conf, i) ? get_string(227) : get_string(228)), conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[i]->name);
lines++;
}
2017-09-21 10:21:51 +10:00
if (lines == 23) {
s_printf(get_string(225));
s_readstring(buffer, 9);
s_printf("\r\n");
2017-10-13 16:55:33 +10:00
if (strlen(buffer) > 0) {
if (buffer[0] >= '0' && buffer[0] <= '9') {
toggle_area = atoi(buffer);
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[toggle_area]->read_sec_level <= gUser->sec_level) {
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
}
lines = 0;
2017-10-13 16:55:33 +10:00
break;
}
if (buffer[0] == 'a' || buffer[0] == 'A') {
for (j = 0; j < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; j++) {
2017-10-13 16:55:33 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[j]->read_sec_level <= gUser->sec_level) {
if (!msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
break;
}
if (buffer[0] == 'n' || buffer[0] == 'N') {
for (j = 0; j < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; j++) {
2017-10-13 16:55:33 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[j]->read_sec_level <= gUser->sec_level) {
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
break;
}
2017-09-21 10:21:51 +10:00
}
lines = 0;
}
}
2017-09-21 10:21:51 +10:00
if (lines > 0) {
s_printf(get_string(225));
s_readstring(buffer, 9);
s_printf("\r\n");
2017-10-13 16:55:33 +10:00
if (strlen(buffer) > 0) {
if (buffer[0] >= '0' && buffer[0] <= '9') {
toggle_area = atoi(buffer);
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[toggle_area]->read_sec_level <= gUser->sec_level) {
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
}
lines = 0;
} else if (buffer[0] == 'a' || buffer[0] == 'A') {
for (j = 0; j < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; j++) {
2017-10-13 16:55:33 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[j]->read_sec_level <= gUser->sec_level) {
if (!msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
} else if (buffer[0] == 'n' || buffer[0] == 'N') {
for (j = 0; j < conf.mail_conferences[gUser->cur_mail_conf]->mail_area_count; j++) {
2017-10-13 16:55:33 +10:00
if (conf.mail_conferences[gUser->cur_mail_conf]->mail_areas[j]->read_sec_level <= gUser->sec_level) {
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
2017-10-13 16:55:33 +10:00
} else {
done = 1;
}
2017-10-13 16:58:25 +10:00
} else {
done = 1;
2017-09-21 10:21:51 +10:00
}
} else {
done = 1;
}
} while (!done);
}
2017-09-21 16:07:31 +10:00
void msgbase_reset_pointers(int conference, int msgarea, int readm, int msgno) {
2017-09-21 16:07:31 +10:00
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamLastRead jlr;
s_JamMsgHeader jmh;
int max_msg;
int active_msgs;
int i, j, k;
2017-09-21 16:07:31 +10:00
jb = open_jam_base(conf.mail_conferences[conference]->mail_areas[msgarea]->path);
if (!jb) {
dolog("Unable to open message base");
return;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
return;
}
j = 0;
if (msgno == -1 && readm) {
k = jbh.ActiveMsgs;
} else if (msgno == -1 && !readm) {
k = 0;
} else {
if (msgno > jbh.ActiveMsgs) {
k = jbh.ActiveMsgs;
} else {
k = msgno;
}
}
for (i = 0; j < k; i++) {
memset(&jmh, 0, sizeof(s_JamMsgHeader));
if (JAM_ReadMsgHeader(jb, i, &jmh, NULL) != 0) {
dolog("Failed to read msg header: Erro %d", JAM_Errno(jb));
return;
}
if (jmh.Attribute & JAM_MSG_DELETED) {
continue;
}
j++;
}
max_msg = i;
2017-09-21 16:07:31 +10:00
if (JAM_ReadLastRead(jb, gUser->id, &jlr) != JAM_NO_USER) {
jlr.LastReadMsg = max_msg;
jlr.HighReadMsg = max_msg;
JAM_WriteLastRead(jb, gUser->id, &jlr);
} else {
jlr.LastReadMsg = max_msg;
jlr.HighReadMsg = max_msg;
jlr.UserCRC = JAM_Crc32(gUser->loginname, strlen(gUser->loginname));
jlr.UserID = gUser->id;
2017-09-21 16:07:31 +10:00
JAM_WriteLastRead(jb, gUser->id, &jlr);
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
2017-09-21 16:07:31 +10:00
}
void msgbase_reset_all_pointers(int readm) {
2017-09-21 16:07:31 +10:00
int i, j;
for (i = 0; i < conf.mail_conference_count; i++) {
for (j = 0; j < conf.mail_conferences[i]->mail_area_count; j++) {
msgbase_reset_pointers(i, j, readm, -1);
2017-09-21 16:07:31 +10:00
}
}
}
int new_messages(struct user_record *user, int conference, int area) {
int count = 0;
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamLastRead jlr;
struct msg_headers *msghs;
jb = open_jam_base(conf.mail_conferences[conference]->mail_areas[area]->path);
if (!jb) {
return 0;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
return 0;
}
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
if (jbh.ActiveMsgs == 0) {
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
return 0;
}
2018-07-31 10:42:56 +10:00
msghs = read_message_headers(conference, area, user, 0);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
count = msghs->msg_count;
}
2018-07-31 10:42:56 +10:00
free_message_headers(msghs);
}
} else {
2018-07-31 10:42:56 +10:00
msghs = read_message_headers(conference, area, user, 0);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
if (msghs->msgs[msghs->msg_count - 1]->msg_h->MsgNum > jlr.HighReadMsg) {
count = msghs->msgs[msghs->msg_count - 1]->msg_h->MsgNum - jlr.HighReadMsg;
}
}
2018-07-31 10:42:56 +10:00
free_message_headers(msghs);
}
}
JAM_CloseMB(jb);
2018-02-10 16:01:30 +10:00
free(jb);
return count;
}