|
|
1.1 root 1: /* newuser.cpp */
2:
3: /* Synchronet new user routine */
4:
5: /* $Id: newuser.cpp,v 1.10 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: #include "cmdshell.h"
40:
41: /****************************************************************************/
42: /* This function is invoked when a user enters "NEW" at the NN: prompt */
43: /* Prompts user for personal information and then sends feedback to sysop. */
44: /* Called from function waitforcall */
45: /****************************************************************************/
46: void sbbs_t::newuser()
47: {
48: char c,str[512];
49: char tmp[512];
50: int file;
51: uint i,j;
52: long misc;
53: bool usa;
54: FILE *stream;
55:
56: if(cur_rate<cfg.node_minbps) {
57: bprintf(text[MinimumModemSpeed],cfg.node_minbps);
58: sprintf(str,"%stooslow.msg",cfg.text_dir);
59: if(fexist(str))
60: printfile(str,0);
61: sprintf(str,"New user modem speed: %lu<%u"
62: ,cur_rate,cfg.node_minbps);
63: logline("N!",str);
64: hangup();
65: return; }
66:
67: getnodedat(cfg.node_num,&thisnode,0);
68: if(thisnode.misc&NODE_LOCK) {
69: bputs(text[NodeLocked]);
70: logline("N!","New user locked node logon attempt");
71: hangup();
72: return; }
73:
74: if(cfg.sys_misc&SM_CLOSED) {
75: bputs(text[NoNewUsers]);
76: hangup();
77: return; }
78: getnodedat(cfg.node_num,&thisnode,1);
79: thisnode.status=NODE_NEWUSER;
80: thisnode.connection=0xffff;
81: putnodedat(cfg.node_num,&thisnode);
82: memset(&useron,0,sizeof(user_t)); /* Initialize user info to null */
83: if(cfg.new_pass[0] && online==ON_REMOTE) {
84: c=0;
85: while(++c<4) {
86: bputs(text[NewUserPasswordPrompt]);
87: getstr(str,40,K_UPPER);
88: if(!strcmp(str,cfg.new_pass))
89: break;
90: sprintf(tmp,"NUP Attempted: '%s'",str);
91: logline("N!",tmp); }
92: if(c==4) {
93: sprintf(str,"%snupguess.msg",cfg.text_dir);
94: if(fexist(str))
95: printfile(str,P_NOABORT);
96: hangup();
97: return; } }
98:
99: if(autoterm || yesno(text[AutoTerminalQ])) {
100: useron.misc|=AUTOTERM;
101: useron.misc|=autoterm; }
102:
103: if(!(useron.misc&AUTOTERM)) {
104: if(yesno(text[AnsiTerminalQ]))
105: useron.misc|=ANSI; }
106:
107: if(useron.misc&ANSI) {
108: useron.rows=0; /* Auto-rows */
109: if(useron.misc&(RIP|WIP) || yesno(text[ColorTerminalQ]))
110: useron.misc|=COLOR; }
111: else
112: useron.rows=24;
113: if(!yesno(text[ExAsciiTerminalQ]))
114: useron.misc|=NO_EXASCII;
115:
116: /* Sets defaults per sysop config */
117: useron.misc|=(cfg.new_misc&~(DELETED|INACTIVE|QUIET|NETMAIL));
118: useron.qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL);
119: useron.firston=useron.laston=useron.pwmod=time(NULL);
120: if(cfg.new_expire) {
121: now=time(NULL);
122: useron.expire=now+((long)cfg.new_expire*24L*60L*60L); }
123: else
124: useron.expire=0;
125: useron.sex=SP;
126: useron.prot=cfg.new_prot;
127: strcpy(useron.note,cid); /* Caller ID if supported, NULL otherwise */
128: if((i=userdatdupe(0,U_NOTE,LEN_NOTE,cid,true))!=0) { /* Duplicate IP address */
129: sprintf(useron.comment,"Warning: same IP address as user #%d",i);
130: logline("N!",useron.comment);
131: }
132:
133: strcpy(useron.alias,"New"); /* just for status line */
134: strcpy(useron.modem,connection);
135: if(!lastuser(&cfg)) { /* Automatic sysop access for first user */
136: useron.level=99;
137: useron.exempt=useron.flags1=useron.flags2=0xffffffffUL;
138: useron.flags3=useron.flags4=0xffffffffUL;
139: useron.rest=0L; }
140: else {
141: useron.level=cfg.new_level;
142: useron.flags1=cfg.new_flags1;
143: useron.flags2=cfg.new_flags2;
144: useron.flags3=cfg.new_flags3;
145: useron.flags4=cfg.new_flags4;
146: useron.rest=cfg.new_rest;
147: useron.exempt=cfg.new_exempt; }
148:
149: useron.cdt=cfg.new_cdt;
150: useron.min=cfg.new_min;
151: useron.freecdt=cfg.level_freecdtperday[useron.level];
152:
153: if(cfg.total_fcomps)
154: strcpy(useron.tmpext,cfg.fcomp[0]->ext);
155: else
156: strcpy(useron.tmpext,"ZIP");
157: for(i=0;i<cfg.total_xedits;i++)
158: if(!stricmp(cfg.xedit[i]->code,cfg.new_xedit) && chk_ar(cfg.xedit[i]->ar,&useron))
159: break;
160: if(i<cfg.total_xedits)
161: useron.xedit=i+1;
162:
163:
164: useron.shell=cfg.new_shell;
165:
166: useron.alias[0]=0;
167: while(online) {
168: if(sys_status&SS_RLOGIN && rlogin_name[0])
169: strcpy(useron.alias,rlogin_name);
170: else {
171: while(online) {
172: if(cfg.uq&UQ_ALIASES)
173: bputs(text[EnterYourAlias]);
174: else
175: bputs(text[EnterYourRealName]);
176: getstr(useron.alias,LEN_ALIAS
177: ,K_UPRLWR|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL);
178: truncsp(useron.alias);
179: if(useron.alias[0]<=SP || !isalpha(useron.alias[0])
180: || strchr(useron.alias,0xff)
181: || matchuser(&cfg,useron.alias) || trashcan(useron.alias,"name")
182: || (!(cfg.uq&UQ_ALIASES) && !strchr(useron.alias,SP))) {
183: bputs(text[YouCantUseThatName]);
184: continue; }
185: break; }
186: }
187: if(!online) return;
188: if(cfg.uq&UQ_ALIASES && cfg.uq&UQ_REALNAME) {
189: while(online) {
190: bputs(text[EnterYourRealName]);
191: if(!getstr(useron.name,LEN_NAME
192: ,K_UPRLWR|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)
193: || trashcan(useron.name,"name")
194: || strchr(useron.name,0xff)
195: || !strchr(useron.name,SP)
196: || (cfg.uq&UQ_DUPREAL
197: && userdatdupe(useron.number,U_NAME,LEN_NAME
198: ,useron.name,0)))
199: bputs(text[YouCantUseThatName]);
200: else
201: break; } }
202: else if(cfg.uq&UQ_COMPANY) {
203: bputs(text[EnterYourCompany]);
204: getstr(useron.name,LEN_NAME,(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL); }
205: if(!useron.name[0])
206: strcpy(useron.name,useron.alias);
207: if(!online) return;
208: if(!useron.handle[0])
209: sprintf(useron.handle,"%.*s",LEN_HANDLE,useron.alias);
210: while(cfg.uq&UQ_HANDLE && online) {
211: bputs(text[EnterYourHandle]);
212: if(!getstr(useron.handle,LEN_HANDLE
213: ,K_LINE|K_EDIT|K_AUTODEL|(cfg.uq&UQ_NOEXASC))
214: || strchr(useron.handle,0xff)
215: || (cfg.uq&UQ_DUPHAND
216: && userdatdupe(0,U_HANDLE,LEN_HANDLE,useron.handle,0))
217: || trashcan(useron.handle,"name"))
218: bputs(text[YouCantUseThatName]);
219: else
220: break; }
221: if(!online) return;
222: while(!(sys_status&SS_RLOGIN) && /* cfg.uq&UQ_EMAIL && */ online) {
223: bputs(text[EnterNetMailAddress]);
224: if(getstr(useron.netmail,LEN_NETMAIL,K_EDIT|K_AUTODEL|K_LINE))
225: break;
226: }
227: if(useron.netmail[0] && yesno(text[ForwardMailQ]))
228: useron.misc|=NETMAIL;
229: else
230: useron.misc&=~NETMAIL;
231: if(cfg.uq&UQ_ADDRESS)
232: while(online) { /* Get address and zip code */
233: bputs(text[EnterYourAddress]);
234: if(getstr(useron.address,LEN_ADDRESS
235: ,K_UPRLWR|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL))
236: break; }
237: if(!online) return;
238: while(cfg.uq&UQ_LOCATION && online) {
239: bputs(text[EnterYourCityState]);
240: if(getstr(useron.location,LEN_LOCATION
241: ,K_UPRLWR|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)
242: && (cfg.uq&UQ_NOCOMMAS || strchr(useron.location,',')))
243: break;
244: bputs("\r\nYou must include a comma between the city and state.\r\n");
245: useron.location[0]=0; }
246: if(cfg.uq&UQ_ADDRESS)
247: while(online) {
248: bputs(text[EnterYourZipCode]);
249: if(getstr(useron.zipcode,LEN_ZIPCODE
250: ,K_UPPER|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL))
251: break; }
252: if(!online) return;
253: if(cfg.uq&UQ_PHONE) {
254: usa=yesno(text[CallingFromNorthAmericaQ]);
255: while(online) {
256: bputs(text[EnterYourPhoneNumber]);
257: if(!usa) {
258: if(getstr(useron.phone,LEN_PHONE
259: ,K_UPPER|K_LINE|(cfg.uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)<5)
260: continue; }
261: else {
262: if(gettmplt(useron.phone,cfg.sys_phonefmt
263: ,K_LINE|(cfg.uq&UQ_NOEXASC)|K_EDIT)<strlen(cfg.sys_phonefmt))
264: continue; }
265: if(!trashcan(useron.phone,"phone"))
266: break; } }
267: if(!online) return;
268: if(cfg.uq&UQ_SEX) {
269: bputs(text[EnterYourSex]);
270: useron.sex=(char)getkeys("MF",0); }
271: while(cfg.uq&UQ_BIRTH && online) {
272: bputs(text[EnterYourBirthday]);
273: if(gettmplt(useron.birth,"nn/nn/nn",K_EDIT)==8 && getage(&cfg,useron.birth))
274: break; }
275: if(yesno(text[UserInfoCorrectQ]))
276: break; }
277: if(!online) return;
278: sprintf(str,"New user: %s",useron.alias);
279: logline("N",str);
280: if(!online) return;
281: CLS;
282: sprintf(str,"%ssbbs.msg",cfg.text_dir);
283: printfile(str,P_NOABORT);
284: if(lncntr)
285: pause();
286: CLS;
287: sprintf(str,"%ssystem.msg",cfg.text_dir);
288: printfile(str,P_NOABORT);
289: if(lncntr)
290: pause();
291: CLS;
292: sprintf(str,"%snewuser.msg",cfg.text_dir);
293: printfile(str,P_NOABORT);
294: if(lncntr)
295: pause();
296: CLS;
297: answertime=time(NULL); /* could take 10 minutes to get this far */
298:
299: if(cfg.total_xedits && cfg.uq&UQ_XEDIT && !noyes("Use an external editor")) {
300: if(useron.xedit) useron.xedit--;
301: for(i=0;i<cfg.total_xedits;i++)
302: uselect(1,i,"External Editor",cfg.xedit[i]->name,cfg.xedit[i]->ar);
303: if((int)(i=uselect(0,useron.xedit,0,0,0))>=0)
304: useron.xedit=i+1; }
305:
306: if(cfg.total_shells>1 && cfg.uq&UQ_CMDSHELL) {
307: for(i=0;i<cfg.total_shells;i++)
308: uselect(1,i,"Command Shell",cfg.shell[i]->name,cfg.shell[i]->ar);
309: if((int)(i=uselect(0,useron.shell,0,0,0))>=0)
310: useron.shell=i; }
311:
312: c=0;
313: while(c<LEN_PASS) { /* Create random password */
314: useron.pass[c]=sbbs_random(43)+'0';
315: if(isalnum(useron.pass[c]))
316: c++; }
317: useron.pass[c]=0;
318:
319: if(!(sys_status&SS_RLOGIN)) {
320: bprintf(text[YourPasswordIs],useron.pass);
321:
322: if(cfg.sys_misc&SM_PWEDIT && yesno(text[NewPasswordQ]))
323: while(online) {
324: bputs(text[NewPassword]);
325: getstr(str,LEN_PASS,K_UPPER|K_LINE);
326: truncsp(str);
327: if(chkpass(str,&useron,true)) {
328: strcpy(useron.pass,str);
329: CRLF;
330: bprintf(text[YourPasswordIs],useron.pass);
331: break; }
332: CRLF; }
333:
334: c=0;
335: while(online) {
336: bprintf(text[NewUserPasswordVerify]);
337: console|=CON_R_ECHOX;
338: if(!(cfg.sys_misc&SM_ECHO_PW))
339: console|=CON_L_ECHOX;
340: str[0]=0;
341: getstr(str,LEN_PASS,K_UPPER);
342: console&=~(CON_R_ECHOX|CON_L_ECHOX);
343: if(!strcmp(str,useron.pass)) break;
344: sprintf(tmp,"Failed PW verification: '%s' instead of '%s'",str
345: ,useron.pass);
346: logline(nulstr,tmp);
347: if(++c==4) {
348: logline("N!","Couldn't figure out password.");
349: hangup(); }
350: bputs(text[IncorrectPassword]);
351: bprintf(text[YourPasswordIs],useron.pass); }
352: }
353:
354: if(!online) return;
355: if(cfg.new_magic[0]) {
356: bputs(text[MagicWordPrompt]);
357: str[0]=0;
358: getstr(str,50,K_UPPER);
359: if(strcmp(str,cfg.new_magic)) {
360: bputs(text[FailedMagicWord]);
361: sprintf(tmp,"Failed magic word: '%s'",str);
362: logline("N!",tmp);
363: hangup(); }
364: if(!online) return; }
365:
366: i=1;
367: bputs(text[CheckingSlots]);
368: sprintf(str,"%s/user/name.dat",cfg.data_dir);
369: if(fexist(str)) {
370: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
371: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
372: hangup();
373: return; }
374: j=filelength(file)/(LEN_ALIAS+2); /* total users */
375: while(i<=j) {
376: fread(str,LEN_ALIAS+2,1,stream);
377: for(c=0;c<LEN_ALIAS;c++)
378: if(str[c]==ETX) break;
379: str[c]=0;
380: if(!c) { /* should be a deleted user */
381: getuserrec(&cfg,i,U_MISC,8,str);
382: misc=ahtoul(str);
383: if(misc&DELETED) { /* deleted bit set too */
384: getuserrec(&cfg,i,U_LASTON,8,str);
385: now=ahtoul(str); /* delete long enough ? */
386: if((time(NULL)-now)/86400>=cfg.sys_deldays) break; } }
387: i++; }
388: fclose(stream); }
389:
390: j=lastuser(&cfg); /* Check against data file */
391: if(i<=j) { /* Overwriting existing user */
392: getuserrec(&cfg,i,U_MISC,8,str);
393: misc=ahtoul(str);
394: if(!(misc&DELETED)) /* Not deleted? Set usernumber to end+1 */
395: i=j+1; }
396:
397: useron.number=i;
398: putuserdat(&cfg,&useron);
399: putusername(useron.number,useron.alias);
400: logline(nulstr,"Wrote user data");
401: if(cfg.new_sif[0]) {
402: sprintf(str,"%suser/%4.4u.dat",cfg.data_dir,useron.number);
403: create_sif_dat(cfg.new_sif,str); }
404: if(!(cfg.uq&UQ_NODEF))
405: maindflts(&useron);
406:
407: delallmail(useron.number);
408:
409: if(useron.number!=1 && cfg.node_valuser) {
410: sprintf(str,"%sfeedback.msg",cfg.text_dir);
411: CLS;
412: printfile(str,P_NOABORT);
413: sprintf(str,text[NewUserFeedbackHdr]
414: ,nulstr,getage(&cfg,useron.birth),useron.sex,useron.birth
415: ,useron.name,useron.phone,useron.comp,useron.modem);
416: email(cfg.node_valuser,str,"New User Validation",WM_EMAIL);
417: if(!useron.fbacks && !useron.emails) {
418: if(online) { /* didn't hang up */
419: bprintf(text[NoFeedbackWarning],username(&cfg,cfg.node_valuser,tmp));
420: email(cfg.node_valuser,str,"New User Validation",WM_EMAIL);
421: } /* give 'em a 2nd try */
422: if(!useron.fbacks && !useron.emails) {
423: bprintf(text[NoFeedbackWarning],username(&cfg,cfg.node_valuser,tmp));
424: logline("N!","Aborted feedback");
425: hangup();
426: putuserrec(&cfg,useron.number,U_COMMENT,60,"Didn't leave feedback");
427: putuserrec(&cfg,useron.number,U_MISC,8
428: ,ultoa(useron.misc|DELETED,tmp,16));
429: putusername(useron.number,nulstr);
430: return; } } }
431:
432: sprintf(str,"%sfile/%04u.IN",cfg.data_dir,useron.number); /* delete any files */
433: delfiles(str,ALLFILES); /* waiting for user */
434: rmdir(str);
435: sprintf(tmp,"%04u.*",useron.number);
436: sprintf(str,"%sfile",cfg.data_dir);
437: delfiles(str,tmp);
438:
439: answertime=starttime=time(NULL); /* set answertime to now */
440: sprintf(str,"%suser/ptrs/%04u.ixb",cfg.data_dir,useron.number); /* msg ptrs */
441: remove(str);
442: sprintf(str,"%smsgs/%04u.msg",cfg.data_dir,useron.number); /* delete short msg */
443: remove(str);
444: sprintf(str,"%suser/%04u.msg",cfg.data_dir,useron.number); /* delete ex-comment */
445: remove(str);
446: if(cfg.newuser_mod[0])
447: exec_bin(cfg.newuser_mod,&main_csi);
448: user_event(EVENT_NEWUSER);
449: getuserdat(&cfg,&useron); // In case event(s) modified user data
450: logline("N+","Successful new user logon");
451: sys_status|=SS_NEWUSER;
452: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.