_                _   _                 ____            _     _ 	
   / \   _ __   ___ | |_| |__   ___ _ __  |  _ \ _ __ ___ (_) __| |	
  / _ \ | '_ \ / _ \| __| '_ \ / _ \ '__| | | | | '__/ _ \| |/ _\` |	
 / ___ \| | | | (_) | |_| | | |  __/ |    | |_| | | | (_) | | (_| |	
/_/   \_\_| |_|\___/ \__|_| |_|\___|_|    |____/|_|  \___/|_|\__,_|	
                                                                bbs
  XQTRs lair...
Home // Blog // NULL emag. // Files // Docs // Tutors // GitHub repo
                                                                                
                                                                                
                                                                                
    as i am learning python, i made this simple lib/program to read a JAM       
    base. it can read the header file and also read info/text from a            
    message. for sure i will evolve it and make it even better, but for         
    the purposes of the mag, is enough for now. just change the file name       
    of the jam base and test it yourself.                                       
                                                                                
    you can use it freely. u can read message text and make all sort of         
    things with it, in your projects.                                           
                                                                                
    python is a "universal" programming language now days, so expect more       
    things written in python also.                                              
                                                                                
--- cut here ---------------------------------------------------------------    
#!/usr/bin/python3                                                              
import struct                                                                   
from datetime import datetime                                                   
import os                                                                       
                                                                                
jam_local =        int('00000001',16)                                           
jam_intransit =    int('00000002',16)                                           
jam_priv =         int('00000004',16)                                           
jam_rcvd =         int('00000008',16)                                           
jam_sent =         int('00000010',16)                                           
jam_killsent =     int('00000020',16)                                           
jam_achvsent =     int('00000040',16)                                           
jam_hold =         int('00000080',16)                                           
jam_crash =        int('00000100',16)                                           
jam_imm =          int('00000200',16)                                           
jam_direct =       int('00000400',16)                                           
jam_gate =         int('00000800',16)                                           
jam_freq =         int('00001000',16)                                           
jam_fattch =       int('00002000',16)                                           
jam_truncfile =    int('00004000',16)                                           
jam_killfile =     int('00008000',16)                                           
jam_rcptreq =      int('00010000',16)                                           
jam_confmreq =     int('00020000',16)                                           
jam_orphan =       int('00040000',16)                                           
jam_encrypt =      int('00080000',16)                                           
jam_compress =     int('00100000',16)                                           
jam_escaped =      int('00200000',16)                                           
jam_fpu =          int('00400000',16)                                           
jam_typelocal =    int('00800000',16)                                           
jam_typeecho =     int('01000000',16)                                           
jam_typenet =      int('02000000',16)                                           
jam_nodisp =       int('20000000',16)                                           
jam_locked =       int('40000000',16)                                           
jam_deleted =      int('80000000',16)                                           
base_filename = ''                                                              
mbase_header=dict()                                                             
msg_header=dict()                                                               
# mbase_header["signature"]                                                     
# mbase_header["created"]                                                       
# mbase_header["modcounter"]                                                    
# mbase_header["activemsgs"]                                                    
# mbase_header["passwordcrc"]                                                   
# mbase_header["basemsgnum"]                                                    
#functions for msg attributes                                                   
def isdeleted():                                                                
  global msg_header                                                             
  if (jam_deleted & msg_header["attr1"] ) !=  0:                                
    return True                                                                 
  else:                                                                         
    return False                                                                
def islocal():                                                                  
  global msg_header                                                             
  if (jam_local & msg_header["attr1"] ) != 0:                                   
    return True                                                                 
  else:                                                                         
    return False                                                                
                                                                                
def isreceived():                                                               
  global msg_header                                                             
  if (jam_rcvd & msg_header["attr1"] ) != 0:                                    
    return True                                                                 
  else:                                                                         
    return False                                                                
# read the header file and get info                                             
# returns 0 if is succesful, -1 if file doesn't exist and -2 if file            
# is not valid jam base                                                         
def get_msg_base_hdr(filename):                                                 
  global mbase_header                                                           
  global base_filename                                                          
  base_filename = filename                                                      
  filename = filename + '.jhr'                                                  
  if os.path.exists(filename) == False:                                         
    return -1                                                                   
  jamf = "ssssIIIII"                                                            
  with open(filename, mode='rb') as file:                                       
    fileMsgHdr = file.read(struct.calcsize(jamf))                               
  jam_hdr = struct.unpack(jamf, fileMsgHdr[0:24])                               
  mbase_header["signature"] = jam_hdr[:4]                                       
  mbase_header["created"] = \                                                   
  datetime.fromtimestamp(jam_hdr[4]).strftime('%Y-%m-%d %H:%M:%S')              
  mbase_header["modcounter"] = jam_hdr[5]                                       
  mbase_header["activemsgs"] = jam_hdr[6]                                       
  mbase_header["passwordcrc"] = jam_hdr[7]                                      
  mbase_header["basemsgnum"] = jam_hdr[8]                                       
  if mbase_header["signature"] == (b'J', b'A', b'M', b'\x00'):                  
    return 0                                                                    
  else:                                                                         
    return -2                                                                   
# read the message header                                                       
def read_msg_header(filename,num):                                              
  global msg_header                                                             
  global base_filename                                                          
  base_filename = filename                                                      
  jdx_name = filename + '.jdx'  # get header offset from index file             
  if os.path.exists(jdx_name) == False:                                         
    return -1                                                                   
  jdx = open(jdx_name,"rb")                                                     
  jdx_size = os.path.getsize(jdx_name)                                          
  offset = (num - mbase_header["basemsgnum"])*8                                 
  if offset>jdx_size:                                                           
    jdx.close()                                                                 
    return -2                                                                   
  jdx.seek((num - mbase_header["basemsgnum"])*8)                                
  jdxf = "