diff --git a/src/libprs500/lrf/lrfcreator.py b/src/libprs500/lrf/lrfcreator.py new file mode 100644 index 0000000000..ae6d1064c0 --- /dev/null +++ b/src/libprs500/lrf/lrfcreator.py @@ -0,0 +1,68 @@ +## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from cStringIO import StringIO +from zlib import compress +from xml.dom import minidom as dom + +from libprs500.lrf.meta import LRFMetaFile, LRFException + +GIF_PIXEL = 'GIF89a\x01\x00\x01\x00\xf0\x00\x00Mhh\x00\x00\x00!\xf9\x04\x00\x00'\ + '\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;' + +def create_lrf_file(): + buff = StringIO() + buff.write(LRFMetaFile.LRF_HEADER) + buff.write("".join(['\0' for i in range(0x56 - 6)])) + lrf = LRFMetaFile(buff) + lrf.version = 999 # No reason + lrf.xor_key = 0x30 # No reason + lrf.root_object_id = 0x32 # No reason + lrf.binding = 0x01 # front to back 0x10 for back to front + lrf.dpi = 1600 # TODO: Play with this + lrf.width = 600 # TODO: Play with this + lrf.height = 800 # TODO: Play with this + lrf.color_depth = 24 # Seems like a good idea + lrf.toc_object_id = 0x42 # No reason + lrf.thumbnail_type = 0x14 # GIF + lrf.thumbnail_size = len(GIF_PIXEL) + + doc = dom.getDOMImplementation().createDocument(None, None, None) + info = doc.createElement('Info') + info.setAttribute('version', '1.0') + book_info = doc.createElement('BookInfo') + doc_info = doc.createElement('DocInfo') + info.appendChild(book_info) + info.appendChild(doc_info) + info = doc.toxml(encoding='utf-16') + stream = compress(info) + lrf.compressed_info_size = 4 + len(stream) + lrf.uncompressed_info_size = len(info) + buff.write(stream + GIF_PIXEL) + pos = buff.tell() + if pos%16 != 0: + buff.write("".join(['\0' for i in range(16 - pos%16)])) + + + buff.seek(0) + return lrf + + + +class LRFCreator(object): + pass + +if __name__ == "__main__": + open('test.lrf', 'wb').write(create_lrf_file()._file.read()) \ No newline at end of file diff --git a/src/libprs500/lrf/lrftypes.py b/src/libprs500/lrf/lrftypes.py new file mode 100644 index 0000000000..07cdad3954 --- /dev/null +++ b/src/libprs500/lrf/lrftypes.py @@ -0,0 +1,93 @@ +## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import struct + +from libprs500.prstypes import field +from libprs500.lrf.meta import WORD, DWORD + +class LRFTag(list): + """ + Base class for all LRF tags. + + An LRFTag is simply a sequence of bytes. The first two bytes are the tag id. + Tag ids are always of the form (encoded little endian) # f5 where # is a byte. + Thus there can be atmost 256 distinct tags. + """ + id = field(fmt=WORD, start=0) + + def __init__(self, _id, size): + """ + @param _id: The tag id should be an integer + @param _size: The initial size of this tag + """ + list.__init__(self, ['\0' for i in range(size+4)]) + self.id = _id + + def pack(self, val, fmt=DWORD, start=0): + """ + Encode C{val} and write it to buffer. + + @param fmt: See U{struct} + @param start: Position in buffer at which to write encoded data + """ + self[start:start+struct.calcsize(fmt)] = struct.pack(fmt, val) + + def unpack(self, fmt=DWORD, start=0): + """ + Return decoded data from buffer. + + @param fmt: See U{struct} + @param start: Position in buffer from which to decode + """ + end = start + struct.calcsize(fmt) + return struct.unpack(fmt, "".join(list.__getslice__(self, start, end))) + +class ObjectStart(LRFTag): + """ Tag that marks the start of an LRFObject """ + ID = 0xf500 + + # Stored in 4 bytes. Thus there can be only 1024*1024*1024 objects in an LRF file + object_id = field(fmt=DWORD, start=0) + # Stored in 2 bytes. Thus there can be at most 256**2 distinct object types. + object_type = field(fmt=WORD, start=4) + + def __init__(self, _id, _type): + LRFTag.__init__(self, ObjectStart.ID, 6) + self.object_id = _id + self.object_type = _type + +class ObjectEnd(LRFTag): + """ Tag that marks the end of an LRFObject """ + ID = 0xf501 + + def __init__(self): + LRFTag.__init__(self, ObjectEnd.ID, 0) + +class LRFObject(list): + """ + Base class for all LRF objects. An LRF object is simply a sequence of + L{LRFTag}s. It must start with an L{ObjectStart} tag and end with + an L{ObjectEnd} tag. + """ + def __str__(self): + return "".join(self) + +class BookAttr(LRFObject): + """ + Global properties for an LRF ebook. Root element of the LRF element + structure. + """ + \ No newline at end of file diff --git a/src/libprs500/lrf/makelrf.py b/src/libprs500/lrf/makelrf.py index 0c6f98af98..4d1aa77deb 100755 --- a/src/libprs500/lrf/makelrf.py +++ b/src/libprs500/lrf/makelrf.py @@ -77,7 +77,7 @@ def makelrf(author=None, title=None, \ if not os.access(src, os.R_OK): raise LRFException("Unable to read from file: " + src) if thumbnail: - thumb = os.path.abspath(options.thumbnail) + thumb = os.path.abspath(thumbnail) if not os.access(thumb, os.R_OK): raise LRFException("Unable to read from " + thumb) else: @@ -88,7 +88,7 @@ def makelrf(author=None, title=None, \ if not title: title = os.path.basename(src) label = os.path.basename(src) - id = hashlib.md5(os.path.basename(label)).hexdigest() + id = 'FB' + hashlib.md5(os.path.basename(label)).hexdigest()[:14] name, ext = os.path.splitext(label) cwd = os.path.dirname(src) dirpath = None @@ -163,7 +163,7 @@ def main(cargs=None): dest="title", help="Set the book title") parser.add_option("-a", "--author", action="store", type="string", \ dest="author", help="Set the author") - parser.add_option('-r', '--rasterize', action='store_true', \ + parser.add_option('-r', '--rasterize', action='store_false', \ dest="rasterize", help="Convert pdfs into image files.") parser.add_option('-c', '--cover', action='store', dest='cover',\ diff --git a/src/libprs500/lrf/meta.py b/src/libprs500/lrf/meta.py index 6f4fd0c182..a8d2a57549 100644 --- a/src/libprs500/lrf/meta.py +++ b/src/libprs500/lrf/meta.py @@ -213,13 +213,14 @@ class LRFMetaFile(object): title = xml_field("Title", parent="BookInfo") author = xml_field("Author", parent="BookInfo") + # 16 characters. First two chars should be FB for personal use ebooks. book_id = xml_field("BookID", parent="BookInfo") publisher = xml_field("Publisher", parent="BookInfo") label = xml_field("Label", parent="BookInfo") category = xml_field("Category", parent="BookInfo") classification = xml_field("Classification", parent="BookInfo") free_text = xml_field("FreeText", parent="BookInfo") - + # Should use ISO 639 language codes language = xml_field("Language", parent="DocInfo") creator = xml_field("Creator", parent="DocInfo") # Format is %Y-%m-%d @@ -296,7 +297,7 @@ class LRFMetaFile(object): else: candidate = candidate.encode('utf-16') return candidate.strip() - except zlib.error, e: + except zlib.error: raise LRFException("Unable to decompress document meta information") def fset(self, info): @@ -453,6 +454,22 @@ class LRFMetaFile(object): slice = self.thumbnail[0:16] self.thumbnail_type = self._detect_thumbnail_type(slice) + def seek(self, *args): + """ See L{file.seek} """ + return self._file.seek(*args) + + def tell(self): + """ See L{file.tell} """ + return self._file.tell() + + def read(self): + """ See L{file.read} """ + return self._file.read() + + def write(self, val): + """ See L{file.write} """ + self._file.write(val) + def main(): import sys, os.path @@ -520,11 +537,3 @@ def main(): print str(f[1]) + ":", lrf.__getattribute__(f[0]) if options.get_thumbnail: print "Thumbnail:", td - -def zeroes(num): - temp = [ '\0' for i in range(num) ] - return "".join(temp) - -def create_lrf_header(): - buffer = StringIO() - buffer.write()