Skip to content

Instantly share code, notes, and snippets.

@moyix
Created January 24, 2025 18:01
Show Gist options
  • Save moyix/6fd663e71f6c401d055c854ce46dff38 to your computer and use it in GitHub Desktop.
Save moyix/6fd663e71f6c401d055c854ce46dff38 to your computer and use it in GitHub Desktop.
Tiny decoder for Chromium Web Custom MIME Data Format
#!/usr/bin/env python3
# Refs:
# https://stackoverflow.com/questions/68745902/what-is-the-data-format-specification-for-chromium-web-custom-mime-data-format/73076391#73076391
# https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/base/clipboard/custom_data_helper.cc
import sys
import json
def read_u16string(bs):
length = int.from_bytes(bs[:4], "little")
byte_length = length * 2
if length % 2 != 0:
byte_length += 2
return bs[4 : 4 + length * 2].decode("utf-16le"), bs[4 + byte_length :]
def decode_chromium_web_custom(bs):
# Format:
# 0-3: UInt32LE length of data
# 4-7: UInt32LE count of pairs
# [count pairs of]
# U16String key
# U16String value
# where U16String is:
# 0-3: UInt32LE length of string
# 4-4+length: UTF-16LE string
data_len = int.from_bytes(bs[:4], "little")
data = bs[4 : 4 + data_len]
assert len(bs) - 4 == data_len
count = int.from_bytes(data[:4], "little")
data = data[4:]
pairs = []
for _ in range(count):
key, data = read_u16string(data)
value, data = read_u16string(data)
pairs.append((key, value))
return pairs
def encode_chromium_web_custom(pairs):
data = b""
for k, v in pairs:
data += len(k).to_bytes(4, "little") + k.encode("utf-16le")
if len(k) % 2 != 0:
data += b"\0\0"
data += len(v).to_bytes(4, "little") + v.encode("utf-16le")
if len(v) % 2 != 0:
data += b"\0\0"
return len(data).to_bytes(4, "little") + len(pairs).to_bytes(4, "little") + data
def print_pairs(pairs):
for k, v in pairs:
if k.endswith("+json"):
js = json.loads(v)
print(f"{k}: {json.dumps(js, indent=2)}")
else:
print(f"{k}: {v}")
print()
if __name__ == "__main__":
pairs = decode_chromium_web_custom(open(sys.argv[1], "rb").read())
print_pairs(pairs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment