|
|
1.1 root 1: /* un_rep.cpp */
2:
3: /* Synchronet QWK replay (REP) packet unpacking routine */
4:
5: /* $Id: un_rep.cpp,v 1.36 2006/01/31 02:51:59 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 2006 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: #include "qwk.h"
40:
41: /****************************************************************************/
42: /* Unpacks .REP packet, 'repname' is the path and filename of the packet */
43: /****************************************************************************/
44: bool sbbs_t::unpack_rep(char* repfile)
45: {
46: char str[MAX_PATH+1],fname[MAX_PATH+1]
47: ,*AttemptedToUploadREPpacket="Attempted to upload REP packet";
48: char tmp[512];
49: char from[26];
50: char to[26];
51: char inbox[MAX_PATH+1];
52: char block[QWK_BLOCK_LEN];
53: int file;
54: uint i,j,k,lastsub=INVALID_SUB;
55: long l,size,misc;
56: ulong n;
57: ulong ex;
58: node_t node;
59: FILE* rep;
60: DIR* dir;
61: DIRENT* dirent;
62: BOOL twit_list;
63:
64: sprintf(fname,"%stwitlist.cfg",cfg.ctrl_dir);
65: twit_list=fexist(fname);
66:
67: if(repfile!=NULL)
68: strcpy(str,repfile);
69: else
70: sprintf(str,"%s%s.rep",cfg.temp_dir,cfg.sys_id);
71: if(!fexistcase(str)) {
72: bputs(text[QWKReplyNotReceived]);
73: logline("U!",AttemptedToUploadREPpacket);
74: logline(nulstr,"REP file not received");
75: return(false);
76: }
77: for(k=0;k<cfg.total_fextrs;k++)
78: if(!stricmp(cfg.fextr[k]->ext,useron.tmpext) && chk_ar(cfg.fextr[k]->ar,&useron))
79: break;
80: if(k>=cfg.total_fextrs)
81: k=0;
82: ex=EX_OUTL|EX_OUTR;
83: if(online!=ON_REMOTE)
84: ex|=EX_OFFLINE;
85: i=external(cmdstr(cfg.fextr[k]->cmd,str,ALLFILES,NULL),ex);
86: if(i) {
87: bputs(text[QWKExtractionFailed]);
88: logline("U!",AttemptedToUploadREPpacket);
89: logline(nulstr,"Extraction failed");
90: return(false);
91: }
92: sprintf(str,"%s%s.msg",cfg.temp_dir,cfg.sys_id);
93: if(!fexistcase(str)) {
94: bputs(text[QWKReplyNotReceived]);
95: logline("U!",AttemptedToUploadREPpacket);
96: logline(nulstr,"MSG file not received");
97: return(false);
98: }
99: if((rep=fnopen(&file,str,O_RDONLY))==NULL) {
100: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
101: return(false);
102: }
103: size=filelength(file);
104: fread(block,QWK_BLOCK_LEN,1,rep);
105: if(strnicmp((char *)block,cfg.sys_id,strlen(cfg.sys_id))) {
106: fclose(rep);
107: bputs(text[QWKReplyNotReceived]);
108: logline("U!",AttemptedToUploadREPpacket);
109: logline(nulstr,"Incorrect BBSID");
110: return(false);
111: }
112: logline("U+","Uploaded REP packet");
113: /********************/
114: /* Process messages */
115: /********************/
116: bputs(text[QWKUnpacking]);
117:
118: for(l=QWK_BLOCK_LEN;l<size;l+=i*QWK_BLOCK_LEN) {
119: if(terminated) {
120: bprintf("!Terminated");
121: break;
122: }
123:
124: lncntr=0; /* defeat pause */
125: if(fseek(rep,l,SEEK_SET)!=0) {
126: sprintf(str,"%s.msg", cfg.sys_id);
127: errormsg(WHERE,ERR_SEEK,str,l);
128: break;
129: }
130: if(fread(block,1,QWK_BLOCK_LEN,rep)!=QWK_BLOCK_LEN) {
131: sprintf(str,"%s.msg", cfg.sys_id);
132: errormsg(WHERE,ERR_READ,str,ftell(rep));
133: break;
134: }
135: sprintf(tmp,"%.6s",block+116);
136: i=atoi(tmp); /* i = number of blocks */
137: if(i<2) {
138: sprintf(str,"%s.msg blocks (read '%s' at offset %ld)", cfg.sys_id, tmp, l);
139: errormsg(WHERE,ERR_CHK,str,i);
140: i=1;
141: continue;
142: }
143: if(atoi(block+1)==0) { /**********/
144: if(useron.rest&FLAG('E')) { /* E-mail */
145: bputs(text[R_Email]); /**********/
146: continue;
147: }
148:
149: sprintf(str,"%25.25s",block+21);
150: truncsp(str);
151: if(!stricmp(str,"NETMAIL")) { /* QWK to FidoNet NetMail */
152: qwktonetmail(rep,block,NULL,0);
153: continue;
154: }
155: if(strchr(str,'@')) {
156: qwktonetmail(rep,block,str,0);
157: continue;
158: }
159: if(!stricmp(str,"SBBS")) { /* to SBBS, config stuff */
160: qwkcfgline(block+71,INVALID_SUB);
161: continue;
162: }
163:
164: if(useron.etoday>=cfg.level_emailperday[useron.level]
165: && !(useron.rest&FLAG('Q'))) {
166: bputs(text[TooManyEmailsToday]);
167: continue;
168: }
169: j=atoi(str);
170: if(j && j>lastuser(&cfg))
171: j=0;
172: if(!j)
173: j=matchuser(&cfg,str,TRUE /* sysop_alias */);
174: if(!j) {
175: bputs(text[UnknownUser]);
176: continue;
177: }
178: if(j==1 && useron.rest&FLAG('S')) {
179: bprintf(text[R_Feedback],cfg.sys_op);
180: continue;
181: }
182:
183: getuserrec(&cfg,j,U_MISC,8,str);
184: misc=ahtoul(str);
185: if(misc&NETMAIL && cfg.sys_misc&SM_FWDTONET) {
186: getuserrec(&cfg,j,U_NETMAIL,LEN_NETMAIL,str);
187: qwktonetmail(rep,block,str,0);
188: continue;
189: }
190:
191: sprintf(smb.file,"%smail",cfg.data_dir);
192: smb.retry_time=cfg.smb_retry_time;
193:
194: if(lastsub!=INVALID_SUB) {
195: smb_close(&smb);
196: lastsub=INVALID_SUB;
197: }
198:
199: smb.subnum=INVALID_SUB;
200: if((k=smb_open(&smb))!=0) {
201: errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error);
202: continue;
203: }
204:
205: if(!filelength(fileno(smb.shd_fp))) {
206: smb.status.max_crcs=cfg.mail_maxcrcs;
207: smb.status.max_msgs=0;
208: smb.status.max_age=cfg.mail_maxage;
209: smb.status.attr=SMB_EMAIL;
210: if((k=smb_create(&smb))!=0) {
211: smb_close(&smb);
212: errormsg(WHERE,ERR_CREATE,smb.file,k);
213: continue;
214: }
215: }
216:
217: if((k=smb_locksmbhdr(&smb))!=0) {
218: smb_close(&smb);
219: errormsg(WHERE,ERR_LOCK,smb.file,k);
220: continue;
221: }
222:
223: if((k=smb_getstatus(&smb))!=0) {
224: smb_close(&smb);
225: errormsg(WHERE,ERR_READ,smb.file,k);
226: continue;
227: }
228:
229: smb_unlocksmbhdr(&smb);
230:
231: if(!qwktomsg(rep,block,0,INVALID_SUB,j)) {
232: smb_close(&smb);
233: continue;
234: }
235: smb_close(&smb);
236:
237: if(j==1) {
238: useron.fbacks++;
239: logon_fbacks++;
240: putuserrec(&cfg,useron.number,U_FBACKS,5
241: ,ultoa(useron.fbacks,tmp,10));
242: }
243: else {
244: useron.emails++;
245: logon_emails++;
246: putuserrec(&cfg,useron.number,U_EMAILS,5
247: ,ultoa(useron.emails,tmp,10));
248: }
249: useron.etoday++;
250: putuserrec(&cfg,useron.number,U_ETODAY,5
251: ,ultoa(useron.etoday,tmp,10));
252: bprintf(text[Emailed],username(&cfg,j,tmp),j);
253: sprintf(str,"%s sent e-mail to %s #%d"
254: ,useron.alias,username(&cfg,j,tmp),j);
255: logline("E+",str);
256: if(useron.rest&FLAG('Q')) {
257: sprintf(tmp,"%-25.25s",block+46);
258: truncsp(tmp);
259: }
260: else
261: strcpy(tmp,useron.alias);
262: for(k=1;k<=cfg.sys_nodes;k++) { /* Tell user, if online */
263: getnodedat(k,&node,0);
264: if(node.useron==j && !(node.misc&NODE_POFF)
265: && (node.status==NODE_INUSE
266: || node.status==NODE_QUIET)) {
267: sprintf(str,text[EmailNodeMsg]
268: ,cfg.node_num,tmp);
269: putnmsg(&cfg,k,str);
270: break;
271: }
272: }
273: if(k>cfg.sys_nodes) {
274: sprintf(str,text[UserSentYouMail],tmp);
275: putsmsg(&cfg,j,str);
276: }
277: } /* end of email */
278:
279: /**************************/
280: else { /* message on a sub-board */
281: /**************************/
282: n=atol((char *)block+1); /* conference number */
283: for(j=0;j<usrgrps;j++) {
284: for(k=0;k<usrsubs[j];k++)
285: if(cfg.sub[usrsub[j][k]]->qwkconf==n)
286: break;
287: if(k<usrsubs[j])
288: break;
289: }
290:
291: if(j>=usrgrps) {
292: if(n<1000) { /* version 1 method, start at 101 */
293: j=n/100;
294: k=n-(j*100);
295: }
296: else { /* version 2 method, start at 1001 */
297: j=n/1000;
298: k=n-(j*1000);
299: }
300: j--; /* j is group */
301: k--; /* k is sub */
302: if(j>=usrgrps || k>=usrsubs[j] || cfg.sub[usrsub[j][k]]->qwkconf) {
303: bprintf(text[QWKInvalidConferenceN],n);
304: sprintf(str,"%s: Invalid conference number %lu",useron.alias,n);
305: logline("P!",str);
306: continue;
307: }
308: }
309:
310: n=usrsub[j][k];
311:
312: /* if posting, add to new-scan config for QWKnet nodes automatically */
313: if(useron.rest&FLAG('Q'))
314: subscan[n].cfg|=SUB_CFG_NSCAN;
315:
316: sprintf(str,"%-25.25s","SBBS");
317: if(!strnicmp((char *)block+21,str,25)) { /* to SBBS, config stuff */
318: qwkcfgline((char *)block+71,n);
319: continue;
320: }
321:
322: if(!SYSOP && cfg.sub[n]->misc&SUB_QNET) { /* QWK Netted */
323: sprintf(str,"%-25.25s","DROP"); /* Drop from new-scan? */
324: if(!strnicmp((char *)block+71,str,25)) /* don't allow post */
325: continue;
326: sprintf(str,"%-25.25s","ADD"); /* Add to new-scan? */
327: if(!strnicmp((char *)block+71,str,25)) /* don't allow post */
328: continue;
329: }
330:
331: if(useron.rest&FLAG('Q') && !(cfg.sub[n]->misc&SUB_QNET)) {
332: bputs(text[CantPostOnSub]);
333: logline("P!","Attempted to post on non-QWKnet sub");
334: continue;
335: }
336:
337: if(useron.rest&FLAG('P')) {
338: bputs(text[R_Post]);
339: logline("P!","Post attempted");
340: continue;
341: }
342:
343: if(useron.ptoday>=cfg.level_postsperday[useron.level]
344: && !(useron.rest&FLAG('Q'))) {
345: bputs(text[TooManyPostsToday]);
346: continue;
347: }
348:
349: if(useron.rest&FLAG('N')
350: && cfg.sub[n]->misc&(SUB_FIDO|SUB_PNET|SUB_QNET|SUB_INET)) {
351: bputs(text[CantPostOnSub]);
352: logline("P!","Networked post attempted");
353: continue;
354: }
355:
356: if(!chk_ar(cfg.sub[n]->post_ar,&useron)) {
357: bputs(text[CantPostOnSub]);
358: logline("P!","Post attempted");
359: continue;
360: }
361:
362: if((block[0]=='*' || block[0]=='+')
363: && !(cfg.sub[n]->misc&SUB_PRIV)) {
364: bputs(text[PrivatePostsNotAllowed]);
365: logline("P!","Private post attempt");
366: continue;
367: }
368:
369: if(block[0]=='*' || block[0]=='+' /* Private post */
370: || cfg.sub[n]->misc&SUB_PONLY) {
371: sprintf(str,"%-25.25s",nulstr);
372: sprintf(tmp,"%-25.25s","ALL");
373: if(!strnicmp((char *)block+21,str,25)
374: || !strnicmp((char *)block+21,tmp,25)) { /* to blank */
375: bputs(text[NoToUser]); /* or all */
376: continue;
377: }
378: }
379:
380: if(!SYSOP && !(useron.rest&FLAG('Q'))) {
381: sprintf(str,"%-25.25s","SYSOP");
382: if(!strnicmp((char *)block+21,str,25)) {
383: sprintf(str,"%-25.25s",username(&cfg,1,tmp));
384: memcpy((char *)block+21,str,25); /* change from sysop */
385: } /* to user name */
386: }
387:
388: /* TWIT FILTER */
389: if(twit_list) {
390: sprintf(fname,"%stwitlist.cfg",cfg.ctrl_dir);
391: sprintf(from,"%25.25s",block+46); /* From user */
392: truncsp(from);
393: sprintf(to,"%25.25s",block+21); /* To user */
394: truncsp(to);
395:
396: if(findstr(from,fname) || findstr(to,fname)) {
397: sprintf(str,"Filtering post from %s to %s on %s %s"
398: ,from
399: ,to
400: ,cfg.grp[cfg.sub[n]->grp]->sname,cfg.sub[n]->lname);
401: logline("P!",str);
402: continue;
403: }
404: }
405:
406: if(n!=lastsub) {
407: if(lastsub!=INVALID_SUB)
408: smb_close(&smb);
409: lastsub=INVALID_SUB;
410: sprintf(smb.file,"%s%s",cfg.sub[n]->data_dir,cfg.sub[n]->code);
411: smb.retry_time=cfg.smb_retry_time;
412: smb.subnum=n;
413: if((j=smb_open(&smb))!=0) {
414: errormsg(WHERE,ERR_OPEN,smb.file,j,smb.last_error);
415: continue;
416: }
417:
418: if(!filelength(fileno(smb.shd_fp))) {
419: smb.status.max_crcs=cfg.sub[n]->maxcrcs;
420: smb.status.max_msgs=cfg.sub[n]->maxmsgs;
421: smb.status.max_age=cfg.sub[n]->maxage;
422: smb.status.attr=cfg.sub[n]->misc&SUB_HYPER ? SMB_HYPERALLOC:0;
423: if((j=smb_create(&smb))!=0) {
424: smb_close(&smb);
425: lastsub=INVALID_SUB;
426: errormsg(WHERE,ERR_CREATE,smb.file,j);
427: continue;
428: }
429: }
430:
431: if((j=smb_locksmbhdr(&smb))!=0) {
432: smb_close(&smb);
433: lastsub=INVALID_SUB;
434: errormsg(WHERE,ERR_LOCK,smb.file,j);
435: continue;
436: }
437: if((j=smb_getstatus(&smb))!=0) {
438: smb_close(&smb);
439: lastsub=INVALID_SUB;
440: errormsg(WHERE,ERR_READ,smb.file,j);
441: continue;
442: }
443: smb_unlocksmbhdr(&smb);
444: lastsub=n;
445: }
446:
447: if(!qwktomsg(rep,block,0,n,0))
448: continue;
449:
450: logon_posts++;
451: user_posted_msg(&cfg, &useron, 1);
452: bprintf(text[Posted],cfg.grp[cfg.sub[n]->grp]->sname
453: ,cfg.sub[n]->lname);
454: sprintf(str,"%s posted on %s %s"
455: ,useron.alias,cfg.grp[cfg.sub[n]->grp]->sname,cfg.sub[n]->lname);
456: signal_sub_sem(&cfg,n);
457: logline("P+",str);
458: if(!(useron.rest&FLAG('Q')))
459: user_event(EVENT_POST);
460: } /* end of public message */
461: }
462:
463: update_qwkroute(NULL); /* Write ROUTE.DAT */
464:
465: if(lastsub!=INVALID_SUB)
466: smb_close(&smb);
467: fclose(rep);
468:
469: if(useron.rest&FLAG('Q')) { /* QWK Net Node */
470: sprintf(str,"%s%s.msg",cfg.temp_dir,cfg.sys_id);
471: if(fexistcase(str))
472: remove(str);
473: sprintf(str,"%s%s.rep",cfg.temp_dir,cfg.sys_id);
474: if(fexistcase(str))
475: remove(str);
476: sprintf(str,"%sATTXREF.DAT",cfg.temp_dir);
477: if(fexistcase(str))
478: remove(str);
479:
480: dir=opendir(cfg.temp_dir);
481: while(dir!=NULL && (dirent=readdir(dir))!=NULL) { /* Extra files */
482: // Move files
483: sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
484: if(isdir(str))
485: continue;
486:
487: // Create directory if necessary
488: sprintf(inbox,"%sqnet/%s.in",cfg.data_dir,useron.alias);
489: MKDIR(inbox);
490:
491: sprintf(fname,"%s/%s",inbox,dirent->d_name);
492: mv(str,fname,1);
493: sprintf(str,text[ReceivedFileViaQWK],dirent->d_name,useron.alias);
494: putsmsg(&cfg,1,str);
495: }
496: if(dir!=NULL)
497: closedir(dir);
498: sprintf(str,"%sqnet-rep.now",cfg.data_dir);
499: ftouch(str);
500: }
501:
502: bputs(text[QWKUnpacked]);
503: CRLF;
504: /**********************************************/
505: /* Hang-up now if that's what the user wanted */
506: /**********************************************/
507: autohangup();
508:
509: return(true);
510: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.