|
|
1.1 root 1: /* postmsg.cpp */
2:
3: /* Synchronet user create/post public message routine */
4:
5: /* $Id: postmsg.cpp,v 1.3 2000/12/31 03:41:55 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39:
40: /****************************************************************************/
41: /* Posts a message on subboard number sub, with 'top' as top of message. */
42: /* Returns 1 if posted, 0 if not. */
43: /****************************************************************************/
44: bool sbbs_t::postmsg(uint subnum, smbmsg_t *remsg, long wm_mode)
45: {
46: char str[256],touser[256],title[LEN_TITLE+1],buf[SDT_BLOCK_LEN]
47: ,top[256];
48: ushort xlat,msgattr;
49: int i,j,x,file,storage;
50: ulong l,length,offset,crc=0xffffffff;
51: FILE *instream;
52: smbmsg_t msg,tmpmsg;
53:
54: if(remsg) {
55: sprintf(title,"%.*s",LEN_TITLE,remsg->subj);
56: if(cfg.sub[subnum]->misc&SUB_INET) // All Internet posts to "All" 05/20/97
57: touser[0]=0;
58: else if(remsg->hdr.attr&MSG_ANONYMOUS)
59: strcpy(touser,text[Anonymous]);
60: else
61: strcpy(touser,remsg->from);
62: msgattr=(ushort)(remsg->hdr.attr&MSG_PRIVATE);
63: sprintf(top,text[RegardingByToOn],title,touser,remsg->to
64: ,timestr((time_t *)&remsg->hdr.when_written.time)
65: ,zonestr(remsg->hdr.when_written.zone)); }
66: else {
67: title[0]=0;
68: touser[0]=0;
69: top[0]=0;
70: msgattr=0; }
71:
72: if(useron.rest&FLAG('P')) {
73: bputs(text[R_Post]);
74: return(false); }
75:
76: if((cfg.sub[subnum]->misc&(SUB_QNET|SUB_FIDO|SUB_PNET|SUB_INET))
77: && (useron.rest&FLAG('N'))) {
78: bputs(text[CantPostOnSub]);
79: return(false); }
80:
81: if(useron.ptoday>=cfg.level_postsperday[useron.level]) {
82: bputs(text[TooManyPostsToday]);
83: return(false); }
84:
85: bprintf(text[Posting],cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname);
86: action=NODE_PMSG;
87: nodesync();
88:
89: if(!(msgattr&MSG_PRIVATE) && (cfg.sub[subnum]->misc&SUB_PONLY
90: || (cfg.sub[subnum]->misc&SUB_PRIV && !noyes(text[PrivatePostQ]))))
91: msgattr|=MSG_PRIVATE;
92:
93: if(sys_status&SS_ABORT)
94: return(false);
95:
96: if(!(cfg.sub[subnum]->misc&SUB_INET) // Prompt for TO: user
97: && (cfg.sub[subnum]->misc&SUB_TOUSER || msgattr&MSG_PRIVATE || touser[0])) {
98: if(!touser[0] && !(msgattr&MSG_PRIVATE))
99: strcpy(touser,"All");
100: bputs(text[PostTo]);
101: i=LEN_ALIAS;
102: if(cfg.sub[subnum]->misc&(SUB_PNET|SUB_INET))
103: i=60;
104: if(cfg.sub[subnum]->misc&SUB_FIDO)
105: i=35;
106: if(cfg.sub[subnum]->misc&SUB_QNET)
107: i=25;
108: getstr(touser,i,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
109: if(stricmp(touser,"ALL")
110: && !(cfg.sub[subnum]->misc&(SUB_PNET|SUB_FIDO|SUB_QNET|SUB_INET|SUB_ANON))) {
111: if(cfg.sub[subnum]->misc&SUB_NAME) {
112: if(!userdatdupe(useron.number,U_NAME,LEN_NAME,touser,0)) {
113: bputs(text[UnknownUser]);
114: return(false); } }
115: else {
116: if((i=finduser(touser))==0)
117: return(false);
118: username(&cfg,i,touser); } }
119: if(sys_status&SS_ABORT)
120: return(false); }
121:
122: if(!touser[0])
123: strcpy(touser,"All"); // Default to ALL
124:
125: if(!stricmp(touser,"SYSOP") && !SYSOP) // Change SYSOP to user #1
126: username(&cfg,1,touser);
127:
128: if(msgattr&MSG_PRIVATE && !stricmp(touser,"ALL")) {
129: bputs(text[NoToUser]);
130: return(false); }
131: if(msgattr&MSG_PRIVATE)
132: wm_mode|=WM_PRIVATE;
133:
134: if(cfg.sub[subnum]->misc&SUB_AONLY
135: || (cfg.sub[subnum]->misc&SUB_ANON && useron.exempt&FLAG('A')
136: && !noyes(text[AnonymousQ])))
137: msgattr|=MSG_ANONYMOUS;
138:
139: if(cfg.sub[subnum]->mod_ar[0] && chk_ar(cfg.sub[subnum]->mod_ar,&useron))
140: msgattr|=MSG_MODERATED;
141:
142: if(cfg.sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum))
143: msgattr|=MSG_PERMANENT;
144:
145: if(msgattr&MSG_PRIVATE)
146: bputs(text[PostingPrivately]);
147:
148: if(msgattr&MSG_ANONYMOUS)
149: bputs(text[PostingAnonymously]);
150:
151: if(cfg.sub[subnum]->misc&SUB_NAME)
152: bputs(text[UsingRealName]);
153:
154: sprintf(str,"%sINPUT.MSG",cfg.node_dir);
155: if(!writemsg(str,top,title,wm_mode,subnum,touser)) {
156: bputs(text[Aborted]);
157: return(false); }
158:
159: bputs(text[WritingIndx]);
160:
161: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
162: errormsg(WHERE,ERR_OPEN,cfg.sub[subnum]->code,i);
163: return(false); }
164:
165: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
166: smb.retry_time=cfg.smb_retry_time;
167: if((i=smb_open(&smb))!=0) {
168: smb_stack(&smb,SMB_STACK_POP);
169: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
170: return(false); }
171:
172: if(filelength(fileno(smb.shd_fp))<1) { /* Create it if it doesn't exist */
173: smb.status.max_crcs=cfg.sub[subnum]->maxcrcs;
174: smb.status.max_msgs=cfg.sub[subnum]->maxmsgs;
175: smb.status.max_age=cfg.sub[subnum]->maxage;
176: smb.status.attr=cfg.sub[subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
177: if((i=smb_create(&smb))!=0) {
178: smb_close(&smb);
179: smb_stack(&smb,SMB_STACK_POP);
180: errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
181: return(false); } }
182:
183: if((i=smb_locksmbhdr(&smb))!=0) {
184: smb_close(&smb);
185: smb_stack(&smb,SMB_STACK_POP);
186: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
187: return(false); }
188:
189: if((i=smb_getstatus(&smb))!=0) {
190: smb_close(&smb);
191: smb_stack(&smb,SMB_STACK_POP);
192: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error);
193: return(false); }
194:
195: length=flength(str)+2; /* +2 for translation string */
196:
197: if(length&0xfff00000UL) {
198: smb_close(&smb);
199: smb_stack(&smb,SMB_STACK_POP);
200: errormsg(WHERE,ERR_LEN,str,length);
201: return(false); }
202:
203: if(smb.status.attr&SMB_HYPERALLOC) {
204: offset=smb_hallocdat(&smb);
205: storage=SMB_HYPERALLOC; }
206: else {
207: if((i=smb_open_da(&smb))!=0) {
208: smb_unlocksmbhdr(&smb);
209: smb_close(&smb);
210: smb_stack(&smb,SMB_STACK_POP);
211: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
212: return(false); }
213: if(cfg.sub[subnum]->misc&SUB_FAST) {
214: offset=smb_fallocdat(&smb,length,1);
215: storage=SMB_FASTALLOC; }
216: else {
217: offset=smb_allocdat(&smb,length,1);
218: storage=SMB_SELFPACK; }
219: smb_close_da(&smb); }
220:
221: if((file=open(str,O_RDONLY|O_BINARY))==-1
222: || (instream=fdopen(file,"rb"))==NULL) {
223: smb_freemsgdat(&smb,offset,length,1);
224: smb_unlocksmbhdr(&smb);
225: smb_close(&smb);
226: smb_stack(&smb,SMB_STACK_POP);
227: errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
228: return(false); }
229:
230: setvbuf(instream,NULL,_IOFBF,2*1024);
231: fseek(smb.sdt_fp,offset,SEEK_SET);
232: xlat=XLAT_NONE;
233: fwrite(&xlat,2,1,smb.sdt_fp);
234: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
235: while(!feof(instream)) {
236: memset(buf,0,x);
237: j=fread(buf,1,x,instream);
238: if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
239: buf[j-1]=buf[j-2]=0; /* Convert to NULL */
240: if(cfg.sub[subnum]->maxcrcs) {
241: for(i=0;i<j;i++)
242: crc=ucrc32(buf[i],crc); }
243: fwrite(buf,j,1,smb.sdt_fp);
244: x=SDT_BLOCK_LEN; }
245: fflush(smb.sdt_fp);
246: fclose(instream);
247: crc=~crc;
248:
249: memset(&msg,0,sizeof(smbmsg_t));
250: memcpy(msg.hdr.id,"SHD\x1a",4);
251: msg.hdr.version=smb_ver();
252: msg.hdr.attr=msg.idx.attr=msgattr;
253: msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
254: msg.hdr.when_written.zone=msg.hdr.when_imported.zone=cfg.sys_timezone;
255: if(remsg) {
256: msg.hdr.thread_orig=remsg->hdr.number;
257: if(!remsg->hdr.thread_first) {
258: remsg->hdr.thread_first=smb.status.last_msg+1;
259: if((i=smb_lockmsghdr(&smb,remsg))!=0)
260: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
261: else {
262: i=smb_putmsghdr(&smb,remsg);
263: smb_unlockmsghdr(&smb,remsg);
264: if(i)
265: errormsg(WHERE,ERR_WRITE,smb.file,i); } }
266: else {
267: l=remsg->hdr.thread_first;
268: while(1) {
269: tmpmsg.idx.offset=0;
270: if(!loadmsg(&tmpmsg,l))
271: break;
272: if(tmpmsg.hdr.thread_next && tmpmsg.hdr.thread_next!=l) {
273: l=tmpmsg.hdr.thread_next;
274: smb_unlockmsghdr(&smb,&tmpmsg);
275: smb_freemsgmem(&tmpmsg);
276: continue; }
277: tmpmsg.hdr.thread_next=smb.status.last_msg+1;
278: if((i=smb_putmsghdr(&smb,&tmpmsg))!=0)
279: errormsg(WHERE,ERR_WRITE,smb.file,i);
280: smb_unlockmsghdr(&smb,&tmpmsg);
281: smb_freemsgmem(&tmpmsg);
282: break; } } }
283:
284:
285: if(cfg.sub[subnum]->maxcrcs) {
286: i=smb_addcrc(&smb,crc);
287: if(i) {
288: smb_freemsgdat(&smb,offset,length,1);
289: smb_unlocksmbhdr(&smb);
290: smb_close(&smb);
291: smb_stack(&smb,SMB_STACK_POP);
292: bputs("\1r\1h\1iDuplicate message!\r\n");
293: return(false); } }
294:
295: msg.hdr.offset=offset;
296:
297: smb_hfield(&msg,RECIPIENT,strlen(touser),touser);
298: strlwr(touser);
299: msg.idx.to=crc16(touser);
300:
301: strcpy(str,cfg.sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias);
302: smb_hfield(&msg,SENDER,strlen(str),str);
303: strlwr(str);
304: msg.idx.from=crc16(str);
305:
306: sprintf(str,"%u",useron.number);
307: smb_hfield(&msg,SENDEREXT,strlen(str),str);
308:
309: smb_hfield(&msg,SUBJECT,strlen(title),title);
310: strcpy(str,title);
311: strlwr(str);
312: remove_re(str);
313: msg.idx.subj=crc16(str);
314:
315: smb_dfield(&msg,TEXT_BODY,length);
316:
317: smb_unlocksmbhdr(&smb);
318: i=smb_addmsghdr(&smb,&msg,storage);
319: smb_close(&smb);
320: smb_stack(&smb,SMB_STACK_POP);
321:
322: smb_freemsgmem(&msg);
323: if(i) {
324: smb_freemsgdat(&smb,offset,length,1);
325: errormsg(WHERE,ERR_WRITE,smb.file,i);
326: return(false); }
327:
328: useron.ptoday++;
329: useron.posts++;
330: logon_posts++;
331: putuserrec(&cfg,useron.number,U_POSTS,5,ultoa(useron.posts,str,10));
332: putuserrec(&cfg,useron.number,U_PTODAY,5,ultoa(useron.ptoday,str,10));
333: bprintf(text[Posted],cfg.grp[cfg.sub[subnum]->grp]->sname
334: ,cfg.sub[subnum]->lname);
335: sprintf(str,"Posted on %s %s",cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname);
336: logline("P+",str);
337: if(cfg.sub[subnum]->misc&SUB_FIDO && cfg.sub[subnum]->echomail_sem[0]) /* semaphore */
338: if((file=nopen(cmdstr(cfg.sub[subnum]->echomail_sem,nulstr,nulstr,NULL)
339: ,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
340: close(file);
341: return(true);
342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.