Updated for the nntp server

This commit is contained in:
Michiel Broek 2004-04-13 18:25:50 +00:00
parent 3a4f475a3f
commit 3e2f009cb3
8 changed files with 424 additions and 17 deletions

View File

@ -18,13 +18,17 @@ v0.51.4 11-Apr-2004
When a new echomail area is auto created, the creation date and
the newsgroup name will be set.
mbnntp:
New program, news server to read echomail with a news client.
Reading news works, no posts yet.
mbsebbs:
Added loging of virus scanner results.
mbsetup:
Added auto setup for message area creation date. Also creates
a faked newsgroup name in echomail areas. Both settings are
needed for the (upcoming) newsserver.
needed for the newsserver.
v0.51.3 22-Mar-2003 - 11-Apr-2004

2
configure vendored
View File

@ -1270,7 +1270,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_commands="$ac_config_commands default-1"
SUBDIRS="lib mbcico mbfido mbmon mbsebbs mbtask mbsetup unix lang examples html script"
SUBDIRS="lib mbcico mbfido mbmon mbsebbs mbnntp mbtask mbsetup unix lang examples html script"
PACKAGE="mbsebbs"

View File

@ -3,7 +3,7 @@ dnl $Id$
AC_INIT(lib/mbselib.h)
AM_CONFIG_HEADER(config.h)
SUBDIRS="lib mbcico mbfido mbmon mbsebbs mbtask mbsetup unix lang examples html script"
SUBDIRS="lib mbcico mbfido mbmon mbsebbs mbnntp mbtask mbsetup unix lang examples html script"
AC_SUBST(SUBDIRS)
dnl

View File

@ -6,7 +6,7 @@ include ../Makefile.global
SRCS = mbnntp.c openport.c ttyio.c auth.c commands.c
HDRS = mbnntp.h openport.h ttyio.h auth.h commands.h
OBJS = mbnntp.o openport.o ttyio.o auth.o commands.o
LIBS += ../lib/libmbse.a ../lib/libdbase.a ../lib/libmsgbase.a
LIBS += ../lib/libmbse.a ../lib/libmsgbase.a ../lib/libdbase.a
OTHER = Makefile
#############################################################################
@ -55,9 +55,9 @@ depend:
# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
# Dependencies generated by make depend
mbnntp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h openport.h ttyio.h auth.h commands.h mbnntp.h
mbnntp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h ../lib/msg.h openport.h ttyio.h auth.h commands.h mbnntp.h
openport.o: ../config.h ../lib/mbselib.h openport.h
ttyio.o: ../config.h ../lib/mbselib.h ttyio.h
auth.o: ../config.h ../lib/mbselib.h ../lib/users.h mbnntp.h auth.h
commands.o: ../config.h ../lib/mbselib.h mbnntp.h commands.h
commands.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/msg.h ../lib/msgtext.h ttyio.h mbnntp.h commands.h
# End of generated dependencies

View File

@ -29,28 +29,392 @@
#include "../config.h"
#include "../lib/mbselib.h"
#include "../lib/users.h"
#include "../lib/msg.h"
#include "../lib/msgtext.h"
#include "ttyio.h"
#include "mbnntp.h"
#include "commands.h"
void command_list(char *cmd)
unsigned long article = 0L; /* Current article */
char currentgroup[81]; /* Current newsgroup */
extern unsigned long sentbytes;
/*
* Safe sending to the client with charset translation.
*/
void send_xlat(char *inp)
{
char *xl, temp[1024];
int i;
memset(&temp, 0, sizeof(temp));
for (i = 0; i < strlen(inp); i++) {
if (inp[i] & 0x80) {
if ((xl = charset_map_c(inp[i], FALSE))) {
while (*xl) {
temp[i] = *xl++;
if (*xl)
i++;
}
}
} else {
temp[i] = inp[i];
}
}
Syslog('n', "> \"%s\"", printable(temp, 0));
PUTSTR(temp);
PUTSTR((char *)"\r\n");
FLUSHOUT();
sentbytes += (strlen(temp) + 2);
}
/*
* ARTICLE
* BODY
* HEADER
* STAT
*/
void command_abhs(char *buf)
{
char *p, *cmd, *opt, dig[128];
unsigned long art = 0L;
int i;
Syslog('+', "%s", buf);
cmd = strtok(buf, " \0");
opt = strtok(NULL, " \0");
IsDoing("Retrieve");
if (opt == NULL) {
send_nntp("420 No current article has been selected");
return;
}
if (strlen(currentgroup) == 0) {
send_nntp("412 No newsgroup has been selected");
return;
}
if (opt[0] == '<') {
Syslog('n', "\"%s\"", printable(opt, 0));
strcpy(dig, opt+1);
Syslog('n', "\"%s\"", printable(dig, 0));
for (i = 0; i < strlen(dig); i++) {
if (dig[i] == '$') {
dig[i] = '\0';
break;
}
}
Syslog('n', "\"%s\"", printable(dig, 0));
art = atoi(dig);
} else {
art = atoi(opt);
}
Syslog('n', "Article %lu", art);
if (art == 0L) {
send_nntp("420 No current article has been selected");
return;
}
if (! Msg_ReadHeader(art)) {
send_nntp("430 No such article found");
return;
}
if (strcasecmp(cmd, "STAT") == 0) {
send_nntp("223 %lu <%lu$%s@MBNNTP> Article retrieved", art, art, currentgroup);
return;
}
/*
* Setup a default translation
*/
charset_set_in_out((char *)"x-ibmpc", (char *)"iso-8859-1");
if (Msg_Read(art, 75)) {
if (strcasecmp(cmd, "ARTICLE") == 0)
send_nntp("220 %ld <%ld$%s@MBNNTP> Article retrieved - Head and body follow", art, art, currentgroup);
if (strcasecmp(cmd, "HEAD") == 0)
send_nntp("221 %ld <%ld$%s@MBNNTP> Article retrieved - Head follows", art, art, currentgroup);
if (strcasecmp(cmd, "BODY") == 0)
send_nntp("222 %ld <%ld$%s@MBNNTP> Article retrieved - Body follows", art, art, currentgroup);
if ((strcasecmp(cmd, "ARTICLE") == 0) || (strcasecmp(cmd, "HEAD") == 0)) {
send_nntp("Path: MBNNTP!not-for-mail");
send_nntp("From: %s <%s>", Msg.From, Msg.FromAddress);
send_nntp("Newsgroups: %s", currentgroup);
send_nntp("Subject: %s", Msg.Subject);
send_nntp("Date: %s", rfcdate(Msg.Written));
send_nntp("Message-ID: <%lu$%s@MBNNTP>", art, currentgroup);
if (Msg.Reply)
send_nntp("References: <%lu$%s@MBNNTP>", Msg.Reply, currentgroup);
send_nntp("X-JAM-From: %s <%s>", Msg.From, Msg.FromAddress);
if (strlen(Msg.To))
send_nntp("X-JAM-To: %s", Msg.To);
if ((p = (char *)MsgText_First()) != NULL) {
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
if (p[0] == '\001') {
send_nntp("X-JAM-%s", p+1);
} else {
send_nntp("X-JAM-%s", p);
}
}
} while ((p = (char *)MsgText_Next()) != NULL);
}
// send_nntp("X-JAM-Attributes:");
send_nntp("MIME-Version: 1.0");
send_nntp("Content-Type: text/plain; charset=iso-8859-1; format=fixed");
send_nntp("Content-Transfer-Encoding: 8bit");
}
if (strcasecmp(cmd, "ARTICLE") == 0)
send_nntp("");
if ((strcasecmp(cmd, "ARTICLE") == 0) || (strcasecmp(cmd, "BODY") == 0)) {
if ((p = (char *)MsgText_First()) != NULL) {
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
/*
* Kludges, suppress
*/
} else {
if (strcmp(p, ".") == 0) /* Don't send a single dot */
send_nntp("..");
else
send_xlat(p);
}
} while ((p = (char *)MsgText_Next()) != NULL);
}
}
send_nntp(".");
return;
} else {
send_nntp("503 Could not retrieve message");
return;
}
}
/*
* GROUP ggg
*/
void command_group(char *cmd)
{
FILE *fp;
char *temp;
char *temp, *opt;
IsDoing("Group");
Syslog('+', "%s", cmd);
opt = strtok(cmd, " \0");
opt = strtok(NULL, " \0");
if (opt == NULL) {
send_nntp("411 No such news group");
return;
}
send_nntp("215 List of newsgroups follows");
temp = calloc(PATH_MAX, sizeof(char));
sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
if ((fp = fopen(temp, "r"))) {
fread(&msgshdr, sizeof(msgshdr), 1, fp);
while (fread(&msgs, msgshdr.recsize, 1, fp) == 1) {
fseek(fp, msgs.syssize, SEEK_CUR);
if (msgs.Active && ((msgs.Type == ECHOMAIL) || (msgs.Type == NEWS)) && strlen(msgs.Newsgroup) &&
(strcasecmp(opt, msgs.Newsgroup) == 0) && Access(usrconfig.Security, msgs.RDSec)) {
Syslog('n', "Found the group");
if (Msg_Open(msgs.Base)) {
Msg_Number();
Msg_Highest();
Msg_Lowest();
send_nntp("211 %lu %lu %lu %s", MsgBase.Total, MsgBase.Lowest, MsgBase.Highest, msgs.Newsgroup);
sprintf(currentgroup, "%s", msgs.Newsgroup);
} else {
send_nntp("411 No such news group");
}
fclose(fp);
free(temp);
return;
}
fseek(fp, msgshdr.syssize, SEEK_CUR);
}
fclose(fp);
} else {
WriteError("$Can't open %s", temp);
}
free(temp);
send_nntp("411 No such news group");
}
/*
* LIST
* LIST ACTIVE
* LIST NEWSGROUPS
* LIST OVERVIEW.FMT
*/
void command_list(char *cmd)
{
FILE *fp;
char *temp, *opt;
int rw;
IsDoing("List");
Syslog('+', "%s", cmd);
opt = strtok(cmd, " \0");
opt = strtok(NULL, " \0");
if ((opt == NULL) || (strcasecmp(opt, "ACTIVE") == 0) || (strcasecmp(opt, "NEWSGROUPS") == 0)) {
send_nntp("215 Information follows");
temp = calloc(PATH_MAX, sizeof(char));
sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
if ((fp = fopen(temp, "r"))) {
fread(&msgshdr, sizeof(msgshdr), 1, fp);
while (fread(&msgs, msgshdr.recsize, 1, fp) == 1) {
if (msgs.Active && ((msgs.Type == ECHOMAIL) || (msgs.Type == NEWS)) && strlen(msgs.Newsgroup) &&
Access(usrconfig.Security, msgs.RDSec)) {
if (Access(usrconfig.Security, msgs.WRSec))
rw = 'y';
else
rw = 'n';
if (msgs.MsgKinds == RONLY)
rw = 'n';
if (Msg_Open(msgs.Base)) {
if (opt && (strcasecmp(opt, "NEWSGROUPS") == 0))
send_nntp("%s %s", msgs.Newsgroup, msgs.Name);
else
send_nntp("%s %lu %lu %c", msgs.Newsgroup, Msg_Lowest(), Msg_Highest(), rw);
Msg_Close();
}
}
fseek(fp, msgshdr.syssize, SEEK_CUR);
}
fclose(fp);
} else {
WriteError("$Can't open %s", temp);
}
free(temp);
send_nntp(".");
return;
}
if (opt && (strcasecmp(opt, "OVERVIEW.FMT") == 0)) {
send_nntp("215 Order of fields in overview database");
send_nntp("Subject:");
send_nntp("From:");
send_nntp("Date:");
send_nntp("Message-ID:");
send_nntp("References:");
send_nntp("Bytes:");
send_nntp("Lines:");
// send_nntp("Xref:full");
send_nntp(".");
return;
}
/*
* No recognized LIST command
*/
send_nntp("503 Function not available");
msleep(1); /* For the linker only */
colour(0, 0);
}
/*
* XOVER
*/
void command_xover(char *cmd)
{
char *opt, *p, msgid[100], reply[100];
unsigned long i, start, end;
int refs, bytecount, linecount;
IsDoing("Xover");
opt = strtok(cmd, " \0");
opt = strtok(NULL, " \0");
if (MsgBase.Open == FALSE) {
send_nntp("411 No news group current selected");
return;
}
if ((opt == NULL) && (article == 0L)) {
send_nntp("420 No article selected");
return;
}
start = MsgBase.Lowest;
end = MsgBase.Highest;
Syslog('n', "Start %ld, end %ld", start, end);
if (opt != NULL) {
if (strchr(opt, '-')) {
/*
* We have a dash, format 12- or 12-16
*/
p = strtok(opt, "-");
start = atoi(p);
p = strtok(NULL, "\0");
if (p != NULL)
end = atoi(p);
} else {
/*
* Must be a single digit
*/
start = end = atoi(opt);
}
}
Syslog('n', "Start %ld, end %ld", start, end);
send_nntp("224 Overview information follows");
for (i = start; i <= end; i++) {
if (Msg_ReadHeader(i)) {
bytecount = linecount = refs = 0;
if (Msg.Original)
refs++;
if (Msg.Reply)
refs++;
if (Msg_Read(i, 80)) {
if ((p = (char *)MsgText_First()) != NULL) {
do {
if (p[0] != '\001') {
linecount++;
bytecount += strlen(p);
}
} while ((p = (char *)MsgText_Next()) != NULL);
}
}
sprintf(msgid, "<%ld$%s@MBNNTP>", i, currentgroup);
reply[0] = 0;
if (Msg.Reply)
sprintf(reply, "<%ld$%s@MBNNTP>", Msg.Reply, currentgroup);
send_nntp("%lu\t%s\t%s <%s>\t%s\t%s\t%s\t%d\t%d", i, Msg.Subject, Msg.From, Msg.FromAddress,
rfcdate(Msg.Written), msgid, reply, bytecount, linecount);
}
}
send_nntp(".");
}

View File

@ -3,6 +3,9 @@
/* $Id$ */
void command_list(char *); /* LIST */
void command_abhs(char *); /* ARTICLE/BODY/HEADER/STAT */
void command_group(char *); /* GROUP */
void command_list(char *); /* LIST */
void command_xover(char *); /* XOVER */
#endif

View File

@ -32,6 +32,7 @@
#include "../lib/mbselib.h"
#include "../lib/users.h"
#include "../lib/mbsedb.h"
#include "../lib/msg.h"
#include "openport.h"
#include "ttyio.h"
#include "auth.h"
@ -43,6 +44,8 @@ time_t t_end;
char *envptr = NULL;
struct sockaddr_in peeraddr;
pid_t mypid;
unsigned long rcvdbytes = 0L;
unsigned long sentbytes = 0L;
extern char *ttystat[];
extern int authorized;
@ -52,6 +55,7 @@ void die(int onsig)
{
signal(onsig, SIG_IGN);
CloseDupes();
Msg_Close();
if (onsig) {
if (onsig <= NSIG)
@ -61,6 +65,7 @@ void die(int onsig)
}
t_end = time(NULL);
Syslog('+', "Send [%6lu] Received [%6lu]", sentbytes, rcvdbytes);
Syslog(' ', "MBNNTP finished in %s", t_elapsed(t_start, t_end));
if (envptr)
@ -162,8 +167,10 @@ int get_nntp(char *buf, int max)
Syslog('+', "Receiver status %s", ttystat[- c]);
return c;
}
if ((c == '\r') || (c == '\n'))
if ((c == '\r') || (c == '\n')) {
rcvdbytes += (len + 1);
return len;
}
else {
buf[len] = c;
len++;
@ -174,7 +181,8 @@ int get_nntp(char *buf, int max)
return len;
}
}
return 0; /* Not reached */
return 0; /* Not reached */
}
@ -193,6 +201,8 @@ void send_nntp(const char *format, ...)
Syslog('n', "> \"%s\"", printable(out, 0));
PUTSTR(out);
PUTSTR((char *)"\r\n");
FLUSHOUT();
sentbytes += (strlen(out) + 2);
free(out);
}
@ -205,16 +215,18 @@ void nntp(void)
while (TRUE) {
IsDoing("Waiting");
len = get_nntp(buf, sizeof(buf) -1);
if (len < 0)
return;
if (len == 0)
continue;
Syslog('n', "< \"%s\"", printable(buf, 0));
/*
* Process received command
*/
Syslog('n', "< \"%s\"", printable(buf, 0));
if (strncasecmp(buf, "QUIT", 4) == 0) {
send_nntp("205 Goodbye\r\n");
return;
@ -222,9 +234,21 @@ void nntp(void)
auth_user(buf);
} else if (strncasecmp(buf, "AUTHINFO PASS", 13) == 0) {
auth_pass(buf);
} else if (strncasecmp(buf, "ARTICLE", 7) == 0) {
if (check_auth(buf))
command_abhs(buf);
} else if (strncasecmp(buf, "BODY", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
} else if (strncasecmp(buf, "LIST", 4) == 0) {
if (check_auth(buf))
command_list(buf);
} else if (strncasecmp(buf, "GROUP", 5) == 0) {
if (check_auth(buf))
command_group(buf);
} else if (strncasecmp(buf, "HEAD", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
} else if (strncasecmp(buf, "IHAVE", 5) == 0) {
send_nntp("435 Article not wanted - do not send it");
} else if (strncasecmp(buf, "NEWGROUPS", 9) == 0) {
@ -235,22 +259,34 @@ void nntp(void)
send_nntp(".");
} else if (strncasecmp(buf, "SLAVE", 5) == 0) {
send_nntp("202 Slave status noted");
} else if (strncasecmp(buf, "STAT", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
} else if (strncasecmp(buf, "MODE READER", 11) == 0) {
if (authorized)
send_nntp("200 Server ready, posting allowed");
else
send_nntp("201 Server ready, no posting allowed");
} else if (strncasecmp(buf, "XOVER", 5) == 0) {
if (check_auth(buf))
command_xover(buf);
} else if (strncasecmp(buf, "HELP", 4) == 0) {
send_nntp("100 Help text follows");
send_nntp("Recognized commands:");
send_nntp("");
send_nntp("ARTICLE");
send_nntp("AUTHINFO");
send_nntp("BODY");
send_nntp("GROUP");
send_nntp("HEAD");
send_nntp("IHAVE (not implemented, messages are always rejected)");
send_nntp("LIST");
send_nntp("NEWGROUPS (not implemented, always returns an empty list)");
send_nntp("NEWNEWS (not implemented, always returns an empty list)");
send_nntp("QUIT");
send_nntp("SLAVE (has no effect)");
send_nntp("STAT");
send_nntp("XOVER");
send_nntp("");
send_nntp("MBNNTP supports most of RFC-977 and also has support for AUTHINFO and");
send_nntp("limited XOVER support (RFC-2980)");

View File

@ -75,7 +75,7 @@ grlist.o: ../config.h ../lib/mbselib.h screen.h grlist.h ledit.h
m_domain.o: ../config.h ../lib/mbselib.h screen.h mutil.h ledit.h m_global.h m_menu.h m_domain.h
m_fgroup.o: ../config.h ../lib/mbselib.h screen.h mutil.h ledit.h stlist.h m_global.h m_node.h m_archive.h m_ngroup.h m_ticarea.h m_fgroup.h
m_lang.o: ../config.h ../lib/mbselib.h screen.h mutil.h ledit.h stlist.h m_global.h m_lang.h
m_marea.o: ../config.h ../lib/mbselib.h ../lib/msg.h ../lib/mbsedb.h screen.h mutil.h ledit.h grlist.h m_global.h m_node.h m_mgroup.h m_marea.h
m_marea.o: ../config.h ../lib/mbselib.h ../lib/msg.h ../lib/users.h ../lib/mbsedb.h screen.h mutil.h ledit.h grlist.h m_global.h m_node.h m_mgroup.h m_marea.h
m_new.o: ../config.h ../lib/mbselib.h screen.h mutil.h ledit.h stlist.h m_global.h grlist.h m_new.h m_lang.h m_marea.h m_ngroup.h
m_protocol.o: ../config.h ../lib/mbselib.h ../paths.h screen.h mutil.h ledit.h stlist.h m_global.h m_protocol.h
m_ticarea.o: ../config.h ../lib/mbselib.h screen.h mutil.h ledit.h stlist.h grlist.h m_global.h m_node.h m_fgroup.h m_farea.h m_archive.h m_ticarea.h