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>
|
2016-08-02 12:29:39 +10:00
|
|
|
#include <sys/utsname.h>
|
2016-12-04 16:37:23 +10:00
|
|
|
#include <sys/file.h>
|
2016-04-23 14:10:42 +10:00
|
|
|
#include <fcntl.h>
|
2018-10-16 15:05:15 +00:00
|
|
|
|
2016-03-25 18:24:24 +10:00
|
|
|
#include "jamlib/jam.h"
|
2016-04-12 15:19:56 +10:00
|
|
|
#include "lua/lua.h"
|
|
|
|
#include "lua/lualib.h"
|
|
|
|
#include "lua/lauxlib.h"
|
2018-05-22 21:02:22 +10:00
|
|
|
#include "libuuid/uuid.h"
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
#include "bbs.h"
|
|
|
|
#include "mail_utils.h"
|
|
|
|
|
2017-10-20 07:27:58 +10:00
|
|
|
#ifdef __sun
|
|
|
|
#include "os/sunos.h"
|
|
|
|
#endif
|
2016-08-14 19:56:15 +10:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
2016-03-25 18:28:09 +10:00
|
|
|
ret = JAM_OpenMB((char *)path, &jb);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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);
|
2016-08-04 19:25:49 +10:00
|
|
|
dolog("Got %d", ret);
|
2016-03-30 12:59:00 +10:00
|
|
|
return NULL;
|
2016-03-22 18:19:06 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return jb;
|
|
|
|
}
|
|
|
|
|
2016-12-04 16:37:23 +10:00
|
|
|
unsigned long generate_msgid() {
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-04 16:37:23 +10:00
|
|
|
char buffer[1024];
|
2017-03-21 10:47:51 +10:00
|
|
|
time_t unixtime;
|
2017-03-17 15:06:43 +10:00
|
|
|
|
2016-12-04 16:37:23 +10:00
|
|
|
unsigned long msgid;
|
|
|
|
unsigned long lastid;
|
|
|
|
FILE *fptr;
|
2017-03-17 15:06:43 +10:00
|
|
|
|
2016-12-04 16:37:23 +10:00
|
|
|
snprintf(buffer, 1024, "%s/msgserial", conf.bbs_path);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-03-21 10:47:51 +10:00
|
|
|
unixtime = time(NULL);
|
|
|
|
|
2016-12-04 18:06:20 +10:00
|
|
|
fptr = fopen(buffer, "r+");
|
2016-12-04 16:37:23 +10:00
|
|
|
if (fptr) {
|
|
|
|
flock(fileno(fptr), LOCK_EX);
|
2018-10-08 14:13:11 +00:00
|
|
|
fread(&lastid, sizeof(unsigned long), 1, fptr);
|
2017-03-21 10:47:51 +10:00
|
|
|
|
|
|
|
if (unixtime > lastid) {
|
|
|
|
lastid = unixtime;
|
|
|
|
} else {
|
|
|
|
lastid++;
|
|
|
|
}
|
2016-12-04 16:37:23 +10:00
|
|
|
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;
|
2016-12-04 16:37:23 +10:00
|
|
|
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;
|
2016-12-04 16:37:23 +10:00
|
|
|
dolog("Unable to open message id log");
|
|
|
|
}
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%lX", lastid);
|
2017-04-22 18:32:36 +10:00
|
|
|
return strtoul(&buffer[strlen(buffer) - 8], NULL, 16);
|
2016-12-04 16:37:23 +10:00
|
|
|
}
|
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
void free_message_headers(struct msg_headers *msghs) {
|
|
|
|
int i;
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < msghs->msg_count; i++) {
|
2016-03-30 12:59:00 +10:00
|
|
|
free(msghs->msgs[i]->msg_h);
|
2018-10-16 15:05:15 +00:00
|
|
|
free(msghs->msgs[i]->from);
|
|
|
|
free(msghs->msgs[i]->to);
|
|
|
|
free(msghs->msgs[i]->subject);
|
|
|
|
free(msghs->msgs[i]->oaddress);
|
|
|
|
free(msghs->msgs[i]->daddress);
|
|
|
|
free(msghs->msgs[i]->msgid);
|
|
|
|
free(msghs->msgs[i]->replyid);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(msghs->msgs[i]);
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
if (msghs->msg_count > 0) {
|
|
|
|
free(msghs->msgs);
|
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
free(msghs);
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
|
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) {
|
2016-08-14 19:56:15 +10:00
|
|
|
char *myname;
|
|
|
|
if (rn) {
|
2018-10-09 15:55:13 +00:00
|
|
|
myname = str3dup(user->firstname, " ", user->lastname);
|
2016-08-14 19:56:15 +10:00
|
|
|
} else {
|
2016-08-20 13:52:02 +10:00
|
|
|
myname = strdup(user->loginname);
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, msgconf);
|
|
|
|
assert(mc != NULL);
|
2018-02-18 14:11:34 +10:00
|
|
|
if (type == NETWORK_FIDO && address != NULL) {
|
2016-08-14 19:56:15 +10:00
|
|
|
if (strcasecmp(myname, addressed_to) == 0) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct fido_addr *dest = parse_fido_addr(address);
|
|
|
|
if (mc->fidoaddr->zone == dest->zone &&
|
|
|
|
mc->fidoaddr->net == dest->net &&
|
|
|
|
mc->fidoaddr->node == dest->node &&
|
|
|
|
mc->fidoaddr->point == dest->point) {
|
2018-10-08 14:13:11 +00:00
|
|
|
free(dest);
|
|
|
|
free(myname);
|
|
|
|
return 1;
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
int magi_dest = atoi(address);
|
|
|
|
if (magi_dest == mc->maginode) {
|
2018-05-22 21:02:22 +10:00
|
|
|
free(myname);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(myname);
|
|
|
|
return 0;
|
2016-08-14 19:56:15 +10:00
|
|
|
} 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) {
|
2016-08-14 19:56:15 +10:00
|
|
|
char *myname;
|
2018-05-22 21:02:22 +10:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
if (rn) {
|
2018-10-09 15:55:13 +00:00
|
|
|
myname = str3dup(user->firstname, " ", user->lastname);
|
2016-08-14 19:56:15 +10:00
|
|
|
} else {
|
2016-08-20 13:52:02 +10:00
|
|
|
myname = strdup(user->loginname);
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, msgconf);
|
|
|
|
assert(mc != NULL);
|
2018-05-22 21:02:22 +10:00
|
|
|
if (type == NETWORK_FIDO && address != NULL) {
|
2016-08-14 19:56:15 +10:00
|
|
|
if (strcasecmp(myname, addressed_from) == 0) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct fido_addr *orig = parse_fido_addr(address);
|
|
|
|
if (mc->fidoaddr->zone == orig->zone &&
|
|
|
|
mc->fidoaddr->net == orig->net &&
|
|
|
|
mc->fidoaddr->node == orig->node &&
|
|
|
|
mc->fidoaddr->point == orig->point) {
|
2018-10-08 14:13:11 +00:00
|
|
|
free(orig);
|
|
|
|
free(myname);
|
|
|
|
return 1;
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
int magi_orig = atoi(address);
|
|
|
|
if (magi_orig == mc->maginode) {
|
2018-05-22 21:02:22 +10:00
|
|
|
free(myname);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(myname);
|
|
|
|
return 0;
|
2016-08-14 19:56:15 +10:00
|
|
|
} 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;
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-08-14 19:56:15 +10:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
struct fido_addr *dest;
|
|
|
|
struct msg_headers *msghs = NULL;
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, msgconf);
|
|
|
|
assert(mc != NULL);
|
|
|
|
struct mail_area *area = ptr_vector_get(&mc->mail_areas, msgarea);
|
|
|
|
assert(area != NULL);
|
2016-03-30 12:59:00 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(area->path);
|
2016-03-30 12:59:00 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", area->path);
|
2016-03-30 12:59:00 +10:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
JAM_ReadMBHeader(jb, &jbh);
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (jbh.ActiveMsgs <= 0) {
|
|
|
|
JAM_CloseMB(jb);
|
|
|
|
free(jb);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
init_ptr_vector(&vec);
|
|
|
|
msghs = (struct msg_headers *)malloz(sizeof(struct msg_headers));
|
|
|
|
msghs->msg_count = 0;
|
|
|
|
k = 0;
|
|
|
|
for (i = 0; k < jbh.ActiveMsgs; i++) {
|
|
|
|
memset(&jmh, 0, sizeof(s_JamMsgHeader));
|
|
|
|
z = JAM_ReadMsgHeader(jb, i, &jmh, &jsp);
|
|
|
|
if (z != 0) {
|
|
|
|
dolog("Failed to read msg header: %d Erro %d", z, JAM_Errno(jb));
|
|
|
|
continue;
|
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (jmh.Attribute & JAM_MSG_DELETED) {
|
2016-03-30 12:59:00 +10:00
|
|
|
JAM_DelSubPacket(jsp);
|
2018-10-16 15:05:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
jamm = (struct jam_msg *)malloz(sizeof(struct jam_msg));
|
|
|
|
jamm->msg_no = i;
|
|
|
|
jamm->msg_h = (s_JamMsgHeader *)malloz(sizeof(s_JamMsgHeader));
|
|
|
|
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++) {
|
|
|
|
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-08-31 16:20:36 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
}
|
|
|
|
JAM_DelSubPacket(jsp);
|
2018-02-18 13:51:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (jamm->subject == NULL) {
|
|
|
|
jamm->subject = strdup("(No Subject)");
|
|
|
|
}
|
|
|
|
if (jamm->from == NULL) {
|
|
|
|
jamm->from = strdup("(No Sender)");
|
|
|
|
}
|
|
|
|
if (jamm->to == NULL) {
|
|
|
|
jamm->to = strdup("(No Recipient)");
|
|
|
|
}
|
|
|
|
if (jmh.Attribute & JAM_MSG_PRIVATE) {
|
|
|
|
if (!msg_is_to(user, jamm->to, jamm->daddress, mc->nettype, mc->realnames, msgconf) &&
|
|
|
|
!msg_is_from(user, jamm->from, jamm->oaddress, mc->nettype, mc->realnames, msgconf) &&
|
|
|
|
!msg_is_to(user, jamm->to, jamm->daddress, mc->nettype, !mc->realnames, msgconf) &&
|
|
|
|
!msg_is_from(user, jamm->from, jamm->oaddress, mc->nettype, !mc->realnames, msgconf)) {
|
|
|
|
free(jamm->subject);
|
|
|
|
free(jamm->from);
|
|
|
|
free(jamm->to);
|
|
|
|
free(jamm->oaddress);
|
|
|
|
free(jamm->daddress);
|
|
|
|
free(jamm->msgid);
|
|
|
|
free(jamm->replyid);
|
|
|
|
free(jamm->msg_h);
|
|
|
|
free(jamm);
|
|
|
|
k++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (personal) {
|
|
|
|
if (!msg_is_to(user, jamm->to, jamm->daddress, mc->nettype, mc->realnames, msgconf) &&
|
|
|
|
!msg_is_to(user, jamm->to, jamm->daddress, mc->nettype, !mc->realnames, msgconf)) {
|
|
|
|
|
|
|
|
free(jamm->subject);
|
|
|
|
free(jamm->from);
|
|
|
|
free(jamm->to);
|
|
|
|
free(jamm->oaddress);
|
|
|
|
free(jamm->daddress);
|
|
|
|
free(jamm->msgid);
|
|
|
|
free(jamm->replyid);
|
|
|
|
free(jamm->msg_h);
|
|
|
|
free(jamm);
|
|
|
|
k++;
|
|
|
|
continue;
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
|
|
|
|
ptr_vector_append(&vec, jamm);
|
|
|
|
k++;
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +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
|
|
|
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];
|
2016-08-14 19:56:15 +10:00
|
|
|
int len;
|
2016-04-07 14:43:23 +10:00
|
|
|
int totlen;
|
|
|
|
char *body2 = NULL;
|
|
|
|
char *tagline;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
struct stat s;
|
2016-08-02 12:29:39 +10:00
|
|
|
struct utsname name;
|
|
|
|
|
2017-09-11 16:10:38 +10:00
|
|
|
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') {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d", conf.bbs_path, mynode);
|
2016-04-15 21:11:47 +10:00
|
|
|
if (stat(buffer, &s) != 0) {
|
|
|
|
mkdir(buffer, 0755);
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcat(buffer, "/MSGTMP", sizeof buffer);
|
2016-04-07 14:43:23 +10:00
|
|
|
if (stat(buffer, &s) == 0) {
|
|
|
|
remove(buffer);
|
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-04-07 14:43:23 +10:00
|
|
|
// write msgtemp
|
|
|
|
if (quote != NULL) {
|
|
|
|
fptr = fopen(buffer, "w");
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < qlen; i++) {
|
2016-04-09 12:44:25 +10:00
|
|
|
if (quote[i] == '\r') {
|
|
|
|
fprintf(fptr, "\r\n");
|
2016-04-09 12:50:07 +10:00
|
|
|
} 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);
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/MSGINF", conf.bbs_path, mynode);
|
2016-04-07 14:43:23 +10:00
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *area = get_user_area(user);
|
|
|
|
fprintf(fptr, "%s\r\n", area->name);
|
|
|
|
if (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");
|
2018-10-08 14:13:11 +00:00
|
|
|
fprintf(fptr, "NO\r\n");
|
2016-04-07 14:43:23 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fptr);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2017-04-23 12:14:14 +10:00
|
|
|
rundoor(user, conf.external_editor_cmd, conf.external_editor_stdio, conf.external_editor_codepage);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-04-07 14:43:23 +10:00
|
|
|
// readin msgtmp
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof 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);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-12 11:11:44 +10:00
|
|
|
if (body == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
totlen = strlen(body);
|
|
|
|
|
2016-08-02 12:29:39 +10:00
|
|
|
if (email == 1) {
|
2016-04-07 14:43:23 +10:00
|
|
|
tagline = conf.default_tagline;
|
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
tagline = conf.default_tagline;
|
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->tagline != NULL) {
|
|
|
|
tagline = mc->tagline;
|
2016-04-07 14:43:23 +10:00
|
|
|
}
|
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-01-13 19:17:22 +10:00
|
|
|
if (!sig) {
|
|
|
|
uname(&name);
|
2016-08-05 13:49:24 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->nettype == NETWORK_FIDO && !email) {
|
|
|
|
if (mc->fidoaddr->point == 0) {
|
|
|
|
snprintf(buffer, sizeof buffer, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d)\r",
|
2018-10-16 15:21:42 +00:00
|
|
|
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2018-01-13 19:17:22 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%d:%d/%d.%d)\r",
|
2018-10-16 15:21:42 +00:00
|
|
|
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node, mc->fidoaddr->point);
|
2018-10-16 15:05:15 +00:00
|
|
|
}
|
|
|
|
} else if (mc->nettype == NETWORK_MAGI && !email) {
|
|
|
|
snprintf(buffer, sizeof buffer, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r",
|
2018-10-16 15:21:42 +00:00
|
|
|
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
|
|
|
|
mc->maginode);
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_QWK && !email) {
|
|
|
|
snprintf(buffer, sizeof buffer, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (%s)\r",
|
2018-10-16 15:21:42 +00:00
|
|
|
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
|
|
|
|
conf.bwave_name);
|
2016-04-13 20:49:28 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "\r");
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
|
|
|
if (user->autosig) {
|
2018-10-09 15:55:13 +00:00
|
|
|
body2 = (char *)malloz(totlen + 3 + strlen(buffer) + strlen(user->signature));
|
2018-10-13 20:14:31 +10:00
|
|
|
totlen += strlen(buffer) + strlen(user->signature) + 3;
|
2018-01-13 19:17:22 +10:00
|
|
|
} else {
|
2018-10-09 15:55:13 +00:00
|
|
|
body2 = (char *)malloz(totlen + 2 + strlen(buffer));
|
2018-10-13 20:14:31 +10:00
|
|
|
totlen += strlen(buffer) + 2;
|
2016-04-13 20:49:28 +10:00
|
|
|
}
|
|
|
|
} else {
|
2018-10-09 15:55:13 +00:00
|
|
|
body2 = (char *)malloz(totlen + 1);
|
2016-04-13 20:49:28 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-04-07 14:43:23 +10:00
|
|
|
j = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
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') {
|
2018-10-14 22:27:27 +10:00
|
|
|
break;
|
2016-04-07 14:43:23 +10:00
|
|
|
}
|
|
|
|
body2[j++] = body[i];
|
2016-04-07 17:08:38 +10:00
|
|
|
body2[j] = '\0';
|
2016-04-07 14:43:23 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-01-13 19:17:22 +10:00
|
|
|
if (!sig) {
|
|
|
|
if (user->autosig) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcat(body2, "\r", totlen + 1);
|
|
|
|
strlcat(body2, user->signature, totlen + 1);
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcat(body2, buffer, totlen + 1);
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-04-07 16:41:10 +10:00
|
|
|
free(body);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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) {
|
2016-03-22 21:46:43 +10:00
|
|
|
char buffer[256];
|
2016-03-22 18:19:06 +10:00
|
|
|
char linebuffer[80];
|
2016-08-14 19:56:15 +10:00
|
|
|
int doquit = 0;
|
2016-03-22 18:19:06 +10:00
|
|
|
int i;
|
|
|
|
char *msg;
|
|
|
|
int size = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-08-02 12:29:39 +10:00
|
|
|
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("econtent);
|
|
|
|
init_ptr_vector(&content);
|
2016-04-07 14:43:23 +10:00
|
|
|
|
2016-03-22 21:46:43 +10:00
|
|
|
if (quote != NULL) {
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < quotelen; i++) {
|
2016-04-13 22:35:49 +10:00
|
|
|
if (quote[i] == '\r' || lineat == 67) {
|
2018-10-11 14:02:55 +00:00
|
|
|
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("econtent, str3dup(prefix, " ", linebuffer));
|
2016-03-22 21:46:43 +10:00
|
|
|
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--;
|
|
|
|
}
|
2016-03-22 21:46:43 +10:00
|
|
|
} else {
|
2016-12-05 13:38:03 +10:00
|
|
|
if (quote[i] == 27) {
|
|
|
|
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL)
|
2018-10-08 14:13:11 +00:00
|
|
|
i++;
|
2016-12-05 13:38:03 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-03-22 21:46:43 +10:00
|
|
|
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
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(86));
|
|
|
|
s_printf(get_string(87));
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
while (!doquit) {
|
2018-10-11 12:55:00 +00:00
|
|
|
s_printf(get_string(88), ptr_vector_len(&content), "");
|
2018-10-11 02:49:23 +00:00
|
|
|
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] != ' ') {
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = strlen(linebuffer) - 1; i > 15; i--) {
|
2016-04-13 22:35:49 +10:00
|
|
|
if (linebuffer[i] == ' ') {
|
|
|
|
linebuffer[i] = '\0';
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcpy(next_line_buffer, &linebuffer[i + 1], sizeof next_line_buffer);
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf("\e[%dD\e[0K", 70 - i);
|
2016-04-13 22:35:49 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
size++;
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
tagline = conf.default_tagline;
|
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->tagline != NULL) {
|
|
|
|
tagline = mc->tagline;
|
2016-03-27 13:17:25 +10:00
|
|
|
}
|
2018-01-13 19:17:22 +10:00
|
|
|
if (!sig) {
|
|
|
|
uname(&name);
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO && !email) {
|
|
|
|
if (mc->fidoaddr->point == 0) {
|
|
|
|
snprintf(buffer, sizeof buffer,
|
2018-10-16 15:21:42 +00:00
|
|
|
"\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,
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2018-01-13 19:17:22 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer,
|
2018-10-16 15:21:42 +00:00
|
|
|
"\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,
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node, mc->fidoaddr->point);
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_MAGI && !email) {
|
|
|
|
snprintf(buffer, sizeof buffer,
|
|
|
|
"\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r",
|
2018-10-16 15:21:42 +00:00
|
|
|
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
|
|
|
|
mc->maginode);
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_QWK && !email) {
|
|
|
|
snprintf(buffer, sizeof buffer,
|
2018-10-16 15:21:42 +00:00
|
|
|
"\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);
|
2016-04-14 08:52:46 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcpy(buffer, "\r", sizeof buffer);
|
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);
|
2016-04-14 08:52:46 +10:00
|
|
|
}
|
|
|
|
} else {
|
2018-01-13 19:17:22 +10:00
|
|
|
size += 1;
|
2016-08-02 12:29:39 +10:00
|
|
|
}
|
|
|
|
|
2018-10-09 15:55:13 +00:00
|
|
|
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++) {
|
2018-10-11 02:49:23 +00:00
|
|
|
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);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-01-13 19:17:22 +10:00
|
|
|
if (!sig) {
|
|
|
|
if (user->autosig) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcat(msg, "\r", size);
|
|
|
|
strlcat(msg, user->signature, size);
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcat(msg, buffer, size);
|
2018-01-13 19:17:22 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-03-22 21:46:43 +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("econtent, free);
|
|
|
|
destroy_ptr_vector("econtent);
|
2016-08-02 12:29:39 +10:00
|
|
|
}
|
2016-03-22 18:19:06 +10:00
|
|
|
return msg;
|
2018-10-08 14:13:11 +00:00
|
|
|
} 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);
|
2016-03-22 21:46:43 +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("econtent, free);
|
|
|
|
destroy_ptr_vector("econtent);
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2016-03-22 18:19:06 +10:00
|
|
|
return NULL;
|
2016-03-22 21:46:43 +10:00
|
|
|
} else if (toupper(linebuffer[1]) == 'Q') {
|
|
|
|
if (quote == NULL) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(89));
|
2016-03-22 21:46:43 +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
|
|
|
|
2016-08-14 19:56:15 +10: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("econtent); i++) {
|
|
|
|
s_printf(get_string(88), i, ptr_vector_get("econtent, i));
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(90));
|
|
|
|
s_readstring(buffer, 5);
|
2016-03-22 21:46:43 +10:00
|
|
|
qfrom = atoi(buffer);
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(91));
|
|
|
|
s_readstring(buffer, 5);
|
2016-03-22 21:46:43 +10:00
|
|
|
qto = atoi(buffer);
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf("\r\n");
|
2016-08-02 12:29:39 +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
|
|
|
if (qto > ptr_vector_len("econtent)) {
|
|
|
|
qto = ptr_vector_len("econtent);
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
|
|
|
if (qfrom < 0) {
|
|
|
|
qfrom = 0;
|
|
|
|
}
|
|
|
|
if (qfrom > qto) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(92));
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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("econtent, i));
|
|
|
|
ptr_vector_append(&content, copy);
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
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));
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (toupper(linebuffer[1]) == 'L') {
|
2016-08-14 19:56:15 +10:00
|
|
|
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));
|
2016-08-02 12:29:39 +10:00
|
|
|
}
|
2016-03-22 21:46:43 +10:00
|
|
|
} else if (linebuffer[1] == '?') {
|
2016-08-14 19:56:15 +10:00
|
|
|
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') {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(101));
|
|
|
|
s_readstring(buffer, 6);
|
2016-03-23 10:14:31 +10:00
|
|
|
if (strlen(buffer) == 0) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(39));
|
2016-03-23 10:14:31 +10:00
|
|
|
} else {
|
|
|
|
z = atoi(buffer);
|
2018-10-11 12:55:00 +00:00
|
|
|
if (z < 0 || z >= ptr_vector_len(&content)) {
|
2016-08-14 19:56:15 +10:00
|
|
|
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') {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(102));
|
|
|
|
s_readstring(buffer, 6);
|
2016-03-23 10:14:31 +10:00
|
|
|
if (strlen(buffer) == 0) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(39));
|
2016-03-23 10:14:31 +10:00
|
|
|
} else {
|
|
|
|
z = atoi(buffer);
|
2018-10-11 12:55:00 +00:00
|
|
|
if (z < 0 || z >= ptr_vector_len(&content)) {
|
2016-08-14 19:56:15 +10:00
|
|
|
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));
|
2016-08-14 19:56:15 +10:00
|
|
|
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') {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(104));
|
|
|
|
s_readstring(buffer, 6);
|
2016-03-23 10:14:31 +10:00
|
|
|
if (strlen(buffer) == 0) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(39));
|
2016-03-23 10:14:31 +10:00
|
|
|
} else {
|
|
|
|
z = atoi(buffer);
|
2018-10-11 12:55:00 +00:00
|
|
|
if (z < 0 || z >= ptr_vector_len(&content)) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(39));
|
2016-03-23 10:14:31 +10:00
|
|
|
} else {
|
2016-08-14 19:56:15 +10:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2016-03-22 21:46:43 +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("econtent, free);
|
|
|
|
destroy_ptr_vector("econtent);
|
2016-08-02 12:29:39 +10:00
|
|
|
}
|
2016-03-22 18:19:06 +10:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-15 18:36:38 +00:00
|
|
|
stralloc out = EMPTY_STRALLOC;
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-09 22:18:23 +10:00
|
|
|
line_at = 1;
|
|
|
|
char_at = 1;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
} 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
|
|
|
}
|
2018-10-08 14:13:11 +00: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;
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
|
2017-09-09 22:18:23 +10:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
state = 4;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-09 22:18:23 +10:00
|
|
|
if (state == 4) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-09 22:18:23 +10:00
|
|
|
if (char_at > 80) {
|
|
|
|
char_at = 80;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-09 22:18:23 +10:00
|
|
|
if (line_at > line_count) {
|
|
|
|
line_count = line_at;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
|
|
|
|
2018-10-09 15:55:13 +00:00
|
|
|
fake_screen = (struct character_t ***)malloz(sizeof(struct character_t **) * line_count);
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < line_count; i++) {
|
2018-10-09 15:55:13 +00:00
|
|
|
fake_screen[i] = (struct character_t **)malloz(sizeof(struct character_t *) * 80);
|
2018-10-08 14:13:11 +00:00
|
|
|
for (j = 0; j < 80; j++) {
|
2018-10-09 15:55:13 +00:00
|
|
|
fake_screen[i][j] = (struct character_t *)malloz(sizeof(struct character_t));
|
2016-12-05 13:38:03 +10:00
|
|
|
fake_screen[i][j]->c = ' ';
|
|
|
|
fake_screen[i][j]->fg = fg;
|
|
|
|
fake_screen[i][j]->bg = bg;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
line_at = 1;
|
|
|
|
char_at = 1;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2017-09-08 22:23:17 +10:00
|
|
|
|
2016-12-05 13:38:03 +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') {
|
|
|
|
for (tab = 0; tab < 8; tab++) {
|
|
|
|
if (line_at > line_count) line_at = line_count;
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2017-09-18 10:54:11 +10:00
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
} else {
|
2017-09-09 22:18:23 +10:00
|
|
|
if (line_at > line_count) line_at = line_count;
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
} else if (state == 2) {
|
|
|
|
param_count = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
for (j = 0; j < 16; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
|
2016-12-05 13:38:03 +10:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
state = 4;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
if (state == 4) {
|
2018-10-08 14:13:11 +00:00
|
|
|
switch (body[i]) {
|
2016-12-05 13:38:03 +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;
|
|
|
|
state = 0;
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
if (param_count > 0) {
|
|
|
|
line_at = line_at - params[0];
|
|
|
|
} else {
|
|
|
|
line_at--;
|
|
|
|
}
|
2017-09-08 22:23:17 +10:00
|
|
|
if (line_at < 1) {
|
|
|
|
line_at = 1;
|
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
state = 0;
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
if (param_count > 0) {
|
|
|
|
char_at = char_at + params[0];
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
char_at++;
|
2016-12-05 13:38:03 +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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
char_at--;
|
2016-12-05 13:38:03 +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;
|
|
|
|
case 'm':
|
2018-10-08 14:13:11 +00:00
|
|
|
for (j = 0; j < param_count; j++) {
|
|
|
|
switch (params[j]) {
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
state = 0;
|
|
|
|
break;
|
|
|
|
case 'K':
|
|
|
|
if (params[0] == 0) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
} else if (params[0] == 1) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
} else if (params[0] == 2) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
state = 0;
|
|
|
|
break;
|
|
|
|
case 'J':
|
|
|
|
if (params[0] == 0) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (k = line_at; k < line_count; k++) {
|
|
|
|
for (j = 0; j < 80; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
fake_screen[k][j]->c = ' ';
|
|
|
|
fake_screen[k][j]->fg = fg;
|
|
|
|
fake_screen[k][j]->bg = bg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (params[0] == 1) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (k = line_at - 2; k >= 0; k--) {
|
|
|
|
for (j = 0; j < 80; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
fake_screen[k][j]->c = ' ';
|
|
|
|
fake_screen[k][j]->fg = fg;
|
|
|
|
fake_screen[k][j]->bg = bg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (params[0] == 2) {
|
2018-10-08 14:13:11 +00:00
|
|
|
for (k = 0; k < line_count; k++) {
|
|
|
|
for (j = 0; j < 80; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
fake_screen[k][j]->c = ' ';
|
|
|
|
fake_screen[k][j]->fg = fg;
|
|
|
|
fake_screen[k][j]->bg = bg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
state = 0;
|
|
|
|
break;
|
2017-09-08 22:03:05 +10:00
|
|
|
default:
|
|
|
|
// bad ansi
|
|
|
|
state = 0;
|
|
|
|
break;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-06 20:11:41 +10:00
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
fg = 0x07;
|
|
|
|
bg = 0x00;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (i = 0; i < line_count; i++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
buf_at = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
for (j = 0; j < 79; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-05 13:38:03 +10:00
|
|
|
buffer[buf_at++] = 'm';
|
|
|
|
}
|
|
|
|
buffer[buf_at++] = fake_screen[i][j]->c;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
while (buf_at > 0 && buffer[buf_at - 1] == ' ') {
|
2016-12-05 13:38:03 +10:00
|
|
|
buf_at--;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-05 13:38:03 +10:00
|
|
|
buffer[buf_at++] = '\r';
|
2018-10-15 18:36:38 +00:00
|
|
|
stralloc_catb(&out, buffer, buf_at);
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (i = 0; i < line_count; i++) {
|
|
|
|
for (j = 0; j < 80; j++) {
|
2016-12-05 13:38:03 +10:00
|
|
|
free(fake_screen[i][j]);
|
|
|
|
}
|
|
|
|
free(fake_screen[i]);
|
|
|
|
}
|
|
|
|
free(fake_screen);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-15 18:36:38 +00:00
|
|
|
while (out.s[out.len - 2] == '\r') {
|
|
|
|
out.len--;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-15 18:36:38 +00:00
|
|
|
*body_out = out.s;
|
|
|
|
*body_len = out.len;
|
2016-12-05 13:38:03 +10:00
|
|
|
}
|
|
|
|
|
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;
|
2016-08-14 19:56:15 +10:00
|
|
|
s_JamMsgHeader jmh;
|
2018-10-08 14:13:11 +00:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
2016-03-22 18:19:06 +10:00
|
|
|
char *subject = NULL;
|
|
|
|
char *from = NULL;
|
2016-08-02 12:29:39 +10:00
|
|
|
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;
|
2016-03-22 21:46:43 +10:00
|
|
|
char c;
|
|
|
|
char *replybody;
|
2016-03-24 17:23:42 +10:00
|
|
|
struct fido_addr *from_addr = NULL;
|
2016-08-14 19:56:15 +10:00
|
|
|
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;
|
2016-04-08 13:32:04 +10:00
|
|
|
int chars = 0;
|
2016-04-22 14:36:53 +10:00
|
|
|
int ansi;
|
2016-04-23 14:10:42 +10:00
|
|
|
int sem_fd;
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
|
2018-10-11 15:25:00 +10:00
|
|
|
init_ptr_vector(&msg_lines);
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
jb = open_jam_base(ma->path);
|
2016-03-22 18:19:06 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2017-10-13 13:03:06 +10:00
|
|
|
return 0;
|
2016-03-22 18:19:06 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2017-10-13 13:03:06 +10:00
|
|
|
while (doquit == 0) {
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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-02 12:29:39 +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-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_FIDO) {
|
2016-03-30 12:59:00 +10:00
|
|
|
from_addr = parse_fido_addr(msghs->msgs[mailno]->oaddress);
|
2016-08-14 19:56:15 +10:00
|
|
|
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-10-16 15:05:15 +00:00
|
|
|
} else if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_MAGI) {
|
2018-05-22 21:02:22 +10:00
|
|
|
s_printf(get_string(288), msghs->msgs[mailno]->from, atoi(msghs->msgs[mailno]->oaddress));
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_QWK) {
|
2018-06-24 10:28:18 +10:00
|
|
|
s_printf(get_string(289), msghs->msgs[mailno]->from, msghs->msgs[mailno]->oaddress);
|
2016-03-30 12:59:00 +10:00
|
|
|
} else {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(106), msghs->msgs[mailno]->from);
|
2016-03-28 21:10:07 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
s_printf(get_string(107), msghs->msgs[mailno]->to, mc->name);
|
|
|
|
s_printf(get_string(108), msghs->msgs[mailno]->subject, ma->name);
|
2017-04-21 20:31:41 +10:00
|
|
|
gmtime_r((time_t *)&msghs->msgs[mailno]->msg_h->DateWritten, &msg_date);
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s", asctime(&msg_date));
|
2016-03-30 12:59:00 +10:00
|
|
|
buffer[strlen(buffer) - 1] = '\0';
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(109), buffer, mailno + 1, msghs->msg_count);
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(110), (msghs->msgs[mailno]->msg_h->Attribute & JAM_MSG_SENT ? "SENT" : ""),
|
2018-10-16 15:21:42 +00:00
|
|
|
(msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[mailno]->msg_h->MsgNum) ? "FLAGGED" : ""));
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(111));
|
2016-03-22 18:19:06 +10:00
|
|
|
|
2018-10-09 15:55:13 +00:00
|
|
|
body = (char *)malloz(msghs->msgs[mailno]->msg_h->TxtLen);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
2016-04-08 13:09:39 +10:00
|
|
|
lines = 0;
|
2016-04-08 13:32:04 +10:00
|
|
|
chars = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
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);
|
2018-10-08 14:13:11 +00:00
|
|
|
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';
|
2018-10-08 14:13:11 +00:00
|
|
|
} else {
|
2018-10-11 02:49:23 +00:00
|
|
|
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';
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
|
|
|
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 {
|
2016-12-05 13:38:03 +10:00
|
|
|
y = ansi;
|
2018-10-08 14:13:11 +00:00
|
|
|
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));
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00: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;
|
2018-10-08 14:13:11 +00:00
|
|
|
} 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)) {
|
2018-10-08 14:13:11 +00:00
|
|
|
position--;
|
|
|
|
}
|
|
|
|
} else if (c == 67) {
|
|
|
|
c = ' ';
|
|
|
|
should_break = 1;
|
|
|
|
} else if (c == 68) {
|
|
|
|
c = 'b';
|
|
|
|
should_break = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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;
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
if (user->sec_level < ma->write_sec_level) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(113));
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(ma->path);
|
2016-03-28 14:46:48 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
const char *old_subject = msghs->msgs[mailno]->subject;
|
|
|
|
if (old_subject != NULL) {
|
|
|
|
*buffer = '\0';
|
|
|
|
if (strncasecmp(old_subject, "RE:", 3) != 0)
|
|
|
|
strlcpy(buffer, "RE: ", sizeof buffer);
|
|
|
|
strlcat(buffer, old_subject, sizeof buffer);
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-09 15:55:13 +00:00
|
|
|
subject = strdup(buffer);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
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);
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(115));
|
2018-05-09 13:19:49 +10:00
|
|
|
s_readstring_inject(buffer, 64, subject);
|
|
|
|
free(subject);
|
|
|
|
subject = strdup(buffer);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf("\r\n");
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
if (msghs->msgs[mailno]->from != NULL) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcpy(buffer, msghs->msgs[mailno]->from, sizeof buffer);
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->realnames == 0) {
|
2018-10-09 15:55:13 +00:00
|
|
|
from = strdup(user->loginname);
|
2016-03-30 12:59:00 +10:00
|
|
|
} else {
|
2018-10-09 15:55:13 +00:00
|
|
|
from = str3dup(user->firstname, " ", user->lastname);
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NEWSGROUP_AREA) {
|
2018-05-09 13:19:49 +10:00
|
|
|
free(to);
|
2018-10-11 02:49:23 +00:00
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(ma->path);
|
2016-03-30 12:59:00 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->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
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
JAM_ClearMsgHeader(&jmh);
|
2017-04-21 20:31:41 +10:00
|
|
|
jmh.DateWritten = utc_to_local(time(NULL));
|
2017-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_LOCAL;
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
jsp = JAM_NewSubPacket();
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
2016-03-22 21:46:43 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2017-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPEECHO;
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
|
|
|
|
mc->fidoaddr->point);
|
2016-03-30 12:59:00 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->net,
|
|
|
|
mc->fidoaddr->node,
|
|
|
|
mc->fidoaddr->point,
|
|
|
|
generate_msgid());
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
|
2016-04-15 12:34:58 +10:00
|
|
|
if (msghs->msgs[mailno]->msgid != NULL) {
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
2018-10-08 14:13:11 +00:00
|
|
|
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_MAGI) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d", mc->maginode);
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_MSGID;
|
|
|
|
jsf.HiID = 0;
|
2016-03-30 12:59:00 +10:00
|
|
|
jsf.DatLen = strlen(buffer);
|
|
|
|
jsf.Buffer = (char *)buffer;
|
2016-08-02 12:29:39 +10:00
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
2018-05-22 21:02:22 +10:00
|
|
|
if (msghs->msgs[mailno]->msgid != NULL) {
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
2018-10-08 14:13:11 +00:00
|
|
|
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_QWK) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_NETMAIL_AREA) {
|
2017-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPENET;
|
|
|
|
jmh.Attribute |= JAM_MSG_PRIVATE;
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->point);
|
2016-03-25 15:58:08 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2016-03-25 15:58:08 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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);
|
2016-08-02 12:29:39 +10:00
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
from_addr->zone, from_addr->net, from_addr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
from_addr->point);
|
2016-03-30 12:59:00 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
from_addr->zone, from_addr->net, from_addr->node);
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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);
|
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone,
|
|
|
|
mc->fidoaddr->net,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->node,
|
|
|
|
mc->fidoaddr->point,
|
|
|
|
generate_msgid());
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
|
2016-03-30 13:46:09 +10:00
|
|
|
if (msghs->msgs[mailno]->msgid != NULL) {
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
2018-10-08 14:13:11 +00:00
|
|
|
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-03-28 21:10:07 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +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);
|
2016-08-04 19:25:49 +10:00
|
|
|
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-22 21:46:43 +10:00
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
if (JAM_AddMessage(jb, &jmh, jsp, (char *)replybody, strlen(replybody))) {
|
2016-08-04 19:25:49 +10:00
|
|
|
dolog("Failed to add message");
|
2016-04-23 14:10:42 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2016-04-23 14:10:42 +10:00
|
|
|
if (conf.netmail_sem != NULL) {
|
2017-10-13 22:13:00 +10:00
|
|
|
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);
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2016-04-23 14:10:42 +10:00
|
|
|
if (conf.echomail_sem != NULL) {
|
2017-10-13 22:13:00 +10:00
|
|
|
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-08-02 12:29:39 +10:00
|
|
|
}
|
2016-04-23 14:10:42 +10:00
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
}
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
JAM_UnlockMB(jb);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2016-03-30 12:59:00 +10:00
|
|
|
JAM_DelSubPacket(jsp);
|
|
|
|
free(replybody);
|
2017-09-15 11:16:35 +10:00
|
|
|
// JAM_CloseMB(jb);
|
|
|
|
// doquit = 1;
|
2017-04-29 20:17:58 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(ma->path);
|
2017-04-29 20:17:58 +10:00
|
|
|
}
|
2016-03-22 21:46:43 +10:00
|
|
|
}
|
2016-03-30 12:59:00 +10:00
|
|
|
free(body);
|
2018-10-16 15:05:15 +00:00
|
|
|
free(from);
|
|
|
|
free(to);
|
|
|
|
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') {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2016-08-14 19:56:15 +10:00
|
|
|
s_printf(get_string(118));
|
2016-03-30 12:59:00 +10:00
|
|
|
doquit = 1;
|
|
|
|
}
|
2016-11-30 21:45:23 +10:00
|
|
|
free(body);
|
2016-04-22 21:48:52 +10:00
|
|
|
} else if (tolower(c) == 'b') {
|
|
|
|
if (mailno > 0) {
|
|
|
|
mailno--;
|
|
|
|
}
|
2016-11-30 21:45:23 +10:00
|
|
|
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);
|
2016-11-30 21:45:23 +10:00
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (jb != NULL)
|
2018-02-23 14:27:36 +10:00
|
|
|
JAM_CloseMB(jb);
|
2018-10-16 15:05:15 +00:00
|
|
|
free(jb);
|
2018-02-23 14:27:36 +10:00
|
|
|
|
2017-10-13 13:03:06 +10:00
|
|
|
if (doquit == 2) {
|
|
|
|
return 1;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-10-12 20:24:55 +10:00
|
|
|
// list mail in message base
|
|
|
|
if (msghs != NULL && msghs->msg_count > 0) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
jb = open_jam_base(ma->path);
|
2017-10-12 20:24:55 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->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;
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < msghs->msg_count; i++) {
|
2017-10-12 20:24:55 +10:00
|
|
|
if (msghs->msgs[i]->msg_h->MsgNum == k) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2017-10-12 20:24:55 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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);
|
2018-10-16 15:05:15 +00:00
|
|
|
if (msghs == NULL)
|
|
|
|
return;
|
|
|
|
if (msghs->msg_count <= 0) {
|
|
|
|
free_message_headers(msghs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
jb = open_jam_base(ma->path);
|
|
|
|
if (!jb) {
|
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
all_unread = 0;
|
|
|
|
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
|
|
|
|
jlr.LastReadMsg = 0;
|
|
|
|
jlr.HighReadMsg = 0;
|
|
|
|
all_unread = 1;
|
|
|
|
} else if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
|
|
|
|
all_unread = 1;
|
|
|
|
}
|
|
|
|
JAM_CloseMB(jb);
|
|
|
|
free(jb);
|
|
|
|
s_printf(get_string(120), msghs->msg_count);
|
2017-04-12 17:27:59 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
s_readstring(buffer, 6);
|
2017-04-12 17:27:59 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (tolower(buffer[0]) == 'n') {
|
|
|
|
if (all_unread == 0) {
|
|
|
|
k = jlr.HighReadMsg;
|
|
|
|
for (i = 0; i < msghs->msg_count; i++) {
|
|
|
|
if (msghs->msgs[i]->msg_h->MsgNum == k) {
|
|
|
|
break;
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
i += 2;
|
|
|
|
} else {
|
|
|
|
i = 1;
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else {
|
|
|
|
i = atoi(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i > 0 && i <= msghs->msg_count) {
|
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
s_JamSubPacket *jsp;
|
2017-04-12 17:27:59 +10:00
|
|
|
s_JamSubfield jsf;
|
|
|
|
s_JamLastRead jlr;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
if (user->sec_level < ma->write_sec_level) {
|
2017-04-12 17:27:59 +10:00
|
|
|
s_printf(get_string(113));
|
|
|
|
return;
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NEWSGROUP_AREA) {
|
|
|
|
strlcpy(buffer, "ALL", sizeof buffer);
|
2017-04-12 17:27:59 +10:00
|
|
|
} 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) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcpy(buffer, "ALL", sizeof(buffer));
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
2018-05-22 21:02:22 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2017-04-12 17:27:59 +10:00
|
|
|
s_printf(get_string(121));
|
|
|
|
s_readstring(buffer2, 32);
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
2017-04-12 17:27:59 +10:00
|
|
|
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-10-16 15:05:15 +00:00
|
|
|
// TODO: Is this different than `user`?
|
|
|
|
struct mail_conference *gmc = get_user_conf(gUser);
|
|
|
|
if (gmc->domain != NULL) {
|
|
|
|
bbsname = nl_get_bbsname(from_addr, gmc->domain);
|
2018-02-06 08:05:02 +10:00
|
|
|
} 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
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
if (mc->realnames == 0) {
|
2017-04-12 17:27:59 +10:00
|
|
|
from = strdup(user->loginname);
|
|
|
|
} else {
|
2018-10-09 15:55:13 +00:00
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(ma->path);
|
2017-04-12 17:27:59 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2017-04-12 17:27:59 +10:00
|
|
|
free(msg);
|
|
|
|
free(to);
|
|
|
|
free(subject);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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;
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->realnames == 0) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcpy(buffer, user->loginname, sizeof(buffer));
|
2017-04-12 17:27:59 +10:00
|
|
|
} else {
|
2018-10-11 02:49:23 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s %s", user->firstname, user->lastname);
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
jsp = JAM_NewSubPacket();
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2017-04-12 17:27:59 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPEECHO;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->point);
|
2017-04-12 17:27:59 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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);
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->point, generate_msgid());
|
2017-04-12 17:27:59 +10:00
|
|
|
|
2018-10-08 14:13:11 +00: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-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_MAGI) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d", mc->maginode);
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_QWK) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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);
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_NETMAIL_AREA) {
|
2017-04-12 17:27:59 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPENET;
|
|
|
|
jmh.Attribute |= JAM_MSG_PRIVATE;
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point) {
|
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->point);
|
2017-04-12 17:27:59 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
from_addr->zone, from_addr->net, from_addr->node,
|
2018-10-16 15:05:15 +00:00
|
|
|
from_addr->point);
|
2017-04-12 17:27:59 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
from_addr->zone, from_addr->net, from_addr->node);
|
2017-04-12 17:27:59 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00: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;
|
|
|
|
}
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
|
2018-10-16 15:21:42 +00:00
|
|
|
mc->fidoaddr->zone,
|
2018-10-16 15:05:15 +00:00
|
|
|
mc->fidoaddr->net,
|
|
|
|
mc->fidoaddr->node,
|
|
|
|
mc->fidoaddr->point,
|
|
|
|
generate_msgid());
|
2017-04-12 17:27:59 +10:00
|
|
|
|
2018-10-08 14:13:11 +00: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-10-08 14:13:11 +00:00
|
|
|
}
|
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 {
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2017-04-12 17:27:59 +10:00
|
|
|
if (conf.netmail_sem != NULL) {
|
2017-10-13 22:13:00 +10:00
|
|
|
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);
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2017-04-12 17:27:59 +10:00
|
|
|
if (conf.echomail_sem != NULL) {
|
2017-10-13 22:13:00 +10:00
|
|
|
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;
|
2016-12-02 12:23:47 +10:00
|
|
|
int redraw;
|
2017-04-12 22:34:08 +10:00
|
|
|
struct tm msg_date;
|
|
|
|
char c;
|
2018-10-13 20:03:58 +10:00
|
|
|
int offset = 2;
|
|
|
|
int height = 22;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *gmc = get_conf(gUser->cur_mail_conf);
|
|
|
|
if (gmc->header != NULL) {
|
2018-10-13 20:03:58 +10:00
|
|
|
offset = 8;
|
|
|
|
height = 16;
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
|
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) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
jb = open_jam_base(ma->path);
|
2017-04-12 22:34:08 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2017-04-12 22:34:08 +10:00
|
|
|
return;
|
2016-04-12 15:19:56 +10:00
|
|
|
} 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;
|
2016-04-12 15:19:56 +10:00
|
|
|
}
|
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);
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2017-04-12 22:34:08 +10:00
|
|
|
s_readstring(buffer, 6);
|
|
|
|
if (tolower(buffer[0]) == 'n') {
|
|
|
|
if (all_unread == 0) {
|
|
|
|
k = jlr.HighReadMsg;
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
i += 2;
|
2016-03-22 18:19:06 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-04-12 22:34:08 +10:00
|
|
|
} else {
|
|
|
|
i = 1;
|
2016-08-02 12:29:39 +10:00
|
|
|
}
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
start = i - 1;
|
2017-04-12 22:34:08 +10:00
|
|
|
while (!closed) {
|
|
|
|
if (redraw) {
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->header != NULL) {
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[2J\e[1;1H");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_displayansi(mc->header);
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[7;1H");
|
|
|
|
} else {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
|
|
|
}
|
2017-04-12 22:34:08 +10:00
|
|
|
s_printf(get_string(126));
|
2018-10-13 20:03:58 +10:00
|
|
|
for (j = start; j < start + height && 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);
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
}
|
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-10-08 14:13:11 +00:00
|
|
|
}
|
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
|
|
|
}
|
2016-03-27 11:30:52 +10:00
|
|
|
}
|
|
|
|
}
|
2017-04-12 22:34:08 +10:00
|
|
|
s_printf(get_string(190));
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;5H", i - start + offset - 1);
|
2017-04-12 22:34:08 +10:00
|
|
|
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++;
|
2018-10-13 20:03:58 +10:00
|
|
|
if (i > start + height) {
|
|
|
|
start += height;
|
2017-04-12 22:34:08 +10:00
|
|
|
if (start > msghs->msg_count) {
|
2018-10-13 20:03:58 +10:00
|
|
|
start = msghs->msg_count - height;
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
if (i - 1 == msghs->msg_count) {
|
2017-04-12 22:34:08 +10:00
|
|
|
i--;
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;5H", i - start + offset - 1);
|
2017-04-12 22:34:08 +10:00
|
|
|
} else if (!redraw) {
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;1H", i - start + offset - 2);
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;1H", i - start + offset - 1);
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;5H", i - start + offset - 1);
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
} else if (c == 65) {
|
|
|
|
// up
|
|
|
|
i--;
|
|
|
|
if (i - 1 < start) {
|
2018-10-13 20:03:58 +10:00
|
|
|
start -= height;
|
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) {
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;1H", i - start + offset);
|
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-10-08 14:13:11 +00:00
|
|
|
}
|
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);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;1H", i - start + offset - 1);
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-10-13 20:03:58 +10:00
|
|
|
s_printf("\e[%d;5H", i - start + offset - 1);
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2017-09-09 17:57:55 +10:00
|
|
|
} else if (c == 75) {
|
2017-09-09 17:49:23 +10:00
|
|
|
// END KEY
|
|
|
|
i = msghs->msg_count;
|
2018-10-13 20:03:58 +10:00
|
|
|
start = i - height;
|
2017-09-09 17:49:23 +10:00
|
|
|
if (start < 0) {
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
2017-09-09 17:57:55 +10:00
|
|
|
} else if (c == 72) {
|
2017-09-09 17:49:23 +10:00
|
|
|
// 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
|
2018-10-13 20:03:58 +10:00
|
|
|
i = i - height;
|
2018-01-20 12:46:50 +10:00
|
|
|
if (i <= 0) {
|
|
|
|
i = 1;
|
|
|
|
}
|
|
|
|
start = i - 1;
|
|
|
|
redraw = 1;
|
|
|
|
} else if (c == 85 || c == '6') {
|
|
|
|
if (c == '6') {
|
|
|
|
s_getchar();
|
|
|
|
}
|
|
|
|
// PAGE DOWN
|
2018-10-13 20:03:58 +10:00
|
|
|
i = i + height;
|
2018-01-20 12:46:50 +10:00
|
|
|
if (i > msghs->msg_count) {
|
|
|
|
i = msghs->msg_count;
|
|
|
|
}
|
|
|
|
start = i - 1;
|
|
|
|
redraw = 1;
|
2016-03-27 11:30:52 +10:00
|
|
|
}
|
|
|
|
}
|
2017-04-12 22:34:08 +10:00
|
|
|
} else if (c == 13) {
|
2017-09-08 08:46:23 +10:00
|
|
|
redraw = 1;
|
2017-10-13 13:03:06 +10:00
|
|
|
read_message(user, msghs, i - 1, 0);
|
2017-09-09 10:59:32 +10:00
|
|
|
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);
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_user_area(user);
|
|
|
|
jb = open_jam_base(ma->path);
|
2017-09-09 10:59:32 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2017-09-09 10:59:32 +10:00
|
|
|
if (msghs != NULL) {
|
|
|
|
free_message_headers(msghs);
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2017-09-09 10:59:32 +10:00
|
|
|
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);
|
2017-09-09 10:59:32 +10:00
|
|
|
}
|
2018-05-22 08:55:44 +10:00
|
|
|
} else if (tolower(c) == 'f') {
|
|
|
|
redraw = 1;
|
2018-10-08 14:13:11 +00:00
|
|
|
msgbase_flag_unflag(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum);
|
2016-03-27 11:30:52 +10:00
|
|
|
}
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msghs != NULL) {
|
|
|
|
free_message_headers(msghs);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
s_printf(get_string(130));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 14:54:04 +10:00
|
|
|
struct conf_tmp_t {
|
|
|
|
struct mail_conference *conference;
|
|
|
|
int index;
|
|
|
|
};
|
|
|
|
|
|
|
|
void choose_conference() {
|
2017-04-12 22:34:08 +10:00
|
|
|
int i;
|
2018-01-17 14:54:04 +10:00
|
|
|
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);
|
2018-10-16 15:05:15 +00:00
|
|
|
for (i = 0; i < ptr_vector_len(&conf.mail_conferences); ++i) {
|
|
|
|
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, i);
|
|
|
|
if (mc->sec_level <= gUser->sec_level) {
|
2018-10-11 14:02:55 +00:00
|
|
|
struct conf_tmp_t *c = (struct conf_tmp_t *)malloz(sizeof(struct conf_tmp_t));
|
2018-10-16 15:05:15 +00:00
|
|
|
c->conference = mc;
|
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->index = i;
|
|
|
|
ptr_vector_append(&vec, c);
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
2018-01-17 14:54:04 +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);
|
2018-01-17 14:54:04 +10:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (redraw) {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
|
|
|
s_printf(get_string(247));
|
|
|
|
s_printf(get_string(248));
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = start; i < start + 22 && i < list_tmp; i++) {
|
2018-01-17 14:54:04 +10:00
|
|
|
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);
|
2018-01-17 14:54:04 +10:00
|
|
|
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) {
|
2018-01-17 14:54:04 +10:00
|
|
|
start += 22;
|
|
|
|
if (start >= list_tmp) {
|
|
|
|
start = list_tmp - 22;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
selected++;
|
|
|
|
if (selected >= list_tmp) {
|
|
|
|
selected = list_tmp - 1;
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-01-17 14:54:04 +10:00
|
|
|
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);
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} 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 {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-01-17 14:54:04 +10:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
}
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
selected = list_tmp - 1;
|
2018-01-20 12:46:50 +10:00
|
|
|
}
|
|
|
|
start = selected;
|
|
|
|
redraw = 1;
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} 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
|
|
|
}
|
|
|
|
}
|
2018-01-17 14:54:04 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < list_tmp; i++) {
|
2018-01-17 14:54:04 +10:00
|
|
|
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;
|
2018-10-04 10:05:04 +10:00
|
|
|
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;
|
2018-10-04 10:05:04 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *gmc = get_user_conf(gUser);
|
|
|
|
if (gmc->header != NULL) {
|
2018-10-04 10:05:04 +10:00
|
|
|
offset = 8;
|
2018-10-13 20:03:58 +10:00
|
|
|
height = 16;
|
2018-10-04 10:05:04 +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);
|
2018-10-16 15:05:15 +00:00
|
|
|
for (i = 0; i < ptr_vector_len(&gmc->mail_areas); ++i) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, i);
|
|
|
|
if (ma->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));
|
2018-10-16 15:05:15 +00:00
|
|
|
area->area = ma;
|
2018-10-13 20:03:58 +10:00
|
|
|
area->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);
|
2018-01-17 14:54:04 +10:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (redraw) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *gmc = get_user_conf(gUser);
|
|
|
|
if (gmc->header != NULL) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf("\e[2J\e[1;1H");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_displayansi(gmc->header);
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf("\e[7;1H");
|
|
|
|
} else {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(251), gmc->name);
|
2018-01-17 14:54:04 +10:00
|
|
|
s_printf(get_string(248));
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = start; i < start + height && i < list_tmp; i++) {
|
2018-01-17 14:54:04 +10:00
|
|
|
if (i == selected) {
|
2018-01-25 09:37:22 +10:00
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(259), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(249), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
2018-01-17 14:54:04 +10:00
|
|
|
} else {
|
2018-01-25 09:37:22 +10:00
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(260), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
|
2018-10-08 14:13:11 +00:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(250), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
}
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf("\e[%d;5H", selected - start + offset);
|
2018-01-17 14:54:04 +10:00
|
|
|
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-10-04 10:05:04 +10:00
|
|
|
if (selected + 1 >= start + height) {
|
|
|
|
start += height;
|
2018-01-17 14:54:04 +10:00
|
|
|
if (start >= list_tmp) {
|
2018-10-04 10:05:04 +10:00
|
|
|
start = list_tmp - height;
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
selected++;
|
|
|
|
if (selected >= list_tmp) {
|
|
|
|
selected = list_tmp - 1;
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-01-25 09:37:22 +10:00
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected - 1]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(260), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(250), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf("\e[%d;5H", selected - start + offset);
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (c == 65) {
|
|
|
|
// up
|
|
|
|
if (selected - 1 < start) {
|
2018-10-04 10:05:04 +10:00
|
|
|
start -= height;
|
2018-01-17 14:54:04 +10:00
|
|
|
if (start < 0) {
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
selected--;
|
|
|
|
if (selected < 0) {
|
|
|
|
selected = 0;
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-01-25 09:37:22 +10:00
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
|
|
|
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected + 1]->index)) {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(260), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
} else {
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf(get_string(250), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
2018-10-04 10:05:04 +10:00
|
|
|
s_printf("\e[%d;5H", selected - start + offset);
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
2018-01-20 12:46:50 +10:00
|
|
|
} else if (c == 75) {
|
|
|
|
// END KEY
|
|
|
|
selected = list_tmp - 1;
|
2018-10-04 10:05:04 +10:00
|
|
|
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
|
2018-10-04 10:05:04 +10:00
|
|
|
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
|
2018-10-04 10:05:04 +10:00
|
|
|
selected = selected + height;
|
2018-01-20 12:46:50 +10:00
|
|
|
if (selected >= list_tmp) {
|
2018-10-08 14:13:11 +00:00
|
|
|
selected = list_tmp - 1;
|
2018-01-20 12:46:50 +10:00
|
|
|
}
|
|
|
|
start = selected;
|
|
|
|
redraw = 1;
|
2018-01-17 14:54:04 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (c == 13) {
|
|
|
|
gUser->cur_mail_area = area_tmp[selected]->index;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < list_tmp; i++) {
|
2018-01-17 14:54:04 +10:00
|
|
|
free(area_tmp[i]);
|
|
|
|
}
|
|
|
|
free(area_tmp);
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
void next_mail_conf(struct user_record *user) {
|
2018-10-16 15:05:15 +00:00
|
|
|
size_t n = ptr_vector_len(&conf.mail_conferences);
|
|
|
|
size_t start = user->cur_mail_conf;
|
|
|
|
size_t i;
|
|
|
|
for (i = (start + 1) % n; i != start; i = (i + 1) % n) {
|
|
|
|
struct mail_conference *mc = get_conf(i);
|
|
|
|
if (mc->sec_level <= user->sec_level) {
|
2017-04-12 22:34:08 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = 0;
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
void prev_mail_conf(struct user_record *user) {
|
2018-10-16 15:05:15 +00:00
|
|
|
size_t n = ptr_vector_len(&conf.mail_conferences);
|
|
|
|
size_t start = user->cur_mail_conf;
|
|
|
|
size_t i;
|
|
|
|
for (i = (start + n - 1) % n; i != start; i = (i + n - 1) % n) {
|
|
|
|
struct mail_conference *mc = get_conf(i);
|
|
|
|
if (mc->sec_level <= user->sec_level) {
|
2017-04-12 22:34:08 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = 0;
|
2017-04-12 22:34:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
void next_mail_area(struct user_record *user) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
size_t n = ptr_vector_len(&mc->mail_areas);
|
|
|
|
size_t start = user->cur_mail_area;
|
|
|
|
for (size_t i = (start + 1) % n; i != start; i = (i + 1) % n) {
|
|
|
|
struct mail_area *ma = get_area(user->cur_mail_conf, i);
|
|
|
|
if (ma->read_sec_level <= user->sec_level) {
|
|
|
|
user->cur_mail_area = i;
|
2017-04-12 22:34:08 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void prev_mail_area(struct user_record *user) {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_user_conf(user);
|
|
|
|
size_t n = ptr_vector_len(&mc->mail_areas);
|
|
|
|
size_t start = user->cur_mail_area;
|
|
|
|
for (size_t i = (start + n - 1) % n; i != start; i = (i + n - 1) % n) {
|
|
|
|
struct mail_area *ma = get_area(user->cur_mail_conf, i);
|
|
|
|
if (ma->read_sec_level <= user->sec_level) {
|
|
|
|
user->cur_mail_area = i;
|
2017-04-12 22:34:08 +10:00
|
|
|
break;
|
|
|
|
}
|
2016-04-12 15:19:56 +10:00
|
|
|
}
|
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;
|
2016-08-14 19:56:15 +10:00
|
|
|
struct msg_headers *msghs;
|
2016-03-26 16:06:59 +10:00
|
|
|
char c;
|
|
|
|
int i;
|
|
|
|
int j;
|
2016-08-14 19:56:15 +10:00
|
|
|
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));
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
c = s_getc();
|
2016-08-02 12:29:39 +10:00
|
|
|
|
2017-10-10 11:16:34 +10:00
|
|
|
if (tolower(c) == 'y' || tolower(c) == 's') {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (i = 0; i < ptr_vector_len(&conf.mail_conferences); i++) {
|
|
|
|
struct mail_conference *mc = get_conf(i);
|
|
|
|
if (mc->sec_level > user->sec_level) {
|
2016-03-26 16:06:59 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-02-23 14:27:36 +10:00
|
|
|
if (oldscan) {
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(140), i, mc->name);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
lines += 2;
|
2018-02-23 14:27:36 +10:00
|
|
|
if (lines == 22) {
|
|
|
|
s_printf(get_string(6));
|
|
|
|
s_getc();
|
|
|
|
lines = 0;
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
for (j = 0; j < ptr_vector_len(&mc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = get_area(i, j);
|
|
|
|
if (ma->read_sec_level > user->sec_level) {
|
2016-03-26 16:06:59 +10:00
|
|
|
continue;
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-10-10 11:16:34 +10:00
|
|
|
if (tolower(c) == 's' && !msgbase_is_subscribed(i, j)) {
|
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
jb = open_jam_base(ma->path);
|
2016-08-14 19:56:15 +10:00
|
|
|
if (!jb) {
|
|
|
|
dolog("Unable to open message base");
|
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2016-08-14 19:56:15 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-08-14 19:56:15 +10:00
|
|
|
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);
|
2016-08-14 19:56:15 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2018-02-18 13:51:39 +10:00
|
|
|
msghs = read_message_headers(i, j, user, personal);
|
2016-08-14 19:56:15 +10:00
|
|
|
if (msghs != NULL) {
|
|
|
|
if (msghs->msg_count > 0) {
|
2017-10-12 20:24:55 +10:00
|
|
|
if (oldscan) {
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(141), j, ma->name, msghs->msg_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");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(277), i, mc->name);
|
|
|
|
s_printf(get_string(278), j, ma->name, msghs->msg_count);
|
2018-02-27 13:24:24 +10:00
|
|
|
s_printf(get_string(279));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
ch = s_getchar();
|
|
|
|
s_printf("\r\n");
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = j;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
res = read_new_msgs(user, msghs);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
user->cur_mail_conf = orig_conf;
|
|
|
|
user->cur_mail_area = orig_area;
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free_message_headers(msghs);
|
|
|
|
}
|
|
|
|
} else {
|
2017-10-12 20:24:55 +10:00
|
|
|
if (oldscan) {
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(141), j, ma->name, jbh.ActiveMsgs);
|
2017-10-12 20:24:55 +10:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
if (msghs->msg_count > 0) {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(277), i, mc->name);
|
|
|
|
s_printf(get_string(278), j, ma->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");
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = j;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
res = read_new_msgs(user, msghs);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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);
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-08-21 09:39:36 +10:00
|
|
|
if (jlr.HighReadMsg < jbh.ActiveMsgs) {
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2018-02-18 13:51:39 +10:00
|
|
|
msghs = read_message_headers(i, j, user, personal);
|
2016-08-14 19:56:15 +10:00
|
|
|
if (msghs != NULL) {
|
|
|
|
if (msghs->msg_count > 0) {
|
2018-02-23 14:27:36 +10:00
|
|
|
unread_count = 0;
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
}
|
2018-02-23 14:31:31 +10:00
|
|
|
if (unread_count > 0) {
|
2017-10-12 20:24:55 +10:00
|
|
|
if (oldscan) {
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(141), j, ma->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");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(277), i, mc->name);
|
|
|
|
s_printf(get_string(278), j, ma->name, unread_count);
|
2018-02-27 13:24:24 +10:00
|
|
|
s_printf(get_string(279));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
ch = s_getchar();
|
|
|
|
s_printf("\r\n");
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = j;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
res = read_new_msgs(user, msghs);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:27:36 +10:00
|
|
|
user->cur_mail_conf = orig_conf;
|
|
|
|
user->cur_mail_area = orig_area;
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free_message_headers(msghs);
|
|
|
|
}
|
|
|
|
} else {
|
2017-10-12 20:24:55 +10:00
|
|
|
if (oldscan) {
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(141), j, ma->name, jbh.ActiveMsgs - jlr.HighReadMsg);
|
2017-10-12 20:24:55 +10:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
if (msghs->msg_count > 0) {
|
2018-02-23 14:27:36 +10:00
|
|
|
unread_count = 0;
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
if (unread_count > 0) {
|
2018-02-23 14:34:42 +10:00
|
|
|
s_printf("\e[2J\e[1;1H");
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(277), i, mc->name);
|
|
|
|
s_printf(get_string(278), j, ma->name, unread_count);
|
2018-02-23 14:34:42 +10:00
|
|
|
s_printf(get_string(279));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:34:42 +10:00
|
|
|
ch = s_getchar();
|
|
|
|
s_printf("\r\n");
|
2018-10-08 14:13:11 +00:00
|
|
|
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-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:34:42 +10:00
|
|
|
user->cur_mail_conf = i;
|
|
|
|
user->cur_mail_area = j;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-23 14:34:42 +10:00
|
|
|
res = read_new_msgs(user, msghs);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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);
|
|
|
|
}
|
2016-08-14 19:56:15 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2016-08-14 19:56:15 +10:00
|
|
|
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;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-03-26 16:06:59 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-08-14 19:56:15 +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");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-21 10:21:51 +10:00
|
|
|
do {
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *gmc = get_user_conf(gUser);
|
|
|
|
for (i = 0; i < ptr_vector_len(&gmc->mail_areas); i++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, i);
|
|
|
|
if (ma->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)), ma->name);
|
2017-09-21 10:21:51 +10:00
|
|
|
lines++;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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);
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, toggle_area);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
|
|
|
|
}
|
|
|
|
lines = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (buffer[0] == 'a' || buffer[0] == 'A') {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (j = 0; j < ptr_vector_len(&gmc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, j);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
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') {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (j = 0; j < ptr_vector_len(&gmc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, j);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
|
|
|
|
msgbase_sub_unsub(gUser->cur_mail_conf, j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2017-09-21 10:21:51 +10:00
|
|
|
}
|
|
|
|
lines = 0;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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);
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, toggle_area);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
|
|
|
|
}
|
|
|
|
lines = 0;
|
|
|
|
} else if (buffer[0] == 'a' || buffer[0] == 'A') {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (j = 0; j < ptr_vector_len(&gmc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, j);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
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') {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (j = 0; j < ptr_vector_len(&gmc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, j);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level) {
|
2017-10-13 16:55:33 +10:00
|
|
|
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
|
|
|
|
msgbase_sub_unsub(gUser->cur_mail_conf, j);
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
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
|
|
|
|
2018-02-03 11:44:36 +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;
|
2018-02-03 11:44:36 +10:00
|
|
|
s_JamMsgHeader jmh;
|
|
|
|
|
|
|
|
int max_msg;
|
|
|
|
int active_msgs;
|
|
|
|
int i, j, k;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_area(conference, msgarea);
|
|
|
|
jb = open_jam_base(ma->path);
|
2017-09-21 16:07:31 +10:00
|
|
|
if (!jb) {
|
|
|
|
dolog("Unable to open message base");
|
|
|
|
return;
|
|
|
|
}
|
2018-02-03 11:44:36 +10:00
|
|
|
|
|
|
|
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2018-02-03 11:44:36 +10:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; j < k; i++) {
|
2018-02-03 11:44:36 +10:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
max_msg = i;
|
2018-02-03 11:44:36 +10:00
|
|
|
|
2017-09-21 16:07:31 +10:00
|
|
|
if (JAM_ReadLastRead(jb, gUser->id, &jlr) != JAM_NO_USER) {
|
2018-02-03 11:44:36 +10:00
|
|
|
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));
|
2018-10-08 14:13:11 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-02-03 11:44:36 +10:00
|
|
|
void msgbase_reset_all_pointers(int readm) {
|
2018-10-16 15:05:15 +00:00
|
|
|
for (size_t i = 0; i < ptr_vector_len(&conf.mail_conferences); ++i) {
|
|
|
|
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, i);
|
|
|
|
for (size_t j = 0; j < ptr_vector_len(&mc->mail_areas); ++j)
|
2018-02-03 11:44:36 +10:00
|
|
|
msgbase_reset_pointers(i, j, readm, -1);
|
2017-09-21 16:07:31 +10:00
|
|
|
}
|
|
|
|
}
|
2018-01-25 09:37:22 +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;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_area(conference, area);
|
|
|
|
jb = open_jam_base(ma->path);
|
2018-01-25 09:37:22 +10:00
|
|
|
if (!jb) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2018-01-25 09:37:22 +10:00
|
|
|
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);
|
2018-01-25 09:37:22 +10:00
|
|
|
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-01-25 09:37:22 +10:00
|
|
|
}
|
2018-07-31 10:42:56 +10:00
|
|
|
free_message_headers(msghs);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
|
|
|
} 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) {
|
2018-10-08 14:13:11 +00:00
|
|
|
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-01-25 09:37:22 +10:00
|
|
|
}
|
|
|
|
}
|
2018-07-31 10:42:56 +10:00
|
|
|
free_message_headers(msghs);
|
2018-01-25 09:37:22 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2018-01-25 09:37:22 +10:00
|
|
|
return count;
|
|
|
|
}
|