Beispiel #1
0
def parse_exth(data, pos):
    ret = {}
    n = 0
    if (pos != data.find('EXTH')):
        LOG(0, "EXTH header not found where it should be @%d" % pos)
        return None
    else:
        end = pos + calcsize(EXTH_FMT)
        (hlen, count) = unpack(EXTH_FMT, data[pos:end])
        LOG(4, "pos: %d, EXTH header len: %d, record count: %d" % (
            pos, hlen, count))
        pos = end
        while n < count:
            end = pos + calcsize(">2I")
            t, l = unpack(">2I", data[pos:end])
            v = data[end:pos + l]
            if l - 8 == 4:
                v = unpack(">I", v)[0]
            if t in EXTH_RECORD_TYPES:
                rec = EXTH_RECORD_TYPES[t]
                LOG(4, "EXTH record '%s' @%d+%d: '%s'" % (
                    rec, pos, l - 8, v))
                if rec not in ret:
                    ret[rec] = [v]
                else:
                    ret[rec].append(v)

            else:
                LOG(4, "Found an unknown EXTH record type %d @%d+%d: '%s'" %
                        (t, pos, l - 8, repr(v)))
            pos += l
            n += 1
    return ret
Beispiel #2
0
def delete_collection(kjd, collection):
    cn = COLLNAME % collection
    LOG(3, "Deleting collection %s" % cn)
    if cn in kjd:
        del kjd[cn]
    else:
        LOG(1, 'Collection %s does not exist' % collection)
Beispiel #3
0
def add_item(kjd, collection, hash):
    cn = COLLNAME % collection
    if not ((cn) in kjd):
        LOG(1, "Error. collection %s does not exist" % collection)
    else:
        if hash in kjd[cn]['items']:
            LOG(1, "%s was already in %s" % (hash, cn))
        else:
            kjd[cn]['items'].append(hash)
            update_ts(kjd[cn])
Beispiel #4
0
def add_collection(kjd, collection):
    time_ms = int(time() * 1000)
    new_item = {}
    cn = COLLNAME % collection
    LOG(3, "Adding collection %s" % cn)
    if not ((cn) in kjd):
        kjd[cn] = {'items': [], 'lastAccess': time_ms}
    else:
        LOG(1, "Collection %s already exists" % collection)
        update_ts(kjd[cn])
Beispiel #5
0
def remove_item(kjd, collection, hash):
    cn = COLLNAME % collection
    if not ((cn) in kjd):
        LOG(1, "Error. collection %s does not exist" % collection)
    else:
        if hash not in kjd[cn]['items']:
            return
        else:
            kjd[cn]['items'].remove(hash)
            update_ts(kjd[cn])
Beispiel #6
0
def get_books(progress_func=lambda: None):
    ret = {}
    files = glob.glob("%s/*" % BOOKPATH)
    for c, fn in enumerate(files):
        progress_func(c)
        LOG(3, "\n - Processing file #%d: %s" % (c, fn))
        key = make_hash(fn.replace(BOOKPATH, KINDLE_INTERNAL_PATH))
        val = ebook.Book(fn)
        if val.is_a_book:
            ret[key] = val
    return ret
Beispiel #7
0
def load_data():
    try:
        return json.load(open(JSONFILE, 'r'))
    except IOError:
        LOG(2, "File %s not found" % JSONFILE)
        return dict()
Beispiel #8
0
    def __init__(self, fn):
        self.filename = fn

         # Set some fields to defaults
        self.title = fn
        self.author = "??"
        self.language = "??"
        self.is_a_book = False

        f = open(fn)
        d = f.read(68)
        f.close()
        encodings = {
                1252: 'cp1252',
                65001: 'utf-8'
                }
        supported_types = ('BOOKMOBI', 'TEXtREAd')
        self.type = d[60:68]

        if self.type not in supported_types:
            LOG(1, "Unsupported file type %s" % (self.type))
            return None

        try:
            db = parse_palmdb(fn)
        except:
            return None

        self.is_a_book = True
         # now we have a better guess at the title, use it for now
        self.title = db.name

        self.records = db.records
        rec0 = self.records[0].data
        #LOG(5,repr(rec0))
        if self.type == 'BOOKMOBI':
            LOG(3, "This is a MOBI book")
            self.mobi = {}
            for field, pos, fmt in MOBI_HDR_FIELDS:
                end = pos + calcsize(fmt)
                if (end > len(rec0) or
                    ("header_len" in self.mobi
                        and end > self.mobi["header_len"])):
                        continue
                LOG(4, "field: %s, fmt: %s, @ [%d:%d], data: %s" % (
                    field, fmt, pos, end, repr(rec0[pos:end])))
                (self.mobi[field], ) = unpack(">%s" % fmt, rec0[pos:end])

            LOG(3, "self.mobi: %s" % repr(self.mobi))

             # Get and decode the book name
            if self.mobi['locale_language'] in LANGUAGES:
                lang = LANGUAGES[self.mobi['locale_language']]
                if self.mobi['locale_country'] == 0:
                    LOG(2, "Book language: %s" % lang[0][1])
                    self.language = "%s (%s)" % (lang[0][1], lang[0][0])
                elif self.mobi['locale_country'] in lang:
                    country = lang[self.mobi['locale_country']]
                    LOG(2, "Book language is %s (%s)" % (
                        lang[0][1], country[1]))
                    self.language = "%s (%s-%s)" % (
                        lang[0][1],
                        lang[0][0],
                        country[0]
                        )

            pos = self.mobi['full_name_offs']
            end = pos + self.mobi['full_name_len']
            self.title = rec0[pos:end].decode(encodings[self.mobi['encoding']])

            LOG(2, "Book name: %s" % self.title)

            if self.mobi['id'] != 'MOBI':
                LOG(0, "Mobi header missing!")
                return None

            if (0x40 & self.mobi['exth_flags']):  # check for EXTH
                self.exth = parse_exth(rec0, self.mobi['header_len'] + 16)
                LOG(3, "EXTH header: %s" % repr(self.exth))
                if 'author' in self.exth:
                    self.author = ' & '.join(self.exth['author'])
                else:
                    self.author = "n/a"
                self.rawdata = d

                if (('updated title' in self.exth) and
                    (type(self.exth['updated title']) is str)):
                    self.title = ' '.join(self.exth['updated title'])

        elif self.type == 'TEXtREAd':
            LOG(2, "This is an older MOBI book")
            self.rawdata = d
            compression, data_len, rec_count, rec_size, pos = unpack(
                    PRC_HDRFMT, rec0[:calcsize(PRC_HDRFMT)])
            LOG(3, "compression %d, data_len %d, rec_count %d, rec_size %d" %
                    (compression, data_len, rec_count, rec_size))
            if compression == 2:
                data = uncompress(self.records[1].data)
            else:
                data = self.records[1].data
            from BeautifulSoup import BeautifulSoup
            soup = BeautifulSoup(data)

            self.metadata = soup.fetch("dc-metadata")
            try:
                self.title = soup.fetch("dc:title")[0].getText()
                self.author = soup.fetch("dc:creator")[0].getText()
                self.language = soup.fetch("dc:language")[0].getText()
            except:
                self.title, self.author, self.language = ("Unknown", "Unknown",
                        "en-us")