Class: HTML::Pipeline::CamoFilter

Inherits:
Filter
  • Object
show all
Defined in:
lib/html/pipeline/camo_filter.rb

Overview

HTML Filter for replacing http image URLs with camo versions. See:

github.com/atmos/camo

All images provided in user content should be run through this filter so that http image sources do not cause mixed-content warnings in browser clients.

Context options:

:asset_proxy (required) - Base URL for constructed asset proxy URLs.
:asset_proxy_secret_key (required) - The shared secret used to encode URLs.
:asset_proxy_whitelist - Array of host Strings or Regexps to skip
                         src rewriting.

This filter does not write additional information to the context.

Instance Attribute Summary

Attributes inherited from Filter

#context, #result

Instance Method Summary collapse

Methods inherited from Filter

#base_url, call, #current_user, #doc, #has_ancestor?, #html, #initialize, #needs, #parse_html, #repository, #search_text_nodes, to_document, to_html

Constructor Details

This class inherits a constructor from HTML::Pipeline::Filter

Instance Method Details

#asset_host_whitelisted?(host) ⇒ Boolean

Returns:

  • (Boolean)
[View source]

80
81
82
83
84
# File 'lib/html/pipeline/camo_filter.rb', line 80

def asset_host_whitelisted?(host)
  asset_proxy_whitelist.any? do |test|
    test.is_a?(String) ? host == test : test.match(host)
  end
end

#asset_proxy_enabled?Boolean

Private: Return true if asset proxy filter should be enabled

Returns:

  • (Boolean)
[View source]

63
64
65
# File 'lib/html/pipeline/camo_filter.rb', line 63

def asset_proxy_enabled?
  !context[:disable_asset_proxy]
end

#asset_proxy_hostObject

Private: the host to use for generated asset proxied URLs.

[View source]

68
69
70
# File 'lib/html/pipeline/camo_filter.rb', line 68

def asset_proxy_host
  context[:asset_proxy]
end

#asset_proxy_secret_keyObject

[View source]

72
73
74
# File 'lib/html/pipeline/camo_filter.rb', line 72

def asset_proxy_secret_key
  context[:asset_proxy_secret_key]
end

#asset_proxy_url(url) ⇒ Object

The camouflaged URL for a given image URL.

[View source]

53
54
55
# File 'lib/html/pipeline/camo_filter.rb', line 53

def asset_proxy_url(url)
  "#{asset_proxy_host}/#{asset_url_hash(url)}/#{hexencode(url)}"
end

#asset_proxy_whitelistObject

[View source]

76
77
78
# File 'lib/html/pipeline/camo_filter.rb', line 76

def asset_proxy_whitelist
  context[:asset_proxy_whitelist] || []
end

#asset_url_hash(url) ⇒ Object

Private: calculate the HMAC digest for a image source URL.

[View source]

58
59
60
# File 'lib/html/pipeline/camo_filter.rb', line 58

def asset_url_hash(url)
  OpenSSL::HMAC.hexdigest('sha1', asset_proxy_secret_key, url)
end

#callObject

Hijacks images in the markup provided, replacing them with URLs that go through the github asset proxy.

[View source]

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/html/pipeline/camo_filter.rb', line 24

def call
  return doc unless asset_proxy_enabled?

  doc.search("img").each do |element|
    original_src = element['src']
    next unless original_src

    begin
      uri = URI.parse(original_src)
    rescue Exception
      next
    end

    next if uri.host.nil?
    next if asset_host_whitelisted?(uri.host)

    element['src'] = asset_proxy_url(original_src)
    element['data-canonical-src'] = original_src
  end
  doc
end

#hexencode(str) ⇒ Object

Private: helper to hexencode a string. Each byte ends up encoded into two characters, zero padded value in the range [0-9a-f].

[View source]

88
89
90
# File 'lib/html/pipeline/camo_filter.rb', line 88

def hexencode(str)
  str.to_enum(:each_byte).map { |byte| "%02x" % byte }.join
end

#validateObject

Implementation of validate hook. Errors should raise exceptions or use an existing validator.

[View source]

48
49
50
# File 'lib/html/pipeline/camo_filter.rb', line 48

def validate
  needs :asset_proxy, :asset_proxy_secret_key
end