Module: Emf::Detector

Defined in:
lib/emf/detector.rb

Constant Summary collapse

APM_MAGIC =

bytes 0xD7 0xCD 0xC6 0x9A, read as uint32 little-endian

0x9AC6CDD7
EMF_SIGNATURE =
1
EMF_MAGIC_OFFSET =
0x28
EMF_MAGIC =
0x464D4520

Class Method Summary collapse

Class Method Details

.call(bytes) ⇒ Object

Raises:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/emf/detector.rb', line 12

def call(bytes)
  raise FormatError, "input too short (#{bytes.bytesize} bytes)" if bytes.bytesize < 4

  case first_uint32_le(bytes)
  when APM_MAGIC then :wmf_apm
  when EMF_SIGNATURE
    return :emf if looks_like_emf?(bytes)
    return :wmf_standard if looks_like_wmf_metaheader?(bytes)

    raise FormatError, "unrecognised format (signature=1 but no EMF magic or WMF header)"
  else
    return :wmf_standard if looks_like_wmf_metaheader?(bytes)

    raise FormatError, format("unrecognised format (first uint32=0x%08X)", first_uint32_le(bytes))
  end
end

.first_uint32_le(bytes) ⇒ Object



43
44
45
# File 'lib/emf/detector.rb', line 43

def first_uint32_le(bytes)
  read_uint32_le(bytes, 0)
end

.looks_like_emf?(bytes) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
# File 'lib/emf/detector.rb', line 29

def looks_like_emf?(bytes)
  return false unless bytes.bytesize >= EMF_MAGIC_OFFSET + 4

  read_uint32_le(bytes, EMF_MAGIC_OFFSET) == EMF_MAGIC
end

.looks_like_wmf_metaheader?(bytes) ⇒ Boolean

Returns:

  • (Boolean)


35
36
37
38
39
40
41
# File 'lib/emf/detector.rb', line 35

def looks_like_wmf_metaheader?(bytes)
  return false unless bytes.bytesize >= 18

  mt = read_uint16_le(bytes, 0)
  hs = read_uint16_le(bytes, 2)
  [1, 2].include?(mt) && hs == 9
end

.read_uint16_le(bytes, offset) ⇒ Object



54
55
56
# File 'lib/emf/detector.rb', line 54

def read_uint16_le(bytes, offset)
  bytes.getbyte(offset) | (bytes.getbyte(offset + 1) << 8)
end

.read_uint32_le(bytes, offset) ⇒ Object



47
48
49
50
51
52
# File 'lib/emf/detector.rb', line 47

def read_uint32_le(bytes, offset)
  bytes.getbyte(offset) |
    (bytes.getbyte(offset + 1) << 8) |
    (bytes.getbyte(offset + 2) << 16) |
    (bytes.getbyte(offset + 3) << 24)
end