2016-12-06 17:06:28 +10:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <fcntl.h>
|
2018-01-08 08:54:03 +10:00
|
|
|
#include <sqlite3.h>
|
2018-10-09 15:55:15 +00:00
|
|
|
#include <sys/wait.h>
|
2018-10-16 15:05:15 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
#include "jamlib/jam.h"
|
2018-05-22 21:02:22 +10:00
|
|
|
#include "libuuid/uuid.h"
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
#include "bluewave.h"
|
|
|
|
#include "bbs.h"
|
|
|
|
#include "mail_utils.h"
|
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
extern struct bbs_config conf;
|
|
|
|
extern struct user_record *gUser;
|
|
|
|
extern int mynode;
|
|
|
|
extern char upload_filename[1024];
|
|
|
|
extern int sshBBS;
|
2016-12-11 22:14:36 +10:00
|
|
|
extern int bbs_stdin;
|
|
|
|
extern int bbs_stdout;
|
|
|
|
extern int bbs_stderr;
|
2016-12-06 17:06:28 +10:00
|
|
|
|
|
|
|
tLONG convertl(tLONG l) {
|
|
|
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
|
|
unsigned char result_bytes[4];
|
|
|
|
unsigned int result;
|
2018-10-08 14:13:11 +00:00
|
|
|
result_bytes[0] = (unsigned char)((l >> 24) & 0xFF);
|
|
|
|
result_bytes[1] = (unsigned char)((l >> 16) & 0xFF);
|
|
|
|
result_bytes[2] = (unsigned char)((l >> 8) & 0xFF);
|
|
|
|
result_bytes[3] = (unsigned char)(l & 0xFF);
|
2016-12-06 17:06:28 +10:00
|
|
|
memcpy(&result, result_bytes, 4);
|
|
|
|
return result;
|
|
|
|
#else
|
|
|
|
return l;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
tWORD converts(tWORD s) {
|
|
|
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
|
|
unsigned char result_bytes[2];
|
|
|
|
unsigned short result;
|
2018-10-08 14:13:11 +00:00
|
|
|
result_bytes[0] = (unsigned char)((s >> 8) & 0xFF);
|
|
|
|
result_bytes[1] = (unsigned char)(s & 0xFF);
|
2016-12-06 17:06:28 +10:00
|
|
|
memcpy(&result, result_bytes, 4);
|
|
|
|
return result;
|
|
|
|
#else
|
|
|
|
return s;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
int bwave_scan_email(int areano, int totmsgs, FILE *fti_file, FILE *mix_file, FILE *dat_file, int *last_ptr) {
|
|
|
|
sqlite3 *db;
|
|
|
|
sqlite3_stmt *res;
|
|
|
|
int rc;
|
|
|
|
char *sql = "SELECT sender,subject,date,body,id FROM email WHERE recipient LIKE ? AND seen = 0";
|
2018-01-08 09:56:41 +10:00
|
|
|
char *sqlseen = "UPDATE email SET seen = 1 WHERE recipient LIKE ?";
|
2018-01-08 08:54:03 +10:00
|
|
|
char buffer[PATH_MAX];
|
|
|
|
MIX_REC mix;
|
|
|
|
FTI_REC fti;
|
|
|
|
long mixptr;
|
|
|
|
struct tm timeStruct;
|
|
|
|
char *month_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
|
|
|
time_t thetime;
|
|
|
|
char *body;
|
|
|
|
int area_msgs = 0;
|
|
|
|
|
|
|
|
snprintf(buffer, PATH_MAX, "%s/email.sq3", conf.bbs_path);
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
|
|
|
if (rc != SQLITE_OK) {
|
2018-10-08 14:13:11 +00:00
|
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
|
|
sqlite3_close(db);
|
2018-01-08 08:54:03 +10:00
|
|
|
return totmsgs;
|
|
|
|
}
|
|
|
|
sqlite3_busy_timeout(db, 5000);
|
|
|
|
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
|
|
|
|
|
|
|
if (rc == SQLITE_OK) {
|
|
|
|
sqlite3_bind_text(res, 1, gUser->loginname, -1, 0);
|
|
|
|
} else {
|
|
|
|
dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
|
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
return totmsgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
mixptr = ftell(fti_file);
|
|
|
|
|
|
|
|
while (sqlite3_step(res) == SQLITE_ROW) {
|
|
|
|
memset(&fti, 0, sizeof(FTI_REC));
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(fti.from, sqlite3_column_text(res, 0), sizeof fti.from);
|
|
|
|
strlcpy(fti.to, gUser->loginname, sizeof fti.to);
|
Get rid of strncpy() calls.
The poorly named `strncpy` was originally written to
copy data into fixed-sized, disk-resident data structures
in an early version of the research Unix kernel. Thus, it
has peculiar semantics: it takes source and destination
pointer arguments and a length and will *always* modify
exactly `length` bytes in the destination buffer. If
the length of the source (which is presumed to be a
NUL-terminated C-stylestring) is `length` or more chars
long, then the result will not be NUL terminated. If it
is less than `length` bytes long, then the result will be
padded with zeros up to `length`.
This is all well and good for storing a file name into a
fixed-width directory entry in 6th edition Unix, but it's
not useful as a general-purpose string utility.
Replaced with calls to strlcpy(), which always properly
terminates the destination but doesn't have the additional
zeroing behavior. Since the buffers that we're copying
into were allocated with malloz(), and thus are guaranteed
to be filled with zeros, we're not leaking data, but not
double-zeroing either.
A few other things were changed. Lengths of destination
buffers are now given via `sizeof` instead of manifest
constants. One call to `memcpy` took the length from the
size of the source argument, thus possibly writing beyond
the end of the destination buffer. Changed to a call to
strlcpy() with length the sizeof destination.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-15 14:37:46 +00:00
|
|
|
strlcpy(fti.subject, sqlite3_column_text(res, 1), sizeof fti.subject);
|
2018-01-08 08:54:03 +10:00
|
|
|
thetime = sqlite3_column_int(res, 2);
|
|
|
|
localtime_r((time_t *)&thetime, &timeStruct);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(fti.date, sizeof fti.date, "%02d-%s-%04d %02d:%02d", timeStruct.tm_mday, month_name[timeStruct.tm_mon], timeStruct.tm_year + 1900, timeStruct.tm_hour, timeStruct.tm_min);
|
2018-01-08 08:54:03 +10:00
|
|
|
fti.msgnum = converts((tWORD)sqlite3_column_int(res, 4));
|
|
|
|
body = strdup(sqlite3_column_text(res, 3));
|
|
|
|
fti.replyto = 0;
|
|
|
|
fti.replyat = 0;
|
|
|
|
fti.msgptr = convertl(*last_ptr);
|
|
|
|
fti.msglength = convertl(strlen(body));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
*last_ptr += strlen(body);
|
2018-01-08 08:54:03 +10:00
|
|
|
fti.flags |= FTI_MSGLOCAL;
|
|
|
|
fti.flags = converts(fti.flags);
|
|
|
|
fti.orig_zone = 0;
|
|
|
|
fti.orig_net = 0;
|
|
|
|
fti.orig_node = 0;
|
|
|
|
fwrite(body, 1, strlen(body), dat_file);
|
|
|
|
fwrite(&fti, sizeof(FTI_REC), 1, fti_file);
|
|
|
|
free(body);
|
|
|
|
area_msgs++;
|
2018-10-08 14:13:11 +00:00
|
|
|
totmsgs++;
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
|
|
|
|
2018-01-08 09:56:41 +10:00
|
|
|
sqlite3_finalize(res);
|
|
|
|
|
2018-01-08 09:59:20 +10:00
|
|
|
rc = sqlite3_prepare_v2(db, sqlseen, -1, &res, 0);
|
2018-01-08 09:56:41 +10:00
|
|
|
if (rc == SQLITE_OK) {
|
|
|
|
sqlite3_bind_text(res, 1, gUser->loginname, -1, 0);
|
|
|
|
sqlite3_step(res);
|
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
|
|
|
|
memset(&mix, 0, sizeof(MIX_REC));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
snprintf(mix.areanum, 6, "%d", 1);
|
|
|
|
mix.totmsgs = converts(area_msgs);
|
|
|
|
mix.numpers = converts(area_msgs);
|
|
|
|
mix.msghptr = convertl(mixptr);
|
2018-10-08 14:13:11 +00:00
|
|
|
fwrite(&mix, sizeof(MIX_REC), 1, mix_file);
|
2018-01-08 08:54:03 +10:00
|
|
|
|
|
|
|
return totmsgs;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2016-12-06 21:46:08 +10:00
|
|
|
int bwave_scan_area(int confr, int area, int areano, int totmsgs, FILE *fti_file, FILE *mix_file, FILE *dat_file, int *last_ptr) {
|
2018-02-18 13:51:39 +10:00
|
|
|
struct msg_headers *msghs = read_message_headers(confr, area, gUser, 0);
|
2016-12-06 17:06:28 +10:00
|
|
|
int all_unread = 1;
|
|
|
|
s_JamBase *jb;
|
|
|
|
s_JamLastRead jlr;
|
|
|
|
int i;
|
|
|
|
int k;
|
|
|
|
MIX_REC mix;
|
|
|
|
int area_msgs;
|
|
|
|
int personal_msgs;
|
|
|
|
long mixptr;
|
|
|
|
FTI_REC fti;
|
|
|
|
struct fido_addr *fido;
|
|
|
|
char *body;
|
|
|
|
struct tm timeStruct;
|
2018-01-07 22:59:39 +10:00
|
|
|
char realname[66];
|
2016-12-06 17:06:28 +10:00
|
|
|
char *month_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-07 22:59:39 +10:00
|
|
|
snprintf(realname, 65, "%s %s", gUser->firstname, gUser->lastname);
|
2016-12-06 17:06:28 +10:00
|
|
|
if (msghs == NULL) {
|
|
|
|
return totmsgs;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_area(confr, area);
|
|
|
|
jb = open_jam_base(ma->path);
|
2016-12-06 17:06:28 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2016-12-07 09:24:15 +10:00
|
|
|
if (msghs != NULL) {
|
|
|
|
free_message_headers(msghs);
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
return totmsgs;
|
2018-10-16 15:05:15 +00:00
|
|
|
}
|
|
|
|
all_unread = 0;
|
|
|
|
if (JAM_ReadLastRead(jb, gUser->id, &jlr) == JAM_NO_USER) {
|
|
|
|
jlr.LastReadMsg = 0;
|
|
|
|
jlr.HighReadMsg = 0;
|
|
|
|
jlr.UserCRC = JAM_Crc32(gUser->loginname, strlen(gUser->loginname));
|
|
|
|
jlr.UserID = gUser->id;
|
|
|
|
all_unread = 1;
|
|
|
|
} else if (jlr.LastReadMsg == 0 && jlr.HighReadMsg == 0) {
|
|
|
|
all_unread = 1;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +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++) {
|
2016-12-06 17:06:28 +10:00
|
|
|
if (msghs->msgs[i]->msg_h->MsgNum == k) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
i += 1;
|
2016-12-06 17:06:28 +10:00
|
|
|
} else {
|
|
|
|
i = 0;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
mixptr = ftell(fti_file);
|
|
|
|
area_msgs = 0;
|
|
|
|
personal_msgs = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (k = i; k < msghs->msg_count; k++) {
|
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
if (totmsgs == conf.bwave_max_msgs) {
|
|
|
|
break;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
if (msghs->msgs[k]->to != NULL) {
|
2018-01-07 22:59:39 +10:00
|
|
|
if (strcasecmp(msghs->msgs[k]->to, gUser->loginname) == 0 || strncasecmp(msghs->msgs[k]->to, realname, 42) == 0) {
|
2016-12-11 22:14:36 +10:00
|
|
|
personal_msgs++;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
memset(&fti, 0, sizeof(FTI_REC));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
if (msghs->msgs[k]->from != NULL) {
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(fti.from, msghs->msgs[k]->from, sizeof fti.from);
|
2016-12-11 22:14:36 +10:00
|
|
|
} else {
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(fti.from, "(Missing From)", sizeof fti.from);
|
2016-12-11 22:14:36 +10:00
|
|
|
}
|
|
|
|
if (msghs->msgs[k]->to != NULL) {
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(fti.to, msghs->msgs[k]->to, sizeof fti.to);
|
2016-12-11 22:14:36 +10:00
|
|
|
} else {
|
2018-10-15 10:31:28 +10:00
|
|
|
strlcpy(fti.to, "(Missing To)", sizeof fti.to);
|
2016-12-11 22:14:36 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
if (msghs->msgs[k]->subject != NULL) {
|
2018-10-15 10:31:28 +10:00
|
|
|
strlcpy(fti.subject, msghs->msgs[k]->subject, sizeof fti.subject);
|
2016-12-11 22:14:36 +10:00
|
|
|
} else {
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(fti.subject, "(Missing Subject)", sizeof fti.subject);
|
2016-12-11 22:14:36 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
localtime_r((time_t *)&msghs->msgs[k]->msg_h->DateWritten, &timeStruct);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(fti.date, sizeof fti.date, "%02d-%s-%04d %02d:%02d", timeStruct.tm_mday, month_name[timeStruct.tm_mon], timeStruct.tm_year + 1900, timeStruct.tm_hour, timeStruct.tm_min);
|
2016-12-06 17:06:28 +10:00
|
|
|
fti.msgnum = converts((tWORD)msghs->msgs[k]->msg_h->MsgNum);
|
|
|
|
fti.replyto = 0;
|
|
|
|
fti.replyat = 0;
|
2016-12-06 21:46:08 +10:00
|
|
|
fti.msgptr = convertl(*last_ptr);
|
2016-12-06 17:06:28 +10:00
|
|
|
fti.msglength = convertl(msghs->msgs[k]->msg_h->TxtLen);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 21:46:08 +10:00
|
|
|
*last_ptr += msghs->msgs[k]->msg_h->TxtLen;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-03-16 17:50:06 +10:00
|
|
|
if (msghs->msgs[k]->msg_h->Attribute & JAM_MSG_LOCAL) {
|
2016-12-06 17:06:28 +10:00
|
|
|
fti.flags |= FTI_MSGLOCAL;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
fti.flags = converts(fti.flags);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
fido = parse_fido_addr(msghs->msgs[k]->oaddress);
|
|
|
|
if (fido != NULL) {
|
|
|
|
fti.orig_zone = converts(fido->zone);
|
|
|
|
fti.orig_net = converts(fido->net);
|
|
|
|
fti.orig_node = converts(fido->node);
|
|
|
|
free(fido);
|
|
|
|
} else {
|
|
|
|
fti.orig_zone = 0;
|
|
|
|
fti.orig_net = 0;
|
|
|
|
fti.orig_node = 0;
|
|
|
|
}
|
|
|
|
// write msg data
|
2018-10-09 15:55:13 +00:00
|
|
|
body = (char *)malloz(msghs->msgs[k]->msg_h->TxtLen);
|
|
|
|
JAM_ReadMsgText(jb, msghs->msgs[k]->msg_h->TxtOffset, msghs->msgs[k]->msg_h->TxtLen, body);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
fwrite(body, 1, msghs->msgs[k]->msg_h->TxtLen, dat_file);
|
|
|
|
fwrite(&fti, sizeof(FTI_REC), 1, fti_file);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
free(body);
|
|
|
|
jlr.LastReadMsg = msghs->msgs[k]->msg_h->MsgNum;
|
|
|
|
if (jlr.HighReadMsg < msghs->msgs[k]->msg_h->MsgNum) {
|
|
|
|
jlr.HighReadMsg = msghs->msgs[k]->msg_h->MsgNum;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
JAM_WriteLastRead(jb, gUser->id, &jlr);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
area_msgs++;
|
|
|
|
totmsgs++;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-21 21:45:24 +10:00
|
|
|
//if (area_msgs) {
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
memset(&mix, 0, sizeof(MIX_REC));
|
|
|
|
|
|
|
|
snprintf(mix.areanum, 6, "%d", areano);
|
|
|
|
mix.totmsgs = converts(area_msgs);
|
|
|
|
mix.numpers = converts(personal_msgs);
|
|
|
|
mix.msghptr = convertl(mixptr);
|
|
|
|
fwrite(&mix, sizeof(MIX_REC), 1, mix_file);
|
2017-09-21 21:45:24 +10:00
|
|
|
//}
|
2016-12-06 17:06:28 +10:00
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2016-12-06 17:06:28 +10:00
|
|
|
free_message_headers(msghs);
|
|
|
|
return totmsgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bwave_create_packet() {
|
|
|
|
char buffer[1024];
|
|
|
|
char archive[1024];
|
|
|
|
INF_HEADER hdr;
|
2018-10-09 15:55:15 +00:00
|
|
|
struct ptr_vector areas;
|
|
|
|
INF_AREA_INFO *area = NULL;
|
2016-12-06 17:06:28 +10:00
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int area_count;
|
|
|
|
tWORD flags;
|
|
|
|
int lasttot;
|
2016-12-06 21:46:08 +10:00
|
|
|
int last_ptr = 0;
|
2016-12-11 22:14:36 +10:00
|
|
|
int stout;
|
|
|
|
int stin;
|
2018-10-08 14:13:11 +00:00
|
|
|
int sterr;
|
2017-10-18 07:36:58 +10:00
|
|
|
char *weekday[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
|
2018-10-09 15:55:13 +00:00
|
|
|
struct stat s;
|
2016-12-06 17:06:28 +10:00
|
|
|
struct termios oldit;
|
|
|
|
struct termios oldot;
|
2017-10-18 07:36:58 +10:00
|
|
|
struct tm time_tm;
|
|
|
|
time_t thetime;
|
2016-12-06 17:06:28 +10:00
|
|
|
FILE *mix_file;
|
|
|
|
FILE *fti_file;
|
|
|
|
FILE *dat_file;
|
|
|
|
FILE *inf_file;
|
2017-09-21 10:21:51 +10:00
|
|
|
int tot_areas = 0;
|
2016-12-06 17:06:28 +10:00
|
|
|
int totmsgs = 0;
|
2018-02-09 19:35:14 +10:00
|
|
|
int ret;
|
2018-10-09 15:55:15 +00:00
|
|
|
char **args, *arg;
|
2018-06-20 19:31:35 +10:00
|
|
|
char *cmd;
|
|
|
|
pid_t pid;
|
2018-02-09 19:35:14 +10:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
init_ptr_vector(&areas);
|
|
|
|
|
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++) {
|
2017-09-21 10:21:51 +10:00
|
|
|
if (msgbase_is_subscribed(i, j)) {
|
|
|
|
tot_areas++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-09-21 10:21:51 +10:00
|
|
|
if (tot_areas == 0) {
|
|
|
|
s_printf(get_string(224));
|
|
|
|
s_printf(get_string(6));
|
|
|
|
s_getchar();
|
|
|
|
return;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
area_count = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
memset(&hdr, 0, sizeof(INF_HEADER));
|
|
|
|
hdr.ver = PACKET_LEVEL;
|
Get rid of strncpy() calls.
The poorly named `strncpy` was originally written to
copy data into fixed-sized, disk-resident data structures
in an early version of the research Unix kernel. Thus, it
has peculiar semantics: it takes source and destination
pointer arguments and a length and will *always* modify
exactly `length` bytes in the destination buffer. If
the length of the source (which is presumed to be a
NUL-terminated C-stylestring) is `length` or more chars
long, then the result will not be NUL terminated. If it
is less than `length` bytes long, then the result will be
padded with zeros up to `length`.
This is all well and good for storing a file name into a
fixed-width directory entry in 6th edition Unix, but it's
not useful as a general-purpose string utility.
Replaced with calls to strlcpy(), which always properly
terminates the destination but doesn't have the additional
zeroing behavior. Since the buffers that we're copying
into were allocated with malloz(), and thus are guaranteed
to be filled with zeros, we're not leaking data, but not
double-zeroing either.
A few other things were changed. Lengths of destination
buffers are now given via `sizeof` instead of manifest
constants. One call to `memcpy` took the length from the
size of the source argument, thus possibly writing beyond
the end of the destination buffer. Changed to a call to
strlcpy() with length the sizeof destination.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-15 14:37:46 +00:00
|
|
|
strlcpy(hdr.loginname, gUser->loginname, sizeof hdr.loginname);
|
|
|
|
//strlcpy(hdr.aliasname, gUser->loginname, sizeof hdr.aliasname);
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(hdr.aliasname, sizeof hdr.aliasname, "%s %s", gUser->firstname, gUser->lastname);
|
2016-12-06 17:06:28 +10:00
|
|
|
hdr.zone = converts(conf.main_aka->zone);
|
|
|
|
hdr.node = converts(conf.main_aka->node);
|
|
|
|
hdr.net = converts(conf.main_aka->net);
|
|
|
|
hdr.point = converts(conf.main_aka->point);
|
Get rid of strncpy() calls.
The poorly named `strncpy` was originally written to
copy data into fixed-sized, disk-resident data structures
in an early version of the research Unix kernel. Thus, it
has peculiar semantics: it takes source and destination
pointer arguments and a length and will *always* modify
exactly `length` bytes in the destination buffer. If
the length of the source (which is presumed to be a
NUL-terminated C-stylestring) is `length` or more chars
long, then the result will not be NUL terminated. If it
is less than `length` bytes long, then the result will be
padded with zeros up to `length`.
This is all well and good for storing a file name into a
fixed-width directory entry in 6th edition Unix, but it's
not useful as a general-purpose string utility.
Replaced with calls to strlcpy(), which always properly
terminates the destination but doesn't have the additional
zeroing behavior. Since the buffers that we're copying
into were allocated with malloz(), and thus are guaranteed
to be filled with zeros, we're not leaking data, but not
double-zeroing either.
A few other things were changed. Lengths of destination
buffers are now given via `sizeof` instead of manifest
constants. One call to `memcpy` took the length from the
size of the source argument, thus possibly writing beyond
the end of the destination buffer. Changed to a call to
strlcpy() with length the sizeof destination.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-15 14:37:46 +00:00
|
|
|
strlcpy(hdr.sysop, conf.sysop_name, sizeof hdr.sysop);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
Get rid of strncpy() calls.
The poorly named `strncpy` was originally written to
copy data into fixed-sized, disk-resident data structures
in an early version of the research Unix kernel. Thus, it
has peculiar semantics: it takes source and destination
pointer arguments and a length and will *always* modify
exactly `length` bytes in the destination buffer. If
the length of the source (which is presumed to be a
NUL-terminated C-stylestring) is `length` or more chars
long, then the result will not be NUL terminated. If it
is less than `length` bytes long, then the result will be
padded with zeros up to `length`.
This is all well and good for storing a file name into a
fixed-width directory entry in 6th edition Unix, but it's
not useful as a general-purpose string utility.
Replaced with calls to strlcpy(), which always properly
terminates the destination but doesn't have the additional
zeroing behavior. Since the buffers that we're copying
into were allocated with malloz(), and thus are guaranteed
to be filled with zeros, we're not leaking data, but not
double-zeroing either.
A few other things were changed. Lengths of destination
buffers are now given via `sizeof` instead of manifest
constants. One call to `memcpy` took the length from the
size of the source argument, thus possibly writing beyond
the end of the destination buffer. Changed to a call to
strlcpy() with length the sizeof destination.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-15 14:37:46 +00:00
|
|
|
strlcpy(hdr.systemname, conf.bbs_name, sizeof hdr.systemname);
|
2016-12-06 17:06:28 +10:00
|
|
|
hdr.inf_header_len = converts(sizeof(INF_HEADER));
|
|
|
|
hdr.inf_areainfo_len = converts(sizeof(INF_AREA_INFO));
|
|
|
|
hdr.mix_structlen = converts(sizeof(MIX_REC));
|
|
|
|
hdr.fti_structlen = converts(sizeof(FTI_REC));
|
|
|
|
hdr.uses_upl_file = 1;
|
|
|
|
hdr.from_to_len = 35;
|
|
|
|
hdr.subject_len = 71;
|
|
|
|
memcpy(hdr.packet_id, conf.bwave_name, strlen(conf.bwave_name));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d", conf.bbs_path, mynode);
|
2016-12-07 09:24:15 +10:00
|
|
|
|
|
|
|
if (stat(buffer, &s) != 0) {
|
|
|
|
mkdir(buffer, 0755);
|
|
|
|
}
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/", conf.bbs_path, mynode);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 10:43:39 +10:00
|
|
|
if (stat(buffer, &s) == 0) {
|
|
|
|
recursive_delete(buffer);
|
|
|
|
}
|
|
|
|
mkdir(buffer, 0755);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/%s.FTI", conf.bbs_path, mynode, conf.bwave_name);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 21:46:08 +10:00
|
|
|
fti_file = fopen(buffer, "wb");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/%s.MIX", conf.bbs_path, mynode, conf.bwave_name);
|
2016-12-06 21:46:08 +10:00
|
|
|
mix_file = fopen(buffer, "wb");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/%s.DAT", conf.bbs_path, mynode, conf.bwave_name);
|
2016-12-06 21:46:08 +10:00
|
|
|
dat_file = fopen(buffer, "wb");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
s_printf("\r\n");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
totmsgs = bwave_scan_email(area_count + 1, totmsgs, fti_file, mix_file, dat_file, &last_ptr);
|
|
|
|
s_printf(get_string(195), "Private Email", "Private Email", totmsgs);
|
2018-01-08 08:54:03 +10:00
|
|
|
|
|
|
|
flags = 0;
|
2018-10-09 15:55:15 +00:00
|
|
|
area = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO));
|
2018-01-08 08:54:03 +10:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
snprintf(area->areanum, 6, "%d", area_count + 1);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
memcpy(area->echotag, "PRIVATE_EMAIL", 13);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(area->title, "Private Email", 49);
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_POST;
|
|
|
|
flags |= INF_NO_PUBLIC;
|
|
|
|
flags |= INF_SCANNING;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
area->area_flags = converts(flags);
|
|
|
|
area->network_type = INF_NET_FIDONET;
|
|
|
|
ptr_vector_append(&areas, area);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
area_count++;
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (totmsgs < conf.bwave_max_msgs) {
|
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++) {
|
|
|
|
struct mail_area *ma = get_area(i, j);
|
|
|
|
if (ma->read_sec_level <= gUser->sec_level && ma->qwkname != NULL && msgbase_is_subscribed(i, j)) {
|
2018-01-08 08:54:03 +10:00
|
|
|
lasttot = totmsgs;
|
2018-10-08 14:13:11 +00:00
|
|
|
totmsgs = bwave_scan_area(i, j, area_count + 1, totmsgs, fti_file, mix_file, dat_file, &last_ptr);
|
2018-10-16 15:05:15 +00:00
|
|
|
s_printf(get_string(195), mc->name, ma->name, totmsgs - lasttot);
|
2018-01-08 08:54:03 +10:00
|
|
|
//if (lasttot == totmsgs) {
|
|
|
|
// continue;
|
|
|
|
//}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
area = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO));
|
2018-10-08 14:13:11 +00:00
|
|
|
|
Get rid of strncpy() calls.
The poorly named `strncpy` was originally written to
copy data into fixed-sized, disk-resident data structures
in an early version of the research Unix kernel. Thus, it
has peculiar semantics: it takes source and destination
pointer arguments and a length and will *always* modify
exactly `length` bytes in the destination buffer. If
the length of the source (which is presumed to be a
NUL-terminated C-stylestring) is `length` or more chars
long, then the result will not be NUL terminated. If it
is less than `length` bytes long, then the result will be
padded with zeros up to `length`.
This is all well and good for storing a file name into a
fixed-width directory entry in 6th edition Unix, but it's
not useful as a general-purpose string utility.
Replaced with calls to strlcpy(), which always properly
terminates the destination but doesn't have the additional
zeroing behavior. Since the buffers that we're copying
into were allocated with malloz(), and thus are guaranteed
to be filled with zeros, we're not leaking data, but not
double-zeroing either.
A few other things were changed. Lengths of destination
buffers are now given via `sizeof` instead of manifest
constants. One call to `memcpy` took the length from the
size of the source argument, thus possibly writing beyond
the end of the destination buffer. Changed to a call to
strlcpy() with length the sizeof destination.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-15 14:37:46 +00:00
|
|
|
snprintf(area->areanum, sizeof area->areanum, "%d", area_count + 1);
|
2018-10-16 15:05:15 +00:00
|
|
|
strlcpy(area->echotag, ma->qwkname, sizeof area->echotag);
|
|
|
|
strlcpy(area->title, ma->name, sizeof area->title);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
flags = 0;
|
|
|
|
if (ma->write_sec_level <= gUser->sec_level) {
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_POST;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_NO_PUBLIC;
|
|
|
|
flags |= INF_NETMAIL;
|
|
|
|
flags |= INF_ECHO;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_NO_PRIVATE;
|
|
|
|
flags |= INF_ECHO;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_LOCAL_AREA) {
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_NO_PRIVATE;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
flags |= INF_SCANNING;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
area->area_flags = converts(flags);
|
|
|
|
area->network_type = INF_NET_FIDONET;
|
2018-01-08 08:54:03 +10:00
|
|
|
|
2018-10-09 15:55:15 +00:00
|
|
|
ptr_vector_append(&areas, area);
|
2018-01-08 08:54:03 +10:00
|
|
|
area_count++;
|
|
|
|
if (totmsgs == conf.bwave_max_msgs) {
|
|
|
|
break;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
if (totmsgs == conf.bwave_max_msgs) {
|
|
|
|
break;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
fclose(dat_file);
|
|
|
|
fclose(mix_file);
|
|
|
|
fclose(fti_file);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 10:43:39 +10:00
|
|
|
snprintf(buffer, 1024, "%s/node%d/bwave/%s.INF", conf.bbs_path, mynode, conf.bwave_name);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 21:46:08 +10:00
|
|
|
inf_file = fopen(buffer, "wb");
|
2016-12-06 17:06:28 +10:00
|
|
|
fwrite(&hdr, sizeof(INF_HEADER), 1, inf_file);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
for (i = 0; i < area_count; i++) {
|
2018-10-09 15:55:15 +00:00
|
|
|
fwrite(ptr_vector_get(&areas, i), sizeof(INF_AREA_INFO), 1, inf_file);
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
fclose(inf_file);
|
2018-10-08 14:13:11 +00: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(&areas, free);
|
|
|
|
destroy_ptr_vector(&areas);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
if (totmsgs > 0) {
|
|
|
|
// create archive
|
2017-10-18 07:36:58 +10:00
|
|
|
if (gUser->bwavestyle) {
|
|
|
|
thetime = time(NULL);
|
|
|
|
localtime_r(&thetime, &time_tm);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2017-10-18 19:33:41 +10:00
|
|
|
if (gUser->bwavepktno / 10 != time_tm.tm_wday) {
|
|
|
|
gUser->bwavepktno = time_tm.tm_wday * 10;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(archive, sizeof archive, "%s/node%d/%s.%s%d",
|
|
|
|
conf.bbs_path, mynode, conf.bwave_name, weekday[time_tm.tm_wday], gUser->bwavepktno % 10);
|
2017-10-18 07:36:58 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(archive, sizeof archive, "%s/node%d/%s.%03d", conf.bbs_path, mynode, conf.bwave_name, gUser->bwavepktno);
|
2017-10-18 07:36:58 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct archiver *arc = ptr_vector_get(&conf.archivers, gUser->defarchiver - 1);
|
|
|
|
assert(arc != NULL);
|
|
|
|
char *b = buffer;
|
|
|
|
size_t blen = sizeof buffer;
|
|
|
|
for (const char *p = arc->pack; *p != '\0' && blen >= 1; ++p) {
|
|
|
|
if (*p != '*') {
|
|
|
|
*b++ = *p;
|
|
|
|
--blen;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
size_t alen = 0;
|
|
|
|
if (*p == 'a') {
|
|
|
|
strlcpy(b, archive, blen);
|
|
|
|
alen = strlen(archive);
|
|
|
|
} else if (*p == 'f') {
|
|
|
|
snprintf(b, blen, "%s/node%d/bwave/%s.INF %s/node%d/bwave/%s.MIX %s/node%d/bwave/%s.FTI %s/node%d/bwave/%s.DAT",
|
|
|
|
conf.bbs_path, mynode, conf.bwave_name, conf.bbs_path, mynode, conf.bwave_name, conf.bbs_path,
|
|
|
|
mynode, conf.bwave_name, conf.bbs_path, mynode, conf.bwave_name);
|
|
|
|
alen = strlen(b);
|
|
|
|
} else if (*p == '*') {
|
|
|
|
*b++ = '*';
|
|
|
|
alen = 1;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
b += alen;
|
|
|
|
blen -= alen;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
*b = '\0';
|
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
if (sshBBS) {
|
|
|
|
stout = dup(STDOUT_FILENO);
|
|
|
|
stin = dup(STDIN_FILENO);
|
|
|
|
sterr = dup(STDERR_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(bbs_stdout, STDOUT_FILENO);
|
|
|
|
dup2(bbs_stderr, STDERR_FILENO);
|
|
|
|
dup2(bbs_stdin, STDIN_FILENO);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-09 15:55:16 +00:00
|
|
|
args = split_on_space(buffer, NULL);
|
2018-10-09 15:55:15 +00:00
|
|
|
cmd = args[0];
|
2018-06-20 19:31:35 +10:00
|
|
|
pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
execvp(cmd, args);
|
|
|
|
exit(0);
|
|
|
|
} else if (pid > 0) {
|
|
|
|
waitpid(pid, &ret, 0);
|
|
|
|
} else {
|
|
|
|
ret = -1;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
free(args);
|
2016-12-11 22:14:36 +10:00
|
|
|
if (sshBBS) {
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(stout, STDOUT_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
dup2(sterr, STDERR_FILENO);
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(stin, STDIN_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
close(stin);
|
|
|
|
close(stout);
|
|
|
|
close(sterr);
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-02-09 19:35:14 +10:00
|
|
|
if (ret != -1 && ret >> 8 != 127) {
|
|
|
|
do_download(gUser, archive);
|
|
|
|
} else {
|
|
|
|
s_printf(get_string(274));
|
|
|
|
}
|
2016-12-10 17:55:47 +10:00
|
|
|
|
2016-12-07 10:43:39 +10:00
|
|
|
snprintf(buffer, 1024, "%s/node%d/bwave", conf.bbs_path, mynode);
|
|
|
|
recursive_delete(buffer);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
unlink(archive);
|
|
|
|
gUser->bwavepktno++;
|
2016-12-07 09:31:19 +10:00
|
|
|
if (gUser->bwavepktno > 999) {
|
|
|
|
gUser->bwavepktno = 0;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
save_user(gUser);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
s_printf(get_string(6));
|
|
|
|
s_getc();
|
|
|
|
}
|
|
|
|
|
|
|
|
int bwave_add_message(int confr, int area, unsigned int dwritten, char *to, char *subject, struct fido_addr *destaddr, char *msg) {
|
|
|
|
s_JamBase *jb;
|
|
|
|
s_JamMsgHeader jmh;
|
2018-10-08 14:13:11 +00:00
|
|
|
s_JamSubPacket *jsp;
|
2016-12-06 17:06:28 +10:00
|
|
|
s_JamSubfield jsf;
|
|
|
|
int z;
|
|
|
|
char buffer[256];
|
2018-05-22 21:02:22 +10:00
|
|
|
uuid_t magi_msgid;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_area(confr, area);
|
|
|
|
jb = open_jam_base(ma->path);
|
2016-12-06 17:06:28 +10:00
|
|
|
if (!jb) {
|
2018-10-16 15:05:15 +00:00
|
|
|
dolog("Error opening JAM base.. %s", ma->path);
|
2016-12-06 17:06:28 +10:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
JAM_ClearMsgHeader(&jmh);
|
2016-12-06 17:06:28 +10:00
|
|
|
jmh.DateWritten = dwritten;
|
2017-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_LOCAL;
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_conf(confr);
|
|
|
|
if (mc->realnames == 0) {
|
2018-10-11 02:49:23 +00:00
|
|
|
strlcpy(buffer, gUser->loginname, sizeof buffer);
|
2016-12-06 17:06:28 +10:00
|
|
|
} else {
|
2018-10-11 02:49:23 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s %s", gUser->firstname, gUser->lastname);
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
jsp = JAM_NewSubPacket();
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_SENDERNAME;
|
|
|
|
jsf.HiID = 0;
|
2016-12-06 17:06:28 +10:00
|
|
|
jsf.DatLen = strlen(buffer);
|
|
|
|
jsf.Buffer = (char *)buffer;
|
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NEWSGROUP_AREA) {
|
2018-10-14 13:24:09 +00:00
|
|
|
strlcpy(buffer, "ALL", sizeof buffer);
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_RECVRNAME;
|
|
|
|
jsf.HiID = 0;
|
2016-12-09 19:47:33 +10:00
|
|
|
jsf.DatLen = strlen(buffer);
|
|
|
|
jsf.Buffer = (char *)buffer;
|
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
|
|
|
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_RECVRNAME;
|
|
|
|
jsf.HiID = 0;
|
2016-12-09 19:47:33 +10:00
|
|
|
jsf.DatLen = strlen(to);
|
|
|
|
jsf.Buffer = (char *)to;
|
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_SUBJECT;
|
|
|
|
jsf.HiID = 0;
|
2016-12-06 17:06:28 +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-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPEECHO;
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_conference *mc = get_conf(confr);
|
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point) {
|
2018-10-14 13:24:09 +00:00
|
|
|
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);
|
2018-05-22 21:02:22 +10:00
|
|
|
} else {
|
2018-10-14 13:24:09 +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);
|
2018-05-22 21:02:22 +10:00
|
|
|
}
|
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);
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-10-14 13:24:09 +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,
|
|
|
|
mc->fidoaddr->point,
|
|
|
|
generate_msgid());
|
2016-12-06 17:06:28 +10:00
|
|
|
|
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_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);
|
2018-10-08 14:13:11 +00:00
|
|
|
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-05-22 21:02:22 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_NETMAIL_AREA && mc->nettype == NETWORK_FIDO) {
|
2017-03-16 17:50:06 +10:00
|
|
|
jmh.Attribute |= JAM_MSG_TYPENET;
|
|
|
|
jmh.Attribute |= JAM_MSG_PRIVATE;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->fidoaddr->point) {
|
2018-10-14 13:24:09 +00:00
|
|
|
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-12-06 17:06:28 +10:00
|
|
|
} else {
|
2018-10-14 13:24:09 +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-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_OADDRESS;
|
|
|
|
jsf.HiID = 0;
|
2016-12-06 17:06:28 +10:00
|
|
|
jsf.DatLen = strlen(buffer);
|
|
|
|
jsf.Buffer = (char *)buffer;
|
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
|
|
|
|
|
|
|
if (destaddr != NULL) {
|
|
|
|
if (destaddr->point) {
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d.%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
destaddr->zone,
|
|
|
|
destaddr->net,
|
|
|
|
destaddr->node,
|
|
|
|
destaddr->point);
|
2016-12-06 17:06:28 +10:00
|
|
|
} else {
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%d:%d/%d",
|
2018-10-16 15:21:42 +00:00
|
|
|
destaddr->zone,
|
|
|
|
destaddr->net,
|
|
|
|
destaddr->node);
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_DADDRESS;
|
|
|
|
jsf.HiID = 0;
|
2016-12-06 17:06:28 +10:00
|
|
|
jsf.DatLen = strlen(buffer);
|
|
|
|
jsf.Buffer = (char *)buffer;
|
|
|
|
JAM_PutSubfield(jsp, &jsf);
|
|
|
|
}
|
|
|
|
|
2018-10-14 13:24:09 +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,
|
|
|
|
mc->fidoaddr->point,
|
|
|
|
generate_msgid());
|
2016-12-06 17:06:28 +10:00
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
jsf.LoID = JAMSFLD_MSGID;
|
|
|
|
jsf.HiID = 0;
|
2016-12-06 17:06:28 +10:00
|
|
|
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 {
|
|
|
|
dolog("Failed to lock msg base!");
|
2018-02-10 16:01:30 +10:00
|
|
|
JAM_CloseMB(jb);
|
2018-10-08 14:13:11 +00:00
|
|
|
free(jb);
|
2016-12-06 17:06:28 +10:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (JAM_AddMessage(jb, &jmh, jsp, (char *)msg, strlen(msg))) {
|
|
|
|
dolog("Failed to add message");
|
|
|
|
JAM_UnlockMB(jb);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
JAM_DelSubPacket(jsp);
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2016-12-06 17:06:28 +10:00
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
JAM_UnlockMB(jb);
|
|
|
|
|
|
|
|
JAM_DelSubPacket(jsp);
|
|
|
|
JAM_CloseMB(jb);
|
2018-02-10 16:01:30 +10:00
|
|
|
free(jb);
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bwave_upload_reply() {
|
|
|
|
char buffer[1024];
|
|
|
|
char msgbuffer[1024];
|
|
|
|
char originlinebuffer[256];
|
|
|
|
int i;
|
|
|
|
UPL_HEADER upl_hdr;
|
|
|
|
UPL_REC upl_rec;
|
|
|
|
int j;
|
|
|
|
int confr;
|
|
|
|
int area;
|
|
|
|
tWORD msg_attr;
|
|
|
|
struct fido_addr addr;
|
2018-10-12 20:30:24 +00:00
|
|
|
stralloc sa = EMPTY_STRALLOC;
|
2016-12-06 17:06:28 +10:00
|
|
|
char *body;
|
|
|
|
char *tagline;
|
2018-10-09 15:55:13 +00:00
|
|
|
struct stat s;
|
2016-12-06 17:06:28 +10:00
|
|
|
int echomail = 0;
|
|
|
|
int netmail = 0;
|
|
|
|
FILE *upl_file;
|
|
|
|
FILE *msg_file;
|
|
|
|
int sem_fd;
|
2016-12-07 20:04:42 +10:00
|
|
|
int msg_count;
|
2016-12-11 22:14:36 +10:00
|
|
|
int stout;
|
|
|
|
int stin;
|
|
|
|
int sterr;
|
2018-01-08 08:54:03 +10:00
|
|
|
sqlite3 *db;
|
2018-10-08 14:13:11 +00:00
|
|
|
sqlite3_stmt *res;
|
|
|
|
int rc;
|
2018-01-08 08:54:03 +10:00
|
|
|
char *csql = "CREATE TABLE IF NOT EXISTS email ("
|
2018-10-08 14:13:11 +00:00
|
|
|
"id INTEGER PRIMARY KEY,"
|
|
|
|
"sender TEXT COLLATE NOCASE,"
|
|
|
|
"recipient TEXT COLLATE NOCASE,"
|
|
|
|
"subject TEXT,"
|
|
|
|
"body TEXT,"
|
|
|
|
"date INTEGER,"
|
|
|
|
"seen INTEGER);";
|
2018-01-08 08:54:03 +10:00
|
|
|
char *isql = "INSERT INTO email (sender, recipient, subject, body, date, seen) VALUES(?, ?, ?, ?, ?, 0)";
|
2018-10-08 14:13:11 +00:00
|
|
|
char *err_msg = 0;
|
2018-10-09 15:55:15 +00:00
|
|
|
char **args, *arg;
|
2018-06-20 19:31:35 +10:00
|
|
|
char *cmd;
|
|
|
|
pid_t pid;
|
|
|
|
int ret;
|
2016-12-07 20:04:42 +10:00
|
|
|
msg_count = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 09:24:15 +10:00
|
|
|
snprintf(buffer, 1024, "%s/node%d", conf.bbs_path, mynode);
|
|
|
|
|
|
|
|
if (stat(buffer, &s) != 0) {
|
|
|
|
mkdir(buffer, 0755);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 10:43:39 +10:00
|
|
|
snprintf(buffer, 1024, "%s/node%d/bwave/", conf.bbs_path, mynode);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 10:43:39 +10:00
|
|
|
if (stat(buffer, &s) == 0) {
|
|
|
|
recursive_delete(buffer);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
mkdir(buffer, 0755);
|
|
|
|
|
2016-12-10 17:55:47 +10:00
|
|
|
if (!do_upload(gUser, buffer)) {
|
|
|
|
s_printf(get_string(211));
|
|
|
|
recursive_delete(buffer);
|
|
|
|
return;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
struct archiver *arc = ptr_vector_get(&conf.archivers, gUser->defarchiver - 1);
|
|
|
|
assert(arc != NULL);
|
|
|
|
char *b = buffer;
|
|
|
|
size_t blen = sizeof buffer;
|
|
|
|
for (const char *p = arc->unpack; *p != '\0' && blen > 1; ++p) {
|
|
|
|
if (*p != '*') {
|
|
|
|
*b++ = *p;
|
|
|
|
--blen;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
size_t alen = 0;
|
|
|
|
if (*p == 'a') {
|
|
|
|
strlcpy(b, upload_filename, blen);
|
|
|
|
alen = strlen(upload_filename);
|
|
|
|
} else if (*p == 'd') {
|
|
|
|
snprintf(b, blen, "%s/node%d/bwave/", conf.bbs_path, mynode);
|
|
|
|
alen = strlen(b);
|
|
|
|
} else if (*p == '*') {
|
|
|
|
*b++ = '*';
|
|
|
|
alen = 1;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
b += alen;
|
|
|
|
blen -= alen;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
*b = '\0';
|
2016-12-11 22:14:36 +10:00
|
|
|
if (sshBBS) {
|
|
|
|
stout = dup(STDOUT_FILENO);
|
|
|
|
stin = dup(STDIN_FILENO);
|
|
|
|
sterr = dup(STDERR_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(bbs_stdout, STDOUT_FILENO);
|
|
|
|
dup2(bbs_stderr, STDERR_FILENO);
|
|
|
|
dup2(bbs_stdin, STDIN_FILENO);
|
|
|
|
}
|
2018-10-09 15:55:16 +00:00
|
|
|
args = split_on_space(buffer, NULL);
|
2018-10-09 15:55:15 +00:00
|
|
|
cmd = args[0];
|
2018-06-20 19:31:35 +10:00
|
|
|
pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
execvp(cmd, args);
|
|
|
|
exit(0);
|
|
|
|
} else if (pid > 0) {
|
|
|
|
waitpid(pid, &ret, 0);
|
|
|
|
} else {
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
free(args);
|
2016-12-11 22:14:36 +10:00
|
|
|
if (sshBBS) {
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(stout, STDOUT_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
dup2(sterr, STDERR_FILENO);
|
2016-12-11 22:14:36 +10:00
|
|
|
dup2(stin, STDIN_FILENO);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-11 22:14:36 +10:00
|
|
|
close(stin);
|
|
|
|
close(stout);
|
|
|
|
close(sterr);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
unlink(upload_filename);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/%s.UPL", conf.bbs_path, mynode, conf.bwave_name);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
upl_file = fopen(buffer, "r");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
if (!upl_file) {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/%s.upl", conf.bbs_path, mynode, conf.bwave_name);
|
2016-12-06 17:06:28 +10:00
|
|
|
upl_file = fopen(buffer, "r");
|
|
|
|
if (!upl_file) {
|
|
|
|
s_printf(get_string(196));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
if (!fread(&upl_hdr, sizeof(UPL_HEADER), 1, upl_file)) {
|
|
|
|
s_printf(get_string(196));
|
|
|
|
fclose(upl_file);
|
2018-10-08 14:13:11 +00:00
|
|
|
return;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
while (fread(&upl_rec, sizeof(UPL_REC), 1, upl_file)) {
|
2018-01-08 08:54:03 +10:00
|
|
|
if (strcmp("PRIVATE_EMAIL", upl_rec.echotag) == 0) {
|
|
|
|
if (msg_attr & UPL_INACTIVE) {
|
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (strcasecmp(upl_rec.from, gUser->loginname) != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(msgbuffer, 1024, "%s/node%d/bwave/%s", conf.bbs_path, mynode, upl_rec.filename);
|
2018-10-09 15:55:13 +00:00
|
|
|
body = file2str(msgbuffer);
|
|
|
|
if (body == NULL) {
|
2018-01-08 08:54:03 +10:00
|
|
|
continue;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
char *b = body;
|
|
|
|
for (char *p = body; *p != '\0'; ++p) {
|
|
|
|
if (*p != '\n')
|
|
|
|
*b++ = *p;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
*b = '\0';
|
2018-01-08 08:54:03 +10:00
|
|
|
|
2018-10-14 13:24:09 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/email.sq3", conf.bbs_path);
|
2018-01-08 08:54:03 +10:00
|
|
|
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
|
|
sqlite3_close(db);
|
|
|
|
free(body);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sqlite3_busy_timeout(db, 5000);
|
|
|
|
|
|
|
|
rc = sqlite3_exec(db, csql, 0, 0, &err_msg);
|
2018-10-08 14:13:11 +00:00
|
|
|
if (rc != SQLITE_OK) {
|
2018-01-08 08:54:03 +10:00
|
|
|
|
|
|
|
dolog("SQL error: %s", err_msg);
|
|
|
|
|
|
|
|
sqlite3_free(err_msg);
|
|
|
|
sqlite3_close(db);
|
|
|
|
|
|
|
|
free(body);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = sqlite3_prepare_v2(db, isql, -1, &res, 0);
|
|
|
|
|
|
|
|
if (rc == SQLITE_OK) {
|
|
|
|
sqlite3_bind_text(res, 1, gUser->loginname, -1, 0);
|
|
|
|
sqlite3_bind_text(res, 2, upl_rec.to, -1, 0);
|
|
|
|
sqlite3_bind_text(res, 3, upl_rec.subj, -1, 0);
|
|
|
|
sqlite3_bind_text(res, 4, body, -1, 0);
|
|
|
|
sqlite3_bind_int(res, 5, convertl(upl_rec.unix_date));
|
|
|
|
} else {
|
|
|
|
dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
|
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
free(body);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sqlite3_step(res);
|
|
|
|
|
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
free(body);
|
2018-01-08 09:01:27 +10:00
|
|
|
msg_count++;
|
2018-01-08 08:54:03 +10:00
|
|
|
} else {
|
|
|
|
// find area
|
|
|
|
confr = -1;
|
|
|
|
area = -1;
|
2018-10-08 14:13:11 +00:00
|
|
|
|
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);
|
|
|
|
for (j = 0; j < ptr_vector_len(&mc->mail_areas); j++) {
|
|
|
|
struct mail_area *ma = ptr_vector_get(&mc->mail_areas, j);
|
|
|
|
if (strcmp(ma->qwkname, upl_rec.echotag) == 0) {
|
2018-01-08 08:54:03 +10:00
|
|
|
confr = i;
|
|
|
|
area = j;
|
|
|
|
break;
|
|
|
|
}
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
if (confr != -1) {
|
|
|
|
break;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (confr != -1 && area != -1) {
|
|
|
|
// import message
|
2018-10-16 15:05:15 +00:00
|
|
|
struct mail_area *ma = get_area(confr, area);
|
|
|
|
if (ma->write_sec_level <= gUser->sec_level) {
|
2018-01-08 08:54:03 +10:00
|
|
|
msg_attr = converts(upl_rec.msg_attr);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (msg_attr & UPL_INACTIVE) {
|
2016-12-06 17:06:28 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (strcasecmp(upl_rec.from, gUser->loginname) != 0) {
|
2016-12-06 17:06:28 +10:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
addr.zone = 0;
|
|
|
|
addr.net = 0;
|
|
|
|
addr.node = 0;
|
2018-10-08 14:13:11 +00:00
|
|
|
addr.zone = 0;
|
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (ma->type == TYPE_NETMAIL_AREA) {
|
2018-01-08 08:54:03 +10:00
|
|
|
if (!(msg_attr & UPL_NETMAIL)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
addr.zone = converts(upl_rec.destzone);
|
|
|
|
addr.net = converts(upl_rec.destnet);
|
|
|
|
addr.node = converts(upl_rec.destnode);
|
|
|
|
addr.zone = converts(upl_rec.destpoint);
|
|
|
|
netmail = 1;
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (ma->type == TYPE_ECHOMAIL_AREA || ma->type == TYPE_NEWSGROUP_AREA) {
|
2018-01-08 08:54:03 +10:00
|
|
|
if (msg_attr & UPL_PRIVATE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
echomail = 1;
|
|
|
|
} else { // Local area
|
|
|
|
if (msg_attr & UPL_PRIVATE) {
|
|
|
|
continue;
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(msgbuffer, sizeof buffer, "%s/node%d/bwave/%s", conf.bbs_path, mynode, upl_rec.filename);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
tagline = conf.default_tagline;
|
|
|
|
struct mail_conference *mc = get_conf(confr);
|
|
|
|
if (mc->tagline != NULL) {
|
|
|
|
tagline = mc->tagline;
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
if (mc->nettype == NETWORK_FIDO) {
|
|
|
|
if (mc->fidoaddr->point == 0) {
|
|
|
|
snprintf(originlinebuffer, sizeof originlinebuffer, "\r--- %s\r * Origin: %s (%d:%d/%d)\r",
|
|
|
|
upl_hdr.reader_tear, tagline,
|
|
|
|
mc->fidoaddr->zone, mc->fidoaddr->net, mc->fidoaddr->node);
|
2018-01-08 08:54:03 +10:00
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(originlinebuffer, sizeof originlinebuffer, "\r--- %s\r * Origin: %s (%d:%d/%d.%d)\r",
|
|
|
|
upl_hdr.reader_tear, tagline,
|
|
|
|
mc->fidoaddr->zone,
|
|
|
|
mc->fidoaddr->net,
|
|
|
|
mc->fidoaddr->node,
|
|
|
|
mc->fidoaddr->point);
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
2018-10-16 15:05:15 +00:00
|
|
|
} else if (mc->nettype == NETWORK_MAGI) {
|
|
|
|
snprintf(originlinebuffer, sizeof originlinebuffer, "\r--- %s\r * Origin: %s (@%d)\r",
|
|
|
|
upl_hdr.reader_tear, tagline, mc->maginode);
|
|
|
|
} else if (mc->nettype == NETWORK_QWK) {
|
|
|
|
snprintf(originlinebuffer, sizeof originlinebuffer, "\r--- $s\r * Origin: %s (%s)\r",
|
|
|
|
upl_hdr.reader_tear, tagline, conf.bwave_name);
|
2018-01-08 08:54:03 +10:00
|
|
|
} else {
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(originlinebuffer, sizeof originlinebuffer, "\r");
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-10-12 20:30:24 +00:00
|
|
|
sa = file2stralloc(msgbuffer);
|
|
|
|
if (sa.s == NULL) {
|
2018-01-08 08:54:03 +10:00
|
|
|
continue;
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
2018-10-12 20:30:24 +00:00
|
|
|
stralloc_cats(&sa, originlinebuffer);
|
|
|
|
stralloc_0(&sa);
|
|
|
|
body = sa.s;
|
|
|
|
char *p, *s;
|
|
|
|
|
|
|
|
for (p = s = body; *p != '\0'; ++p) {
|
|
|
|
if (*p != '\n')
|
|
|
|
*s++ = *p;
|
2018-01-08 08:54:03 +10:00
|
|
|
}
|
2018-10-12 20:30:24 +00:00
|
|
|
*s = '\0';
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
if (bwave_add_message(confr, area, convertl(upl_rec.unix_date), upl_rec.to, upl_rec.subj, &addr, body) != 0) {
|
|
|
|
// failed to add message
|
|
|
|
s_printf(get_string(197));
|
|
|
|
} else {
|
|
|
|
msg_count++;
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-01-08 08:54:03 +10:00
|
|
|
free(body);
|
2016-12-06 17:06:28 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-08 08:54:03 +10:00
|
|
|
|
2018-10-16 15:05:15 +00:00
|
|
|
snprintf(buffer, sizeof buffer, "%s/node%d/bwave/", conf.bbs_path, mynode);
|
2016-12-07 10:43:39 +10:00
|
|
|
recursive_delete(buffer);
|
|
|
|
|
2016-12-07 20:04:42 +10:00
|
|
|
if (netmail == 1) {
|
|
|
|
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-12-07 20:04:42 +10:00
|
|
|
close(sem_fd);
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-07 20:04:42 +10:00
|
|
|
if (echomail == 1) {
|
|
|
|
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-12-07 20:04:42 +10:00
|
|
|
close(sem_fd);
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2016-12-07 20:04:42 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
s_printf("\r\n");
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-07 20:04:42 +10:00
|
|
|
if (msg_count > 0) {
|
2018-10-08 14:13:11 +00:00
|
|
|
s_printf(get_string(204), msg_count);
|
2016-12-07 20:04:42 +10:00
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2016-12-06 17:06:28 +10:00
|
|
|
s_printf(get_string(6));
|
|
|
|
s_getc();
|
|
|
|
}
|