winlnk 0.0.1 → 0.0.2

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
  SHA1:
3
- metadata.gz: d699909354195807a0b6d300658026db1e52e616
4
- data.tar.gz: b8e3fd8963ef84caed6b84a7c63d403cb146e5b9
3
+ metadata.gz: 62d79fd0022714edcf75ebca7c62d4618ee7bec8
4
+ data.tar.gz: a415b7a951b807ce1024668944ee2d1b040c8556
5
5
  SHA512:
6
- metadata.gz: 7280505f2676cc21b09add97b80cd3b1930e485868ac6eab1ec1aef497e2d257972a6794d200fa8423414defc79d4f4b014dd8dfee0055b746188807f0fd53c7
7
- data.tar.gz: 9ef3ed9c34971b91ae4761981edea2ec100b3bbbc59cd9312bff95e98db13cc439bd3ae5d5ee56fc5372e3879d049a70158cc0418de24bf44bdc9da048c9c396
6
+ metadata.gz: 4ac603dfe9b4097ab7107703f60ad73f82c69b83b0dec231145291a6354dc258d03fa6a3f56e6ab18a978cfd2217824ef9b9acdd0d338043a8aa0245ab006d33
7
+ data.tar.gz: 5c5c25772657a052a916c310b8481dc0f8b2e07ecb76b2f9b71d0af461e9ff7374523498d639679d43bdaf3c8dd24473389b37db40fbab4ee365ff9dd2cd3b38
data/README CHANGED
@@ -22,5 +22,5 @@ Usage
22
22
 
23
23
  To read the link target, create an instance and get its path attribute.
24
24
 
25
- link = WinLnk.new("path/to/link.lnk")
25
+ link = WinLnk.new("path/to/link.lnk", "the ANSI code page")
26
26
  p link.path
data/lib/winlnk.rb CHANGED
@@ -64,6 +64,22 @@ class WinLnk
64
64
 
65
65
  # Returns the LinkFlags of the link.
66
66
  attr_reader :flags
67
+ # Returns the attributes of the link target.
68
+ attr_reader :attributes
69
+ # Returns the creation time of the link target.
70
+ attr_reader :btime
71
+ # Returns the access time of the link target.
72
+ attr_reader :atime
73
+ # Returns the write time of the link target.
74
+ attr_reader :mtime
75
+ # Returns the least significant 32 bits of the size of the link target.
76
+ attr_reader :file_size
77
+ # Returns the index of the icon within the given icon location.
78
+ attr_reader :icon_index
79
+ # Returns the expected window state of an application launched by the link.
80
+ attr_reader :show_cmd
81
+ # Returns the shortcut key to activate the application launched by the link.
82
+ attr_reader :hot_key
67
83
  # Returns the path pointed to by the link.
68
84
  attr_reader :path
69
85
  # Returns the description of the link.
@@ -125,11 +141,13 @@ class WinLnk
125
141
  @atime = filetime2posixtime(times[3] << 32 | times[2])
126
142
  @mtime = filetime2posixtime(times[5] << 32 | times[4])
127
143
  @file_size, @icon_index, @show_cmd, @hot_key = data(0x34, 16).unpack("V3v")
128
- reserved = data(0x44, 8).unpack("vV2")
144
+ _reserved = data(0x44, 8).unpack("vV2")
129
145
  return 0x4c
130
146
  end
131
147
 
132
148
  def filetime2posixtime(filetime)
149
+ # If the value is 0, the time is not set.
150
+ return nil if filetime == 0
133
151
  # Windows FILETIME is the time from 1601-01-01 in 100-nanosecond unit.
134
152
  filetime -= 116444736000000000
135
153
  return Time.at(filetime / 10000000, filetime % 10000000 / 10)
@@ -149,26 +167,41 @@ class WinLnk
149
167
  end
150
168
 
151
169
  def read_link_info(off)
152
- len, = data(off, 4).unpack("V")
153
- raise ParseError.new("Too short LinkInfo") if len < 0x1c
154
- header_len, li_flags, vol_id_off, base_path_off,
155
- net_rel_link_off, suffix_off = data(off + 4, 24).unpack("V6")
170
+ len, header_len = data(off, 8).unpack("V2")
171
+ raise ParseError.new("Too short LinkInfo header") if header_len < 0x1c
172
+ (li_flags, _vol_id_off, base_path_off, net_rel_link_off, suffix_off,
173
+ base_path_unicode_off, suffix_unicode_off) =
174
+ data(off + 8, header_len - 8).unpack("V7")
156
175
  if @@debug
157
176
  printf("LinkInfo header size: %u\n", header_len)
158
177
  printf("LinkInfo flags: %b\n", li_flags)
159
178
  end
160
179
 
180
+ printf("Unicode LocalBasePath: %p\n", base_path_unicode_off) if @@debug
181
+ printf("Unicode Suffix: %p\n", suffix_unicode_off) if @@debug
182
+ suffix = suffix_unicode_off ?
183
+ utf16z(off + suffix_unicode_off) : asciz(off + suffix_off)
161
184
  if li_flags & LI_FLAG_LOCAL != 0
162
- base_path, = data_all(off + base_path_off).unpack("Z*")
163
- suffix, = data_all(off + suffix_off).unpack("Z*")
164
- @path = (base_path + suffix).force_encoding(@codepage)
165
- end
166
- if li_flags & LI_FLAG_NETWORK != 0
185
+ base_path = base_path_unicode_off ?
186
+ utf16z(off + base_path_unicode_off) :
187
+ asciz(off + base_path_off)
188
+ make_encodings_be_compatible(base_path, suffix)
189
+ @path = base_path << suffix
190
+ elsif li_flags & LI_FLAG_NETWORK != 0
167
191
  # Parse the CommonNetworkRelativeLink structure.
168
- net_name_off, = data(off + net_rel_link_off + 8, 2).unpack("v")
169
- net_name, = data_all(off + net_rel_link_off + net_name_off).unpack("Z*")
170
- suffix, = data_all(off + suffix_off).unpack("Z*")
171
- @path = (net_name + "\\" + suffix).force_encoding(@codepage)
192
+ net_name_off, = data(off + net_rel_link_off + 8, 4).unpack("V")
193
+ (_common_net_rel_link_size, _common_net_rel_link_flags,
194
+ net_name_off, _dev_name_off, _net_provider_type,
195
+ net_name_unicode_off, _dev_name_unicode_off) =
196
+ data(off + net_rel_link_off, net_name_off).unpack("V7")
197
+ printf("Unicode NetName: %p\n", net_name_unicode_off) if @@debug
198
+ net_name = net_name_unicode_off ?
199
+ utf16z(off + net_rel_link_off + net_name_unicode_off) :
200
+ asciz(off + net_rel_link_off + net_name_off)
201
+ make_encodings_be_compatible(net_name, suffix)
202
+ @path = net_name << "\\" << suffix
203
+ else
204
+ raise ParseError.new("Unknown LinkInfoFlags")
172
205
  end
173
206
  return off + len
174
207
  end
@@ -185,14 +218,35 @@ class WinLnk
185
218
  end
186
219
  end
187
220
 
221
+ def asciz(off)
222
+ # Check if "@#{off}" does not go out of the string.
223
+ raise ParseError.new("Truncated file") if @data.size < off
224
+ str = @data.unpack("@#{off} Z*")[0]
225
+ # Check if the terminating null character existed.
226
+ raise ParseError.new("Truncated file") if @data.size - off <= str.bytesize
227
+ return str.force_encoding(@codepage)
228
+ end
229
+
230
+ def utf16z(off)
231
+ zz = off
232
+ while @data.size >= zz + 2
233
+ if @data.getbyte(zz) == 0 && @data.getbyte(zz + 1) == 0
234
+ return @data[off...zz].encode!("UTF-8", "UTF-16LE")
235
+ end
236
+ zz += 2
237
+ end
238
+ raise ParseError.new("Truncated file")
239
+ end
240
+
188
241
  def data(off, len)
189
242
  raise ParseError.new("Truncated file") if @data.size < off + len
190
243
  return @data[off, len]
191
244
  end
192
245
 
193
- def data_all(off)
194
- raise ParseError.new("Truncated file") if @data.size < off
195
- return @data[off..-1]
246
+ def make_encodings_be_compatible(a, b)
247
+ return if Encoding::compatible?(a, b)
248
+ a.encode!("UTF-8")
249
+ b.encode!("UTF-8")
196
250
  end
197
251
 
198
252
  # This exception is raised when failed to parse a link.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,85 @@
1
+ #
2
+ # Copyright (c) 2019 KAMADA Ken'ichi.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ # 1. Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # 2. Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
+ # SUCH DAMAGE.
25
+ #
26
+
27
+ require "test/unit"
28
+ require "winlnk"
29
+
30
+ class TestInternal < Test::Unit::TestCase
31
+ def test_filetime2posixtime
32
+ # A dummy file.
33
+ lnk = WinLnk.new("test/local_cmd.lnk", "US-ASCII")
34
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0),
35
+ lnk.send(:filetime2posixtime, 116444736000000000))
36
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0),
37
+ lnk.send(:filetime2posixtime, 116444736000000009))
38
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0, 1),
39
+ lnk.send(:filetime2posixtime, 116444736000000010))
40
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0, 999999),
41
+ lnk.send(:filetime2posixtime, 116444736009999990))
42
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0, 999999),
43
+ lnk.send(:filetime2posixtime, 116444736009999999))
44
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 1),
45
+ lnk.send(:filetime2posixtime, 116444736010000000))
46
+ assert_equal(Time.utc(2014, 6, 21, 4, 36, 55),
47
+ lnk.send(:filetime2posixtime, 130477990150000000))
48
+ end
49
+
50
+ def test_asciz
51
+ lnk = WinLnk.new("test/local_cmd.lnk", "US-ASCII")
52
+ asciz = ->(data, off) do
53
+ lnk.instance_variable_set(:@data, data)
54
+ return lnk.send(:asciz, off)
55
+ end
56
+
57
+ assert_equal("abc", asciz.call("abc\0def\0".b, 0))
58
+ assert_equal("bc", asciz.call("abc\0def\0".b, 1))
59
+ assert_equal("", asciz.call("abc\0def\0".b, 3))
60
+ assert_equal("def", asciz.call("abc\0def\0".b, 4))
61
+ assert_equal("", asciz.call("abc\0def\0".b, 7))
62
+ assert_raise(WinLnk::ParseError) { asciz.call("abc\0def\0".b, 8) }
63
+ assert_raise(WinLnk::ParseError) { asciz.call("".b, 1) }
64
+ assert_raise(WinLnk::ParseError) { asciz.call("abc".b, 0) }
65
+ end
66
+
67
+ def test_utf16z
68
+ lnk = WinLnk.new("test/local_cmd.lnk", "US-ASCII")
69
+ utf16z = ->(data, off) do
70
+ lnk.instance_variable_set(:@data, data)
71
+ return lnk.send(:utf16z, off)
72
+ end
73
+
74
+ assert_equal("ab", utf16z.call("a\0b\0\0\0c\0d\0\0\0".b, 0))
75
+ assert_equal("ab", utf16z.call("\0a\0b\0\0\0c\0d\0\0\0".b, 1))
76
+ assert_equal("cd", utf16z.call("a\0b\0\0\0c\0d\0\0\0".b, 6))
77
+ assert_equal("abc\0\0def".encode("UTF-8", "UTF-16LE"),
78
+ utf16z.call("abc\0\0def\0\0".b, 0))
79
+ assert_equal("", utf16z.call("\0\0".b, 0))
80
+ assert_equal("a", utf16z.call("\n\0a\0\0\0".b, 2))
81
+ assert_raise(WinLnk::ParseError) { utf16z.call("\0", 0) }
82
+ assert_raise(WinLnk::ParseError) { utf16z.call("", 0) }
83
+ assert_raise(WinLnk::ParseError) { utf16z.call("", 1) }
84
+ end
85
+ end
@@ -0,0 +1,156 @@
1
+ #
2
+ # Copyright (c) 2019 KAMADA Ken'ichi.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ # 1. Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # 2. Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
+ # SUCH DAMAGE.
25
+ #
26
+
27
+ require "test/unit"
28
+ require "winlnk"
29
+
30
+ class TestSpecimen < Test::Unit::TestCase
31
+ def test_local_cmd
32
+ lnk = WinLnk.new("test/local_cmd.lnk", "Windows-31J")
33
+
34
+ assert_equal('C:\Windows\System32\cmd with space.exe', lnk.path)
35
+ assert_equal('This is a comment.', lnk.description)
36
+ assert_equal('..\Windows\System32\cmd with space.exe', lnk.relative_path)
37
+ assert_equal('C:\Windows\System32', lnk.working_directory)
38
+ assert_equal('arg1 "arg 2"', lnk.arguments)
39
+ assert_equal(nil, lnk.icon_location)
40
+
41
+ assert_equal(0x2020, lnk.attributes)
42
+ assert_equal(Time.utc(2019, 7, 1, 14, 00, 40, 918391), lnk.btime)
43
+ assert_equal(Time.utc(2019, 7, 1, 14, 00, 40, 918391), lnk.atime)
44
+ assert_equal(Time.utc(2014, 10, 29, 1, 28, 18, 835387), lnk.mtime)
45
+ assert_equal(357376, lnk.file_size)
46
+ assert_equal(0, lnk.icon_index)
47
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
48
+ assert_equal(0, lnk.hot_key)
49
+ end
50
+
51
+ def test_local_win31j
52
+ lnk = WinLnk.new("test/local_win31j.lnk", "Windows-31J")
53
+
54
+ # Default code page
55
+ assert_equal('C:\Temp\リンク先.txt'.encode("Windows-31J"), lnk.path)
56
+ # UTF-8
57
+ assert_equal('コメント', lnk.description)
58
+ assert_equal('.\リンク先.txt', lnk.relative_path)
59
+ assert_equal('C:\Temp', lnk.working_directory)
60
+ assert_equal(nil, lnk.arguments)
61
+ assert_equal('%SystemRoot%\system32\SHELL32.dll', lnk.icon_location)
62
+
63
+ assert_equal(0x2020, lnk.attributes)
64
+ assert_equal(Time.utc(2019, 6, 30, 13, 51, 53, 537221), lnk.btime)
65
+ assert_equal(Time.utc(2019, 6, 30, 13, 51, 53, 537221), lnk.atime)
66
+ assert_equal(Time.utc(2019, 6, 30, 13, 52, 1, 861622), lnk.mtime)
67
+ assert_equal(10, lnk.file_size)
68
+ assert_equal(70, lnk.icon_index)
69
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
70
+ assert_equal(0, lnk.hot_key)
71
+ end
72
+
73
+ def test_local_unicode
74
+ lnk = WinLnk.new("test/local_unicode.lnk", "Windows-31J")
75
+
76
+ assert_equal('C:\Temp\💎.txt', lnk.path)
77
+ assert_equal(nil, lnk.description)
78
+ assert_equal('.\💎.txt', lnk.relative_path)
79
+ assert_equal('C:\Temp', lnk.working_directory)
80
+ assert_equal(nil, lnk.arguments)
81
+ assert_equal(nil, lnk.icon_location)
82
+
83
+ assert_equal(0x2020, lnk.attributes)
84
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 42, 626696), lnk.btime)
85
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 42, 626696), lnk.atime)
86
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 42, 626696), lnk.mtime)
87
+ assert_equal(0, lnk.file_size)
88
+ assert_equal(0, lnk.icon_index)
89
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
90
+ assert_equal(0, lnk.hot_key)
91
+ end
92
+
93
+ def test_net_win31j
94
+ lnk = WinLnk.new("test/net_win31j.lnk", "Windows-31J")
95
+
96
+ # Default code page
97
+ assert_equal('\\\\TEST\SHARE\リンク先.txt'.encode("Windows-31J"), lnk.path)
98
+ # UTF-8
99
+ assert_equal(nil, lnk.description)
100
+ assert_equal(nil, lnk.relative_path)
101
+ assert_equal('\\\\test\share', lnk.working_directory)
102
+ assert_equal(nil, lnk.arguments)
103
+ assert_equal(nil, lnk.icon_location)
104
+
105
+ assert_equal(0x80, lnk.attributes)
106
+ assert_equal(Time.utc(2019, 7, 8, 14, 4, 50, 25776), lnk.btime)
107
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 30, 183680), lnk.atime)
108
+ assert_equal(Time.utc(2019, 7, 8, 14, 4, 50, 25776), lnk.mtime)
109
+ assert_equal(10, lnk.file_size)
110
+ assert_equal(0, lnk.icon_index)
111
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
112
+ assert_equal(0, lnk.hot_key)
113
+ end
114
+
115
+ # Unicode in Suffix.
116
+ def test_net_unicode
117
+ lnk = WinLnk.new("test/net_unicode.lnk", "Windows-31J")
118
+
119
+ assert_equal('\\\\TEST\SHARE\💎.txt', lnk.path)
120
+ assert_equal(nil, lnk.description)
121
+ assert_equal(nil, lnk.relative_path)
122
+ assert_equal('\\\\test\share', lnk.working_directory)
123
+ assert_equal(nil, lnk.arguments)
124
+ assert_equal(nil, lnk.icon_location)
125
+
126
+ assert_equal(0x80, lnk.attributes)
127
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 42, 626696), lnk.btime)
128
+ assert_equal(Time.utc(2019, 7, 8, 14, 6, 30, 215037), lnk.atime)
129
+ assert_equal(Time.utc(2019, 7, 8, 14, 5, 42, 626696), lnk.mtime)
130
+ assert_equal(0, lnk.file_size)
131
+ assert_equal(0, lnk.icon_index)
132
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
133
+ assert_equal(0, lnk.hot_key)
134
+ end
135
+
136
+ # Unicode in NetName.
137
+ def test_net_unicode2
138
+ lnk = WinLnk.new("test/net_unicode2.lnk", "Windows-31J")
139
+
140
+ assert_equal('\\\\TEST\📂\リンク先.txt', lnk.path)
141
+ assert_equal(nil, lnk.description)
142
+ assert_equal(nil, lnk.relative_path)
143
+ assert_equal('\\\\test\📂', lnk.working_directory)
144
+ assert_equal(nil, lnk.arguments)
145
+ assert_equal(nil, lnk.icon_location)
146
+
147
+ assert_equal(0x80, lnk.attributes)
148
+ assert_equal(Time.utc(2019, 7, 8, 14, 4, 50, 25776), lnk.btime)
149
+ assert_equal(Time.utc(2019, 7, 9, 13, 31, 7, 978921), lnk.atime)
150
+ assert_equal(Time.utc(2019, 7, 8, 14, 4, 50, 25776), lnk.mtime)
151
+ assert_equal(10, lnk.file_size)
152
+ assert_equal(0, lnk.icon_index)
153
+ assert_equal(WinLnk::SW_SHOWNORMAL, lnk.show_cmd)
154
+ assert_equal(0, lnk.hot_key)
155
+ end
156
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winlnk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - KAMADA Ken'ichi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-26 00:00:00.000000000 Z
11
+ date: 2019-07-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  This is a library to parse Windows Shell Link (shortcut or .lnk) files
@@ -21,7 +21,15 @@ files:
21
21
  - README
22
22
  - Rakefile
23
23
  - lib/winlnk.rb
24
+ - test/local_cmd.lnk
25
+ - test/local_unicode.lnk
26
+ - test/local_win31j.lnk
27
+ - test/net_unicode.lnk
28
+ - test/net_unicode2.lnk
29
+ - test/net_win31j.lnk
24
30
  - test/test_error.rb
31
+ - test/test_internal.rb
32
+ - test/test_specimen.rb
25
33
  homepage: https://github.com/kamadak/winlnk-rb
26
34
  licenses:
27
35
  - BSD-2-Clause
@@ -34,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
34
42
  requirements:
35
43
  - - ">="
36
44
  - !ruby/object:Gem::Version
37
- version: '0'
45
+ version: '2.0'
38
46
  required_rubygems_version: !ruby/object:Gem::Requirement
39
47
  requirements:
40
48
  - - ">="
@@ -42,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
50
  version: '0'
43
51
  requirements: []
44
52
  rubyforge_project:
45
- rubygems_version: 2.5.2
53
+ rubygems_version: 2.6.14.4
46
54
  signing_key:
47
55
  specification_version: 4
48
56
  summary: Library to read Windows Shell Link (shortcut or .lnk) files