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



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



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.



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

def asset_proxy_host
  context[:asset_proxy]
end

#asset_proxy_secret_keyObject



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.



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



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.



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.



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].



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.



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

def validate
  needs :asset_proxy, :asset_proxy_secret_key
end