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

Parameters:

  • hash (Hash<String, String>)

    字符串翻译表



85
86
87
88
89
# File 'lib/R3EXS/ast.rb', line 85

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)


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/R3EXS/ast.rb', line 125

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 节点



95
96
97
98
99
100
101
102
# File 'lib/R3EXS/ast.rb', line 95

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 节点



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/R3EXS/ast.rb', line 108

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