#!/usr/bin/python # as described in http://www.sven.de/librie/Librie/MgrTabFormat # this is what goes in /mssony/librie/booklist/MgrTbl.dat import sys import os import rfc822 import struct import time import LrfFile import xml.dom.minidom def pack_to(len, bytes): return (bytes + struct.pack("x" * len))[:len] class xml_attrs: def __init__(self, s=None, node=None): if s: self.xpp = xml.dom.minidom.parseString(s) else: self.xpp = node def __getattr__(self, a): return xml_attrs(node=self.xpp.getElementsByTagName(a)[0]) def Text(self): return self.xpp.childNodes[0].wholeText def unlink(self): return self.xpp.unlink() # this lets "" encode to "" def encode_utf16(s): if not s: return "" return s.encode("utf-16") # "<" for all, little endian; "H" for all of these 2-byte fields class MgrField: def __init__(self, lrfname): self.lrfname = os.path.basename(lrfname) self.title = u"" self.titlereading = u"" self.author = u"" self.authorreading = u"" self.publisher = u"" self.location = "" lrf = LrfFile.LrfFile(lrfname) # this is the full cover - should thumbnail it # (use PIL, or double-pipe - avoid the tmpfile) # http://permalink.gmane.org/gmane.linux.hardware.sony.librie/1545 # says "60x80" for the thumbnail... conv = os.popen("convert -scale 20% - /tmp/x.gif", "w") conv.write(lrf.gif) conv.close() self.cover_image_data = open("/tmp/x.gif").read() self.cover_image_type = 0x14 # lrf.uinfo also has CreationDate, Title, Author, BookID, Publisher... xlrf = xml_attrs(lrf.uinfo.rstrip("\0")) xbook = xlrf.Info.BookInfo self.id = xbook.BookID.Text() self.publisher = xbook.Publisher.Text() self.author = xbook.Author.Text() self.title = xbook.Title.Text() xdoc = xlrf.Info.DocInfo self.when = xdoc.CreationDate.Text() xlrf.unlink() def import_fields(self, fields): for k,v in fields.items(): setattr(self, k.lower(), v.decode("iso-8859-1")) def set_size(self, size): self.size = size def set_mtime(self, mtime): self.unixtime = mtime def prep(self): # some things are derived... if not hasattr(self, "id"): self.id = unicode(self.lrfname.replace(".lrf","",1)) # self.id = "zdVnISprTxmeHKjx" if not hasattr(self, "when"): self.when = time.strftime("%Y-%m-%d", time.gmtime(self.unixtime)) if not hasattr(self, "cover_image_data"): # read and convert, later self.cover_image_data = open("/usr/share/galeon/general.png", "r").read() # 0x11 for JPEG, 0x12 for PNG, 0x13 for BMP and 0x14 for GIF. self.cover_image_type = 0x12 # if not self.titlereading: # self.titlereading = self.title # if not self.authorreading: # self.authorreading = self.author if not self.location: # BookListItem.cs makes this upper case self.location = "a:/ebook/bbeb/book/" + self.lrfname def marshall(self): bytes = [] # emit the headerfields bytes.append(struct.pack("<H", 0)) # dummy recordlen bytes.append(struct.pack("<H", len(encode_utf16(self.title)))) bytes.append(struct.pack("<H", len(encode_utf16(self.titlereading)))) bytes.append(struct.pack("<H", len(encode_utf16(self.author)))) bytes.append(struct.pack("<H", len(encode_utf16(self.authorreading)))) bytes.append(struct.pack("<H", len(encode_utf16(self.publisher)))) bytes.append(struct.pack("<H", len(self.location.encode("ascii")))) bytes.append(struct.pack("<H", len(self.cover_image_data))) bytes.append(struct.pack("<H", 0x60)) # unknown bytes.append(struct.pack("x" * 15)) # now add the values bytes.append(pack_to(32, encode_utf16(self.id))) bytes.append(pack_to(15, self.when.encode("ascii"))) bytes.append(encode_utf16(self.title)) bytes.append(encode_utf16(self.titlereading)) bytes.append(encode_utf16(self.author)) bytes.append(encode_utf16(self.authorreading)) bytes.append(encode_utf16(self.publisher)) bytes.append(self.location.encode("ascii")) bytes.append(struct.pack("<L", self.size)) bytes.append(struct.pack("x" * 16)) bytes.append(struct.pack("B", self.cover_image_type)) bytes.append(self.cover_image_data) # now fix the length bytes[0] = struct.pack("<H", len("".join(bytes))) return "".join(bytes) def get_keys(lrfname): fp = open(lrfname.replace(".lrf", ".info", 1), "r") m = rfc822.Message(fp) return m.dict def write_datafile(stickbase): mgrtbl_name = os.path.join(stickbase, "mssony/librie/booklist/MgrTbl.dat") mgrtbl = open(mgrtbl_name, "w") bookdir = os.path.join(stickbase, "ebook/bbeb/book") for lrfname in os.listdir(bookdir): if not lrfname.endswith(".lrf"): continue bookname = os.path.join(bookdir, lrfname) mgr = MgrField(bookname) # metadata = get_keys(bookname) # mgr.import_fields(metadata) mgr.set_size(os.path.getsize(bookname)) mgr.set_mtime(os.path.getmtime(bookname)) mgr.prep() mgrtbl.write(mgr.marshall()) mgrtbl.close() if __name__ == "__main__": prog, stickbase = sys.argv write_datafile(stickbase)