postmsg.cpp 13.29 KiB
/* postmsg.cpp */
/* Synchronet user create/post public message routine */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
/****************************************************************************/
/* Posts a message on subboard number sub, with 'top' as top of message. */
/* Returns 1 if posted, 0 if not. */
/****************************************************************************/
bool sbbs_t::postmsg(uint subnum, smbmsg_t *remsg, long wm_mode)
{
char str[256],touser[256],title[LEN_TITLE+1],buf[SDT_BLOCK_LEN]
,top[256];
ushort xlat,msgattr;
int i,j,x,file,storage;
ulong l,length,offset,crc=0xffffffff;
FILE *instream;
smbmsg_t msg,tmpmsg;
if(remsg) {
sprintf(title,"%.*s",LEN_TITLE,remsg->subj);
if(cfg.sub[subnum]->misc&SUB_INET) // All Internet posts to "All" 05/20/97
touser[0]=0;
else if(remsg->hdr.attr&MSG_ANONYMOUS)
strcpy(touser,text[Anonymous]);
else
strcpy(touser,remsg->from);
msgattr=(ushort)(remsg->hdr.attr&MSG_PRIVATE);
sprintf(top,text[RegardingByToOn],title,touser,remsg->to
,timestr((time_t *)&remsg->hdr.when_written.time)
,zonestr(remsg->hdr.when_written.zone)); }
else {
title[0]=0;
touser[0]=0;
top[0]=0;
msgattr=0; }
if(useron.rest&FLAG('P')) {
bputs(text[R_Post]);
return(false); }
if((cfg.sub[subnum]->misc&(SUB_QNET|SUB_FIDO|SUB_PNET|SUB_INET))
&& (useron.rest&FLAG('N'))) {
bputs(text[CantPostOnSub]);
return(false); }
if(useron.ptoday>=cfg.level_postsperday[useron.level]) {
bputs(text[TooManyPostsToday]);
return(false); }
bprintf(text[Posting],cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname);
action=NODE_PMSG;
nodesync();
if(!(msgattr&MSG_PRIVATE) && (cfg.sub[subnum]->misc&SUB_PONLY
|| (cfg.sub[subnum]->misc&SUB_PRIV && !noyes(text[PrivatePostQ]))))
msgattr|=MSG_PRIVATE;
if(sys_status&SS_ABORT)
return(false);
if(!(cfg.sub[subnum]->misc&SUB_INET) // Prompt for TO: user
&& (cfg.sub[subnum]->misc&SUB_TOUSER || msgattr&MSG_PRIVATE || touser[0])) {
if(!touser[0] && !(msgattr&MSG_PRIVATE))
strcpy(touser,"All");
bputs(text[PostTo]);
i=LEN_ALIAS;
if(cfg.sub[subnum]->misc&(SUB_PNET|SUB_INET))
i=60;
if(cfg.sub[subnum]->misc&SUB_FIDO)
i=35;
if(cfg.sub[subnum]->misc&SUB_QNET)
i=25;
getstr(touser,i,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
if(stricmp(touser,"ALL")
&& !(cfg.sub[subnum]->misc&(SUB_PNET|SUB_FIDO|SUB_QNET|SUB_INET|SUB_ANON))) {
if(cfg.sub[subnum]->misc&SUB_NAME) {
if(!userdatdupe(useron.number,U_NAME,LEN_NAME,touser,0)) {
bputs(text[UnknownUser]);
return(false); } }
else {
if((i=finduser(touser))==0)
return(false);
username(&cfg,i,touser); } }
if(sys_status&SS_ABORT)
return(false); }
if(!touser[0])
strcpy(touser,"All"); // Default to ALL
if(!stricmp(touser,"SYSOP") && !SYSOP) // Change SYSOP to user #1
username(&cfg,1,touser);
if(msgattr&MSG_PRIVATE && !stricmp(touser,"ALL")) {
bputs(text[NoToUser]);
return(false); }
if(msgattr&MSG_PRIVATE)
wm_mode|=WM_PRIVATE;
if(cfg.sub[subnum]->misc&SUB_AONLY
|| (cfg.sub[subnum]->misc&SUB_ANON && useron.exempt&FLAG('A')
&& !noyes(text[AnonymousQ])))
msgattr|=MSG_ANONYMOUS;
if(cfg.sub[subnum]->mod_ar[0] && chk_ar(cfg.sub[subnum]->mod_ar,&useron))
msgattr|=MSG_MODERATED;
if(cfg.sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum))
msgattr|=MSG_PERMANENT;
if(msgattr&MSG_PRIVATE)
bputs(text[PostingPrivately]);
if(msgattr&MSG_ANONYMOUS)
bputs(text[PostingAnonymously]);
if(cfg.sub[subnum]->misc&SUB_NAME)
bputs(text[UsingRealName]);
sprintf(str,"%sINPUT.MSG",cfg.node_dir);
if(!writemsg(str,top,title,wm_mode,subnum,touser)) {
bputs(text[Aborted]);
return(false); }
bputs(text[WritingIndx]);
if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
errormsg(WHERE,ERR_OPEN,cfg.sub[subnum]->code,i);
return(false); }
sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
smb.retry_time=cfg.smb_retry_time;
if((i=smb_open(&smb))!=0) {
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
return(false); }
if(filelength(fileno(smb.shd_fp))<1) { /* Create it if it doesn't exist */
smb.status.max_crcs=cfg.sub[subnum]->maxcrcs;
smb.status.max_msgs=cfg.sub[subnum]->maxmsgs;
smb.status.max_age=cfg.sub[subnum]->maxage;
smb.status.attr=cfg.sub[subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
if((i=smb_create(&smb))!=0) {
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
return(false); } }
if((i=smb_locksmbhdr(&smb))!=0) {
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
return(false); }
if((i=smb_getstatus(&smb))!=0) {
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error);
return(false); }
length=flength(str)+2; /* +2 for translation string */
if(length&0xfff00000UL) {
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_LEN,str,length);
return(false); }
if(smb.status.attr&SMB_HYPERALLOC) {
offset=smb_hallocdat(&smb);
storage=SMB_HYPERALLOC; }
else {
if((i=smb_open_da(&smb))!=0) {
smb_unlocksmbhdr(&smb);
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
return(false); }
if(cfg.sub[subnum]->misc&SUB_FAST) {
offset=smb_fallocdat(&smb,length,1);
storage=SMB_FASTALLOC; }
else {
offset=smb_allocdat(&smb,length,1);
storage=SMB_SELFPACK; }
smb_close_da(&smb); }
if((file=open(str,O_RDONLY|O_BINARY))==-1
|| (instream=fdopen(file,"rb"))==NULL) {
smb_freemsgdat(&smb,offset,length,1);
smb_unlocksmbhdr(&smb);
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
return(false); }
setvbuf(instream,NULL,_IOFBF,2*1024);
fseek(smb.sdt_fp,offset,SEEK_SET);
xlat=XLAT_NONE;
fwrite(&xlat,2,1,smb.sdt_fp);
x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
while(!feof(instream)) {
memset(buf,0,x);
j=fread(buf,1,x,instream);
if(j<1)
break;
if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
buf[j-1]=buf[j-2]=0; /* Convert to NULL */
if(cfg.sub[subnum]->maxcrcs) {
for(i=0;i<j;i++)
crc=ucrc32(buf[i],crc); }
fwrite(buf,j,1,smb.sdt_fp);
x=SDT_BLOCK_LEN; }
fflush(smb.sdt_fp);
fclose(instream);
crc=~crc;
memset(&msg,0,sizeof(smbmsg_t));
memcpy(msg.hdr.id,"SHD\x1a",4);
msg.hdr.version=smb_ver();
msg.hdr.attr=msg.idx.attr=msgattr;
msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
msg.hdr.when_written.zone=msg.hdr.when_imported.zone=cfg.sys_timezone;
if(remsg) {
msg.hdr.thread_orig=remsg->hdr.number;
if(!remsg->hdr.thread_first) {
remsg->hdr.thread_first=smb.status.last_msg+1;
if((i=smb_lockmsghdr(&smb,remsg))!=0)
errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
else {
i=smb_putmsghdr(&smb,remsg);
smb_unlockmsghdr(&smb,remsg);
if(i)
errormsg(WHERE,ERR_WRITE,smb.file,i); } }
else {
l=remsg->hdr.thread_first;
while(1) {
tmpmsg.idx.offset=0;
if(!loadmsg(&tmpmsg,l))
break;
if(tmpmsg.hdr.thread_next && tmpmsg.hdr.thread_next!=l) {
l=tmpmsg.hdr.thread_next;
smb_unlockmsghdr(&smb,&tmpmsg);
smb_freemsgmem(&tmpmsg);
continue; }
tmpmsg.hdr.thread_next=smb.status.last_msg+1;
if((i=smb_putmsghdr(&smb,&tmpmsg))!=0)
errormsg(WHERE,ERR_WRITE,smb.file,i);
smb_unlockmsghdr(&smb,&tmpmsg);
smb_freemsgmem(&tmpmsg);
break; } } }
if(cfg.sub[subnum]->maxcrcs) {
i=smb_addcrc(&smb,crc);
if(i) {
smb_freemsgdat(&smb,offset,length,1);
smb_unlocksmbhdr(&smb);
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
attr(cfg.color[clr_err]);
bputs("Duplicate message!\r\n");
return(false);
}
}
msg.hdr.offset=offset;
smb_hfield(&msg,RECIPIENT,strlen(touser),touser);
strlwr(touser);
msg.idx.to=crc16(touser);
strcpy(str,cfg.sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias);
smb_hfield(&msg,SENDER,strlen(str),str);
strlwr(str);
msg.idx.from=crc16(str);
sprintf(str,"%u",useron.number);
smb_hfield(&msg,SENDEREXT,strlen(str),str);
smb_hfield(&msg,SUBJECT,strlen(title),title);
strcpy(str,title);
strlwr(str);
remove_re(str);
msg.idx.subj=crc16(str);
smb_dfield(&msg,TEXT_BODY,length);
smb_unlocksmbhdr(&smb);
i=smb_addmsghdr(&smb,&msg,storage);
smb_close(&smb);
smb_stack(&smb,SMB_STACK_POP);
smb_freemsgmem(&msg);
if(i) {
smb_freemsgdat(&smb,offset,length,1);
errormsg(WHERE,ERR_WRITE,smb.file,i);
return(false); }
useron.ptoday++;
useron.posts++;
logon_posts++;
putuserrec(&cfg,useron.number,U_POSTS,5,ultoa(useron.posts,str,10));
putuserrec(&cfg,useron.number,U_PTODAY,5,ultoa(useron.ptoday,str,10));
bprintf(text[Posted],cfg.grp[cfg.sub[subnum]->grp]->sname
,cfg.sub[subnum]->lname);
sprintf(str,"Posted on %s %s",cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname);
logline("P+",str);
if(cfg.sub[subnum]->misc&SUB_FIDO && cfg.sub[subnum]->echomail_sem[0]) /* semaphore */
if((file=nopen(cmdstr(cfg.sub[subnum]->echomail_sem,nulstr,nulstr,NULL)
,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
close(file);
return(true);
}
extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, uint subnum, smbmsg_t* msg, char* msgbuf)
{
char pad=0;
ushort xlat;
int i;
int storage;
ulong l;
ulong length;
ulong offset;
ulong crc=0xffffffff;
if(!SMB_IS_OPEN(smb)) {
if(subnum==INVALID_SUB)
sprintf(smb->file,"%smail",cfg->data_dir);
else
sprintf(smb->file,"%s%s",cfg->sub[subnum]->data_dir,cfg->sub[subnum]->code);
smb->retry_time=cfg->smb_retry_time;
if((i=smb_open(smb))!=0)
return(i);
}
if(filelength(fileno(smb->shd_fp))<1) { /* Create it if it doesn't exist */
if(subnum==INVALID_SUB) {
smb->status.max_crcs=cfg->mail_maxcrcs;
smb->status.max_age=cfg->mail_maxage;
smb->status.max_msgs=MAX_SYSMAIL;
smb->status.attr=SMB_EMAIL;
} else {
smb->status.max_crcs=cfg->sub[subnum]->maxcrcs;
smb->status.max_msgs=cfg->sub[subnum]->maxmsgs;
smb->status.max_age=cfg->sub[subnum]->maxage;
smb->status.attr=cfg->sub[subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
}
if((i=smb_create(smb))!=0)
return(i);
}
if((i=smb_locksmbhdr(smb))!=0)
return(i);
if((i=smb_getstatus(smb))!=0) {
smb_unlocksmbhdr(smb);
return(i);
}
length=strlen(msgbuf)+sizeof(xlat); /* +2 for translation string */
if(length&0xfff00000UL) {
smb_unlocksmbhdr(smb);
return(-1);
}
/* Allocate Data Blocks */
if(smb->status.attr&SMB_HYPERALLOC) {
offset=smb_hallocdat(smb);
storage=SMB_HYPERALLOC;
} else {
if((i=smb_open_da(smb))!=0) {
smb_unlocksmbhdr(smb);
return(i);
}
if((subnum==INVALID_SUB && cfg->sys_misc&SM_FASTMAIL)
|| (subnum!=INVALID_SUB && cfg->sub[subnum]->misc&SUB_FAST)) {
offset=smb_fallocdat(smb,length,1);
storage=SMB_FASTALLOC;
} else {
offset=smb_allocdat(smb,length,1);
storage=SMB_SELFPACK;
}
smb_close_da(smb);
}
smb_fseek(smb->sdt_fp,offset,SEEK_SET);
xlat=XLAT_NONE;
smb_fwrite(&xlat,sizeof(xlat),smb->sdt_fp);
smb_fwrite(msgbuf,length-sizeof(xlat),smb->sdt_fp);
for(l=length;l%SDT_BLOCK_LEN;l++)
smb_fwrite(&pad,1,smb->sdt_fp);
fflush(smb->sdt_fp);
if(smb->status.max_crcs) {
for(i=0;msgbuf[i];i++)
crc=ucrc32(msgbuf[i],crc);
crc=~crc;
i=smb_addcrc(smb,crc);
if(i) {
smb_freemsgdat(smb,offset,length,1);
smb_unlocksmbhdr(smb);
return(i);
}
}
memcpy(msg->hdr.id,"SHD\x1a",4);
msg->hdr.version=smb_ver();
msg->hdr.when_imported.time=time(NULL);
msg->hdr.when_imported.zone=cfg->sys_timezone;
msg->hdr.offset=offset;
smb_dfield(msg,TEXT_BODY,length);
smb_unlocksmbhdr(smb);
if((i=smb_addmsghdr(smb,msg,storage))!=0)
smb_freemsgdat(smb,offset,length,1);
return(i);
}