All Downloads are FREE. Search and download functionalities are using the official Maven repository.

Explore the source code of the class BIFFRecords.py

# -*- coding: cp1252 -*-
from struct import pack
from UnicodeUtils import upack1, upack2, upack2rt

class SharedStringTable(object):
    _SST_ID = 0x00FC
    _CONTINUE_ID = 0x003C

    def __init__(self, encoding):
        self.encoding = encoding
        self._str_indexes = {}
        self._rt_indexes = {}
        self._tally = []
        self._add_calls = 0
        # Following 3 attrs are used for temporary storage in the
        # get_biff_record() method and methods called by it. The pseudo-
        # initialisation here is for documentation purposes only.
        self._sst_record = None
        self._continues = None
        self._current_piece = None

    def add_str(self, s):
        if self.encoding != 'ascii' and not isinstance(s, unicode):
            s = unicode(s, self.encoding)
        self._add_calls += 1
        if s not in self._str_indexes:
            idx = len(self._str_indexes) + len(self._rt_indexes)
            self._str_indexes[s] = idx
            self._tally.append(1)
        else:
            idx = self._str_indexes[s]
            self._tally[idx] += 1
        return idx
	
    def add_rt(self, rt):
        rtList = []
        for s, xf in rt:
            if self.encoding != 'ascii' and not isinstance(s, unicode):
                s = unicode(s, self.encoding)
            rtList.append((s, xf))
        rt = tuple(rtList)
        self._add_calls += 1
        if rt not in self._rt_indexes:
            idx = len(self._str_indexes) + len(self._rt_indexes)
            self._rt_indexes[rt] = idx
            self._tally.append(1)
        else:
            idx = self._rt_indexes[rt]
            self._tally[idx] += 1
        return idx

    def del_str(self, idx):
        # This is called when we are replacing the contents of a string cell.
        # handles both regular and rt strings
        assert self._tally[idx] > 0
        self._tally[idx] -= 1
        self._add_calls -= 1

    def str_index(self, s):
        return self._str_indexes[s]

    def rt_index(self, rt):
        return self._rt_indexes[rt]

    def get_biff_record(self):
        self._sst_record = ''
        self._continues = [None, None]
        self._current_piece = pack(' 0x2020: # limit for BIFF7/8
            chunks = []
            pos = 0
            while pos < len(data):
                chunk_pos = pos + 0x2020
                chunk = data[pos:chunk_pos]
                chunks.append(chunk)
                pos = chunk_pos
            continues = pack('<2H', self._REC_ID, len(chunks[0])) + chunks[0]
            for chunk in chunks[1:]:
                continues += pack('<2H%ds'%len(chunk), 0x003C, len(chunk), chunk)
                # 0x003C -- CONTINUE record id
            return continues
        else:
            return self.get_rec_header() + data


class Biff8BOFRecord(BiffRecord):
    """
    Offset Size Contents
    0      2    Version, contains 0600H for BIFF8 and BIFF8X
    2      2    Type of the following data:
                  0005H = Workbook globals
                  0006H = Visual Basic module
                  0010H = Worksheet
                  0020H = Chart
                  0040H = Macro sheet
                  0100H = Workspace file
    4      2    Build identifier
    6      2    Build year
    8      4    File history flags
    12     4    Lowest Excel version that can read all records in this file
    """
    _REC_ID      = 0x0809
    # stream types
    BOOK_GLOBAL = 0x0005
    VB_MODULE   = 0x0006
    WORKSHEET   = 0x0010
    CHART       = 0x0020
    MACROSHEET  = 0x0040
    WORKSPACE   = 0x0100

    def __init__(self, rec_type):
        version  = 0x0600
        build    = 0x0DBB
        year     = 0x07CC
        file_hist_flags = 0x00L
        ver_can_read    = 0x06L

        self._rec_data = pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read)


class InteraceHdrRecord(BiffRecord):
    _REC_ID = 0x00E1

    def __init__(self):
        self._rec_data = pack('BB', 0xB0, 0x04)


class InteraceEndRecord(BiffRecord):
    _REC_ID = 0x00E2

    def __init__(self):
        self._rec_data = ''


class MMSRecord(BiffRecord):
    _REC_ID = 0x00C1

    def __init__(self):
        self._rec_data = pack('> 15
            c = low_15 | high_15
            passwd_hash ^= c
        passwd_hash ^= len(plaintext)
        passwd_hash ^= 0xCE4B
        return passwd_hash

    def __init__(self, passwd = ""):
        self._rec_data = pack('