Class: RailsWayback::HistoricalAssetResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_wayback/historical_asset_resolver.rb

Defined Under Namespace

Classes: Resolution

Constant Summary collapse

TYPE_DIRECTORIES =
{
  audio: "audios",
  font: "fonts",
  image: "images",
  javascript: "javascripts",
  stylesheet: "stylesheets",
  video: "videos"
}.freeze
ENCODED_TRAVERSAL =
/%(?:2e|2f|5c)/i

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.historical_url?(source, sha:) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/rails_wayback/historical_asset_resolver.rb', line 53

def self.historical_url?(source, sha:)
  source.to_s.include?("/refs/#{sha}/assets/")
end

.url(sha:, public_path:, mount: RailsWayback::EngineMount.path) ⇒ Object



47
48
49
50
51
# File 'lib/rails_wayback/historical_asset_resolver.rb', line 47

def self.url(sha:, public_path:, mount: RailsWayback::EngineMount.path)
  base = mount.to_s.sub(%r{/+\z}, "")
  escaped = Rack::Utils.escape_path(public_path.to_s)
  "#{base}/refs/#{sha}/assets/#{escaped}"
end

Instance Method Details

#resolve(root:, source:, type: nil) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/rails_wayback/historical_asset_resolver.rb', line 20

def resolve(root:, source:, type: nil)
  candidates(source, type).each do |candidate|
    resolution = resolve_public_path(root: root, public_path: candidate)
    return resolution if resolution
  end
  nil
end

#resolve_public_path(root:, public_path:) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rails_wayback/historical_asset_resolver.rb', line 28

def resolve_public_path(root:, public_path:)
  relative = normalize(public_path)
  return unless relative

  public_root = Pathname.new(root).join("public")
  return unless safe_public_root?(public_root)

  candidate = public_root.join(relative)
  return unless candidate.file?

  public_real = public_root.realpath
  candidate_real = candidate.realpath
  return unless under?(candidate_real, public_real)

  Resolution.new(path: candidate_real, public_path: relative, size_bytes: candidate_real.size)
rescue SystemCallError
  nil
end