neri 0.9.3 → 0.9.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9c11506aa1729506a8f2386ea1a37e45c6ef5f72cec65e3677931ef6f18910f
4
- data.tar.gz: fb4307dd5e026985659ab652e27436759bd60531f1b9044ab6ca82f6d28eab22
3
+ metadata.gz: 54122cb7af8b62506615a9be8916791a0051fd6cfc4ad395727a23714997b019
4
+ data.tar.gz: c79aa6b985eadfa33888aeb35af6fe70f4b17ec89d38d581bffccbf789de5b3b
5
5
  SHA512:
6
- metadata.gz: b2d6307c498084b7327d96fb041304b6df4f2aca8756a81f90d6065b1a5b966eef64056d76ca6917267bd75f531ec1bead1e987195fc7379276d0de3233af7aa
7
- data.tar.gz: b2002fe10dc92c4c87ddf7e961d77c5bddda93f0b9782b41e87e2b4ae5cc969b11123217b98f4d91d75a25c64db934a3db8eab6ed39be6072f3c046214923811
6
+ metadata.gz: a3bf286b9a366b38a4c37749ea48d690724331bd5aa208a435cbff987e160fc501d2617014a05ac047864c6a97f62e3f571ca077857119877d392640ab542fb2
7
+ data.tar.gz: d1830c564fdbe69c2418936ce86227509292ea0c05af462a5ac886fd8f8ebf5bbc931fb08a99a23dc71685df84d913bbe1b2c669eb31491fe17818b0b2fcf704
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: false,
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-first
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-first"
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 /^(--.+)/
@@ -317,6 +323,7 @@ options:
317
323
  unless options[:enable_did_you_mean] || @rubyopt.index("--disable-did_you_mean")
318
324
  @rubyopt += " --disable-did_you_mean"
319
325
  end
326
+ @rubyopt.sub!(%r{-r\S+/bundler/setup}, "")
320
327
  if @data_files.size > 1 || options[:encryption_key]
321
328
  options[:datafile] ||= "#{basename}.dat"
322
329
  end
@@ -328,27 +335,54 @@ options:
328
335
  end
329
336
 
330
337
  def dll_dependencies
331
- require "Win32API"
332
-
333
- enumprocessmodules = Win32API.new("psapi" , "EnumProcessModules", ["L","P","L","P"], "L")
334
- getmodulefilename = Win32API.new("kernel32", "GetModuleFileNameW", ["L","P","L"], "L")
335
- getcurrentprocess = Win32API.new("kernel32", "GetCurrentProcess" , [], "L")
336
-
338
+ require "fiddle/import"
339
+
340
+ pointer_type = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
341
+ psapi = Fiddle.dlopen("psapi.dll")
342
+ kernel32 = Fiddle.dlopen("kernel32.dll")
343
+ enumprocessmodules = Fiddle::Function.new(
344
+ psapi["EnumProcessModules"],
345
+ [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP],
346
+ Fiddle::TYPE_LONG,
347
+ Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
348
+ )
349
+ getmodulefilename = Fiddle::Function.new(
350
+ kernel32["GetModuleFileNameW"],
351
+ [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG],
352
+ Fiddle::TYPE_LONG,
353
+ Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
354
+ )
355
+ getcurrentprocess = Fiddle::Function.new(
356
+ kernel32["GetCurrentProcess"],
357
+ [],
358
+ Fiddle::TYPE_LONG,
359
+ Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
360
+ )
361
+
337
362
  bytes_needed = 4 * 32
338
363
  module_handle_buffer = nil
339
364
  process_handle = getcurrentprocess.call
340
365
  loop do
341
366
  module_handle_buffer = "\x00" * bytes_needed
342
367
  bytes_needed_buffer = [0].pack("I")
343
- enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
368
+ enumprocessmodules.call(
369
+ [process_handle].pack("I").unpack1("i"),
370
+ [module_handle_buffer].pack("p").unpack1(pointer_type),
371
+ [module_handle_buffer.size].pack("I").unpack1("i"),
372
+ [bytes_needed_buffer].pack("p").unpack1(pointer_type)
373
+ )
344
374
  bytes_needed = bytes_needed_buffer.unpack1("I")
345
375
  break if bytes_needed <= module_handle_buffer.size
346
376
  end
347
-
377
+
348
378
  handles = module_handle_buffer.unpack("I*")
349
379
  dependencies = handles.select { |handle| handle > 0 }.map do |handle|
350
380
  str = "\x00\x00" * 256
351
- modulefilename_length = getmodulefilename.call(handle, str, str.size)
381
+ modulefilename_length = getmodulefilename.call(
382
+ [handle].pack("I").unpack1("i"),
383
+ [str].pack("p").unpack1(pointer_type),
384
+ [str.size].pack("I").unpack1("i")
385
+ )
352
386
  str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
353
387
  end
354
388
 
@@ -535,6 +569,20 @@ options:
535
569
  @data_files.select { |file| File.directory? file }.each do |dir|
536
570
  data_files += Dir.glob("#{dir}/**/*").select { |file| File.file? file }
537
571
  end
572
+ data_files.uniq! { |file| File.expand_path(file) }
573
+
574
+ unless options[:virtual_directory]
575
+ dir_pwd = Dir.pwd.encode(Encoding::UTF_8)
576
+ virtual_directories = Pathname.new(dir_pwd).ascend.to_a.map(&:to_s)
577
+ data_files.each do |file|
578
+ fullpath = File.expand_path(file)
579
+ next if fullpath.start_with?(rubydir) || Pathname.new(file).absolute?
580
+ virtual_directories.shift until fullpath.start_with?(virtual_directories.first)
581
+ end
582
+ options[:virtual_directory] = relative_path(dir_pwd, virtual_directories.first, "/_neri_virtual_directory_/")
583
+ nputs "virtual_directory: #{options[:virtual_directory]}"
584
+ end
585
+
538
586
  if options[:encryption_key]
539
587
  require "digest/sha2"
540
588
  @encryption_key = Digest::SHA2.hexdigest(options[:encryption_key])
@@ -542,19 +590,20 @@ options:
542
590
  Neri.key = @encryption_key || "0" * 64
543
591
  File.open(datafile, "wb") do |f|
544
592
  pos = 0
545
- files_str = data_files.map { |file|
593
+ file_informations = data_files.map do |file|
546
594
  fullpath = File.expand_path(file)
547
595
  filename = if fullpath.start_with?(rubydir)
548
- relative_path(fullpath, rubydir, "*neri*#{File::SEPARATOR}")
596
+ relative_path(fullpath, rubydir, "#{options[:system_dir]}#{File::SEPARATOR}")
549
597
  else
550
598
  file
551
599
  end
552
- filedata = [filename, File.size(file), pos]
600
+ filedata = [filename, File.size(file), pos].join("\t")
601
+ nputs_v " - #{filename}:#{File.size(file)} bytes"
553
602
  pos += File.size(file)
554
603
  pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
555
- nputs_v " - #{filename}:#{File.size(file)} bytes"
556
- filedata.join("\t")
557
- }.join("\n").encode(Encoding::UTF_8)
604
+ filedata
605
+ end
606
+ files_str = file_informations.join("\n").encode(Encoding::UTF_8)
558
607
 
559
608
  f.write(format("%#{BLOCK_LENGTH}d", files_str.bytesize))
560
609
  f.write(xor(files_str))
@@ -716,6 +765,9 @@ END
716
765
  ruby_code = "Neri.key='#{@encryption_key}';" if @encryption_key
717
766
  if options[:datafile]
718
767
  ruby_code += "Neri.datafile='#{system_dir}' + #{unpack_filename(options[:datafile])};"
768
+ if options[:virtual_directory]
769
+ ruby_code += "Neri.virtual_directory=#{unpack_filename(options[:virtual_directory])};"
770
+ end
719
771
  ruby_code += "load #{unpack_filename(File.basename(scriptfile))}"
720
772
  else
721
773
  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
- alias _neri_orig_require require
4
- alias _neri_orig_load load
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
- def require(feature)
7
- Neri.require(feature)
8
- end
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
- Neri.load(file, priv)
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
- @system_dir = nil
18
- @files = {}
19
- @fullpath_files = nil
20
- @current_directory = nil
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.split("\n").each do |line|
41
+ files_str.each_line do |line|
33
42
  filename, length, offset = line.split("\t")
34
- @files[filename] = [length.to_i, offset.to_i + pos]
43
+ @file_informations[filename] = [length.to_i, offset.to_i + pos]
35
44
  end
36
- @current_directory = nil
45
+ @fullpath_files = @file_informations.transform_keys { |k| File.expand_path(k) }
37
46
  end
38
47
 
39
48
  def key=(key)
40
- @xor = key.scan(/../).map { |a| a.to_i(16) }.pack("c*")
49
+ @xor ||= key.scan(/../).map { |a| a.to_i(16) }.pack("c*")
41
50
  end
42
51
 
43
- def require(feature)
44
- feature = feature.encode(Encoding::UTF_8)
45
- filepath = nil
46
- (feature.start_with?(/[a-z]:/i, "\\", "/", ".") ? [""] : load_path).each do |path|
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
- code = load_code(filepath)
57
- eval(code, TOPLEVEL_BINDING, filepath)
58
- $LOADED_FEATURES.push(filepath)
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
- file = file.encode(Encoding::UTF_8)
64
- filepath = nil
65
- paths = file.start_with?(/[a-z]:/i, "\\", "/", ".") ? [""] : load_path + [""]
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 _neri_orig_load(file, priv) unless filepath
82
+ return neri_original_load(file, priv) unless path_str
71
83
 
72
- code = load_code(filepath)
84
+ code = load_code(path_str)
73
85
  if priv
74
- Module.new.module_eval(code, filepath)
86
+ Module.new.module_eval(code, path_str)
75
87
  else
76
- eval(code, TOPLEVEL_BINDING, filepath)
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
- str = nil
88
- if exist_in_datafile?(filename)
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
- @files.keys
105
+ @file_informations.keys
99
106
  end
100
107
 
101
108
  def exist_in_datafile?(filename)
102
- fullpath_files.key?(File.expand_path(filename.encode(Encoding::UTF_8)))
109
+ file_information(filename) != nil
103
110
  end
104
111
 
105
112
  private
106
113
 
107
- def fullpath_files
108
- if @current_directory != Dir.pwd
109
- @current_directory = Dir.pwd
110
- @fullpath_files = @files.transform_keys { |k| File.expand_path(k) }
111
- end
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 load_path
135
- paths = $LOAD_PATH.map { |path| path.encode(Encoding::UTF_8) }
136
- return paths unless @system_dir
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
- paths.map { |path| path.sub(@system_dir, "*neri*#{File::SEPARATOR}") + File::SEPARATOR }
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
@@ -1,3 +1,3 @@
1
1
  module Neri
2
- VERSION = -"0.9.3"
2
+ VERSION = -"0.9.7"
3
3
  end
data/neri.gemspec CHANGED
@@ -30,6 +30,4 @@ Gem::Specification.new do |spec|
30
30
  spec.bindir = "exe"
31
31
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ["lib"]
33
-
34
- spec.add_dependency "win32api"
35
33
  end
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.3
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - nodai2hITC
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-21 00:00:00.000000000 Z
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