package door import ( "bufio" "log" "os" "path" "strconv" "strings" "time" ) /* https://github.com/NuSkooler/ansi-bbs/blob/master/docs/dropfile_formats/door32_sys.txt door32.sys: 0 Line 1 : Comm type (0=local, 1=serial, 2=telnet) 0 Line 2 : Comm or socket handle 38400 Line 3 : Baud rate Mystic 1.07 Line 4 : BBSID (software name and version) 1 Line 5 : User record position (1-based) James Coyle Line 6 : User's real name g00r00 Line 7 : User's handle/alias 255 Line 8 : User's security level 58 Line 9 : User's time left (in minutes) 1 Line 10: Emulation *(See below) 1 Line 11: Current node number Emulation: 0 = Ascii 1 = Ansi 2 = Avatar 3 = RIP 4 = Max Graphics http://wiki.synchro.net/ref:door.sys door.sys: Line # Example Description Comment 1 COM1: Comm Port COM0: = LOCAL MODE 2 2400 Baud (DCE) Rate 300 to 38400 3 8 Parity 7 or 8 4 1 Node Number 1 to 99 5 19200 DTE Rate Was Y/N (LOCKED at 19200) 6 Y Screen Display Y=On N=Off 7 Y Printer Toggle Y=On N=Off 8 Y Page Bell Y=On N=Off 9 Y Caller Alarm Y=On N=Off 10 Rick Greer User Full Name 11 Lewisville, Tx. Calling From 12 214 221-7814 Home Phone 13 214 221-7814 Work/Data Phone 14 PASSWORD Password 15 110 Security Level 16 1456 Total Times On 0 through 32767 17 03/14/88 Last Date Called mm/dd/yy 18 7560 Seconds Remaining THIS call 19 126 Minutes Remaining THIS call 20 GR Graphics Mode GR=Graph, NG=Non-Graph, 7E=7,E Caller 21 23 Page Length rows of text 22 Y User Mode Y = Expert, N = Novice 23 1234567 Conferences/Forums Registered In ABCDEFG 24 7 Conference Exited To DOOR From G 25 01/01/99 User Expiration Date mm/dd/yy 26 1 User File's Record Number 1+ 27 Y Default Protocol X, C, Y, G, I, N, Etc. 28 0 Total Uploads 29 0 Total Downloads 30 0 Daily Download “K” Total 31 999999 Daily Download Max. “K” Limit 32 10/22/88 Caller's Birthdate mm/dd/yy 33 G:\GAP\MAIN Path to the MAIN directory where user file is 34 G:\GAP\GEN Path to the GEN directory 35 Michael Sysop's Name name BBS refers to Sysop as 36 Stud Alias name user's alias or handle 37 00:05 Event time hh:mm 38 Y Error correcting connection Y/N 39 N ANSI supported & caller using NG mode Y/N 40 Y Use Record Locking Y/N 41 14 BBS Default Color CGA color code (1-15) 42 10 Time Credits in Minutes -32768 through 32767 43 07/07/90 Last New File Scan Date mm/dd/yy 44 14:32 Time of This Call hh:mm 45 07:30 Time of Last Call hh:mm 46 6 Maximum daily files available 47 3 Files d/led so far today 48 23456 Total “K” Bytes Uploaded 49 76329 Total “K” Bytes Downloaded 50 A File Sucker User Comment 51 10 Total Doors Opened 52 10283 Total Messages Left 0 through 32767 */ // DropFile Information type DropfileConfig struct { Comm_type int // Comm type (0 local, 2 telnet "linux fd") Comm_handle int // Handle to use to talk to the user BBSID string // BBS Software name User_number int // User number Real_name string // User's Real Name Handle string // User's Handle/Nick Security_level int // Security Level (if given) Time_left int // Time Left (minutes) Node int // BBS Node number } // Read the BBS door file. We only support door32.sys. func (d *Door) ReadDropfile(filename string) { var file *os.File var err error var base string = strings.ToLower(path.Base(filename)) var isDoor32, isDoorSys bool if strings.Contains(base, "door.sys") { isDoorSys = true } else if strings.Contains(base, "door32.sys") { isDoor32 = true } else { log.Panicf("Unknown dropfile format: %s\n", base) } file, err = os.Open(filename) if err != nil { log.Panicf("Open(%s): %s\n", filename, err) } defer file.Close() var lines []string // read line by line // The scanner handles DOS and linux file endings. var scanner *bufio.Scanner = bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() lines = append(lines, line) } if isDoor32 { // door32.sys: // 0 Line 1 : Comm type (0=local, 1=serial, 2=telnet) // 0 Line 2 : Comm or socket handle // Mystic 1.07 Line 4 : BBSID (software name and version) // 1 Line 5 : User record position (1-based) // James Coyle Line 6 : User's real name // g00r00 Line 7 : User's handle/alias // 255 Line 8 : User's security level // 58 Line 9 : User's time left (in minutes) // 1 Line 11: Current node number d.Config.Comm_type, err = strconv.Atoi(lines[0]) if err != nil { log.Panicf("Door32 Comm Type (expected integer): %s\n", err) } d.Config.Comm_handle, err = strconv.Atoi(lines[1]) if err != nil { log.Panicf("Door32 Comm Handle (expected integer): %s\n", err) } d.Config.BBSID = lines[3] d.Config.User_number, err = strconv.Atoi(lines[4]) if err != nil { log.Panicf("Door32 User Number (expected integer): %s\n", err) } d.Config.Real_name = lines[5] d.Config.Handle = lines[6] d.Config.Security_level, err = strconv.Atoi(lines[7]) if err != nil { log.Panicf("Door32 Security Level (expected integer): %s\n", err) } d.Config.Time_left, err = strconv.Atoi(lines[8]) if err != nil { log.Panicf("Door32 Time Left (expected integer): %s\n", err) } d.Config.Node, err = strconv.Atoi(lines[10]) if err != nil { log.Panicf("Door32 Node Number (expected integer): %s\n", err) } } else if isDoorSys { // Door.sys: // Line 1: COM1: Comm Port, COM0: = LOCAL MODE // Line 4: 1 Node Number // Line 10: Rick Greer User Full Name // Line 11: Lewisville, Tx. Calling From // Line 15: 110 Security Level // Line 18: 7560 Seconds Remaining // Line 19: 126 Minutes Remaining // Line 26: 1 User File's Record Number // Line 35: Michael Sysop's Name // Line 36: Stud Alias name if lines[0] == "COM0:" { d.Config.Comm_type = 0 } d.Config.Node, err = strconv.Atoi(lines[3]) if err != nil { log.Panicf("Door.sys Node Number (expected integer): %s\n", err) } d.Config.Real_name = lines[9] d.Config.User_number, err = strconv.Atoi(lines[25]) if err != nil { log.Panicf("Door.sys User Number (expected integer): %s\n", err) } d.Config.Handle = lines[35] d.Config.Security_level, err = strconv.Atoi(lines[14]) if err != nil { log.Panicf("Door.sys Security Level (expected integer): %s\n", err) } d.Config.Time_left, err = strconv.Atoi(lines[18]) if err != nil { log.Panicf("Door.sys Time Left (expected integer): %s\n", err) } } if d.Config.Comm_type == 0 { d.READFD = 0 d.WRITEFD = 1 } else if d.Config.Comm_type == 2 { d.READFD = d.Config.Comm_handle d.WRITEFD = d.Config.Comm_handle } else { log.Panicf("Unsupported Comm type %d\n", d.Config.Comm_type) } d.StartTime = time.Now() // Calculate when time expires. d.TimeOut = time.Now().Add(time.Duration(d.Config.Time_left) * time.Minute) }