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

3512 lines
94 KiB
C

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/file.h>
#include <fcntl.h>
#include <libgen.h>
#include "jamlib/jam.h"
#include "lua/lua.h"
#include "lua/lualib.h"
#include "lua/lauxlib.h"
#include "libuuid/uuid.h"
#include "bbs.h"
#include "mail_utils.h"
#ifdef __sun
#include "os/sunos.h"
#endif
extern struct bbs_config conf;
extern struct user_record *gUser;
extern int mynode;
time_t utc_to_local(time_t utc) {
time_t local;
struct tm date_time;
localtime_r(&utc, &date_time);
#ifdef __sun
local = utc + gmtoff(utc);
#else
local = utc + date_time.tm_gmtoff;
#endif
return local;
}
s_JamBase *open_jam_base(char *path) {
int ret;
s_JamBase *jb;
ret = JAM_OpenMB((char *)path, &jb);
if (ret != 0) {
if (ret == JAM_IO_ERROR) {
free(jb);
ret = JAM_CreateMB((char *)path, 1, &jb);
if (ret != 0) {
free(jb);
return NULL;
}
} else {
free(jb);
dolog("Got %d", ret);
return NULL;
}
}
return jb;
}
unsigned long generate_msgid() {
char buffer[1024];
time_t unixtime;
unsigned long msgid;
unsigned long lastid;
FILE *fptr;
snprintf(buffer, 1024, "%s/msgserial", conf.bbs_path);
unixtime = time(NULL);
fptr = fopen(buffer, "r+");
if (fptr) {
flock(fileno(fptr), LOCK_EX);
fread(&lastid, sizeof(unsigned long), 1, fptr);
if (unixtime > lastid) {
lastid = unixtime;
} else {
lastid++;
}
rewind(fptr);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
fptr = fopen(buffer, "w");
if (fptr) {
lastid = unixtime;
flock(fileno(fptr), LOCK_EX);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
lastid = unixtime;
dolog("Unable to open message id log");
}
}
snprintf(buffer, sizeof buffer, "%lX", lastid);
return strtoul(&buffer[strlen(buffer) - 8], NULL, 16);
}
void free_message_headers(struct msg_headers *msghs) {
int i;
for (i = 0; i < msghs->msg_count; i++) {
free(msghs->msgs[i]->msg_h);
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);
free(msghs->msgs[i]);
}
if (msghs->msg_count > 0) {
free(msghs->msgs);
}
free(msghs);
}
int msg_is_to(struct user_record *user, char *addressed_to, char *address, int type, int rn, int msgconf) {
char *myname;
if (rn) {
myname = str3dup(user->firstname, " ", user->lastname);
} else {
myname = strdup(user->loginname);
}
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, msgconf);
assert(mc != NULL);
if (type == NETWORK_FIDO && address != NULL) {
if (strcasecmp(myname, addressed_to) == 0) {
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) {
free(dest);
free(myname);
return 1;
}
free(dest);
}
free(myname);
return 0;
} else if (type == NETWORK_MAGI && address != NULL) {
if (strcasecmp(myname, addressed_to) == 0) {
int magi_dest = atoi(address);
if (magi_dest == mc->maginode) {
free(myname);
return 1;
}
}
free(myname);
return 0;
} else {
if (strcasecmp(myname, addressed_to) == 0) {
free(myname);
return 1;
}
free(myname);
return 0;
}
}
int msg_is_from(struct user_record *user, char *addressed_from, char *address, int type, int rn, int msgconf) {
char *myname;
if (rn) {
myname = str3dup(user->firstname, " ", user->lastname);
} else {
myname = strdup(user->loginname);
}
struct mail_conference *mc = ptr_vector_get(&conf.mail_conferences, msgconf);
assert(mc != NULL);
if (type == NETWORK_FIDO && address != NULL) {
if (strcasecmp(myname, addressed_from) == 0) {
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) {
free(orig);
free(myname);
return 1;
}
free(orig);
}
free(myname);
return 0;
} else if (type == NETWORK_MAGI && address != NULL) {
if (strcasecmp(myname, addressed_from) == 0) {
int magi_orig = atoi(address);
if (magi_orig == mc->maginode) {
free(myname);
return 1;
}
}
free(myname);
return 0;
} else {
if (strcasecmp(myname, addressed_from) == 0) {
free(myname);
return 1;
}
free(myname);
return 0;
}
}
struct msg_headers *read_message_headers(int msgconf, int msgarea, struct user_record *user, int personal) {
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
struct jam_msg *jamm;
struct ptr_vector vec;
int to_us;
int i;
int z;
int j;
int k;
struct fido_addr *dest;
struct msg_headers *msghs = NULL;
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);
jb = open_jam_base(area->path);
if (!jb) {
dolog("Error opening JAM base.. %s", area->path);
return NULL;
}
JAM_ReadMBHeader(jb, &jbh);
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;
}
if (jmh.Attribute & JAM_MSG_DELETED) {
JAM_DelSubPacket(jsp);
continue;
}
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);
}
}
JAM_DelSubPacket(jsp);
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;
}
}
ptr_vector_append(&vec, jamm);
k++;
}
msghs->msg_count = ptr_vector_len(&vec);
msghs->msgs = (struct jam_msg **)consume_ptr_vector(&vec);
JAM_CloseMB(jb);
free(jb);
return msghs;
}
char *external_editor(struct user_record *user, char *to, char *from, char *quote, int qlen, char *qfrom, char *subject, int email, int sig) {
char c;
FILE *fptr;
char *body = NULL;
char buffer[256];
int len;
int totlen;
char *body2 = NULL;
char *tagline;
int i;
int j;
struct stat s;
struct utsname name;
if (conf.external_editor_cmd != NULL && user->exteditor != 0) {
if (user->exteditor == 2) {
s_printf(get_string(85));
c = s_getc();
} else {
c = 'y';
}
if (tolower(c) == 'y') {
snprintf(buffer, sizeof buffer, "%s/node%d", conf.bbs_path, mynode);
if (stat(buffer, &s) != 0) {
mkdir(buffer, 0755);
}
strlcat(buffer, "/MSGTMP", sizeof buffer);
if (stat(buffer, &s) == 0) {
remove(buffer);
}
// write msgtemp
if (quote != NULL) {
fptr = fopen(buffer, "w");
for (i = 0; i < qlen; i++) {
if (quote[i] == '\r') {
fprintf(fptr, "\r\n");
} else if (quote[i] == 0x1) {
continue;
} else if (quote[i] == '\e' && quote[i + 1] == '[') {
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL)
i++;
} else if (quote[i] != '\n') {
fprintf(fptr, "%c", quote[i]);
}
}
fclose(fptr);
}
snprintf(buffer, sizeof buffer, "%s/node%d/MSGINF", conf.bbs_path, mynode);
fptr = fopen(buffer, "w");
fprintf(fptr, "%s\r\n", user->loginname);
if (qfrom != NULL) {
fprintf(fptr, "%s\r\n", qfrom);
} else {
fprintf(fptr, "%s\r\n", to);
}
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 {
if (!sig) {
struct mail_area *area = get_user_area(user);
fprintf(fptr, "%s\r\n", area->name);
if (area->type == TYPE_NETMAIL_AREA) {
fprintf(fptr, "YES\r\n");
} else {
fprintf(fptr, "NO\r\n");
}
} else {
fprintf(fptr, "None\r\n");
fprintf(fptr, "NO\r\n");
}
}
fclose(fptr);
rundoor(user, conf.external_editor_cmd, conf.external_editor_stdio, conf.external_editor_codepage);
// readin msgtmp
snprintf(buffer, sizeof buffer, "%s/node%d/MSGTMP", conf.bbs_path, mynode);
body = file2str(buffer);
if (body == NULL) {
return NULL;
}
totlen = strlen(body);
if (email == 1) {
tagline = conf.default_tagline;
} else {
tagline = conf.default_tagline;
struct mail_conference *mc = get_user_conf(user);
if (mc->tagline != NULL) {
tagline = mc->tagline;
}
}
if (!sig) {
uname(&name);
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",
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
} else {
snprintf(buffer, sizeof buffer, "\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);
}
} else if (mc->nettype == NETWORK_MAGI && !email) {
snprintf(buffer, sizeof buffer, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r",
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
mc->maginode);
} else if (mc->nettype == NETWORK_QWK && !email) {
snprintf(buffer, sizeof buffer, "\r---\r * MagickaBBS * %s\r",
tagline);
} else {
snprintf(buffer, sizeof buffer, "\r");
}
if (user->autosig) {
body2 = (char *)malloz(totlen + 3 + strlen(buffer) + strlen(user->signature));
totlen += strlen(buffer) + strlen(user->signature) + 3;
} else {
body2 = (char *)malloz(totlen + 2 + strlen(buffer));
totlen += strlen(buffer) + 2;
}
} else {
body2 = (char *)malloz(totlen + 1);
}
j = 0;
for (i = 0; i < totlen; i++) {
if (body[i] == '\n') {
continue;
} else if (body[i] == '\0') {
break;
}
body2[j++] = body[i];
body2[j] = '\0';
}
if (!sig) {
if (user->autosig) {
strlcat(body2, "\r", totlen + 1);
strlcat(body2, user->signature, totlen + 1);
}
strlcat(body2, buffer, totlen + 1);
}
free(body);
return body2;
}
}
return editor(user, quote, qlen, qfrom, email, sig);
}
char *editor(struct user_record *user, char *quote, int quotelen, char *from, int email, int sig) {
char buffer[256];
char linebuffer[80];
int doquit = 0;
int i;
char *msg;
int size = 0;
int lineat = 0;
int qfrom, qto;
int z;
char *tagline;
struct utsname name;
char next_line_buffer[80];
struct ptr_vector content;
struct ptr_vector quotecontent;
memset(next_line_buffer, 0, 80);
init_ptr_vector(&quotecontent);
init_ptr_vector(&content);
if (quote != NULL) {
for (i = 0; i < quotelen; i++) {
if (quote[i] == '\r' || lineat == 67) {
char prefix[] = {from[0], '>', '\0'};
ptr_vector_append(&quotecontent, str3dup(prefix, " ", linebuffer));
lineat = 0;
linebuffer[0] = '\0';
if (quote[i] != '\r') {
i--;
}
} else {
if (quote[i] == 27) {
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL)
i++;
continue;
}
linebuffer[lineat++] = quote[i];
linebuffer[lineat] = '\0';
}
}
}
s_printf(get_string(86));
s_printf(get_string(87));
while (!doquit) {
s_printf(get_string(88), ptr_vector_len(&content), "");
strlcpy(linebuffer, next_line_buffer, sizeof(linebuffer));
s_readstring_inject(linebuffer, 70, next_line_buffer);
memset(next_line_buffer, 0, 70);
if (strlen(linebuffer) == 70 && linebuffer[69] != ' ') {
for (i = strlen(linebuffer) - 1; i > 15; i--) {
if (linebuffer[i] == ' ') {
linebuffer[i] = '\0';
strlcpy(next_line_buffer, &linebuffer[i + 1], sizeof next_line_buffer);
s_printf("\e[%dD\e[0K", 70 - i);
break;
}
}
}
if (linebuffer[0] == '/' && strlen(linebuffer) == 2) {
if (toupper(linebuffer[1]) == 'S') {
for (i = 0; i < ptr_vector_len(&content); i++) {
size += strlen(ptr_vector_get(&content, i)) + 1;
}
size++;
tagline = conf.default_tagline;
struct mail_conference *mc = get_user_conf(user);
if (mc->tagline != NULL) {
tagline = mc->tagline;
}
if (!sig) {
uname(&name);
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",
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
} else {
snprintf(buffer, sizeof buffer,
"\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);
}
} else if (mc->nettype == NETWORK_MAGI && !email) {
snprintf(buffer, sizeof buffer,
"\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s (@%d)\r",
VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, tagline,
mc->maginode);
} else if (mc->nettype == NETWORK_QWK && !email) {
snprintf(buffer, sizeof buffer, "\r---\r * MagickaBBS * %s\r",
tagline);
} else {
strlcpy(buffer, "\r", sizeof buffer);
}
if (user->autosig) {
size += 3;
size += strlen(buffer) + strlen(user->signature);
} else {
size += 2;
size += strlen(buffer);
}
} else {
size += 1;
}
msg = (char *)malloz(size);
for (i = 0; i < ptr_vector_len(&content); i++) {
strlcat(msg, ptr_vector_get(&content, i), size);
strlcat(msg, "\r", size);
}
ptr_vector_apply(&content, free);
destroy_ptr_vector(&content);
if (!sig) {
if (user->autosig) {
strlcat(msg, "\r", size);
strlcat(msg, user->signature, size);
}
strlcat(msg, buffer, size);
}
if (quote != NULL) {
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
return msg;
} else if (toupper(linebuffer[1]) == 'A') {
ptr_vector_apply(&content, free);
destroy_ptr_vector(&content);
if (quote != NULL) {
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
return NULL;
} else if (toupper(linebuffer[1]) == 'Q') {
if (quote == NULL) {
s_printf(get_string(89));
} else {
s_printf("\r\n");
for (i = 0; i < ptr_vector_len(&quotecontent); i++) {
s_printf(get_string(88), i, ptr_vector_get(&quotecontent, i));
}
s_printf(get_string(90));
s_readstring(buffer, 5);
qfrom = atoi(buffer);
s_printf(get_string(91));
s_readstring(buffer, 5);
qto = atoi(buffer);
s_printf("\r\n");
if (qto > ptr_vector_len(&quotecontent)) {
qto = ptr_vector_len(&quotecontent);
}
if (qfrom < 0) {
qfrom = 0;
}
if (qfrom > qto) {
s_printf(get_string(92));
}
for (i = qfrom; i <= qto; i++) {
char *copy = strdup(ptr_vector_get(&quotecontent, i));
ptr_vector_append(&content, copy);
}
s_printf(get_string(86));
s_printf(get_string(87));
for (i = 0; i < ptr_vector_len(&content); i++) {
s_printf(get_string(88), i, ptr_vector_get(&content, i));
}
}
} else if (toupper(linebuffer[1]) == 'L') {
s_printf(get_string(86));
s_printf(get_string(87));
for (i = 0; i < ptr_vector_len(&content); i++) {
s_printf(get_string(88), i, ptr_vector_get(&content, i));
}
} else if (linebuffer[1] == '?') {
s_printf(get_string(93));
s_printf(get_string(94));
s_printf(get_string(95));
s_printf(get_string(96));
s_printf(get_string(97));
s_printf(get_string(98));
s_printf(get_string(99));
s_printf(get_string(100));
} else if (toupper(linebuffer[1]) == 'D') {
s_printf(get_string(101));
s_readstring(buffer, 6);
if (strlen(buffer) == 0) {
s_printf(get_string(39));
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
} else {
free(ptr_vector_del(&content, i));
}
}
} else if (toupper(linebuffer[1]) == 'E') {
s_printf(get_string(102));
s_readstring(buffer, 6);
if (strlen(buffer) == 0) {
s_printf(get_string(39));
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
} else {
s_printf(get_string(88), z, ptr_vector_get(&content, z));
s_printf(get_string(103), z);
s_readstring(linebuffer, 70);
free(ptr_vector_get(&content, z));
ptr_vector_put(&content, strdup(linebuffer), z);
}
}
} else if (toupper(linebuffer[1]) == 'I') {
s_printf(get_string(104));
s_readstring(buffer, 6);
if (strlen(buffer) == 0) {
s_printf(get_string(39));
} else {
z = atoi(buffer);
if (z < 0 || z >= ptr_vector_len(&content)) {
s_printf(get_string(39));
} else {
s_printf(get_string(103), z);
s_readstring(linebuffer, 70);
ptr_vector_ins(&content, strdup(linebuffer), z);
}
}
}
} else {
ptr_vector_append(&content, strdup(linebuffer));
}
}
if (quote != NULL) {
ptr_vector_apply(&quotecontent, free);
destroy_ptr_vector(&quotecontent);
}
return NULL;
}
struct character_t {
char c;
int fg;
int bg;
};
void unmangle_ansi(char *body, int len, char **body_out, int *body_len) {
// count lines
int line_count = 1;
int line_at = 1;
int char_at = 1;
int fg = 0x07;
int bg = 0x00;
int state = 0;
int save_char_at = 0;
int save_line_at = 0;
int params[16];
int param_count = 0;
int bold = 0;
stralloc out = EMPTY_STRALLOC;
char buffer[1024];
int buf_at;
int i, j, k;
struct character_t ***fake_screen;
int ansi;
int tab;
line_at = 1;
char_at = 1;
for (i = 0; i < len; i++) {
if (state == 0) {
if (body[i] == 27) {
state = 1;
continue;
} else {
if (body[i] == '\r') {
char_at = 1;
line_at++;
} else if (body[i] == '\t') {
char_at += 8;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
} else {
char_at++;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
}
if (line_at > line_count) {
line_count = line_at;
}
}
} else if (state == 1) {
if (body[i] == '[') {
state = 2;
continue;
} else {
state = 0;
continue;
}
} else if (state == 2) {
param_count = 0;
for (j = 0; j < 16; j++) {
params[j] = 0;
}
state = 3;
}
if (state == 3) {
if (body[i] == ';') {
if (param_count < 15) {
param_count++;
}
continue;
} else if (body[i] >= '0' && body[i] <= '9') {
if (!param_count) param_count = 1;
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
continue;
} else {
state = 4;
}
}
if (state == 4) {
switch (body[i]) {
case 'H':
case 'f':
if (params[0]) params[0]--;
if (params[1]) params[1]--;
line_at = params[0] + 1;
char_at = params[1] + 1;
if (char_at > 80) {
char_at = 80;
}
if (line_at > line_count) {
line_count = line_at;
}
state = 0;
break;
case 'A':
if (param_count > 0) {
line_at = line_at - params[0];
} else {
line_at--;
}
if (line_at < 1) {
line_at = 1;
}
state = 0;
break;
case 'B':
if (param_count > 0) {
line_at = line_at + params[0];
} else {
line_at++;
}
if (line_at > line_count) {
line_count = line_at;
}
state = 0;
break;
case 'C':
if (param_count > 0) {
char_at = char_at + params[0];
} else {
char_at++;
}
if (char_at > 80) {
char_at = 80;
}
state = 0;
break;
case 'D':
if (param_count > 0) {
char_at = char_at - params[0];
} else {
char_at--;
}
if (char_at < 1) {
char_at = 1;
}
state = 0;
break;
case 's':
save_char_at = char_at;
save_line_at = line_at;
state = 0;
break;
case 'u':
char_at = save_char_at;
line_at = save_line_at;
state = 0;
break;
default:
state = 0;
break;
}
}
}
fake_screen = (struct character_t ***)malloz(sizeof(struct character_t **) * line_count);
for (i = 0; i < line_count; i++) {
fake_screen[i] = (struct character_t **)malloz(sizeof(struct character_t *) * 80);
for (j = 0; j < 80; j++) {
fake_screen[i][j] = (struct character_t *)malloz(sizeof(struct character_t));
fake_screen[i][j]->c = ' ';
fake_screen[i][j]->fg = fg;
fake_screen[i][j]->bg = bg;
}
}
line_at = 1;
char_at = 1;
for (i = 0; i < len; i++) {
if (state == 0) {
if (body[i] == 27) {
state = 1;
continue;
} else {
if (body[i] == '\r') {
char_at = 1;
line_at++;
} else if (body[i] == '\t') {
for (tab = 0; tab < 8; tab++) {
if (line_at > line_count) line_at = line_count;
fake_screen[line_at - 1][char_at - 1]->c = ' ';
fake_screen[line_at - 1][char_at - 1]->fg = fg;
fake_screen[line_at - 1][char_at - 1]->bg = bg;
char_at++;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
}
} else {
if (line_at > line_count) line_at = line_count;
fake_screen[line_at - 1][char_at - 1]->c = body[i];
fake_screen[line_at - 1][char_at - 1]->fg = fg;
fake_screen[line_at - 1][char_at - 1]->bg = bg;
char_at++;
while (char_at > 80) {
line_at++;
char_at -= 80;
}
}
}
} else if (state == 1) {
if (body[i] == '[') {
state = 2;
continue;
} else {
state = 0;
continue;
}
} else if (state == 2) {
param_count = 0;
for (j = 0; j < 16; j++) {
params[j] = 0;
}
state = 3;
}
if (state == 3) {
if (body[i] == ';') {
if (param_count < 15) {
param_count++;
}
continue;
} else if (body[i] >= '0' && body[i] <= '9') {
if (!param_count) param_count = 1;
params[param_count - 1] = params[param_count - 1] * 10 + (body[i] - '0');
continue;
} else {
state = 4;
}
}
if (state == 4) {
switch (body[i]) {
case 'H':
case 'f':
if (params[0]) params[0]--;
if (params[1]) params[1]--;
line_at = params[0] + 1;
char_at = params[1] + 1;
state = 0;
break;
case 'A':
if (param_count > 0) {
line_at = line_at - params[0];
} else {
line_at--;
}
if (line_at < 1) {
line_at = 1;
}
state = 0;
break;
case 'B':
if (param_count > 0) {
line_at = line_at + params[0];
} else {
line_at++;
}
if (line_at > line_count) {
line_at = line_count;
}
state = 0;
break;
case 'C':
if (param_count > 0) {
char_at = char_at + params[0];
} else {
char_at++;
}
if (char_at > 80) {
char_at = 80;
}
state = 0;
break;
case 'D':
if (param_count > 0) {
char_at = char_at - params[0];
} else {
char_at--;
}
if (char_at < 1) {
char_at = 1;
}
state = 0;
break;
case 's':
save_char_at = char_at;
save_line_at = line_at;
state = 0;
break;
case 'u':
char_at = save_char_at;
line_at = save_line_at;
state = 0;
break;
case 'm':
for (j = 0; j < param_count; j++) {
switch (params[j]) {
case 0:
fg = 0x07;
bg = 0x00;
bold = 0;
break;
case 1:
bold = 1;
if (fg < 0x08) {
fg += 0x08;
}
break;
case 2:
bold = 0;
if (fg > 0x07) {
fg -= 0x08;
}
break;
case 30:
if (bold) {
fg = 0x08;
} else {
fg = 0x00;
}
break;
case 31:
if (bold) {
fg = 0x0C;
} else {
fg = 0x04;
}
break;
case 32:
if (bold) {
fg = 0x0A;
} else {
fg = 0x02;
}
break;
case 33:
if (bold) {
fg = 0x0E;
} else {
fg = 0x06;
}
break;
case 34:
if (bold) {
fg = 0x09;
} else {
fg = 0x01;
}
break;
case 35:
if (bold) {
fg = 0x0D;
} else {
fg = 0x05;
}
break;
case 36:
if (bold) {
fg = 0x0B;
} else {
fg = 0x03;
}
break;
case 37:
if (bold) {
fg = 0x0F;
} else {
fg = 0x07;
}
break;
case 40:
bg = 0x00;
break;
case 41:
bg = 0x04;
break;
case 42:
bg = 0x02;
break;
case 43:
bg = 0x06;
break;
case 44:
bg = 0x01;
break;
case 45:
bg = 0x05;
break;
case 46:
bg = 0x03;
break;
case 47:
bg = 0x07;
break;
}
}
state = 0;
break;
case 'K':
if (params[0] == 0) {
for (k = char_at - 1; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
} else if (params[0] == 1) {
for (k = 0; k < char_at; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
} else if (params[0] == 2) {
for (k = 0; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
}
state = 0;
break;
case 'J':
if (params[0] == 0) {
for (k = char_at - 1; k < 80; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
for (k = line_at; k < line_count; k++) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
} else if (params[0] == 1) {
for (k = 0; k < char_at; k++) {
fake_screen[line_at - 1][k]->c = ' ';
fake_screen[line_at - 1][k]->fg = fg;
fake_screen[line_at - 1][k]->bg = bg;
}
for (k = line_at - 2; k >= 0; k--) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
} else if (params[0] == 2) {
for (k = 0; k < line_count; k++) {
for (j = 0; j < 80; j++) {
fake_screen[k][j]->c = ' ';
fake_screen[k][j]->fg = fg;
fake_screen[k][j]->bg = bg;
}
}
}
state = 0;
break;
default:
// bad ansi
state = 0;
break;
}
}
}
fg = 0x07;
bg = 0x00;
for (i = 0; i < line_count; i++) {
buf_at = 0;
for (j = 0; j < 79; j++) {
if (fake_screen[i][j]->fg != fg || fake_screen[i][j]->bg != bg) {
buffer[buf_at++] = 27;
buffer[buf_at++] = '[';
fg = fake_screen[i][j]->fg;
if (fg < 0x08) {
buffer[buf_at++] = '0';
buffer[buf_at++] = ';';
buffer[buf_at++] = '3';
switch (fg) {
case 0x00:
buffer[buf_at++] = '0';
break;
case 0x04:
buffer[buf_at++] = '1';
break;
case 0x02:
buffer[buf_at++] = '2';
break;
case 0x06:
buffer[buf_at++] = '3';
break;
case 0x01:
buffer[buf_at++] = '4';
break;
case 0x05:
buffer[buf_at++] = '5';
break;
case 0x03:
buffer[buf_at++] = '6';
break;
case 0x07:
buffer[buf_at++] = '7';
break;
}
} else {
buffer[buf_at++] = '1';
buffer[buf_at++] = ';';
buffer[buf_at++] = '3';
switch (fg) {
case 0x08:
buffer[buf_at++] = '0';
break;
case 0x0C:
buffer[buf_at++] = '1';
break;
case 0x0A:
buffer[buf_at++] = '2';
break;
case 0x0E:
buffer[buf_at++] = '3';
break;
case 0x09:
buffer[buf_at++] = '4';
break;
case 0x0D:
buffer[buf_at++] = '5';
break;
case 0x0B:
buffer[buf_at++] = '6';
break;
case 0x0F:
buffer[buf_at++] = '7';
break;
}
}
bg = fake_screen[i][j]->bg;
buffer[buf_at++] = ';';
buffer[buf_at++] = '4';
switch (bg) {
case 0x00:
buffer[buf_at++] = '0';
break;
case 0x04:
buffer[buf_at++] = '1';
break;
case 0x02:
buffer[buf_at++] = '2';
break;
case 0x06:
buffer[buf_at++] = '3';
break;
case 0x01:
buffer[buf_at++] = '4';
break;
case 0x05:
buffer[buf_at++] = '5';
break;
case 0x03:
buffer[buf_at++] = '6';
break;
case 0x07:
buffer[buf_at++] = '7';
break;
}
buffer[buf_at++] = 'm';
}
buffer[buf_at++] = fake_screen[i][j]->c;
}
while (buf_at > 0 && buffer[buf_at - 1] == ' ') {
buf_at--;
}
buffer[buf_at++] = '\r';
stralloc_catb(&out, buffer, buf_at);
}
for (i = 0; i < line_count; i++) {
for (j = 0; j < 80; j++) {
free(fake_screen[i][j]);
}
free(fake_screen[i]);
}
free(fake_screen);
while (out.s[out.len - 2] == '\r') {
out.len--;
}
*body_out = out.s;
*body_len = out.len;
}
int read_message(struct user_record *user, struct msg_headers *msghs, int mailno, int newscan) {
s_JamBase *jb;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
s_JamSubfield jsf;
s_JamLastRead jlr;
char buffer[256];
char qwkuuid[38];
int z, z2;
struct tm msg_date;
char *subject = NULL;
char *from = NULL;
char *to = NULL;
char *body = NULL;
char *body2 = NULL;
int lines = 0;
char c;
char *replybody;
struct fido_addr *from_addr = NULL;
int i, j;
int doquit = 0;
int skip_line = 0;
int chars = 0;
int ansi;
int sem_fd;
int start_line;
int should_break;
int position;
int y;
uuid_t magi_msgid;
uuid_t qwk_msgid;
struct ptr_vector msg_lines;
init_ptr_vector(&msg_lines);
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 0;
}
while (doquit == 0) {
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.UserCRC = JAM_Crc32(user->loginname, strlen(user->loginname));
jlr.UserID = user->id;
jlr.HighReadMsg = msghs->msgs[mailno]->msg_h->MsgNum;
}
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;
}
struct mail_conference *mc = get_user_conf(user);
if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_FIDO) {
from_addr = parse_fido_addr(msghs->msgs[mailno]->oaddress);
s_printf(get_string(105), msghs->msgs[mailno]->from, from_addr->zone, from_addr->net, from_addr->node, from_addr->point);
free(from_addr);
} else if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_MAGI) {
s_printf(get_string(288), msghs->msgs[mailno]->from, atoi(msghs->msgs[mailno]->oaddress));
} else if (msghs->msgs[mailno]->oaddress != NULL && mc->nettype == NETWORK_QWK) {
s_printf(get_string(289), msghs->msgs[mailno]->from, msghs->msgs[mailno]->oaddress);
} else {
s_printf(get_string(106), msghs->msgs[mailno]->from);
}
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);
gmtime_r((time_t *)&msghs->msgs[mailno]->msg_h->DateWritten, &msg_date);
snprintf(buffer, sizeof buffer, "%s", asctime(&msg_date));
buffer[strlen(buffer) - 1] = '\0';
s_printf(get_string(109), buffer, mailno + 1, msghs->msg_count);
s_printf(get_string(110), (msghs->msgs[mailno]->msg_h->Attribute & JAM_MSG_SENT ? "SENT" : ""),
(msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[mailno]->msg_h->MsgNum) ? "FLAGGED" : ""));
s_printf(get_string(111));
body = (char *)malloz(msghs->msgs[mailno]->msg_h->TxtLen);
JAM_ReadMsgText(jb, msghs->msgs[mailno]->msg_h->TxtOffset, msghs->msgs[mailno]->msg_h->TxtLen, (char *)body);
if (!newscan) {
JAM_WriteLastRead(jb, user->id, &jlr);
}
z2 = msghs->msgs[mailno]->msg_h->TxtLen;
lines = 0;
chars = 0;
body2 = body;
z = z2;
unmangle_ansi(body2, z, &body, &z2);
free(body2);
start_line = 0;
// count the number of lines...
for (z = 0; z < z2; z++) {
if (body[z] == '\r' || chars == 80) {
char *msg_line = (char *)malloz(z - start_line + 1);
ptr_vector_append(&msg_lines, msg_line);
if (z == start_line) {
msg_line[0] = '\0';
} else {
strlcpy(msg_line, &body[start_line], z - start_line + 1);
msg_line[z - start_line] = '\0';
}
if (body[z] == '\r') {
start_line = z + 1;
} else {
start_line = z;
}
chars = 0;
} else {
if (body[z] == 27) {
ansi = z;
while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", body[z]) == NULL)
z++;
if (body[z] == 'm') {
// do nothing
} else {
y = ansi;
for (j = z + 1; j < z2; j++) {
body[y] = body[j];
y++;
}
z2 = z2 - (z2 - y);
z = ansi - 1;
}
} else {
chars++;
}
}
}
lines = 0;
position = 0;
should_break = 0;
while (!should_break) {
s_printf("\e[7;1H");
for (z = position; z < ptr_vector_len(&msg_lines); z++) {
s_printf("%s\e[K\r\n", ptr_vector_get(&msg_lines, z));
if (z - position >= 15) {
break;
}
}
s_printf(get_string(187));
if (newscan) {
s_printf(get_string(234));
} else {
s_printf(get_string(186));
}
c = s_getc();
if (tolower(c) == 'r') {
should_break = 1;
} else if (tolower(c) == 'q') {
should_break = 1;
} else if (tolower(c) == 'j' && newscan == 1) {
should_break = 1;
} else if (tolower(c) == 'f') {
should_break = 1;
} else if (c == '\e') {
c = s_getc();
if (c == 91) {
c = s_getc();
if (c == 65) {
position--;
if (position < 0) {
position = 0;
}
} else if (c == 66) {
position++;
if (position + 15 >= ptr_vector_len(&msg_lines)) {
position--;
}
} else if (c == 67) {
c = ' ';
should_break = 1;
} else if (c == 68) {
c = 'b';
should_break = 1;
}
}
}
}
if (tolower(c) == 'r') {
JAM_CloseMB(jb);
free(jb);
jb = NULL;
struct mail_area *ma = get_user_area(user);
if (user->sec_level < ma->write_sec_level) {
s_printf(get_string(113));
jb = open_jam_base(ma->path);
} else {
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);
}
subject = strdup(buffer);
s_printf(get_string(114));
s_readstring_inject(buffer, 32, msghs->msgs[mailno]->from);
to = strdup(buffer);
if (ma->type == TYPE_LOCAL_AREA && (strcasecmp(to, "all") != 0 && check_user(to) && check_fullname_j(to))) {
s_printf(get_string(55));
free(body);
free(subject);
free(to);
free(from);
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
return 0;
}
s_printf(get_string(115));
s_readstring_inject(buffer, 64, subject);
free(subject);
subject = strdup(buffer);
s_printf("\r\n");
if (msghs->msgs[mailno]->from != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->from, sizeof buffer);
}
struct mail_conference *mc = get_user_conf(user);
if (mc->realnames == 0) {
from = strdup(user->loginname);
} else {
from = str3dup(user->firstname, " ", user->lastname);
}
if (ma->type == TYPE_NEWSGROUP_AREA) {
free(to);
to = strdup("ALL");
}
replybody = external_editor(user, to, from, body, z2, msghs->msgs[mailno]->from, subject, 0, 0);
if (replybody != NULL) {
jb = open_jam_base(ma->path);
if (!jb) {
dolog("Error opening JAM base.. %s", ma->path);
free(replybody);
free(body);
free(subject);
free(to);
free(from);
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
return 0;
}
JAM_ClearMsgHeader(&jmh);
jmh.DateWritten = utc_to_local(time(NULL));
jmh.Attribute |= JAM_MSG_LOCAL;
jsp = JAM_NewSubPacket();
jsf.LoID = JAMSFLD_SENDERNAME;
jsf.HiID = 0;
jsf.DatLen = strlen(from);
jsf.Buffer = (char *)from;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_RECVRNAME;
jsf.HiID = 0;
jsf.DatLen = strlen(to);
jsf.Buffer = (char *)to;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_SUBJECT;
jsf.HiID = 0;
jsf.DatLen = strlen(subject);
jsf.Buffer = (char *)subject;
JAM_PutSubfield(jsp, &jsf);
if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
jmh.Attribute |= JAM_MSG_TYPEECHO;
if (mc->nettype == NETWORK_FIDO) {
if (mc->fidoaddr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
mc->fidoaddr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
mc->fidoaddr->zone,
mc->fidoaddr->net,
mc->fidoaddr->node,
mc->fidoaddr->point,
generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
if (msghs->msgs[mailno]->msgid != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
}
} else if (mc->nettype == NETWORK_MAGI) {
snprintf(buffer, sizeof buffer, "%d", mc->maginode);
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
uuid_generate(magi_msgid);
uuid_unparse_lower(magi_msgid, buffer);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
if (msghs->msgs[mailno]->msgid != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
}
} else if (mc->nettype == NETWORK_QWK) {
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(conf.bwave_name);
jsf.Buffer = (char *)conf.bwave_name;
JAM_PutSubfield(jsp, &jsf);
if (conf.external_address != NULL) {
uuid_generate(qwk_msgid);
uuid_unparse_lower(qwk_msgid, qwkuuid);
snprintf(buffer, sizeof buffer, "<%s@%s>", qwkuuid, conf.external_address);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
if (msghs->msgs[mailno]->msgid != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
}
}
}
} else if (ma->type == TYPE_NETMAIL_AREA) {
jmh.Attribute |= JAM_MSG_TYPENET;
jmh.Attribute |= JAM_MSG_PRIVATE;
if (mc->nettype == NETWORK_FIDO) {
if (mc->fidoaddr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
mc->fidoaddr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
from_addr = parse_fido_addr(msghs->msgs[mailno]->oaddress);
if (from_addr != NULL) {
if (from_addr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
from_addr->zone, from_addr->net, from_addr->node,
from_addr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
from_addr->zone, from_addr->net, from_addr->node);
}
jsf.LoID = JAMSFLD_DADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
free(from_addr);
}
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
mc->fidoaddr->zone,
mc->fidoaddr->net,
mc->fidoaddr->node,
mc->fidoaddr->point,
generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
if (msghs->msgs[mailno]->msgid != NULL) {
strlcpy(buffer, msghs->msgs[mailno]->msgid, sizeof buffer);
jsf.LoID = JAMSFLD_REPLYID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.ReplyCRC = JAM_Crc32(buffer, strlen(buffer));
}
}
}
while (1) {
z = JAM_LockMB(jb, 100);
if (z == 0) {
break;
} else if (z == JAM_LOCK_FAILED) {
sleep(1);
} else {
free(replybody);
free(body);
free(subject);
free(to);
free(from);
dolog("Failed to lock msg base!");
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
return 0;
}
}
if (JAM_AddMessage(jb, &jmh, jsp, (char *)replybody, strlen(replybody))) {
dolog("Failed to add message");
} else {
if (ma->type == TYPE_NETMAIL_AREA) {
if (conf.netmail_sem != NULL) {
sem_fd = open(conf.netmail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
close(sem_fd);
}
} else if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
if (conf.echomail_sem != NULL) {
sem_fd = open(conf.echomail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
close(sem_fd);
}
}
}
JAM_UnlockMB(jb);
JAM_DelSubPacket(jsp);
free(replybody);
// JAM_CloseMB(jb);
// doquit = 1;
} else {
jb = open_jam_base(ma->path);
}
}
free(body);
free(from);
free(to);
free(subject);
} else if (tolower(c) == 'j' && newscan == 1) {
free(body);
doquit = 1;
} else if (tolower(c) == 'q') {
free(body);
doquit = 2;
} else if (c == ' ') {
mailno++;
if (mailno >= msghs->msg_count) {
s_printf(get_string(118));
doquit = 1;
}
free(body);
} else if (tolower(c) == 'b') {
if (mailno > 0) {
mailno--;
}
free(body);
} else if (tolower(c) == 'f') {
msgbase_flag_unflag(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[mailno]->msg_h->MsgNum);
free(body);
} else {
free(body);
}
ptr_vector_apply(&msg_lines, free);
destroy_ptr_vector(&msg_lines);
}
if (jb != NULL)
JAM_CloseMB(jb);
free(jb);
if (doquit == 2) {
return 1;
}
return 0;
}
int read_new_msgs(struct user_record *user, struct msg_headers *msghs) {
s_JamBase *jb;
s_JamLastRead jlr;
int all_unread;
int i;
int k;
char buffer[7];
int res;
// list mail in message base
if (msghs != NULL && msghs->msg_count > 0) {
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 0;
} else {
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
}
if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
all_unread = 1;
}
JAM_CloseMB(jb);
free(jb);
if (all_unread == 0) {
k = jlr.HighReadMsg;
for (i = 0; i < msghs->msg_count; i++) {
if (msghs->msgs[i]->msg_h->MsgNum == k) {
i += 2;
break;
}
if (msghs->msgs[i]->msg_h->MsgNum > k) {
i++;
break;
}
}
} else {
i = 1;
}
if (i > 0 && i <= msghs->msg_count) {
res = read_message(user, msghs, i - 1, 1);
s_printf("\r\n");
return res;
}
}
}
return 0;
}
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
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
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);
s_readstring(buffer, 6);
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;
}
}
i += 2;
} else {
i = 1;
}
} else {
i = atoi(buffer);
}
if (i > 0 && i <= msghs->msg_count) {
read_message(user, msghs, i - 1, 0);
}
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];
char qwkuuid[38];
int z;
int sem_fd;
char *bbsname;
uuid_t magi_msgid;
uuid_t qwk_msgid;
s_JamBase *jb;
s_JamMsgHeader jmh;
s_JamSubPacket *jsp;
s_JamSubfield jsf;
s_JamLastRead jlr;
struct mail_area *ma = get_user_area(user);
if (user->sec_level < ma->write_sec_level) {
s_printf(get_string(113));
return;
}
if (ma->type == TYPE_NEWSGROUP_AREA) {
strlcpy(buffer, "ALL", sizeof buffer);
} else {
s_printf(get_string(54));
s_readstring(buffer, 32);
}
if (strlen(buffer) == 0) {
strlcpy(buffer, "ALL", sizeof(buffer));
}
if (ma->type == TYPE_LOCAL_AREA && (strcasecmp(buffer, "all") != 0 && check_user(buffer) && check_fullname_j(buffer))) {
s_printf(get_string(55));
return;
}
if (ma->type == TYPE_NETMAIL_AREA) {
s_printf(get_string(121));
s_readstring(buffer2, 32);
struct mail_conference *mc = get_user_conf(user);
if (mc->nettype == NETWORK_FIDO) {
from_addr = parse_fido_addr(buffer2);
if (!from_addr) {
s_printf(get_string(122));
return;
} else {
if (from_addr->zone == 0 && from_addr->net == 0 && from_addr->node == 0 && from_addr->point == 0) {
free(from_addr);
s_printf(get_string(122));
return;
}
// 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);
} else {
bbsname = strdup("Unknown");
}
s_printf(get_string(123), from_addr->zone, from_addr->net, from_addr->node, from_addr->point, bbsname);
free(bbsname);
}
}
}
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
struct mail_conference *mc = get_user_conf(user);
if (mc->realnames == 0) {
from = strdup(user->loginname);
} else {
from = str3dup(user->firstname, " ", user->lastname);
}
msg = external_editor(user, to, from, NULL, 0, NULL, subject, 0, 0);
free(from);
if (msg != NULL) {
jb = open_jam_base(ma->path);
if (!jb) {
dolog("Error opening JAM base.. %s", ma->path);
free(msg);
free(to);
free(subject);
return;
}
JAM_ClearMsgHeader(&jmh);
jmh.DateWritten = (uint32_t)utc_to_local(time(NULL));
jmh.Attribute |= JAM_MSG_LOCAL;
if (mc->realnames == 0) {
strlcpy(buffer, user->loginname, sizeof(buffer));
} else {
snprintf(buffer, sizeof buffer, "%s %s", user->firstname, user->lastname);
}
jsp = JAM_NewSubPacket();
jsf.LoID = JAMSFLD_SENDERNAME;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_RECVRNAME;
jsf.HiID = 0;
jsf.DatLen = strlen(to);
jsf.Buffer = (char *)to;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_SUBJECT;
jsf.HiID = 0;
jsf.DatLen = strlen(subject);
jsf.Buffer = (char *)subject;
JAM_PutSubfield(jsp, &jsf);
if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
jmh.Attribute |= JAM_MSG_TYPEECHO;
if (mc->nettype == NETWORK_FIDO) {
if (mc->fidoaddr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
mc->fidoaddr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
mc->fidoaddr->point, generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
} else if (mc->nettype == NETWORK_MAGI) {
snprintf(buffer, sizeof buffer, "%d", mc->maginode);
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
uuid_generate(magi_msgid);
uuid_unparse_lower(magi_msgid, buffer);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
} else if (mc->nettype == NETWORK_QWK) {
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(conf.bwave_name);
jsf.Buffer = (char *)conf.bwave_name;
JAM_PutSubfield(jsp, &jsf);
if (conf.external_address != NULL) {
uuid_generate(qwk_msgid);
uuid_unparse_lower(qwk_msgid, qwkuuid);
snprintf(buffer, sizeof buffer, "<%s@%s>", qwkuuid, conf.external_address);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
}
}
} else if (ma->type == TYPE_NETMAIL_AREA) {
jmh.Attribute |= JAM_MSG_TYPENET;
jmh.Attribute |= JAM_MSG_PRIVATE;
if (mc->nettype == NETWORK_FIDO) {
if (mc->fidoaddr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node,
mc->fidoaddr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
if (from_addr != NULL) {
if (from_addr->point) {
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
from_addr->zone, from_addr->net, from_addr->node,
from_addr->point);
} else {
snprintf(buffer, sizeof buffer, "%d:%d/%d",
from_addr->zone, from_addr->net, from_addr->node);
}
jsf.LoID = JAMSFLD_DADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
free(from_addr);
from_addr = NULL;
}
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d %08lx",
mc->fidoaddr->zone,
mc->fidoaddr->net,
mc->fidoaddr->node,
mc->fidoaddr->point,
generate_msgid());
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
jmh.MsgIdCRC = JAM_Crc32(buffer, strlen(buffer));
}
}
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);
free(jb);
return;
}
if (JAM_AddMessage(jb, &jmh, jsp, (char *)msg, strlen(msg))) {
dolog("Failed to add message");
} else {
if (ma->type == TYPE_NETMAIL_AREA) {
if (conf.netmail_sem != NULL) {
sem_fd = open(conf.netmail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
close(sem_fd);
}
} else if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
if (conf.echomail_sem != NULL) {
sem_fd = open(conf.echomail_sem, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
close(sem_fd);
}
}
}
JAM_UnlockMB(jb);
JAM_DelSubPacket(jsp);
free(msg);
JAM_CloseMB(jb);
free(jb);
}
free(to);
free(subject);
}
void list_messages(struct user_record *user) {
struct msg_headers *msghs;
s_JamBase *jb;
int all_unread;
s_JamLastRead jlr;
char buffer[256];
int i;
int k;
int j;
int start;
int closed;
int redraw;
struct tm msg_date;
char c;
int offset = 2;
int height = 22;
struct mail_conference *gmc = get_conf(gUser->cur_mail_conf);
if (gmc->header != NULL) {
offset = 8;
height = 16;
}
struct mail_conference *mc = get_user_conf(user);
s_printf("\r\n");
// list mail in message base
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
if (msghs != NULL && msghs->msg_count > 0) {
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;
} else {
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(125), msghs->msg_count);
s_readstring(buffer, 6);
if (tolower(buffer[0]) == 'n') {
if (all_unread == 0) {
k = jlr.HighReadMsg;
for (i = 0; i < msghs->msg_count; i++) {
if (msghs->msgs[i]->msg_h->MsgNum == k) {
break;
}
}
if (i == msghs->msg_count - 1) {
i = 1;
} else {
i += 2;
}
} else {
i = 1;
}
} else {
i = atoi(buffer);
if (i <= 0) {
i = 1;
}
}
closed = 0;
redraw = 1;
start = i - 1;
while (!closed) {
if (redraw) {
if (mc->header != NULL) {
s_printf("\e[2J\e[1;1H");
s_displayansi(mc->header);
s_printf("\e[7;1H");
} else {
s_printf("\e[2J\e[1;1H");
}
s_printf(get_string(126));
for (j = start; j < start + height && j < msghs->msg_count; j++) {
gmtime_r((time_t *)&msghs->msgs[j]->msg_h->DateWritten, &msg_date);
if (j == i - 1) {
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);
}
} else if (msghs->msgs[j]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
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);
}
} else {
if (conf.date_style == 1) {
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);
}
}
} else {
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);
}
} else if (msghs->msgs[j]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
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);
}
} else {
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);
}
}
}
}
s_printf(get_string(190));
s_printf("\e[%d;5H", i - start + offset - 1);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
closed = 1;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
i++;
if (i > start + height) {
start += height;
if (start > msghs->msg_count) {
start = msghs->msg_count - height;
}
redraw = 1;
}
if (i - 1 == msghs->msg_count) {
i--;
s_printf("\e[%d;5H", i - start + offset - 1);
} else if (!redraw) {
s_printf("\e[%d;1H", i - start + offset - 2);
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)) {
if (conf.date_style == 1) {
s_printf(get_string(287), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(287), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 2]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
if (conf.date_style == 1) {
s_printf(get_string(127), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(127), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else {
if (conf.date_style == 1) {
s_printf(get_string(128), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(128), i - 1, msghs->msgs[i - 2]->subject, msghs->msgs[i - 2]->from, msghs->msgs[i - 2]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
}
s_printf("\e[%d;1H", i - start + offset - 1);
gmtime_r((time_t *)&msghs->msgs[i - 1]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 1]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
if (conf.date_style == 1) {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else {
if (conf.date_style == 1) {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
}
s_printf("\e[%d;5H", i - start + offset - 1);
}
} else if (c == 65) {
// up
i--;
if (i - 1 < start) {
start -= height;
if (start < 0) {
start = 0;
}
redraw = 1;
}
if (i <= 1) {
start = 0;
i = 1;
redraw = 1;
} else if (!redraw) {
s_printf("\e[%d;1H", i - start + offset);
gmtime_r((time_t *)&msghs->msgs[i]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
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);
} else {
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);
}
} else if (msghs->msgs[i]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
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);
}
} else {
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);
}
}
s_printf("\e[%d;1H", i - start + offset - 1);
gmtime_r((time_t *)&msghs->msgs[i - 1]->msg_h->DateWritten, &msg_date);
if (msgbase_is_flagged(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum)) {
if (conf.date_style == 1) {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(286), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else if (msghs->msgs[i - 1]->msg_h->MsgNum > jlr.HighReadMsg || all_unread) {
if (conf.date_style == 1) {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(188), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
} else {
if (conf.date_style == 1) {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100);
} else {
s_printf(get_string(189), i, msghs->msgs[i - 1]->subject, msghs->msgs[i - 1]->from, msghs->msgs[i - 1]->to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100);
}
}
s_printf("\e[%d;5H", i - start + offset - 1);
}
} else if (c == 75) {
// END KEY
i = msghs->msg_count;
start = i - height;
if (start < 0) {
start = 0;
}
redraw = 1;
} else if (c == 72) {
// HOME KEY
i = 1;
start = 0;
redraw = 1;
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
i = i - height;
if (i <= 0) {
i = 1;
}
start = i - 1;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
i = i + height;
if (i > msghs->msg_count) {
i = msghs->msg_count;
}
start = i - 1;
redraw = 1;
}
}
} else if (c == 13) {
redraw = 1;
read_message(user, msghs, i - 1, 0);
free_message_headers(msghs);
msghs = read_message_headers(user->cur_mail_conf, user->cur_mail_area, user, 0);
struct mail_area *ma = get_user_area(user);
jb = open_jam_base(ma->path);
if (!jb) {
dolog("Error opening JAM base.. %s", ma->path);
if (msghs != NULL) {
free_message_headers(msghs);
}
return;
} else {
all_unread = 0;
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
jlr.LastReadMsg = 0;
jlr.HighReadMsg = 0;
all_unread = 1;
}
JAM_CloseMB(jb);
free(jb);
}
} else if (tolower(c) == 'f') {
redraw = 1;
msgbase_flag_unflag(user, user->cur_mail_conf, user->cur_mail_area, msghs->msgs[i - 1]->msg_h->MsgNum);
}
}
}
if (msghs != NULL) {
free_message_headers(msghs);
}
} else {
s_printf(get_string(130));
}
}
struct conf_tmp_t {
struct mail_conference *conference;
int index;
};
void choose_conference() {
int i;
int list_tmp = 0;
struct conf_tmp_t **conf_tmp;
int redraw = 1;
int start = 0;
int selected = 0;
char c;
struct ptr_vector vec;
init_ptr_vector(&vec);
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) {
struct conf_tmp_t *c = (struct conf_tmp_t *)malloz(sizeof(struct conf_tmp_t));
c->conference = mc;
c->index = i;
ptr_vector_append(&vec, c);
}
}
list_tmp = ptr_vector_len(&vec);
conf_tmp = (struct conf_tmp_t **)consume_ptr_vector(&vec);
while (1) {
if (redraw) {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(247));
s_printf(get_string(248));
for (i = start; i < start + 22 && i < list_tmp; i++) {
if (i == selected) {
s_printf(get_string(249), i - start + 2, conf_tmp[i]->index, conf_tmp[i]->conference->name);
} else {
s_printf(get_string(250), i - start + 2, conf_tmp[i]->index, conf_tmp[i]->conference->name);
}
}
s_printf("\e[%d;5H", selected - start + 2);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
break;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
if (selected + 1 >= start + 22) {
start += 22;
if (start >= list_tmp) {
start = list_tmp - 22;
}
redraw = 1;
}
selected++;
if (selected >= list_tmp) {
selected = list_tmp - 1;
} else {
if (!redraw) {
s_printf(get_string(250), selected - start + 1, conf_tmp[selected - 1]->index, conf_tmp[selected - 1]->conference->name);
s_printf(get_string(249), selected - start + 2, conf_tmp[selected]->index, conf_tmp[selected]->conference->name);
s_printf("\e[%d;5H", selected - start + 2);
}
}
} else if (c == 65) {
// up
if (selected - 1 < start) {
start -= 22;
if (start < 0) {
start = 0;
}
redraw = 1;
}
selected--;
if (selected < 0) {
selected = 0;
} else {
if (!redraw) {
s_printf(get_string(249), selected - start + 2, conf_tmp[selected]->index, conf_tmp[selected]->conference->name);
s_printf(get_string(250), selected - start + 3, conf_tmp[selected + 1]->index, conf_tmp[selected + 1]->conference->name);
s_printf("\e[%d;5H", selected - start + 2);
}
}
} else if (c == 75) {
// END KEY
selected = list_tmp - 1;
start = list_tmp - 22;
if (start < 0) {
start = 0;
}
redraw = 1;
} else if (c == 72) {
// HOME KEY
selected = 0;
start = 0;
redraw = 1;
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
selected = selected - 22;
if (selected < 0) {
selected = 0;
}
start = selected;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
selected = selected + 22;
if (selected >= list_tmp) {
selected = list_tmp - 1;
}
start = selected;
redraw = 1;
}
}
} else if (c == 13) {
gUser->cur_mail_conf = conf_tmp[selected]->index;
gUser->cur_mail_area = 0;
break;
}
}
for (i = 0; i < list_tmp; i++) {
free(conf_tmp[i]);
}
free(conf_tmp);
}
struct area_tmp_t {
struct mail_area *area;
int index;
};
void choose_area() {
int i;
int list_tmp = 0;
struct area_tmp_t **area_tmp;
int redraw = 1;
int start = 0;
int selected = 0;
char c;
int offset = 2;
int height = 22;
struct ptr_vector vec;
struct mail_conference *gmc = get_user_conf(gUser);
if (gmc->header != NULL) {
offset = 8;
height = 16;
}
init_ptr_vector(&vec);
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) {
struct area_tmp_t *area = (struct area_tmp_t *)malloz(sizeof(struct area_tmp_t));
area->area = ma;
area->index = i;
ptr_vector_append(&vec, area);
}
}
list_tmp = ptr_vector_len(&vec);
area_tmp = (struct area_tmp_t **)consume_ptr_vector(&vec);
while (1) {
if (redraw) {
struct mail_conference *gmc = get_user_conf(gUser);
if (gmc->header != NULL) {
s_printf("\e[2J\e[1;1H");
s_displayansi(gmc->header);
s_printf("\e[7;1H");
} else {
s_printf("\e[2J\e[1;1H");
}
s_printf(get_string(251), gmc->name);
s_printf(get_string(248));
for (i = start; i < start + height && i < list_tmp; i++) {
if (i == selected) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
s_printf(get_string(259), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
} else {
s_printf(get_string(249), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
}
} else {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) {
s_printf(get_string(260), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
} else {
s_printf(get_string(250), i - start + offset, area_tmp[i]->index, area_tmp[i]->area->name);
}
}
}
s_printf("\e[%d;5H", selected - start + offset);
redraw = 0;
}
c = s_getchar();
if (tolower(c) == 'q') {
break;
} else if (c == 27) {
c = s_getchar();
if (c == 91) {
c = s_getchar();
if (c == 66) {
// down
if (selected + 1 >= start + height) {
start += height;
if (start >= list_tmp) {
start = list_tmp - height;
}
redraw = 1;
}
selected++;
if (selected >= list_tmp) {
selected = list_tmp - 1;
} else {
if (!redraw) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected - 1]->index)) {
s_printf(get_string(260), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
} else {
s_printf(get_string(250), selected - start + (offset - 1), area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name);
}
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
} else {
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
}
s_printf("\e[%d;5H", selected - start + offset);
}
}
} else if (c == 65) {
// up
if (selected - 1 < start) {
start -= height;
if (start < 0) {
start = 0;
}
redraw = 1;
}
selected--;
if (selected < 0) {
selected = 0;
} else {
if (!redraw) {
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) {
s_printf(get_string(259), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
} else {
s_printf(get_string(249), selected - start + offset, area_tmp[selected]->index, area_tmp[selected]->area->name);
}
if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected + 1]->index)) {
s_printf(get_string(260), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
} else {
s_printf(get_string(250), selected - start + (offset + 1), area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name);
}
s_printf("\e[%d;5H", selected - start + offset);
}
}
} else if (c == 75) {
// END KEY
selected = list_tmp - 1;
start = list_tmp - height;
if (start < 0) {
start = 0;
}
redraw = 1;
} else if (c == 72) {
// HOME KEY
selected = 0;
start = 0;
redraw = 1;
} else if (c == 86 || c == '5') {
if (c == '5') {
s_getchar();
}
// PAGE UP
selected = selected - height;
if (selected < 0) {
selected = 0;
}
start = selected;
redraw = 1;
} else if (c == 85 || c == '6') {
if (c == '6') {
s_getchar();
}
// PAGE DOWN
selected = selected + height;
if (selected >= list_tmp) {
selected = list_tmp - 1;
}
start = selected;
redraw = 1;
}
}
} else if (c == 13) {
gUser->cur_mail_area = area_tmp[selected]->index;
break;
}
}
for (i = 0; i < list_tmp; i++) {
free(area_tmp[i]);
}
free(area_tmp);
}
void next_mail_conf(struct user_record *user) {
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) {
break;
}
}
user->cur_mail_conf = i;
user->cur_mail_area = 0;
}
void prev_mail_conf(struct user_record *user) {
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) {
break;
}
}
user->cur_mail_conf = i;
user->cur_mail_area = 0;
}
void next_mail_area(struct user_record *user) {
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;
break;
}
}
}
void prev_mail_area(struct user_record *user) {
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;
break;
}
}
}
void do_mail_scan(struct user_record *user, int oldscan, int personal) {
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamLastRead jlr;
struct msg_headers *msghs;
char c;
int i;
int j;
int lines = 0;
int orig_conf;
int orig_area;
int res = 0;
char ch;
int unread_count;
int k;
if (personal) {
s_printf(get_string(276));
} else {
s_printf(get_string(139));
}
c = s_getc();
if (tolower(c) == 'y' || tolower(c) == 's') {
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) {
continue;
}
if (oldscan) {
s_printf(get_string(140), i, mc->name);
lines += 2;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
}
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) {
continue;
}
if (tolower(c) == 's' && !msgbase_is_subscribed(i, j)) {
continue;
}
jb = open_jam_base(ma->path);
if (!jb) {
dolog("Unable to open message base");
continue;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
free(jb);
continue;
}
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
if (jbh.ActiveMsgs == 0) {
JAM_CloseMB(jb);
free(jb);
continue;
}
if (ma->type == TYPE_NETMAIL_AREA) {
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
if (oldscan) {
s_printf(get_string(141), j, ma->name, msghs->msg_count);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, mc->name);
s_printf(get_string(278), j, ma->name, msghs->msg_count);
s_printf(get_string(279));
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
user->cur_mail_conf = i;
user->cur_mail_area = j;
res = read_new_msgs(user, msghs);
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
}
free_message_headers(msghs);
}
} else {
if (oldscan) {
s_printf(get_string(141), j, ma->name, jbh.ActiveMsgs);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, mc->name);
s_printf(get_string(278), j, ma->name, msghs->msg_count);
s_printf(get_string(279));
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
user->cur_mail_conf = i;
user->cur_mail_area = j;
res = read_new_msgs(user, msghs);
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
free_message_headers(msghs);
}
}
}
} else {
if (jlr.HighReadMsg < jbh.ActiveMsgs) {
if (ma->type == TYPE_NETMAIL_AREA) {
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
unread_count = 0;
for (k = msghs->msg_count - 1; k >= 0; k--) {
if (msghs->msgs[k]->msg_no < jlr.HighReadMsg) {
break;
}
unread_count++;
}
if (unread_count > 0) {
if (oldscan) {
s_printf(get_string(141), j, ma->name, unread_count);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, mc->name);
s_printf(get_string(278), j, ma->name, unread_count);
s_printf(get_string(279));
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
user->cur_mail_conf = i;
user->cur_mail_area = j;
res = read_new_msgs(user, msghs);
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
}
}
free_message_headers(msghs);
}
} else {
if (oldscan) {
s_printf(get_string(141), j, ma->name, jbh.ActiveMsgs - jlr.HighReadMsg);
lines++;
if (lines == 22) {
s_printf(get_string(6));
s_getc();
lines = 0;
}
} else {
msghs = read_message_headers(i, j, user, personal);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
unread_count = 0;
for (k = msghs->msg_count - 1; k >= 0; k--) {
if (msghs->msgs[k]->msg_no < jlr.HighReadMsg) {
break;
}
unread_count++;
}
if (unread_count > 0) {
s_printf("\e[2J\e[1;1H");
s_printf(get_string(277), i, mc->name);
s_printf(get_string(278), j, ma->name, unread_count);
s_printf(get_string(279));
ch = s_getchar();
s_printf("\r\n");
if (tolower(ch) == 'y') {
orig_conf = user->cur_mail_conf;
orig_area = user->cur_mail_area;
user->cur_mail_conf = i;
user->cur_mail_area = j;
res = read_new_msgs(user, msghs);
user->cur_mail_conf = orig_conf;
user->cur_mail_area = orig_area;
}
}
}
free_message_headers(msghs);
}
}
}
} else {
JAM_CloseMB(jb);
free(jb);
continue;
}
}
JAM_CloseMB(jb);
free(jb);
if (res) {
break;
}
}
if (res) {
break;
}
}
s_printf(get_string(6));
s_getc();
}
}
void full_mail_scan_personal(struct user_record *user) {
do_mail_scan(user, 0, 1);
}
void full_mail_scan(struct user_record *user) {
do_mail_scan(user, 0, 0);
}
void mail_scan(struct user_record *user) {
do_mail_scan(user, 1, 0);
}
void msg_conf_sub_bases() {
int i;
int lines = 0;
char buffer[10];
int toggle_area;
int done = 0;
int j;
s_printf("\e[1;1H\e[2J");
do {
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);
lines++;
}
if (lines == 23) {
s_printf(get_string(225));
s_readstring(buffer, 9);
s_printf("\r\n");
if (strlen(buffer) > 0) {
if (buffer[0] >= '0' && buffer[0] <= '9') {
toggle_area = atoi(buffer);
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, toggle_area);
if (ma->read_sec_level <= gUser->sec_level) {
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
}
lines = 0;
break;
}
if (buffer[0] == 'a' || buffer[0] == 'A') {
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) {
if (!msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
break;
}
if (buffer[0] == 'n' || buffer[0] == 'N') {
for (j = 0; j < 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) {
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
break;
}
}
lines = 0;
}
}
if (lines > 0) {
s_printf(get_string(225));
s_readstring(buffer, 9);
s_printf("\r\n");
if (strlen(buffer) > 0) {
if (buffer[0] >= '0' && buffer[0] <= '9') {
toggle_area = atoi(buffer);
struct mail_area *ma = ptr_vector_get(&gmc->mail_areas, toggle_area);
if (ma->read_sec_level <= gUser->sec_level) {
msgbase_sub_unsub(gUser->cur_mail_conf, toggle_area);
}
lines = 0;
} else if (buffer[0] == 'a' || buffer[0] == 'A') {
for (j = 0; j < 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) {
if (!msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
} else if (buffer[0] == 'n' || buffer[0] == 'N') {
for (j = 0; j < 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) {
if (msgbase_is_subscribed(gUser->cur_mail_conf, j)) {
msgbase_sub_unsub(gUser->cur_mail_conf, j);
}
}
}
} else {
done = 1;
}
} else {
done = 1;
}
} else {
done = 1;
}
} while (!done);
}
void msgbase_reset_pointers(int conference, int msgarea, int readm, int msgno) {
s_JamBase *jb;
s_JamBaseHeader jbh;
s_JamLastRead jlr;
s_JamMsgHeader jmh;
int max_msg;
int active_msgs;
int i, j, k;
struct mail_area *ma = get_area(conference, msgarea);
jb = open_jam_base(ma->path);
if (!jb) {
dolog("Unable to open message base");
return;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
free(jb);
return;
}
j = 0;
if (msgno == -1 && readm) {
k = jbh.ActiveMsgs;
} else if (msgno == -1 && !readm) {
k = 0;
} else {
if (msgno > jbh.ActiveMsgs) {
k = jbh.ActiveMsgs;
} else {
k = msgno;
}
}
for (i = 0; j < k; i++) {
memset(&jmh, 0, sizeof(s_JamMsgHeader));
if (JAM_ReadMsgHeader(jb, i, &jmh, NULL) != 0) {
dolog("Failed to read msg header: Erro %d", JAM_Errno(jb));
return;
}
if (jmh.Attribute & JAM_MSG_DELETED) {
continue;
}
j++;
}
max_msg = i;
if (JAM_ReadLastRead(jb, gUser->id, &jlr) != JAM_NO_USER) {
jlr.LastReadMsg = max_msg;
jlr.HighReadMsg = max_msg;
JAM_WriteLastRead(jb, gUser->id, &jlr);
} else {
jlr.LastReadMsg = max_msg;
jlr.HighReadMsg = max_msg;
jlr.UserCRC = JAM_Crc32(gUser->loginname, strlen(gUser->loginname));
jlr.UserID = gUser->id;
JAM_WriteLastRead(jb, gUser->id, &jlr);
}
JAM_CloseMB(jb);
free(jb);
}
void msgbase_reset_all_pointers(int readm) {
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)
msgbase_reset_pointers(i, j, readm, -1);
}
}
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;
struct mail_area *ma = get_area(conference, area);
jb = open_jam_base(ma->path);
if (!jb) {
return 0;
}
if (JAM_ReadMBHeader(jb, &jbh) != 0) {
JAM_CloseMB(jb);
free(jb);
return 0;
}
if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) {
if (jbh.ActiveMsgs == 0) {
JAM_CloseMB(jb);
free(jb);
return 0;
}
msghs = read_message_headers(conference, area, user, 0);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
count = msghs->msg_count;
}
free_message_headers(msghs);
}
} else {
msghs = read_message_headers(conference, area, user, 0);
if (msghs != NULL) {
if (msghs->msg_count > 0) {
if (msghs->msgs[msghs->msg_count - 1]->msg_h->MsgNum > jlr.HighReadMsg) {
count = msghs->msgs[msghs->msg_count - 1]->msg_h->MsgNum - jlr.HighReadMsg;
}
}
free_message_headers(msghs);
}
}
JAM_CloseMB(jb);
free(jb);
return count;
}