Parent

Class/Module Index [+]

Quicksearch

Rex::OLE::Directory

This class serves as the root directory entry in addition to an abstraction around the concept of a directory as a whole.

Attributes

num_entries[RW]

XXX: num_entries is not maintained once a stream/storage is added!

Public Class Methods

new(stg) click to toggle source
# File lib/rex/ole/directory.rb, line 25
def initialize(stg)
        super

        @num_entries = 1
end

Public Instance Methods

each_entry(&block) click to toggle source
# File lib/rex/ole/directory.rb, line 39
def each_entry(&block)
        yield_entries(self, &block)
end
flatten_tree(entries, parent) click to toggle source

NOTE: this may not be necessary if we were to use each_entry

# File lib/rex/ole/directory.rb, line 172
def flatten_tree(entries, parent)
        entries << parent
        parent.each { |el|
                flatten_tree(entries, el)
        }
end
from_s(sid, buf) click to toggle source

low-level functions

# File lib/rex/ole/directory.rb, line 85
def from_s(sid, buf)
        super

        if (@_sidRightSib != DIR_NOSTREAM)
                raise RuntimeError, 'Root Entry is invalid! (has right sibling)'
        end
        if (@_sidLeftSib != DIR_NOSTREAM)
                raise RuntimeError, 'Root Entry is invalid! (has left sibling)'
        end
end
populate_children(entries, parent, sid) click to toggle source

recursively add entries to their proper parents :)

# File lib/rex/ole/directory.rb, line 156
def populate_children(entries, parent, sid)
        node = entries[sid]
        dlog("populate_children(entries, \"#{parent.name}\", #{sid}) - node: #{node.name}", 'rex', LEV_3)
        parent << node
        if (node.type == STGTY_STORAGE) and (node._sidChild != DIR_NOSTREAM)
                populate_children(entries, node, node._sidChild)
        end
        if (node._sidLeftSib != DIR_NOSTREAM)
                populate_children(entries, parent, node._sidLeftSib)
        end
        if (node._sidRightSib != DIR_NOSTREAM)
                populate_children(entries, parent, node._sidRightSib)
        end
end
read() click to toggle source
# File lib/rex/ole/directory.rb, line 96
def read
        @children = []
        visited = []
        entries = []
        root_node = nil
        sect = @stg.header._sectDirStart
        while (sect != SECT_END)

                if (visited.include?(sect))
                        raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect
                end
                visited << sect

                sbuf = @stg.read_sector(sect, @stg.header.sector_size)
                while (sbuf.length >= DIRENTRY_SZ)
                        debuf = sbuf.slice!(0, DIRENTRY_SZ)

                        type = Util.get8(debuf, 0x42)
                        case type
                        when STGTY_ROOT
                                if (entries.length != 0)
                                        raise RuntimeError, 'Root Entry found, but not first encountered!'
                                end
                                if (root_node)
                                        raise RuntimeError, 'Multiple root directory sectors detected (0x%08x)' % sect
                                end
                                de = self
                                root_node = de

                        when STGTY_STORAGE
                                de = SubStorage.new @stg

                        when STGTY_STREAM
                                de = Stream.new @stg

                        when STGTY_INVALID
                                # skip invalid entries
                                next

                        else
                                raise RuntimeError, 'Unsupported directory entry type (0x%02x)' % type
                        end

                        # read content
                        de.from_s(entries.length, debuf)
                        entries << de
                end
                sect = @stg.next_sector(sect)
        end

        @num_entries = entries.length

        # sort out the tree structure, starting with the root
        if (@_sidChild != DIR_NOSTREAM)
                populate_children(entries, root_node, @_sidChild)
        end
end
set_ministream_params(start, size) click to toggle source
# File lib/rex/ole/directory.rb, line 44
def set_ministream_params(start, size)
        @_sectStart = start
        @_ulSize = size
end
write() click to toggle source
# File lib/rex/ole/directory.rb, line 180
def write
        # flatten the directory again
        entries = []
        flatten_tree(entries, self)
        dlog("flattened tree has #{entries.length} entries...", 'rex', LEV_3)

        # count directory sectors
        ds_count = entries.length / 4
        if ((entries.length % 4) > 0)
                # one more sector to hold the rest
                ds_count += 1
        end

        # put the root entry first
        sbuf = self.pack

        # add the rest
        prev_sect = nil
        dir_start = nil
        entries.each { |de|
                # we already got the root entry, no more!
                next if (de.type == STGTY_ROOT)

                dir = de.pack
                dlog("writing dir entry #{de.name}", 'rex', LEV_3)
                sbuf << dir

                if (sbuf.length == @stg.header.sector_size)
                        # we have a full sector, add it!
                        sect = @stg.write_sector(sbuf, nil, prev_sect)
                        prev_sect = sect
                        dir_start ||= sect
                        # reset..
                        sbuf = ""
                end
        }

        # still a partial sector left?
        if (sbuf.length > 0)
                # add it! (NOTE: it will get padded with nul bytes if its not sector sized)
                sect = @stg.write_sector(sbuf, nil, prev_sect)
                prev_sect = sect
                dir_start ||= sect
        end

        @stg.header._sectDirStart = dir_start
end
yield_entries(de, &block) click to toggle source

woop, recursive each

# File lib/rex/ole/directory.rb, line 33
def yield_entries(de, &block)
        block.call(de)
        de.each { |el|
                yield_entries(el, &block)
        }
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.