Copy Link
Add to Bookmark
Report

NULL mag Issue 07 27 Read filebases with Python

eZine's profile picture
Published in 
null magazine
 · 26 Dec 2020

  




on the same concept we begin translating things for mystic bbs into
python code, lets write some code to get the filebases options, from
the fbase.dat file.

the record of each filebase has the following format:

RecFileBase = Record
Index : Word;
Name : String[60];
FtpName : String[60];
FileName : String[40];
DispFile : String[20];
Template : String[20];
ListACS : String[30];
FtpACS : String[30];
DLACS : String[30];
ULACS : String[30];
HatchACS : String[30];
SysOpACS : String[30];
PassEACS : String[30];
Path : String[mysMaxPathSize];
DefScan : Byte;
Flags : LongInt;
Created : LongInt;
NetAddr : Byte;
EchoTag : String[40];
ListEACS : String[30];
Res : Array[1..53] of Byte;
End;

this is a pascal format record. we must have in mind that pascal,
stores strings in a unique way. before the string, it always puts the
size of the string. so a string[60] type variable, will be actually 61
bytes in the file. for this reason we have to pad this byte and not
use it at all or we can read it and then copy only those bytes from
the string that follows. in this example i am padding the size and not
using at all.

lets begin... first import the libs we need

import os
import struct

we will need this handy function to convert bytes to a string format:

def byte2str(v):
s=''.join(str(v))
return s[2:-1]

check if the file exists... otherwise exit with an error value

if os.path.exists(filename) == False:
return -1

we have to check if the index of the base we want is a valid number. so
we take the size of the fbases.dat file and divide it with the size of
the record to find how many bases includes.

size = os.path.getsize(filename) # the file size
fbaserec = "<Hx60sx60sx40sx20sx20sx30sx30sx30sx30sx30sx30sx30sx80s\
BIIBx40sx30s53B"

sf = struct.calcsize(fbaserec) # the record size
items = size // sf # number of bases we have stored in the file

if the index is more than the items we have stored, exit the function
with an error

if i > items:
return -3

open the fbases.dat file and go to the position of the file base we
want, with the seek function

f = open(filename, 'rb')
try:
f.seek((i-1)*sf,1)
except:
return -2

read the bytes of the record

fbaseb = f.read(sf)

unpack the data and close the file

s = struct.unpack(fbaserec,fbaseb)
f.close()

we store all data into a dictionary. we are converting any strings that
are represented as bytes to a string format and also remove the \\x00
chars from it.

res = {}
res['index'] = s[0]
res['name'] = byte2str(s[1]).replace('\\x00','')
res['ftpname'] = byte2str(s[2]).replace('\\x00','')
res['filename'] = byte2str(s[3]).replace('\\x00','')
res['dispfile'] = byte2str(s[4]).replace('\\x00','')
res['template'] = byte2str(s[5]).replace('\\x00','')
res['listacs'] = byte2str(s[6]).replace('\\x00','')
res['ftpacs'] = byte2str(s[7]).replace('\\x00','')
res['downloadacs'] = byte2str(s[8]).replace('\\x00','')
res['uploadacs'] = byte2str(s[9]).replace('\\x00','')
res['hatchacs'] = byte2str(s[10]).replace('\\x00','')
res['sysopacs'] = byte2str(s[11]).replace('\\x00','')
res['passeacs'] = byte2str(s[12]).replace('\\x00','')
res['path'] = byte2str(s[13]).replace('\\x00','')
res['defscan'] = s[14]
res['flags'] = s[15]
res['created'] = s[16]
res['netaddr'] = s[17]
res['echotag'] = byte2str(s[18]).replace('\\x00','')
res['listeacs'] = byte2str(s[19]).replace('\\x00','')
res['reserved'] = s[20:]

the result will be our dictionary variable

return res


i hope this is easy to understand and will be helpful in your projects.
below the complete code, just copy/paste

/./././././././././././././././././././././././././././././././././././././



#!/usr/bin/python3

import os
import struct
import sys

# Type
# RecFileBase = Record
# Index : Word;
# Name : String[60];
# FtpName : String[60];
# FileName : String[40];
# DispFile : String[20];
# Template : String[20];
# ListACS : String[30];
# FtpACS : String[30];
# DLACS : String[30];
# ULACS : String[30];
# HatchACS : String[30];
# SysOpACS : String[30];
# PassEACS : String[30];
# Path : String[mysMaxPathSize];
# DefScan : Byte;
# Flags : LongInt;
# Created : LongInt;
# NetAddr : Byte;
# EchoTag : String[40];
# ListEACS : String[30];
# Res : Array[1..53] of Byte;
# End;

def readfilebase(i,filename):

def byte2str(v):
s=''.join(str(v))
return s[2:-1]

if os.path.exists(filename) == False:
return -1
size = os.path.getsize(filename)
fbaserec = "<Hx60sx60sx40sx20sx20sx30sx30sx30sx30sx30sx30sx30sx80sBIIB\
x40sx30s53B"

sf = struct.calcsize(fbaserec)
items = size // sf
if i > items:
return -3
f = open(filename, 'rb')
try:
f.seek((i-1)*sf,1)
except:
return -2
fbaseb = f.read(sf)
s = struct.unpack(fbaserec,fbaseb)
f.close()
res = {}
res['index'] = s[0]
res['name'] = byte2str(s[1]).replace('\\x00','')
res['ftpname'] = byte2str(s[2]).replace('\\x00','')
res['filename'] = byte2str(s[3]).replace('\\x00','')
res['dispfile'] = byte2str(s[4]).replace('\\x00','')
res['template'] = byte2str(s[5]).replace('\\x00','')
res['listacs'] = byte2str(s[6]).replace('\\x00','')
res['ftpacs'] = byte2str(s[7]).replace('\\x00','')
res['downloadacs'] = byte2str(s[8]).replace('\\x00','')
res['uploadacs'] = byte2str(s[9]).replace('\\x00','')
res['hatchacs'] = byte2str(s[10]).replace('\\x00','')
res['sysopacs'] = byte2str(s[11]).replace('\\x00','')
res['passeacs'] = byte2str(s[12]).replace('\\x00','')
res['path'] = byte2str(s[13]).replace('\\x00','')
res['defscan'] = s[14]
res['flags'] = s[15]
res['created'] = s[16]
res['netaddr'] = s[17]
res['echotag'] = byte2str(s[18]).replace('\\x00','')
res['listeacs'] = byte2str(s[19]).replace('\\x00','')
res['reserved'] = s[20:]
return res

for i in range(36):
z=readfilebase(i,'fbases.dat')
print(z)

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT