neri 0.9.4 → 0.9.5

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: 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