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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8829588155f0a2fa2381d8a6da3f2010136a1c22b3b5e9168cacddb8d78cae1c
4
- data.tar.gz: 5f0fcf15b0ea35ee9c1dfaf56a83b1284ad542eaa68ab805c077a70b3b487089
3
+ metadata.gz: 588a4e8a5a9ad862218a5ed2b58607fc6433d0dfd3921b82201053194e4b11e2
4
+ data.tar.gz: 643ad4e58dfb6235532967bff42fcbcb2482abf78a47f4e180e22012b3105c52
5
5
  SHA512:
6
- metadata.gz: 7d8bb8a32247d0a4a8e3dfdd3bc933064f531384db15d2f01209c900905b8a1b59166bb61d1cb8137b97eec0d77677c20a8fb26c14e4a3dfbd0877834cff06ae
7
- data.tar.gz: c6551635e0f20d969c770c5bb2b8355c1f0e1f4e1b815089690d3115140a2015d90f0c6221ac2fc927cf013ceac574f70f388a15ecda5a3904bba5e83853ffed
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: 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 /^(--.+)/
@@ -328,27 +334,54 @@ options:
328
334
  end
329
335
 
330
336
  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
-
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(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
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(handle, str, str.size)
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 = data_files.reverse.uniq { |file| File.expand_path(file) }
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
- files_str = data_files.map { |file|
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, "*neri*#{File::SEPARATOR}")
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
- }.join("\n").encode(Encoding::UTF_8)
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
- 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.4"
2
+ VERSION = -"0.9.5"
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.4
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-11-24 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