Class: R3EXS::StringsInjector

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/R3EXS/ast.rb

Overview

用来替换源码里面的字符串和符号

Defined Under Namespace

Classes: Location

Instance Method Summary collapse

Constructor Details

#initialize(hash) ⇒ StringsInjector

初始化 StringsInjector

Parameters:

  • hash (Hash<String, String>)

    字符串翻译表



92
93
94
95
96
# File 'lib/R3EXS/ast.rb', line 92

def initialize(hash)
    @strings_hash = hash
    @content_loc  = []
    @code         = []
end

Instance Method Details

#rewrite(script, ast_root) ⇒ String

将 script 源码中的字符串替换成 @strings_hash 翻译后的字符串

Parameters:

  • script (String)

    Ruby 源码,以二进制编码打开

  • ast_root (Prism::ProgramNode)

    AST 树根节点

Returns:

  • (String)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/R3EXS/ast.rb', line 135

def rewrite(script, ast_root)
    # 首先遍历一遍,找到所有需要替换的字符串的位置
    visit(ast_root)

    # 然后开始替换 code 中的字符串
    # 先将 @content_loc 按照 start_offset 从小到大排序
    @content_loc.sort_by! { |loc| loc.start_offset }

    #  然后将 code 切片,将字符串替换成新的字符串
    start_offset = 0
    @content_loc.each do |loc|
        @code << script[start_offset...loc.start_offset]
        @code << @strings_hash[loc.content]
        start_offset = loc.start_offset + loc.length
    end
    @code << script[start_offset..-1]

    # 将 @code 里面的字符串全部改为二进制编码
    @code.map! { |str| str.force_encoding('ASCII-8BIT') unless str.nil? }
    @code.join
end

#visit_string_node(node) ⇒ void

This method returns an undefined value.

处理类型为 StringNode 的节点

Parameters:

  • node (Prism::StringNode)

    AST 节点



103
104
105
106
107
108
109
110
# File 'lib/R3EXS/ast.rb', line 103

def visit_string_node(node)
    location = node.content_loc
    value    = location.slice
    if @strings_hash.has_key?(value) && @strings_hash[value].to_s != ''
        @content_loc << Location.new(location.start_offset, location.length, value)
    end
    super
end

#visit_symbol_node(node) ⇒ void

This method returns an undefined value.

处理类型为 SymbolNode 的节点

Parameters:

  • node (Prism::SymbolNode)

    AST 节点



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/R3EXS/ast.rb', line 117

def visit_symbol_node(node)
    location = node.value_loc
    # 如果 location 不为 nil,说明这个符号是一个字符串
    if location
        value = location.slice
        if @strings_hash.has_key?(value) && @strings_hash[value].to_s != ''
            @content_loc << Location.new(location.start_offset, location.length, value)
        end
    end
    super
end