or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

file-io.mdindex.mdmanipulation.mdnavigation.md
tile.json

navigation.mddocs/

Container Navigation

Tools for finding and accessing files and directories within CFB containers.

Capabilities

Find Function

Finds a file entry by path or filename within a CFB container. The search is case-insensitive and can match both full paths and just filenames.

/**
 * Find a file entry by path or filename (case-insensitive)
 * @param cfb - CFB container to search in
 * @param path - File path or filename to find
 * @returns Found entry or null if not found
 */
function find(cfb: CFB$Container, path: string): CFB$Entry | null;

interface CFB$Entry {
  /** Case-sensitive internal name */
  name: string;
  /** CFB type (see CFB$EntryType enum) */
  type: number;
  /** Raw content as buffer or array */
  content: CFB$Blob;
  /** Creation time (if available) */
  ct?: Date;
  /** Modification time (if available) */
  mt?: Date;
  /** Red/Black Tree color: 0 = red, 1 = black */
  color: number;
  /** Class ID represented as hex string */
  clsid: string;
  /** User-defined state bits */
  state: number;
  /** Starting sector in the file */
  start: number;
  /** Data size in bytes */
  size: number;
  /** Storage location (fat or minifat) */
  storage?: string;
  /** Content type (used for MAD format) */
  ctype?: string;
}

enum CFB$EntryType { 
  unknown, 
  storage, 
  stream, 
  lockbytes, 
  property, 
  root 
}

Usage Examples:

const CFB = require('cfb');

// Read a CFB file
const cfb = CFB.read('document.xls', { type: 'file' });

// Find by exact path
const workbook = CFB.find(cfb, 'Workbook');
if (workbook) {
  console.log('Found workbook:', workbook.name);
  console.log('Size:', workbook.size, 'bytes');
  console.log('Type:', workbook.type); // 2 = stream
}

// Find by partial path (case-insensitive)
const summary = CFB.find(cfb, 'summaryinformation');
if (summary) {
  console.log('Found summary:', summary.name);
}

// Find in nested structure
const nestedFile = CFB.find(cfb, 'Dir1/Dir2/MyFile');
if (nestedFile) {
  console.log('Content:', nestedFile.content);
}

Container Structure Navigation

Access container structure directly through the container properties.

interface CFB$Container {
  /** List of all file/storage paths in the container */
  FullPaths: string[];
  /** Array of file entries corresponding to FullPaths */
  FileIndex: CFB$Entry[];
  /** Raw binary data structure (when parsed with raw: true) */
  raw?: {
    header: CFB$Blob;
    sectors: CFB$Blob[];
  };
}

Usage Examples:

const CFB = require('cfb');

// Read CFB file
const cfb = CFB.read('document.xls', { type: 'file' });

// List all paths
console.log('All paths in container:');
cfb.FullPaths.forEach((path, index) => {
  const entry = cfb.FileIndex[index];
  console.log(`${path} (${entry.size} bytes, type: ${entry.type})`);
});

// Find all streams (type 2)
const streams = cfb.FileIndex.filter(entry => entry.type === 2);
console.log('Found', streams.length, 'streams');

// Find all storages (type 1)
const storages = cfb.FileIndex.filter(entry => entry.type === 1);
console.log('Found', storages.length, 'storages');

// Access by index
const firstEntry = cfb.FileIndex[0];
console.log('First entry:', firstEntry.name);

Entry Type Classification

Understanding and working with different entry types in CFB containers.

enum CFB$EntryType {
  unknown = 0,   // Unknown entry type
  storage = 1,   // Directory/folder
  stream = 2,    // File/data stream
  lockbytes = 3, // Lock bytes object
  property = 4,  // Property storage
  root = 5       // Root storage
}

enum CFB$StorageType {
  fat = 0,       // Regular FAT storage
  minifat = 1    // Mini FAT storage (for small streams)
}

Usage Examples:

const CFB = require('cfb');

// Read and analyze CFB structure
const cfb = CFB.read('document.xls', { type: 'file' });

// Categorize entries by type
const categorized = {
  root: [],
  storages: [],
  streams: [],
  unknown: []
};

cfb.FileIndex.forEach(entry => {
  switch (entry.type) {
    case 5: // root
      categorized.root.push(entry);
      break;
    case 1: // storage
      categorized.storages.push(entry);
      break;
    case 2: // stream
      categorized.streams.push(entry);
      break;
    default:
      categorized.unknown.push(entry);
  }
});

console.log('Structure analysis:');
console.log('- Root entries:', categorized.root.length);
console.log('- Storages (directories):', categorized.storages.length);
console.log('- Streams (files):', categorized.streams.length);
console.log('- Unknown types:', categorized.unknown.length);

// Find large streams
const largeStreams = categorized.streams.filter(stream => stream.size > 1000);
console.log('Large streams (>1KB):');
largeStreams.forEach(stream => {
  console.log(`- ${stream.name}: ${stream.size} bytes`);
});

Path Matching Patterns

The find function supports various path matching patterns for flexible file location.

Usage Examples:

const CFB = require('cfb');
const cfb = CFB.read('document.xls', { type: 'file' });

// Exact name matching (case-insensitive)
const workbook = CFB.find(cfb, 'Workbook');

// Path-based matching
const docSummary = CFB.find(cfb, '\x05DocumentSummaryInformation');

// Common Office document streams
const commonStreams = [
  'Workbook',           // Excel workbook data
  'WorkbookHdr',        // Excel workbook header
  'WordDocument',       // Word document stream
  'PowerPoint Document', // PowerPoint presentation
  'SummaryInformation', // Document properties
  'DocumentSummaryInformation' // Extended properties
];

commonStreams.forEach(streamName => {
  const stream = CFB.find(cfb, streamName);
  if (stream) {
    console.log(`Found ${streamName}: ${stream.size} bytes`);
  }
});

// Search for streams with specific patterns
const allEntries = cfb.FileIndex.filter(entry => entry.type === 2);
const worksheets = allEntries.filter(entry => 
  entry.name.toLowerCase().includes('sheet')
);
console.log('Found worksheet-related streams:', worksheets.length);

Advanced Navigation Techniques

Recursive Directory Traversal

For complex CFB structures with nested storages:

function traverseStorage(cfb, storagePath = '') {
  const results = [];
  
  cfb.FullPaths.forEach((path, index) => {
    const entry = cfb.FileIndex[index];
    
    // Skip root entry
    if (entry.type === 5) return;
    
    // Check if this path is under the specified storage
    if (storagePath === '' || path.startsWith(storagePath)) {
      results.push({
        path: path,
        entry: entry,
        isStorage: entry.type === 1,
        isStream: entry.type === 2
      });
    }
  });
  
  return results;
}

// Usage
const cfb = CFB.read('complex-document.cfb', { type: 'file' });
const allItems = traverseStorage(cfb);
const rootItems = traverseStorage(cfb, '');

console.log('Total items:', allItems.length);

Content-Based Search

Search for entries based on content patterns:

function findByContentPattern(cfb, pattern) {
  const matches = [];
  
  cfb.FileIndex.forEach((entry, index) => {
    if (entry.type === 2 && entry.content) { // streams only
      const contentStr = Buffer.from(entry.content).toString('binary');
      if (contentStr.includes(pattern)) {
        matches.push({
          path: cfb.FullPaths[index],
          entry: entry
        });
      }
    }
  });
  
  return matches;
}

// Usage
const cfb = CFB.read('document.xls', { type: 'file' });
const xmlEntries = findByContentPattern(cfb, '<?xml');
console.log('Found XML content in', xmlEntries.length, 'streams');