|
|
1.1 root 1: /* str.cpp */
2:
3: /* Synchronet high-level string i/o routines */
4:
5: /* $Id: str.cpp,v 1.13 2000/12/11 23:21:12 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: const char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
41: const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
42: ,"Jul","Aug","Sep","Oct","Nov","Dec"};
43:
44: /****************************************************************************/
45: /* Lists all users who have access to the current sub. */
46: /****************************************************************************/
47: void sbbs_t::userlist(char mode)
48: {
49: char name[256],sort=0;
50: char tmp[512];
51: int i,j,k,users=0;
52: char * line[1000];
53: user_t user;
54:
55: if(lastuser(&cfg)<=1000)
56: sort=yesno(text[SortAlphaQ]);
57: if(sort) {
58: bputs(text[CheckingSlots]); }
59: else {
60: CRLF; }
61: j=0;
62: k=lastuser(&cfg);
63: for(i=1;i<=k && !msgabort();i++) {
64: if(sort && (online==ON_LOCAL || !rioctl(TXBC)))
65: bprintf("%-4d\b\b\b\b",i);
66: user.number=i;
67: getuserdat(&cfg,&user);
68: if(user.misc&(DELETED|INACTIVE))
69: continue;
70: users++;
71: if(mode==UL_SUB) {
72: if(!usrgrps)
73: continue;
74: if(!chk_ar(cfg.grp[usrgrp[curgrp]]->ar,&user))
75: continue;
76: if(!chk_ar(cfg.sub[usrsub[curgrp][cursub[curgrp]]]->ar,&user)
77: || (cfg.sub[usrsub[curgrp][cursub[curgrp]]]->read_ar[0]
78: && !chk_ar(cfg.sub[usrsub[curgrp][cursub[curgrp]]]->read_ar,&user)))
79: continue; }
80: else if(mode==UL_DIR) {
81: if(user.rest&FLAG('T'))
82: continue;
83: if(!usrlibs)
84: continue;
85: if(!chk_ar(cfg.lib[usrlib[curlib]]->ar,&user))
86: continue;
87: if(!chk_ar(cfg.dir[usrdir[curlib][curdir[curlib]]]->ar,&user))
88: continue; }
89: if(sort) {
90: if((line[j]=(char *)MALLOC(128))==0) {
91: errormsg(WHERE,ERR_ALLOC,nulstr,83);
92: for(i=0;i<j;i++)
93: FREE(line[i]);
94: return; }
95: sprintf(name,"%s #%d",user.alias,i);
96: sprintf(line[j],text[UserListFmt],name
97: ,cfg.sys_misc&SM_LISTLOC ? user.location : user.note
98: ,unixtodstr(&cfg,user.laston,tmp)
99: ,user.modem); }
100: else {
101: sprintf(name,"%s #%u",user.alias,i);
102: bprintf(text[UserListFmt],name
103: ,cfg.sys_misc&SM_LISTLOC ? user.location : user.note
104: ,unixtodstr(&cfg,user.laston,tmp)
105: ,user.modem); }
106: j++; }
107: if(i<=k) { /* aborted */
108: if(sort)
109: for(i=0;i<j;i++)
110: FREE(line[i]);
111: return; }
112: if(!sort) {
113: CRLF; }
114: bprintf(text[NTotalUsers],users);
115: if(mode==UL_SUB)
116: bprintf(text[NUsersOnCurSub],j);
117: else if(mode==UL_DIR)
118: bprintf(text[NUsersOnCurDir],j);
119: if(!sort)
120: return;
121: CRLF;
122: qsort((void *)line,j,sizeof(line[0])
123: ,(int(*)(const void*, const void*))pstrcmp);
124: for(i=0;i<j && !msgabort();i++)
125: bputs(line[i]);
126: for(i=0;i<j;i++)
127: FREE(line[i]);
128: }
129:
130: /****************************************************************************/
131: /* SIF input function. See SIF.DOC for more info */
132: /****************************************************************************/
133: void sbbs_t::sif(char *fname, char *answers, long len)
134: {
135: char str[256],tmplt[256],HUGE16 *buf;
136: uint t,max,min,mode,cr;
137: int file;
138: long length,l=0,m,top,a=0;
139:
140: sprintf(str,"%s%s.sif",cfg.text_dir,fname);
141: if((file=nopen(str,O_RDONLY))==-1) {
142: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
143: answers[0]=0;
144: return; }
145: length=filelength(file);
146: if((buf=(char *)MALLOC(length))==0) {
147: close(file);
148: errormsg(WHERE,ERR_ALLOC,str,length);
149: answers[0]=0;
150: return; }
151: if(lread(file,buf,length)!=length) {
152: close(file);
153: errormsg(WHERE,ERR_READ,str,length);
154: answers[0]=0;
155: return; }
156: close(file);
157: while(l<length && online) {
158: mode=min=max=t=cr=0;
159: top=l;
160: while(l<length && buf[l++]!=STX);
161: for(m=l;m<length;m++)
162: if(buf[m]==ETX || !buf[m]) {
163: buf[m]=0;
164: break; }
165: if(l>=length) break;
166: if(online==ON_REMOTE) {
167: rioctl(IOCM|ABORT);
168: rioctl(IOCS|ABORT); }
169: putmsg(buf+l,P_SAVEATR);
170: m++;
171: if(toupper(buf[m])!='C' && toupper(buf[m])!='S')
172: continue;
173: SYNC;
174: if(online==ON_REMOTE)
175: rioctl(IOSM|ABORT);
176: if(a>=len) {
177: errormsg(WHERE,ERR_LEN,fname,len);
178: break; }
179: if((buf[m]&0xdf)=='C') {
180: if((buf[m+1]&0xdf)=='U') { /* Uppercase only */
181: mode|=K_UPPER;
182: m++; }
183: else if((buf[m+1]&0xdf)=='N') { /* Numbers only */
184: mode|=K_NUMBER;
185: m++; }
186: if((buf[m+1]&0xdf)=='L') { /* Draw line */
187: if(useron.misc&COLOR)
188: attr(cfg.color[clr_inputline]);
189: else
190: attr(BLACK|(LIGHTGRAY<<4));
191: bputs(" \b");
192: m++; }
193: if((buf[m+1]&0xdf)=='R') { /* Add CRLF */
194: cr=1;
195: m++; }
196: if(buf[m+1]=='"') {
197: m+=2;
198: for(l=m;l<length;l++)
199: if(buf[l]=='"') {
200: buf[l]=0;
201: break; }
202: answers[a++]=(char)getkeys((char *)buf+m,0); }
203: else {
204: answers[a]=getkey(mode);
205: outchar(answers[a++]);
206: attr(LIGHTGRAY);
207: CRLF; }
208: if(cr) {
209: answers[a++]=CR;
210: answers[a++]=LF; } }
211: else if((buf[m]&0xdf)=='S') { /* String */
212: if((buf[m+1]&0xdf)=='U') { /* Uppercase only */
213: mode|=K_UPPER;
214: m++; }
215: else if((buf[m+1]&0xdf)=='F') { /* Force Upper/Lowr case */
216: mode|=K_UPRLWR;
217: m++; }
218: else if((buf[m+1]&0xdf)=='N') { /* Numbers only */
219: mode|=K_NUMBER;
220: m++; }
221: if((buf[m+1]&0xdf)=='L') { /* Draw line */
222: mode|=K_LINE;
223: m++; }
224: if((buf[m+1]&0xdf)=='R') { /* Add CRLF */
225: cr=1;
226: m++; }
227: if(isdigit(buf[m+1])) {
228: max=buf[++m]&0xf;
229: if(isdigit(buf[m+1]))
230: max=max*10+(buf[++m]&0xf); }
231: if(buf[m+1]=='.' && isdigit(buf[m+2])) {
232: m++;
233: min=buf[++m]&0xf;
234: if(isdigit(buf[m+1]))
235: min=min*10+(buf[++m]&0xf); }
236: if(buf[m+1]=='"') {
237: m++;
238: mode&=~K_NUMBER;
239: while(buf[++m]!='"' && t<80)
240: tmplt[t++]=buf[m];
241: tmplt[t]=0;
242: max=strlen(tmplt); }
243: if(t) {
244: if(gettmplt(str,tmplt,mode)<min) {
245: l=top;
246: continue; } }
247: else {
248: if(!max)
249: continue;
250: if(getstr(str,max,mode)<min) {
251: l=top;
252: continue; } }
253: if(!cr) {
254: for(cr=0;str[cr];cr++)
255: answers[a+cr]=str[cr];
256: while(cr<max)
257: answers[a+cr++]=ETX;
258: a+=max; }
259: else {
260: putrec(answers,a,max,str);
261: putrec(answers,a+max,2,crlf);
262: a+=max+2; } } }
263: answers[a]=0;
264: FREE((char *)buf);
265: }
266:
267: /****************************************************************************/
268: /* SIF output function. See SIF.DOC for more info */
269: /****************************************************************************/
270: void sbbs_t::sof(char *fname, char *answers, long len)
271: {
272: char str[256],HUGE16 *buf,max,min,cr;
273: int file;
274: long length,l=0,m,a=0;
275:
276: sprintf(str,"%s%s.sif",cfg.text_dir,fname);
277: if((file=nopen(str,O_RDONLY))==-1) {
278: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
279: answers[0]=0;
280: return; }
281: length=filelength(file);
282: if((buf=(char *)MALLOC(length))==0) {
283: close(file);
284: errormsg(WHERE,ERR_ALLOC,str,length);
285: answers[0]=0;
286: return; }
287: if(lread(file,buf,length)!=length) {
288: close(file);
289: errormsg(WHERE,ERR_READ,str,length);
290: answers[0]=0;
291: return; }
292: close(file);
293: while(l<length && online) {
294: min=max=cr=0;
295: while(l<length && buf[l++]!=STX);
296: for(m=l;m<length;m++)
297: if(buf[m]==ETX || !buf[m]) {
298: buf[m]=0;
299: break; }
300: if(l>=length) break;
301: if(online==ON_REMOTE) {
302: rioctl(IOCM|ABORT);
303: rioctl(IOCS|ABORT); }
304: putmsg(buf+l,P_SAVEATR);
305: m++;
306: if(toupper(buf[m])!='C' && toupper(buf[m])!='S')
307: continue;
308: SYNC;
309: if(online==ON_REMOTE)
310: rioctl(IOSM|ABORT);
311: if(a>=len) {
312: bprintf("\r\nSOF: %s defined more data than buffer size "
313: "(%lu bytes)\r\n",fname,len);
314: break; }
315: if((buf[m]&0xdf)=='C') {
316: if((buf[m+1]&0xdf)=='U') /* Uppercase only */
317: m++;
318: else if((buf[m+1]&0xdf)=='N') /* Numbers only */
319: m++;
320: if((buf[m+1]&0xdf)=='L') { /* Draw line */
321: if(useron.misc&COLOR)
322: attr(cfg.color[clr_inputline]);
323: else
324: attr(BLACK|(LIGHTGRAY<<4));
325: bputs(" \b");
326: m++; }
327: if((buf[m+1]&0xdf)=='R') { /* Add CRLF */
328: cr=1;
329: m++; }
330: outchar(answers[a++]);
331: attr(LIGHTGRAY);
332: CRLF;
333: if(cr)
334: a+=2; }
335: else if((buf[m]&0xdf)=='S') { /* String */
336: if((buf[m+1]&0xdf)=='U')
337: m++;
338: else if((buf[m+1]&0xdf)=='F')
339: m++;
340: else if((buf[m+1]&0xdf)=='N') /* Numbers only */
341: m++;
342: if((buf[m+1]&0xdf)=='L') {
343: if(useron.misc&COLOR)
344: attr(cfg.color[clr_inputline]);
345: else
346: attr(BLACK|(LIGHTGRAY<<4));
347: m++; }
348: if((buf[m+1]&0xdf)=='R') {
349: cr=1;
350: m++; }
351: if(isdigit(buf[m+1])) {
352: max=buf[++m]&0xf;
353: if(isdigit(buf[m+1]))
354: max=max*10+(buf[++m]&0xf); }
355: if(buf[m+1]=='.' && isdigit(buf[m+2])) {
356: m++;
357: min=buf[++m]&0xf;
358: if(isdigit(buf[m+1]))
359: min=min*10+(buf[++m]&0xf); }
360: if(buf[m+1]=='"') {
361: max=0;
362: m++;
363: while(buf[++m]!='"' && max<80)
364: max++; }
365: if(!max)
366: continue;
367: getrec(answers,a,max,str);
368: bputs(str);
369: attr(LIGHTGRAY);
370: CRLF;
371: if(!cr)
372: a+=max;
373: else
374: a+=max+2; } }
375: FREE((char *)buf);
376: }
377:
378: /****************************************************************************/
379: /* Creates data file 'datfile' from input via sif file 'siffile' */
380: /****************************************************************************/
381: void sbbs_t::create_sif_dat(char *siffile, char *datfile)
382: {
383: char *buf;
384: int file;
385:
386: if((buf=(char *)MALLOC(SIF_MAXBUF))==NULL) {
387: errormsg(WHERE,ERR_ALLOC,siffile,SIF_MAXBUF);
388: return; }
389: memset(buf,SIF_MAXBUF,0); /* initialize to null */
390: sif(siffile,buf,SIF_MAXBUF);
391: if((file=nopen(datfile,O_WRONLY|O_TRUNC|O_CREAT))==-1) {
392: FREE(buf);
393: errormsg(WHERE,ERR_OPEN,datfile,O_WRONLY|O_TRUNC|O_CREAT);
394: return; }
395: write(file,buf,strlen(buf));
396: close(file);
397: FREE(buf);
398: }
399:
400: /****************************************************************************/
401: /* Reads data file 'datfile' and displays output via sif file 'siffile' */
402: /****************************************************************************/
403: void sbbs_t::read_sif_dat(char *siffile, char *datfile)
404: {
405: char *buf;
406: int file;
407: long length;
408:
409: if((file=nopen(datfile,O_RDONLY))==-1) {
410: errormsg(WHERE,ERR_OPEN,datfile,O_RDONLY);
411: return; }
412: length=filelength(file);
413: if(!length) {
414: close(file);
415: return; }
416: if((buf=(char *)MALLOC(length))==NULL) {
417: close(file);
418: errormsg(WHERE,ERR_ALLOC,datfile,length);
419: return; }
420: read(file,buf,length);
421: close(file);
422: sof(siffile,buf,length);
423: FREE(buf);
424: }
425:
426: /****************************************************************************/
427: /* Get string by template. A=Alpha, N=Number, !=Anything */
428: /* First character MUST be an A,N or !. */
429: /* Modes - K_LINE and K_UPPER are supported. */
430: /****************************************************************************/
431: uint sbbs_t::gettmplt(char *strout,char *templt, long mode)
432: {
433: char ch,str[256];
434: char tmplt[128];
435: uint t=strlen(templt),c=0;
436:
437: sys_status&=~SS_ABORT;
438: sprintf(tmplt, "%.*s",sizeof(tmplt)-1, templt);
439: strupr(tmplt);
440: if(useron.misc&ANSI) {
441: if(mode&K_LINE) {
442: if(useron.misc&COLOR)
443: attr(cfg.color[clr_inputline]);
444: else
445: attr(BLACK|(LIGHTGRAY<<4)); }
446: while(c<t) {
447: if(tmplt[c]=='N' || tmplt[c]=='A' || tmplt[c]=='!')
448: outchar(SP);
449: else
450: outchar(tmplt[c]);
451: c++; }
452: bprintf("\x1b[%dD",t); }
453: c=0;
454: if(mode&K_EDIT) {
455: strcpy(str,strout);
456: bputs(str);
457: c=strlen(str); }
458: while((ch=getkey(mode))!=CR && online && !(sys_status&SS_ABORT)) {
459: if(ch==BS) {
460: if(!c)
461: continue;
462: for(ch=1,c--;c;c--,ch++)
463: if(tmplt[c]=='N' || tmplt[c]=='A' || tmplt[c]=='!')
464: break;
465: if(useron.misc&ANSI)
466: bprintf("\x1b[%dD",ch);
467: else while(ch--)
468: outchar(BS);
469: bputs(" \b");
470: continue; }
471: if(ch==24) { /* Ctrl-X */
472: for(;c;c--) {
473: outchar(BS);
474: if(tmplt[c-1]=='N' || tmplt[c-1]=='A' || tmplt[c-1]=='!')
475: bputs(" \b");
476: }
477: }
478: else if(c<t) {
479: if(tmplt[c]=='N' && !isdigit(ch))
480: continue;
481: if(tmplt[c]=='A' && !isalpha(ch))
482: continue;
483: outchar(ch);
484: str[c++]=ch;
485: while(c<t && tmplt[c]!='N' && tmplt[c]!='A' && tmplt[c]!='!'){
486: str[c]=tmplt[c];
487: outchar(tmplt[c++]); } } }
488: str[c]=0;
489: attr(LIGHTGRAY);
490: CRLF;
491: if(!(sys_status&SS_ABORT))
492: strcpy(strout,str);
493: return(c);
494: }
495:
496: /*****************************************************************************/
497: /* Accepts a user's input to change a new-scan time pointer */
498: /* Returns 0 if input was aborted or invalid, 1 if complete */
499: /*****************************************************************************/
500: bool sbbs_t::inputnstime(time_t *dt)
501: {
502: int hour;
503: struct tm tm;
504: struct tm * tp;
505: char pm,str[256];
506:
507: bputs(text[NScanDate]);
508: bputs(timestr(dt));
509: CRLF;
510: tp=gmtime(dt);
511: if(tp==NULL) {
512: errormsg(WHERE,ERR_CHK,"time ptr",0);
513: return(FALSE);
514: }
515: tm=*tp;
516:
517: bputs(text[NScanYear]);
518: ultoa(tm.tm_year+1900,str,10);
519: if(!getstr(str,4,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
520: CRLF;
521: return(false); }
522: tm.tm_year=atoi(str);
523: if(tm.tm_year<1970) { /* unix time is seconds since 1/1/1970 */
524: CRLF;
525: return(false); }
526: tm.tm_year-=1900; /* tm_year is years since 1900 */
527:
528: bputs(text[NScanMonth]);
529: ultoa(tm.tm_mon+1,str,10);
530: if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
531: CRLF;
532: return(false); }
533: tm.tm_mon=atoi(str);
534: if(tm.tm_mon<1 || tm.tm_mon>12) {
535: CRLF;
536: return(false); }
537: tm.tm_mon--; /* tm_mon is zero-based */
538:
539: bputs(text[NScanDay]);
540: ultoa(tm.tm_mday,str,10);
541: if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
542: CRLF;
543: return(false); }
544: tm.tm_mday=atoi(str);
545: if(tm.tm_mday<1 || tm.tm_mday>31) {
546: CRLF;
547: return(false); }
548: bputs(text[NScanHour]);
549: if(cfg.sys_misc&SM_MILITARY)
550: hour=tm.tm_hour;
551: else {
552: if(tm.tm_hour==0) { /* 12 midnite */
553: pm=0;
554: hour=12; }
555: else if(tm.tm_hour>12) {
556: hour=tm.tm_hour-12;
557: pm=1; }
558: else {
559: hour=tm.tm_hour;
560: pm=0; } }
561: ultoa(hour,str,10);
562: if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
563: CRLF;
564: return(false); }
565: tm.tm_hour=atoi(str);
566: if(tm.tm_hour>24) {
567: CRLF;
568: return(false); }
569:
570: bputs(text[NScanMinute]);
571: ultoa(tm.tm_min,str,10);
572: if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
573: CRLF;
574: return(false); }
575:
576: tm.tm_min=atoi(str);
577: if(tm.tm_min>59) {
578: CRLF;
579: return(false); }
580: tm.tm_sec=0;
581: if(!(cfg.sys_misc&SM_MILITARY) && tm.tm_hour && tm.tm_hour<13) {
582: if(pm && yesno(text[NScanPmQ])) {
583: if(tm.tm_hour<12)
584: tm.tm_hour+=12; }
585: else if(!pm && !yesno(text[NScanAmQ])) {
586: if(tm.tm_hour<12)
587: tm.tm_hour+=12; }
588: else if(tm.tm_hour==12)
589: tm.tm_hour=0; }
590: else {
591: CRLF; }
592: *dt=mktime(&tm);
593: return(true);
594: }
595:
596: /*****************************************************************************/
597: /* Checks a password for uniqueness and validity */
598: /*****************************************************************************/
599: bool sbbs_t::chkpass(char *pass, user_t* user, bool unique)
600: {
601: char c,d,first[128],last[128],sysop[41],sysname[41],*p;
602: char alias[LEN_ALIAS+1], name[LEN_NAME+1], handle[LEN_HANDLE+1];
603:
604: if(strlen(pass)<4) {
605: bputs(text[PasswordTooShort]);
606: return(0); }
607: if(!strcmp(pass,user->pass)) {
608: bputs(text[PasswordNotChanged]);
609: return(0); }
610: d=strlen(pass);
611: for(c=1;c<d;c++)
612: if(pass[c]!=pass[c-1])
613: break;
614: if(c==d) {
615: bputs(text[PasswordInvalid]);
616: return(0); }
617: for(c=0;c<3;c++) /* check for 1234 and ABCD */
618: if(pass[c]!=pass[c+1]+1)
619: break;
620: if(c==3) {
621: bputs(text[PasswordObvious]);
622: return(0); }
623: for(c=0;c<3;c++) /* check for 4321 and ZYXW */
624: if(pass[c]!=pass[c+1]-1)
625: break;
626: if(c==3) {
627: bputs(text[PasswordObvious]);
628: return(0); }
629: strcpy(name,user->name);
630: strupr(name);
631: strcpy(alias,user->alias);
632: strupr(alias);
633: strcpy(first,alias);
634: p=strchr(first,SP);
635: if(p) {
636: *p=0;
637: strcpy(last,p+1); }
638: else
639: last[0]=0;
640: strcpy(handle,user->handle);
641: strupr(handle);
642: strcpy(sysop,cfg.sys_op);
643: strupr(sysop);
644: strcpy(sysname,cfg.sys_name);
645: strupr(sysname);
646: if((unique && user->pass[0]
647: && (strstr(pass,user->pass) || strstr(user->pass,pass)))
648: || (name[0]
649: && (strstr(pass,name) || strstr(name,pass)))
650: || strstr(pass,alias) || strstr(alias,pass)
651: || strstr(pass,first) || strstr(first,pass)
652: || (last[0]
653: && (strstr(pass,last) || strstr(last,pass)))
654: || strstr(pass,handle) || strstr(handle,pass)
655: || (user->zipcode[0]
656: && (strstr(pass,user->zipcode) || strstr(user->zipcode,pass)))
657: || (sysname[0]
658: && (strstr(pass,sysname) || strstr(sysname,pass)))
659: || (sysop[0]
660: && (strstr(pass,sysop) || strstr(sysop,pass)))
661: || (cfg.sys_id[0]
662: && (strstr(pass,cfg.sys_id) || strstr(cfg.sys_id,pass)))
663: || (cfg.node_phone[0] && strstr(pass,cfg.node_phone))
664: || (user->phone[0] && strstr(user->phone,pass))
665: || !strncmp(pass,"QWER",3)
666: || !strncmp(pass,"ASDF",3)
667: || !strncmp(pass,"!@#$",3)
668: )
669: {
670: bputs(text[PasswordObvious]);
671: return(0); }
672: return(1);
673: }
674:
675: /****************************************************************************/
676: /* Displays information about sub-board subnum */
677: /****************************************************************************/
678: void sbbs_t::subinfo(uint subnum)
679: {
680: char str[256];
681:
682: bputs(text[SubInfoHdr]);
683: bprintf(text[SubInfoLongName],cfg.sub[subnum]->lname);
684: bprintf(text[SubInfoShortName],cfg.sub[subnum]->sname);
685: bprintf(text[SubInfoQWKName],cfg.sub[subnum]->qwkname);
686: bprintf(text[SubInfoMaxMsgs],cfg.sub[subnum]->maxmsgs);
687: if(cfg.sub[subnum]->misc&SUB_QNET)
688: bprintf(text[SubInfoTagLine],cfg.sub[subnum]->tagline);
689: if(cfg.sub[subnum]->misc&SUB_FIDO)
690: bprintf(text[SubInfoFidoNet]
691: ,cfg.sub[subnum]->origline
692: ,faddrtoa(cfg.sub[subnum]->faddr));
693: sprintf(str,"%s%s.msg",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
694: if(fexist(str) && yesno(text[SubInfoViewFileQ]))
695: printfile(str,0);
696: }
697:
698: /****************************************************************************/
699: /* Displays information about transfer directory dirnum */
700: /****************************************************************************/
701: void sbbs_t::dirinfo(uint dirnum)
702: {
703: char str[256];
704:
705: bputs(text[DirInfoHdr]);
706: bprintf(text[DirInfoLongName],cfg.dir[dirnum]->lname);
707: bprintf(text[DirInfoShortName],cfg.dir[dirnum]->sname);
708: if(cfg.dir[dirnum]->exts[0])
709: bprintf(text[DirInfoAllowedExts],cfg.dir[dirnum]->exts);
710: bprintf(text[DirInfoMaxFiles],cfg.dir[dirnum]->maxfiles);
711: sprintf(str,"%s%s.msg",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
712: if(fexist(str) && yesno(text[DirInfoViewFileQ]))
713: printfile(str,0);
714: }
715:
716: /****************************************************************************/
717: /* Searches the file <name>.can in the TEXT directory for matches */
718: /* Returns 1 if found in list, 0 if not. */
719: /****************************************************************************/
720: extern "C" BOOL DLLCALL trashcan(scfg_t* cfg, char* insearch, char* name)
721: {
722: char* p;
723: char str[128];
724: char search[81];
725: int c;
726: BOOL found;
727: FILE* stream;
728:
729: sprintf(str,"%s%s.can",cfg->text_dir,name);
730:
731: if((stream=fopen(str,"r"))==NULL)
732: return(FALSE);
733:
734: sprintf(search,"%.*s",sizeof(search)-1,insearch);
735: strupr(search);
736:
737: found=FALSE;
738:
739: while(!feof(stream) && !ferror(stream) && !found) {
740: if(!fgets(str,sizeof(str),stream))
741: break;
742:
743: found=FALSE;
744:
745: p=str;
746: while(*p && *p<=' ') p++; /* Skip white-space */
747:
748: if(*p==';') /* comment */
749: continue;
750:
751: if(*p=='!') { /* !match */
752: found=TRUE;
753: p++;
754: }
755:
756: truncsp(p);
757: c=strlen(p);
758: if(c) {
759: c--;
760: strupr(p);
761: if(p[c]=='~') {
762: p[c]=0;
763: if(strstr(search,p))
764: found=!found;
765: }
766:
767: else if(p[c]=='^') {
768: p[c]=0;
769: if(!strncmp(p,search,c))
770: found=!found;
771: }
772:
773: else if(!strcmp(p,search))
774: found=!found;
775: }
776: }
777: fclose(stream);
778: return(found);
779: }
780:
781: bool sbbs_t::trashcan(char *insearch, char *name)
782: {
783: char str[256];
784: bool result;
785:
786: result=::trashcan(&cfg, insearch, name);
787: if(result) {
788: sprintf(str,"%sbad%s.msg",cfg.text_dir,name);
789: if(fexist(str))
790: printfile(str,0);
791: }
792: return(result);
793: }
794:
795:
796: /****************************************************************************/
797: /* Error handling routine. Prints to local and remote screens the error */
798: /* information, function, action, object and access and then attempts to */
799: /* write the error information into the file ERROR.LOG and NODE.LOG */
800: /****************************************************************************/
801: void sbbs_t::errormsg(int line, char *source, char action, char *object
802: ,ulong access, char *extinfo)
803: {
804: char str[512];
805: char tmp[512];
806: char actstr[256];
807:
808: if(errormsg_inside)
809: return;
810: errormsg_inside=true;
811: switch(action) {
812: case ERR_OPEN:
813: strcpy(actstr,"opening");
814: break;
815: case ERR_CLOSE:
816: strcpy(actstr,"closing");
817: break;
818: case ERR_FDOPEN:
819: strcpy(actstr,"fdopen");
820: break;
821: case ERR_READ:
822: strcpy(actstr,"reading");
823: break;
824: case ERR_WRITE:
825: strcpy(actstr,"writing");
826: break;
827: case ERR_REMOVE:
828: strcpy(actstr,"removing");
829: break;
830: case ERR_ALLOC:
831: strcpy(actstr,"allocating memory");
832: break;
833: case ERR_CHK:
834: strcpy(actstr,"checking");
835: break;
836: case ERR_LEN:
837: strcpy(actstr,"checking length");
838: break;
839: case ERR_EXEC:
840: strcpy(actstr,"executing");
841: break;
842: case ERR_CHDIR:
843: strcpy(actstr,"changing directory");
844: break;
845: case ERR_CREATE:
846: strcpy(actstr,"creating");
847: break;
848: case ERR_LOCK:
849: strcpy(actstr,"locking");
850: break;
851: case ERR_UNLOCK:
852: strcpy(actstr,"unlocking");
853: break;
854: case ERR_TIMEOUT:
855: strcpy(actstr,"time-out waiting for resource");
856: break;
857: case ERR_IOCTL:
858: strcpy(actstr,"sending IOCTL");
859: break;
860: default:
861: strcpy(actstr,"UNKNOWN"); }
862: lprintf("!Node %d: ERROR %d (0x%X) in %s line %d %s %s access=%d"
863: ,cfg.node_num, errno, errno, source, line, actstr, object, access);
864: bprintf("\7\r\nERROR - action: %s",actstr); /* tell user about error */
865: bprintf("\7\r\n object: %s",object);
866: bprintf("\7\r\n access: %ld",access);
867: if(access>9 && (long)access!=-1 && (short)access!=-1 && (char)access!=-1)
868: bprintf(" (%lXh)",access);
869: if(cfg.sys_misc&SM_ERRALARM) {
870: sbbs_beep(500,220); sbbs_beep(250,220);
871: sbbs_beep(500,220); sbbs_beep(250,220);
872: sbbs_beep(500,220); sbbs_beep(250,220);
873: nosound(); }
874: bputs("\r\n\r\nThe sysop has been notified. <Hit a key>");
875: getkey(0);
876: CRLF;
877: sprintf(str,"\r\n source: %s\r\n line: %d\r\n action: %s\r\n"
878: " object: %s\r\n access: %ld"
879: ,source,line,actstr,object,access);
880: if(access>9 && (long)access!=-1 && (short)access!=-1 && (char)access!=-1) {
881: sprintf(tmp," (%lXh)",access);
882: strcat(str,tmp); }
883: if(extinfo!=NULL) {
884: sprintf(tmp,"\r\n info: %s",extinfo);
885: strcat(str,tmp);
886: }
887: if(errno) {
888: sprintf(tmp,"\r\n errno: %d",errno);
889: strcat(str,tmp);
890: }
891: #if defined(__MSDOS__) || defined(_WIN32)
892: if(_doserrno && _doserrno!=(ulong)errno) {
893: sprintf(tmp,"\r\n doserrno: %d",_doserrno);
894: strcat(str,tmp);
895: }
896: errno=_doserrno=0;
897: #endif
898: #if defined(_WIN32)
899: if(GetLastError()!=0) {
900: sprintf(tmp,"\r\n winerrno: %d (0x%X)",GetLastError(), GetLastError());
901: strcat(str,tmp);
902: }
903: #endif
904: errorlog(str);
905: errormsg_inside=false;
906: }
907:
908: /*****************************************************************************/
909: /* Error logging to NODE.LOG and DATA\ERROR.LOG function */
910: /*****************************************************************************/
911: void sbbs_t::errorlog(char *text)
912: {
913: char hdr[256],str[256],tmp2[256];
914: int file;
915:
916: if(errorlog_inside) /* let's not go recursive on this puppy */
917: return;
918: errorlog_inside=1;
919: if(cfg.node_num>0) {
920: getnodedat(cfg.node_num,&thisnode,1);
921: criterrs=++thisnode.errors;
922: putnodedat(cfg.node_num,&thisnode);
923: }
924: now=time(NULL);
925: logline("!!",text);
926: sprintf(str,"%serror.log",cfg.data_dir);
927: if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
928: sprintf(tmp2,"ERROR opening/creating %s",str);
929: logline("!!",tmp2);
930: errorlog_inside=0;
931: return; }
932: sprintf(hdr,"%s Node %2d: %s #%d"
933: ,timestr(&now),cfg.node_num,useron.alias,useron.number);
934: write(file,hdr,strlen(hdr));
935: write(file,crlf,2);
936: write(file,text,strlen(text));
937: write(file,"\r\n\r\n",4);
938: close(file);
939: errorlog_inside=0;
940: }
941:
942: /****************************************************************************/
943: /* Generates a 24 character ASCII string that represents the time_t pointer */
944: /* Used as a replacement for ctime() */
945: /****************************************************************************/
946: char * sbbs_t::timestr(time_t *intime)
947: {
948: char mer[3],hour;
949: struct tm *gm;
950:
951: gm=localtime(intime);
952: if(gm==NULL) {
953: strcpy(timestr_output,"Invalid Time");
954: return(timestr_output); }
955: if(cfg.sys_misc&SM_MILITARY) {
956: sprintf(timestr_output,"%s %s %02d %4d %02d:%02d:%02d"
957: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
958: ,gm->tm_hour,gm->tm_min,gm->tm_sec);
959: return(timestr_output); }
960: if(gm->tm_hour>=12) {
961: if(gm->tm_hour==12)
962: hour=12;
963: else
964: hour=gm->tm_hour-12;
965: strcpy(mer,"pm"); }
966: else {
967: if(gm->tm_hour==0)
968: hour=12;
969: else
970: hour=gm->tm_hour;
971: strcpy(mer,"am"); }
972: sprintf(timestr_output,"%s %s %02d %4d %02d:%02d %s"
973: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
974: ,hour,gm->tm_min,mer);
975: return(timestr_output);
976: }
977:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.