1 |
|
package org.stackoverflowusers.file; |
2 |
|
|
3 |
|
import java.io.ByteArrayOutputStream; |
4 |
|
import java.io.File; |
5 |
|
import java.io.FileInputStream; |
6 |
|
import java.io.IOException; |
7 |
|
import java.io.InputStream; |
8 |
|
import java.text.ParseException; |
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
|
23 |
|
|
24 |
|
|
25 |
|
|
26 |
|
|
|
|
| 0% |
Uncovered Elements: 99 (99) |
Complexity: 22 |
Complexity Density: 0.31 |
|
27 |
|
public class WindowsShortcut |
28 |
|
{ |
29 |
|
private boolean isDirectory; |
30 |
|
private boolean isLocal; |
31 |
|
private String real_file; |
32 |
|
|
33 |
|
|
34 |
|
|
35 |
|
|
36 |
|
|
37 |
|
|
38 |
|
|
39 |
|
@param |
40 |
|
@return |
41 |
|
@throws |
42 |
|
|
|
|
| 0% |
Uncovered Elements: 7 (7) |
Complexity: 1 |
Complexity Density: 0.14 |
|
43 |
0 |
public static boolean isPotentialValidLink(File file) throws IOException {... |
44 |
0 |
final int minimum_length = 0x64; |
45 |
0 |
InputStream fis = new FileInputStream(file); |
46 |
0 |
boolean isPotentiallyValid = false; |
47 |
0 |
try { |
48 |
0 |
isPotentiallyValid = file.isFile() |
49 |
|
&& file.getName().toLowerCase().endsWith(".lnk") |
50 |
|
&& fis.available() >= minimum_length |
51 |
|
&& isMagicPresent(getBytes(fis, 32)); |
52 |
|
} finally { |
53 |
0 |
fis.close(); |
54 |
|
} |
55 |
0 |
return isPotentiallyValid; |
56 |
|
} |
57 |
|
|
|
|
| 0% |
Uncovered Elements: 4 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
58 |
0 |
public WindowsShortcut(File file) throws IOException, ParseException {... |
59 |
0 |
InputStream in = new FileInputStream(file); |
60 |
0 |
try { |
61 |
0 |
parseLink(getBytes(in)); |
62 |
|
} finally { |
63 |
0 |
in.close(); |
64 |
|
} |
65 |
|
} |
66 |
|
|
67 |
|
|
68 |
|
@return |
69 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
70 |
0 |
public String getRealFilename() {... |
71 |
0 |
return real_file; |
72 |
|
} |
73 |
|
|
74 |
|
|
75 |
|
|
76 |
|
@return |
77 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
78 |
0 |
public boolean isLocal() {... |
79 |
0 |
return isLocal; |
80 |
|
} |
81 |
|
|
82 |
|
|
83 |
|
|
84 |
|
@return |
85 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
86 |
0 |
public boolean isDirectory() {... |
87 |
0 |
return isDirectory; |
88 |
|
} |
89 |
|
|
90 |
|
|
91 |
|
|
92 |
|
@param |
93 |
|
@return |
94 |
|
@throws |
95 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
96 |
0 |
private static byte[] getBytes(InputStream in) throws IOException {... |
97 |
0 |
return getBytes(in, null); |
98 |
|
} |
99 |
|
|
100 |
|
|
101 |
|
|
102 |
|
@param |
103 |
|
@param |
104 |
|
@return |
105 |
|
@throws |
106 |
|
|
|
|
| 0% |
Uncovered Elements: 17 (17) |
Complexity: 5 |
Complexity Density: 0.45 |
|
107 |
0 |
private static byte[] getBytes(InputStream in, Integer max) throws IOException {... |
108 |
|
|
109 |
0 |
ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
110 |
0 |
byte[] buff = new byte[256]; |
111 |
0 |
while (max == null || max > 0) { |
112 |
0 |
int n = in.read(buff); |
113 |
0 |
if (n == -1) { |
114 |
0 |
break; |
115 |
|
} |
116 |
0 |
bout.write(buff, 0, n); |
117 |
0 |
if (max != null) |
118 |
0 |
max -= n; |
119 |
|
} |
120 |
0 |
in.close(); |
121 |
0 |
return bout.toByteArray(); |
122 |
|
} |
123 |
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
124 |
0 |
private static boolean isMagicPresent(byte[] link) {... |
125 |
0 |
final int magic = 0x0000004C; |
126 |
0 |
final int magic_offset = 0x00; |
127 |
0 |
return link.length >= 32 && bytesToDword(link, magic_offset) == magic; |
128 |
|
} |
129 |
|
|
130 |
|
|
131 |
|
|
132 |
|
@param |
133 |
|
|
|
|
| 0% |
Uncovered Elements: 42 (42) |
Complexity: 6 |
Complexity Density: 0.18 |
|
134 |
0 |
private void parseLink(byte[] link) throws ParseException {... |
135 |
0 |
try { |
136 |
0 |
if (!isMagicPresent(link)) |
137 |
0 |
throw new ParseException("Invalid shortcut; magic is missing", 0); |
138 |
|
|
139 |
|
|
140 |
0 |
byte flags = link[0x14]; |
141 |
|
|
142 |
|
|
143 |
0 |
final int file_atts_offset = 0x18; |
144 |
0 |
byte file_atts = link[file_atts_offset]; |
145 |
0 |
byte is_dir_mask = (byte)0x10; |
146 |
0 |
if ((file_atts & is_dir_mask) > 0) { |
147 |
0 |
isDirectory = true; |
148 |
|
} else { |
149 |
0 |
isDirectory = false; |
150 |
|
} |
151 |
|
|
152 |
|
|
153 |
0 |
final int shell_offset = 0x4c; |
154 |
0 |
final byte has_shell_mask = (byte)0x01; |
155 |
0 |
int shell_len = 0; |
156 |
0 |
if ((flags & has_shell_mask) > 0) { |
157 |
|
|
158 |
0 |
shell_len = bytesToWord(link, shell_offset) + 2; |
159 |
|
} |
160 |
|
|
161 |
|
|
162 |
0 |
int file_start = 0x4c + shell_len; |
163 |
|
|
164 |
0 |
final int file_location_info_flag_offset_offset = 0x08; |
165 |
0 |
int file_location_info_flag = link[file_start + file_location_info_flag_offset_offset]; |
166 |
0 |
isLocal = (file_location_info_flag & 2) == 0; |
167 |
|
|
168 |
|
|
169 |
0 |
final int basename_offset_offset = 0x10; |
170 |
0 |
final int networkVolumeTable_offset_offset = 0x14; |
171 |
0 |
final int finalname_offset_offset = 0x18; |
172 |
0 |
int finalname_offset = link[file_start + finalname_offset_offset] + file_start; |
173 |
0 |
String finalname = getNullDelimitedString(link, finalname_offset); |
174 |
0 |
if (isLocal) { |
175 |
0 |
int basename_offset = link[file_start + basename_offset_offset] + file_start; |
176 |
0 |
String basename = getNullDelimitedString(link, basename_offset); |
177 |
0 |
real_file = basename + finalname; |
178 |
|
} else { |
179 |
0 |
int networkVolumeTable_offset = link[file_start + networkVolumeTable_offset_offset] + file_start; |
180 |
0 |
int shareName_offset_offset = 0x08; |
181 |
0 |
int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset] |
182 |
|
+ networkVolumeTable_offset; |
183 |
0 |
String shareName = getNullDelimitedString(link, shareName_offset); |
184 |
0 |
real_file = shareName + "\\" + finalname; |
185 |
|
} |
186 |
|
} catch (ArrayIndexOutOfBoundsException e) { |
187 |
0 |
throw new ParseException("Could not be parsed, probably not a valid WindowsShortcut", 0); |
188 |
|
} |
189 |
|
} |
190 |
|
|
|
|
| 0% |
Uncovered Elements: 8 (8) |
Complexity: 2 |
Complexity Density: 0.33 |
|
191 |
0 |
private static String getNullDelimitedString(byte[] bytes, int off) {... |
192 |
0 |
int len = 0; |
193 |
|
|
194 |
0 |
while (true) { |
195 |
0 |
if (bytes[off + len] == 0) { |
196 |
0 |
break; |
197 |
|
} |
198 |
0 |
len++; |
199 |
|
} |
200 |
0 |
return new String(bytes, off, len); |
201 |
|
} |
202 |
|
|
203 |
|
|
204 |
|
|
205 |
|
|
206 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
207 |
0 |
private static int bytesToWord(byte[] bytes, int off) {... |
208 |
0 |
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff); |
209 |
|
} |
210 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
211 |
0 |
private static int bytesToDword(byte[] bytes, int off) {... |
212 |
0 |
return (bytesToWord(bytes, off + 2) << 16) | bytesToWord(bytes, off); |
213 |
|
} |
214 |
|
|
215 |
|
} |