_                _   _                 ____            _     _ 	
   / \   _ __   ___ | |_| |__   ___ _ __  |  _ \ _ __ ___ (_) __| |	
  / _ \ | '_ \ / _ \| __| '_ \ / _ \ '__| | | | | '__/ _ \| |/ _\` |	
 / ___ \| | | | (_) | |_| | | |  __/ |    | |_| | | | (_) | | (_| |	
/_/   \_\_| |_|\___/ \__|_| |_|\___|_|    |____/|_|  \___/|_|\__,_|	
                                                                bbs
  XQTRs lair...
Home // Blog // NULL emag. // Files // Docs // Tutors // GitHub repo
read filebases with python;xqtr;mystic;tut08                                    
                                                                                
                                                                                
    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 = " 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 = " 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)