#
# PeepDB v 0.1 "Germ"
# (c) 2001 Alexey Vyskubov alexey@pepper.spb.ru
# some patches by Mark Eichin eichin@thok.org 20031019
# see original at http://linux.piter-press.ru/peepdb/
#
import struct
def to_byte(s):
return struct.unpack('B', s)[0]
def from_byte(x):
return struct.pack('B', x)
def to_word(s):
return struct.unpack('>H', s)[0]
def from_word(x):
return struct.pack('>H', x)
def to_dword(s):
return struct.unpack('>L', s)[0]
def from_dword(x):
return struct.pack('>L', x)
def assign_byte(dt, b, offset):
dt[offset] = b[0]
return dt
def assign_word(dt, w, offset):
dt = dt[:offset]+ w + dt[offset+2:]
return dt
def assign_dword(dt, dw, offset):
dt = assign_word(dt, dw[0:2], offset)
dt = assign_word(dt, dw[2:], offset+2)
return dt
class data_header:
"Common header manipulation"
def __init__(self, size):
self.data = '\0'*size
def put_data_byte(self, b, offset):
self.data = assign_byte(self.data, from_byte(b), offset)
def get_data_byte(self, offset):
return to_byte(self.data[offset])
def put_data_bit(self, bit, byte_offset, bit_offset):
newbyte = self.get_data_byte(byte_offset)
newbit = 2 ** bit_offset
if bit == 0:
newbyte = newbyte & (255 - newbit)
else:
newbyte = newbyte | newbit
def get_data_bit(self, byte_offset, bit_offset):
oldbyte = get_data_byte(byte_offset)
oldbit = 2 ** bit_offset
return oldbyte & oldbit
def put_data_word(self, w, offset):
self.data = assign_word(self.data, from_word(w), offset)
def get_data_word(self, offset):
return to_word(self.data[offset:offset+2])
def put_data_dword(self, dw, offset):
self.data = assign_dword(self.data, from_dword(dw), offset)
def get_data_dword(self, offset):
return to_dword(self.data[offset:offset+4])
def put_data_string(self, str, offset):
self.data = self.data[0:offset]+str+self.data[offset+len(str):]
def get_data_string(self, len, offset):
return self.data[offset:offset+len]
class pdb_header(data_header):
"PalmOS pdb file header"
def set_name(self, nm):
k = len(nm)
if k > 31:
self.put_data_string(nm[0:31]+'\0', 0)
else:
self.put_data_string(nm+'\0', 0)
def set_attributes(self, at):
self.put_data_word(at, 32)
def get_attributes(self):
return self.get_data_word(32)
def set_version(self, ver):
self.put_data_word(ver, 34)
def get_version(self):
return self.get_data_word(34)
def set_create_time(self, time):
self.put_data_dword(time, 36)
def get_create_time(self):
return self.get_data_dword(36)
def set_modify_time(self, time):
self.put_data_dword(time, 40)
def get_modify_time(self):
return self.get_data_dword(40)
def set_backup_time(self, time):
self.put_data_dword(time, 44)
def get_backup_time(self):
return self.get_data_dword(44)
def set_modification_number(self, num):
self.put_data_dword(num, 48)
def get_modification_number(self):
return self.get_data_dword(48)
def set_appInfoID(self, id):
self.put_data_dword(num, 52)
def get_appInfoID(self):
return self.get_data_dword(52)
def set_sortInfoID(self, id):
self.put_data_dword(num, 56)
def get_sortInfoID(self):
return self.get_data_dword(56)
def set_type(self, type):
self.put_data_string(type, 60)
def get_type(self):
return self.get_data_string(60)
def set_creator(self, creat):
self.put_data_string(creat, 64)
def get_creator(self):
return self.get_data_string(64)
def set_id_seed(self, seed):
self.put_data_dword(seed, 68)
def get_id_seed(self):
return self.get_data_dword(68)
def set_next_record_list(self, list):
self.put_data_dword(list, 72)
def get_next_record_list(self):
return self.get_data_dword(72)
def set_number_of_records(self, num):
self.put_data_word(num, 76)
def get_number_of_records(self):
return self.get_data_word(76)
def load_from_file(self, filename):
f = open(filename, 'r')
self.data = f.read(78)
f.close()
def get_from_pdb(self, pdb):
self.data = pdb[0:78]
def init(self, nm):
data_header.__init__(self, 78)
self.set_name(nm)
self.set_create_time(1000000) # FIXME
self.set_modify_time(1000000) # FIXME
self.set_type("NULL")
self.set_creator("NULL")
def __init__(self, mode, nm):
if mode == 'new':
self.init(nm)
else:
if mode == 'load':
self.load_from_file(nm)
else:
if mode == 'get':
self.get_from_pdb(nm)
# FIXME
class record_header(data_header):
"PDB's record header"
def init(self):
data_header.__init__(self, 8)
def __init__(self, hdr):
if hdr == '':
self.init()
else:
self.data = hdr
def set_offset(self, offset):
self.put_data_dword(offset, 0)
def get_offset(self):
return self.get_data_dword(0)
def set_delete_bit(self, bit):
self.put_data_bit(bit, 4, 7)
def set_dirty_bit(self, bit):
self.put_data_bit(bit, 4, 6)
def set_busy_bit(self, bit):
self.put_data_bit(bit, 4, 5)
def set_secret_bit(self, bit):
self.put_data_bit(bit, 4, 4)
def set_category(self, cat):
self.put_data_bit((cat & 8)/8, 4, 3)
self.put_data_bit((cat & 4)/4, 4, 2)
self.put_data_bit((cat & 2)/2, 4, 1)
self.put_data_bit(cat & 1, 4, 0)
def set_id(self, id):
self.put_data_string(id, 5)
def get_id(self):
return self.get_data_string(3, 5)
class palmdb:
"PalmOS pdb format"
def init(self, nm):
self.main_header = pdb_header('new', nm)
self.records=[]
def __init__(self, mode, nm):
if mode == 'new':
self.init(nm)
else:
self.init('noname')
if mode == 'load':
self.load_from_file(nm)
else:
if mode == 'get':
self.get_from_pdb(nm)
# FIXME
# FIXME
def calculate_offsets(self):
ot = 78L + self.main_header.get_number_of_records()*8
# Main PDB's header is 78 bytes
# Record's header is 8 bytes
for rec in range(self.main_header.get_number_of_records()):
self.records[rec][0].set_offset(ot)
ot = ot + len(self.records[rec][1])
def create_new_record(self, id, data):
self.records.append([])
self.main_header.set_number_of_records(self.main_header.get_number_of_records() + 1)
self.records[-1].append(record_header(''))
self.records[-1].append(data)
self.records[-1][0].set_id(id)
self.calculate_offsets()
def clean_all_records(self):
while (len(self.records)>0):
rec = self.records.pop()
del rec[0]
def get_from_pdb(self, pdb):
self.clean_all_records()
self.main_header.get_from_pdb(pdb[0:78])
skip = 78
i = self.main_header.get_number_of_records()
while i > 0:
self.records.append(['', ''])
self.records[-1][0] = record_header(pdb[skip:skip+8])
skip = skip + 8
i = i - 1
i = len(self.records) - 1
while (i >= 0):
start = int(self.records[i][0].get_offset())
if i == len(self.records) - 1:
self.records[i][1] = pdb[start:]
else:
end = int(self.records[i+1][0].get_offset())
self.records[i][1] = pdb[start:end]
i = i - 1
def load_from_file(self, filename):
f = open(filename, 'r')
pdb = f.read()
f.close()
self.get_from_pdb(pdb)
def save_to_file(self, filename):
f = open(filename, 'w')
f.write(self.main_header.data)
for i in range(self.main_header.get_number_of_records()):
f.write(self.records[i][0].data)
for i in range(self.main_header.get_number_of_records()):
f.write(self.records[i][1])
f.close()