neri 0.9.3 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
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