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 = "