neri 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/neri/build.rb +66 -20
- data/lib/neri/runtime.rb +76 -60
- data/lib/neri/version.rb +1 -1
- data/neri.gemspec +0 -2
- metadata +3 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 588a4e8a5a9ad862218a5ed2b58607fc6433d0dfd3921b82201053194e4b11e2
|
4
|
+
data.tar.gz: 643ad4e58dfb6235532967bff42fcbcb2482abf78a47f4e180e22012b3105c52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e653c9a96b631386bd0501ace47feafa2c46d58d68358cb9735f9e1d53a03bcb3f8e7710e8f54c874c932c03c9bc9c91b47e5cee34741b7c1661cffc06d7983
|
7
|
+
data.tar.gz: 8ca1e16f5eb2e768ceec1dc5d1e04a019985411c684d70b186cec26796f044308d01cb68263f86e23dba7ef4e986df95278ede44200e0220e7938618080ff2ca
|
data/lib/neri/build.rb
CHANGED
@@ -18,7 +18,7 @@ module Neri
|
|
18
18
|
|
19
19
|
enable_gems: false,
|
20
20
|
enable_did_you_mean: false,
|
21
|
-
chdir_first:
|
21
|
+
chdir_first: true,
|
22
22
|
pause_last: nil,
|
23
23
|
pause_text: nil,
|
24
24
|
|
@@ -27,6 +27,7 @@ module Neri
|
|
27
27
|
|
28
28
|
datafile: nil,
|
29
29
|
encryption_key: nil,
|
30
|
+
virtual_directory: nil,
|
30
31
|
|
31
32
|
no_exe: false,
|
32
33
|
use_b2ec: false,
|
@@ -111,7 +112,7 @@ options:
|
|
111
112
|
|
112
113
|
--enable-gems
|
113
114
|
--enable-did-you-mean
|
114
|
-
--chdir
|
115
|
+
--no-chdir
|
115
116
|
--pause-last
|
116
117
|
--no-pause-last
|
117
118
|
--pause-text <text>
|
@@ -155,6 +156,7 @@ options:
|
|
155
156
|
|
156
157
|
--create-recipe <recipefile>
|
157
158
|
--recipe <recipefile>
|
159
|
+
--virtual-directory <string>
|
158
160
|
HELP_MESSAGE
|
159
161
|
end
|
160
162
|
|
@@ -209,7 +211,9 @@ options:
|
|
209
211
|
options[:enable_gems] = true
|
210
212
|
when "--enable-did-you-mean"
|
211
213
|
options[:enable_did_you_mean] = true
|
212
|
-
when "--chdir
|
214
|
+
when "--no-chdir"
|
215
|
+
options[:chdir_first] = false
|
216
|
+
when "--chdir-first" # deprecated
|
213
217
|
options[:chdir_first] = true
|
214
218
|
when "--pause-last"
|
215
219
|
options[:pause_last] = true
|
@@ -292,6 +296,8 @@ options:
|
|
292
296
|
filename = ARGV.shift.encode("utf-8")
|
293
297
|
nputs_v "Loading recipe_file '#{filename}'."
|
294
298
|
load File.expand_path(filename)
|
299
|
+
when "--virtual-directory"
|
300
|
+
options[:virtual_directory] = ARGV.shift.encode("utf-8")
|
295
301
|
when "--"
|
296
302
|
break
|
297
303
|
when /^(--.+)/
|
@@ -328,27 +334,54 @@ options:
|
|
328
334
|
end
|
329
335
|
|
330
336
|
def dll_dependencies
|
331
|
-
require "
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
+
require "fiddle/import"
|
338
|
+
|
339
|
+
pointer_type = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
340
|
+
psapi = Fiddle.dlopen("psapi.dll")
|
341
|
+
kernel32 = Fiddle.dlopen("kernel32.dll")
|
342
|
+
enumprocessmodules = Fiddle::Function.new(
|
343
|
+
psapi["EnumProcessModules"],
|
344
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP],
|
345
|
+
Fiddle::TYPE_LONG,
|
346
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
347
|
+
)
|
348
|
+
getmodulefilename = Fiddle::Function.new(
|
349
|
+
kernel32["GetModuleFileNameW"],
|
350
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG],
|
351
|
+
Fiddle::TYPE_LONG,
|
352
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
353
|
+
)
|
354
|
+
getcurrentprocess = Fiddle::Function.new(
|
355
|
+
kernel32["GetCurrentProcess"],
|
356
|
+
[],
|
357
|
+
Fiddle::TYPE_LONG,
|
358
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
359
|
+
)
|
360
|
+
|
337
361
|
bytes_needed = 4 * 32
|
338
362
|
module_handle_buffer = nil
|
339
363
|
process_handle = getcurrentprocess.call
|
340
364
|
loop do
|
341
365
|
module_handle_buffer = "\x00" * bytes_needed
|
342
366
|
bytes_needed_buffer = [0].pack("I")
|
343
|
-
enumprocessmodules.call(
|
367
|
+
enumprocessmodules.call(
|
368
|
+
[process_handle].pack("I").unpack1("i"),
|
369
|
+
[module_handle_buffer].pack("p").unpack1(pointer_type),
|
370
|
+
[module_handle_buffer.size].pack("I").unpack1("i"),
|
371
|
+
[bytes_needed_buffer].pack("p").unpack1(pointer_type)
|
372
|
+
)
|
344
373
|
bytes_needed = bytes_needed_buffer.unpack1("I")
|
345
374
|
break if bytes_needed <= module_handle_buffer.size
|
346
375
|
end
|
347
|
-
|
376
|
+
|
348
377
|
handles = module_handle_buffer.unpack("I*")
|
349
378
|
dependencies = handles.select { |handle| handle > 0 }.map do |handle|
|
350
379
|
str = "\x00\x00" * 256
|
351
|
-
modulefilename_length = getmodulefilename.call(
|
380
|
+
modulefilename_length = getmodulefilename.call(
|
381
|
+
[handle].pack("I").unpack1("i"),
|
382
|
+
[str].pack("p").unpack1(pointer_type),
|
383
|
+
[str.size].pack("I").unpack1("i")
|
384
|
+
)
|
352
385
|
str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
|
353
386
|
end
|
354
387
|
|
@@ -535,7 +568,20 @@ options:
|
|
535
568
|
@data_files.select { |file| File.directory? file }.each do |dir|
|
536
569
|
data_files += Dir.glob("#{dir}/**/*").select { |file| File.file? file }
|
537
570
|
end
|
538
|
-
data_files
|
571
|
+
data_files.uniq! { |file| File.expand_path(file) }
|
572
|
+
|
573
|
+
unless options[:virtual_directory]
|
574
|
+
dir_pwd = Dir.pwd.encode(Encoding::UTF_8)
|
575
|
+
virtual_directories = Pathname.new(dir_pwd).ascend.to_a.map(&:to_s)
|
576
|
+
data_files.each do |file|
|
577
|
+
fullpath = File.expand_path(file)
|
578
|
+
next if fullpath.start_with?(rubydir) || Pathname.new(file).absolute?
|
579
|
+
virtual_directories.shift until fullpath.start_with?(virtual_directories.first)
|
580
|
+
end
|
581
|
+
options[:virtual_directory] = relative_path(dir_pwd, virtual_directories.first, "/_neri_virtual_directory_/")
|
582
|
+
puts "virtual_directory: #{options[:virtual_directory]}"
|
583
|
+
end
|
584
|
+
|
539
585
|
if options[:encryption_key]
|
540
586
|
require "digest/sha2"
|
541
587
|
@encryption_key = Digest::SHA2.hexdigest(options[:encryption_key])
|
@@ -543,23 +589,20 @@ options:
|
|
543
589
|
Neri.key = @encryption_key || "0" * 64
|
544
590
|
File.open(datafile, "wb") do |f|
|
545
591
|
pos = 0
|
546
|
-
|
592
|
+
file_informations = data_files.map do |file|
|
547
593
|
fullpath = File.expand_path(file)
|
548
594
|
filename = if fullpath.start_with?(rubydir)
|
549
|
-
relative_path(fullpath, rubydir, "
|
595
|
+
relative_path(fullpath, rubydir, "#{options[:system_dir]}#{File::SEPARATOR}")
|
550
596
|
else
|
551
597
|
file
|
552
598
|
end
|
553
599
|
filedata = [filename, File.size(file), pos].join("\t")
|
554
600
|
nputs_v " - #{filename}:#{File.size(file)} bytes"
|
555
|
-
if File.expand_path(filename).start_with?(Dir.pwd) && filename.include?("..")
|
556
|
-
cd_path = ".#{File.expand_path(filename).delete_prefix(Dir.pwd)}"
|
557
|
-
filedata += "\n" + [cd_path, File.size(file), pos].join("\t")
|
558
|
-
end
|
559
601
|
pos += File.size(file)
|
560
602
|
pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
|
561
603
|
filedata
|
562
|
-
|
604
|
+
end
|
605
|
+
files_str = file_informations.join("\n").encode(Encoding::UTF_8)
|
563
606
|
|
564
607
|
f.write(format("%#{BLOCK_LENGTH}d", files_str.bytesize))
|
565
608
|
f.write(xor(files_str))
|
@@ -721,6 +764,9 @@ END
|
|
721
764
|
ruby_code = "Neri.key='#{@encryption_key}';" if @encryption_key
|
722
765
|
if options[:datafile]
|
723
766
|
ruby_code += "Neri.datafile='#{system_dir}' + #{unpack_filename(options[:datafile])};"
|
767
|
+
if options[:virtual_directory]
|
768
|
+
ruby_code += "Neri.virtual_directory=#{unpack_filename(options[:virtual_directory])};"
|
769
|
+
end
|
724
770
|
ruby_code += "load #{unpack_filename(File.basename(scriptfile))}"
|
725
771
|
else
|
726
772
|
ruby_code += "load File.expand_path('#{system_dir}' + #{unpack_filename(scriptfile)})"
|
data/lib/neri/runtime.rb
CHANGED
@@ -1,79 +1,91 @@
|
|
1
1
|
require "neri/version"
|
2
|
+
require "pathname"
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module Kernel
|
5
|
+
unless defined?(neri_original_require)
|
6
|
+
alias neri_original_require require
|
7
|
+
private :neri_original_require
|
8
|
+
end
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
unless defined?(neri_original_load)
|
11
|
+
alias neri_original_load load
|
12
|
+
private :neri_original_load
|
13
|
+
end
|
14
|
+
|
15
|
+
def require(feature)
|
16
|
+
Neri.require(feature)
|
17
|
+
end
|
9
18
|
|
10
|
-
def load(file, priv = false)
|
11
|
-
|
19
|
+
def load(file, priv = false)
|
20
|
+
Neri.load(file, priv)
|
21
|
+
end
|
12
22
|
end
|
13
23
|
|
14
24
|
module Neri
|
15
25
|
BLOCK_LENGTH = 32
|
16
26
|
@datafile = nil
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
27
|
+
@file_informations = {}
|
28
|
+
@fullpath_files = {}
|
29
|
+
@virtual_files = {}
|
30
|
+
@virtual_directory = "."
|
21
31
|
@xor = nil
|
22
32
|
|
23
33
|
class << self
|
24
34
|
def datafile=(datafile)
|
25
35
|
@datafile = datafile.encode(Encoding::UTF_8)
|
26
|
-
@system_dir = File.dirname(File.expand_path(@datafile)) + File::SEPARATOR
|
27
36
|
files_length = File.binread(@datafile, BLOCK_LENGTH).to_i
|
28
37
|
files_str = read(files_length, BLOCK_LENGTH)
|
29
38
|
pos = files_length + BLOCK_LENGTH
|
30
39
|
pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
|
31
40
|
files_str.force_encoding(Encoding::UTF_8)
|
32
|
-
files_str.
|
41
|
+
files_str.each_line do |line|
|
33
42
|
filename, length, offset = line.split("\t")
|
34
|
-
@
|
43
|
+
@file_informations[filename] = [length.to_i, offset.to_i + pos]
|
35
44
|
end
|
36
|
-
@
|
45
|
+
@fullpath_files = @file_informations.transform_keys { |k| File.expand_path(k) }
|
37
46
|
end
|
38
47
|
|
39
48
|
def key=(key)
|
40
|
-
@xor
|
49
|
+
@xor ||= key.scan(/../).map { |a| a.to_i(16) }.pack("c*")
|
41
50
|
end
|
42
51
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
["", ".rb"].each do |ext|
|
48
|
-
tmp_path = path + feature + ext
|
49
|
-
filepath ||= tmp_path if exist_in_datafile?(tmp_path)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
return _neri_orig_require(feature) unless filepath
|
54
|
-
return false if $LOADED_FEATURES.index(filepath)
|
52
|
+
def virtual_directory=(path)
|
53
|
+
@virtual_directory = path
|
54
|
+
@virtual_files = @file_informations.transform_keys { |k| File.expand_path(k, path) }
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
def require(feature)
|
58
|
+
feature_path = Pathname.new(feature.encode(Encoding::UTF_8))
|
59
|
+
feature_path = feature_path.sub_ext(".rb") if feature_path.extname == ""
|
60
|
+
return neri_original_require(feature) if feature_path.extname == ".so"
|
61
|
+
|
62
|
+
path_str = if feature_path.absolute? || feature.start_with?(".")
|
63
|
+
path_in_datafile(feature_path)
|
64
|
+
else
|
65
|
+
search_in_load_path(feature_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
return neri_original_require(feature) unless path_str
|
69
|
+
return false if $LOADED_FEATURES.index(path_str)
|
70
|
+
|
71
|
+
code = load_code(path_str)
|
72
|
+
eval(code, TOPLEVEL_BINDING, path_str)
|
73
|
+
$LOADED_FEATURES.push(path_str)
|
59
74
|
true
|
60
75
|
end
|
61
76
|
|
62
77
|
def load(file, priv = false)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
paths.each do |path|
|
67
|
-
filepath ||= path + file if exist_in_datafile?(path + file)
|
68
|
-
end
|
78
|
+
file_path = Pathname.new(file.encode(Encoding::UTF_8))
|
79
|
+
path_str = search_in_load_path(file_path) if file_path.relative? && !file.start_with?(".")
|
80
|
+
path_str ||= path_in_datafile(file_path)
|
69
81
|
|
70
|
-
return
|
82
|
+
return neri_original_load(file, priv) unless path_str
|
71
83
|
|
72
|
-
code = load_code(
|
84
|
+
code = load_code(path_str)
|
73
85
|
if priv
|
74
|
-
Module.new.module_eval(code,
|
86
|
+
Module.new.module_eval(code, path_str)
|
75
87
|
else
|
76
|
-
eval(code, TOPLEVEL_BINDING,
|
88
|
+
eval(code, TOPLEVEL_BINDING, path_str)
|
77
89
|
end
|
78
90
|
true
|
79
91
|
end
|
@@ -84,32 +96,26 @@ module Neri
|
|
84
96
|
|
85
97
|
def file_read(filename, encoding = Encoding::BINARY)
|
86
98
|
filename = filename.encode(Encoding::UTF_8)
|
87
|
-
|
88
|
-
|
89
|
-
length, offset = fullpath_files[File.expand_path(filename)]
|
90
|
-
str = read(length, offset)
|
91
|
-
else
|
92
|
-
str = File.binread(filename)
|
93
|
-
end
|
99
|
+
length, offset = file_information(filename)
|
100
|
+
str = length ? read(length, offset) : File.binread(filename)
|
94
101
|
str.force_encoding(encoding)
|
95
102
|
end
|
96
103
|
|
97
104
|
def files
|
98
|
-
@
|
105
|
+
@file_informations.keys
|
99
106
|
end
|
100
107
|
|
101
108
|
def exist_in_datafile?(filename)
|
102
|
-
|
109
|
+
file_information(filename) != nil
|
103
110
|
end
|
104
111
|
|
105
112
|
private
|
106
113
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
@fullpath_files
|
114
|
+
def file_information(filename)
|
115
|
+
fullpath = File.expand_path(filename)
|
116
|
+
return @fullpath_files[fullpath] if @fullpath_files.key?(fullpath)
|
117
|
+
|
118
|
+
@virtual_files[File.expand_path(filename, @virtual_directory)]
|
113
119
|
end
|
114
120
|
|
115
121
|
def xor(str)
|
@@ -131,11 +137,21 @@ module Neri
|
|
131
137
|
xor(File.binread(@datafile, tmp_length, offset))[0, length]
|
132
138
|
end
|
133
139
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
140
|
+
def search_in_load_path(file_path)
|
141
|
+
$LOAD_PATH.each do |path_str|
|
142
|
+
load_path = Pathname.new(path_str.encode(Encoding::UTF_8))
|
143
|
+
candidate_path_str = path_in_datafile(load_path + file_path)
|
144
|
+
return candidate_path_str if candidate_path_str
|
145
|
+
end
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def path_in_datafile(file_path)
|
150
|
+
fullpath = File.expand_path(file_path.to_s)
|
151
|
+
return fullpath if exist_in_datafile?(fullpath)
|
137
152
|
|
138
|
-
|
153
|
+
virtual_path = File.expand_path(file_path.to_s, @virtual_directory)
|
154
|
+
exist_in_datafile?(virtual_path) ? virtual_path : nil
|
139
155
|
end
|
140
156
|
|
141
157
|
def load_code(file)
|
data/lib/neri/version.rb
CHANGED
data/neri.gemspec
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nodai2hITC
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: win32api
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
11
|
+
date: 2021-12-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: Neri builds Windows batfile or exefile from Ruby script.
|
28
14
|
email:
|
29
15
|
- nodai2h.itc@gmail.com
|