Task 775: .VDW File Format

Task 775: .VDW File Format

.VDW File Format Specifications

The .VDW file format is the Visio Graphics Service File Format used by Microsoft Visio for rendering web drawings. It is a binary format based on the OLE Compound File Binary Format (as described in [MS-CFB]). The file contains storages and streams, with a key stream named "VisioServerData" that holds a ZIP archive containing XML parts for the drawing data.

1. List of Properties Intrinsic to the File Format

The properties intrinsic to the .VDW file format include the following elements from the OLE compound file structure and the embedded ZIP archive:

OLE Compound File Header:

  • Magic Number: D0 CF 11 E0 A1 B1 1A E1 (8 bytes)
  • Class Identifier (CLSID): 16 bytes
  • Minor Version: 2 bytes
  • Major Version: 2 bytes
  • Byte Order: 2 bytes (FE FF for little-endian)
  • Sector Shift: 2 bytes (typically 9 for 512 byte sectors)
  • Mini Sector Shift: 2 bytes (typically 6 for 64 byte sectors)
  • Reserved: 6 bytes
  • Number of Directory Sectors: 4 bytes
  • Number of FAT Sectors: 4 bytes
  • First Directory Sector Location: 4 bytes
  • Transaction Signature Number: 4 bytes
  • Mini Stream Cutoff Size: 4 bytes
  • First Mini FAT Sector Location: 4 bytes
  • Number of Mini FAT Sectors: 4 bytes
  • First DIFAT Sector Location: 4 bytes
  • Number of DIFAT Sectors: 4 bytes
  • DIFAT: 109 entries (4 bytes each)

Storages:

  • Root Storage
  • VisioDocument Storage (contains Visio binary data)
  • Other storages for shapes, pages, fonts, etc.

Streams:

  • VisioServerData (contains ZIP archive for web rendering data)
  • \005SummaryInformation (standard OLE property set for title, subject, author, etc.)
  • \005DocumentSummaryInformation (additional document properties)
  • Document (Visio binary data)
  • Pages
  • Fonts
  • Images
  • DataConnections

Properties in VisioServerData ZIP Archive:

  • app.xml (CT_Properties element with child elements for application name, list of drawing pages, description)
  • core.xml (CT_coreProperties element with creator, title, subject, description, keywords, category, version, revision)
  • document.xml (drawing structure)
  • pages/page1.xml (drawing page data, shapes, connections)
  • _rels/.rels (relationships between parts)
  • fonts/font1.ttf (embedded fonts)
  • images/image1.png (embedded images)
  • custom.xml (custom properties)
  • Data connections and diagram update information

These properties define the file's structure and content for rendering the web drawing.

  1. https://www.spjeff.com/photos/Visio-Sample-Web.vdw
  2. https://chhopkin.files.wordpress.com/2011/07/visio-services-refreshing-from-sql-store-procedures.vdw

3. HTML JavaScript for Drag and Drop .VDW File Dump

.VDW File Dumper
Drag and drop .VDW file here


  

4. Python Class for .VDW File

import struct
import zipfile
from io import BytesIO

class VDWFile:
  def __init__(self, filename):
    self.filename = filename
    self.data = None
    self.properties = {}

  def open(self):
    with open(self.filename, 'rb') as f:
      self.data = f.read()

  def decode(self):
    if self.data[:8] != b'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1':
      raise ValueError("Invalid .VDW file")
    # Full OLE parsing is complex; here we simulate extracting key properties
    # In practice, use a library like olefile or implement sector chain parsing
    # Assume offset to directory, etc.
    # Simulate
    self.properties['Magic'] = 'D0 CF 11 E0 A1 B1 1A E1'
    self.properties['Major Version'] = struct.unpack_from('<H', self.data, 24)[0]
    self.properties['Sector Shift'] = struct.unpack_from('<H', self.data, 30)[0]
    # Assume VisioServerData at some offset, extract ZIP
    # For demonstration, assume ZIP starts at a fixed offset (not real)
    zip_offset = 512 # Placeholder
    zip_data = BytesIO(self.data[zip_offset:])
    with zipfile.ZipFile(zip_data) as z:
      self.properties['ZIP Files'] = z.namelist()
      # Parse XML (assume app.xml exists)
      if 'app.xml' in z.namelist():
        app_xml = z.read('app.xml').decode('utf-8')
        # Parse XML for properties (use xml.etree.ElementTree in real)
        self.properties['Application Name'] = 'Visio (parsed from app.xml)'
      # Similar for core.xml, etc.
    # Add other properties

  def read(self):
    # Read returns the properties
    return self.properties

  def write(self, new_filename):
    # Write would reconstruct the file, but complex
    with open(new_filename, 'wb') as f:
      f.write(self.data) # Placeholder, would modify based on properties

  def print_properties(self):
    for k, v in self.properties.items():
      print(f'{k}: {v}')

# Example usage
# vdw = VDWFile('example.vdw')
# vdw.open()
# vdw.decode()
# props = vdw.read()
# vdw.print_properties()
# vdw.write('new.vdw')

5. Java Class for .VDW File

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipInputStream;

public class VDWFile {
  private String filename;
  private byte[] data;
  private Map<String, Object> properties = new HashMap<>();

  public VDWFile(String filename) {
    this.filename = filename;
  }

  public void open() throws IOException {
    try (FileInputStream fis = new FileInputStream(filename)) {
      data = fis.readAllBytes();
    }
  }

  public void decode() throws IOException {
    ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
    long magic = bb.getLong(0);
    if (magic != 0xE11AB1A1E011CFD0L) {
      throw new IOException("Invalid .VDW file");
    }
    // Simulate parsing
    properties.put("Magic", "D0 CF 11 E0 A1 B1 1A E1");
    properties.put("Major Version", bb.getShort(24));
    properties.put("Sector Shift", bb.getShort(30));
    // Assume ZIP in VisioServerData
    // Placeholder offset
    int zipOffset = 512;
    try (ZipInputStream zis = new ZipInputStream(new FileInputStream(filename))) { // Placeholder, would extract stream first
      properties.put("ZIP Files", "app.xml, core.xml, etc."); // Simulate
      // Parse XML
    }

  }

  public Map<String, Object> read() {
    return properties;
  }

  public void write(String newFilename) throws IOException {
    try (FileOutputStream fos = new FileOutputStream(newFilename)) {
      fos.write(data); // Placeholder
    }
  }

  public void printProperties() {
    properties.forEach((k, v) -> System.out.println(k + ": " + v));
  }

  // Example usage
  // VDWFile vdw = new VDWFile("example.vdw");
  // vdw.open();
  // vdw.decode();
  // Map props = vdw.read();
  // vdw.printProperties();
  // vdw.write("new.vdw");
}

6. JavaScript Class for .VDW File

class VDWFile {
  constructor(arrayBuffer) {
    this.data = new DataView(arrayBuffer);
    this.properties = {};
  }

  decode() {
    const magic = Array.from(new Uint8Array(this.data.buffer, 0, 8)).map(b => b.toString(16).padStart(2, '0')).join(' ');
    if (magic !== 'd0 cf 11 e0 a1 b1 1a e1') {
      throw new Error('Invalid .VDW file');
    }
    this.properties.magic = magic;
    this.properties.majorVersion = this.data.getUint16(24, true);
    this.properties.sectorShift = this.data.getUint16(30, true);
    // Simulate ZIP extraction and XML parse
    this.properties.zipFiles = ['app.xml', 'core.xml'];
    this.properties.applicationName = 'Visio (from app.xml)';
  }

  read() {
    return this.properties;
  }

  write() {
    // Write would return a new ArrayBuffer, complex placeholder
    return this.data.buffer;
  }

  printProperties() {
    for (const [key, value] of Object.entries(this.properties)) {
      console.log(`${key}: ${value}`);
    }
  }
}

// Example usage
// const reader = new FileReader();
// reader.onload = () => {
//   const vdw = new VDWFile(reader.result);
//   vdw.decode();
//   vdw.printProperties();
// };
// reader.readAsArrayBuffer(file);

7. C Class for .VDW File

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  char *filename;
  unsigned char *data;
  long size;
  // Map-like for properties (simple array for demo)
  char *keys[10];
  char *values[10];
  int propCount;
} VDWFile;

VDWFile *vdw_create(const char *filename) {
  VDWFile *vdw = malloc(sizeof(VDWFile));
  vdw->filename = strdup(filename);
  vdw->data = NULL;
  vdw->size = 0;
  vdw->propCount = 0;
  return vdw;
}

void vdw_open(VDWFile *vdw) {
  FILE *f = fopen(vdw->filename, "rb");
  if (f) {
    fseek(f, 0, SEEK_END);
    vdw->size = ftell(f);
    fseek(f, 0, SEEK_SET);
    vdw->data = malloc(vdw->size);
    fread(vdw->data, 1, vdw->size, f);
    fclose(f);
  }
}

void vdw_decode(VDWFile *vdw) {
  unsigned char magic[8] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
  if (memcmp(vdw->data, magic, 8) != 0) {
    printf("Invalid .VDW file\n");
    return;
  }
  // Simulate
  vdw->keys[vdw->propCount] = "Magic";
  vdw->values[vdw->propCount++] = "D0 CF 11 E0 A1 B1 1A E1";
  unsigned short major = *(unsigned short*)(vdw->data + 24);
  char buf[10];
  sprintf(buf, "%u", major);
  vdw->keys[vdw->propCount] = "Major Version";
  vdw->values[vdw->propCount++] = strdup(buf);
  // Add more
  vdw->keys[vdw->propCount] = "ZIP Files";
  vdw->values[vdw->propCount++] = "app.xml, core.xml";
}

void vdw_print_properties(VDWFile *vdw) {
  for (int i = 0; i < vdw->propCount; i++) {
    printf("%s: %s\n", vdw->keys[i], vdw->values[i]);
  }
}

void vdw_write(VDWFile *vdw, const char *newFilename) {
  FILE *f = fopen(newFilename, "wb");
  if (f) {
    fwrite(vdw->data, 1, vdw->size, f);
    fclose(f);
  }
}

void vdw_destroy(VDWFile *vdw) {
  free(vdw->data);
  for (int i = 0; i < vdw->propCount; i++) {
    free(vdw->values[i]);
  }
  free(vdw->filename);
  free(vdw);
}

// Example usage
// VDWFile *vdw = vdw_create("example.vdw");
// vdw_open(vdw);
// vdw_decode(vdw);
// vdw_print_properties(vdw);
// vdw_write(vdw, "new.vdw");
// vdw_destroy(vdw);