Class: Shugoi::SkeletonGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/shugoi/skeleton_generator.rb

Overview

Génère le skeleton HTML (bootcode unicode) injecté dans la page. Parité avec generateSkeleton (render.ts) — mêmes fragments JS, même encodage unicode.

Instance Method Summary collapse

Constructor Details

#initialize(config, guard_cache, config_cache, token_signer) ⇒ SkeletonGenerator

Returns a new instance of SkeletonGenerator.



7
8
9
10
11
12
# File 'lib/shugoi/skeleton_generator.rb', line 7

def initialize(config, guard_cache, config_cache, token_signer)
  @config = config
  @guard_cache = guard_cache
  @config_cache = config_cache
  @token_signer = token_signer
end

Instance Method Details

#generate(site_key, token, base_url, render_url = "./__shugoi/render", locale = "en") ⇒ String

Returns HTML du skeleton ().

Returns:

  • (String)

    HTML du skeleton ()



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/shugoi/skeleton_generator.rb', line 15

def generate(site_key, token, base_url, render_url = "./__shugoi/render", locale = "en")
  @guard_cache.ensure_ready(site_key, @config.signing_secret)
  cfg_data = @config_cache.fetch(site_key)
  flags = cfg_data[:flags]
  detect = @guard_cache.detect

  fragments = []
  fragments << "window.__sg_siteKey=#{json(site_key)}"
  fragments << "window.__sg_baseUrl=#{json(base_url)}"
  fragments << "window.__sg_config=#{json(flags)}"
  fragments << "try{if((location.search||'').indexOf('sg_proof=')>=0){var _qs=location.search.replace(/[?&]sg_proof=[^&]*/,'');var _cu=location.pathname+(_qs?_qs:'')+location.hash;history.replaceState(null,'',_cu)}}catch(e){}"

  pow = Pow.new(@config.signing_secret, @config.pow_difficulty, @config.pow_ttl_ms).challenge
  fragments << "window.__sg_pow=#{json(pow)}"
  now_ms = Utils.now_ms
  fragments << "window.__sg_ntp=#{now_ms}"
  fragments << "window.__sg_serverTime=#{now_ms}"
  fragments << "window.__sg_clockts=#{now_ms}"
  fragments << "window.__sg_disableRestrictedAccess=true" unless @config.restricted_access
  fragments << "try{#{detect}}catch(e){window.__sg_blocked=true}" if detect

  # __sg_showBlock (page de blocage néobrutaliste)
  fragments << show_block_fragment

  fragments << "var t=\"#{token}\""
  fragments << "window.__sg_token=\"#{token}\""
  fragments << "var k=\"#{site_key}\""
  fragments << "var b=\"#{base_url}\""
  fragments << "var r=\"#{render_url}\""

  # rd(p,n) : remplacement du document par le contenu rendu.
  fragments << rd_fragment

  fragments << "_gw(function(){rd(r+\"?token=\"+t,0);setTimeout(_sgCl,1500)})"
  fragments << cleanup_fragment

  combined = fragments.join(";")
  # Échappe `</script>` et `</style>` AVANT l'encodage unicode : sans ça, le HTML parser
  # du navigateur coupe le <script> dès qu'il rencontre `</script>` dans le bootcode
  # (ex. le guard-detect obfusqué contient des balises) → SyntaxError: Unexpected token '<'.
  # Parité avec escapeClosingTags (module Node).
  combined = combined.gsub(%r{</(script|style)}i, "<\\/$1")
  enc = Utils.unicode_encode(combined)
  decoded_call = "[...'#{enc}'].map(x=>String.fromCodePoint(x.codePointAt(0)-917504)).join('')"
  # <meta charset=UTF-8> : garantit que le navigateur lit le bootcode unicode en UTF-8
  # (sans ça, interprété en Latin-1 → RangeError au décodage).
  "<meta charset=\"UTF-8\"><script>eval(#{decoded_call})</script>"
end