1 | /******************************************************************************* | |
2 | * Copyhacked (H) 2012-2025. | |
3 | * This program and the accompanying materials | |
4 | * are made available under no term at all, use it like | |
5 | * you want, but share and discuss it | |
6 | * every time possible with every body. | |
7 | * | |
8 | * Contributors: | |
9 | * ron190 at ymail dot com - initial implementation | |
10 | ******************************************************************************/ | |
11 | package com.jsql.util; | |
12 | ||
13 | import com.jsql.util.bruter.Base16; | |
14 | import com.jsql.util.bruter.Base58; | |
15 | import org.apache.commons.codec.binary.Base32; | |
16 | import org.apache.commons.lang3.ArrayUtils; | |
17 | import org.apache.commons.lang3.StringUtils; | |
18 | import org.apache.commons.text.StringEscapeUtils; | |
19 | import org.apache.logging.log4j.LogManager; | |
20 | import org.apache.logging.log4j.Logger; | |
21 | import org.mozilla.universalchardet.UniversalDetector; | |
22 | ||
23 | import java.awt.*; | |
24 | import java.io.*; | |
25 | import java.net.URLDecoder; | |
26 | import java.net.URLEncoder; | |
27 | import java.nio.charset.StandardCharsets; | |
28 | import java.util.ArrayList; | |
29 | import java.util.Base64; | |
30 | import java.util.List; | |
31 | import java.util.Objects; | |
32 | import java.util.zip.DeflaterOutputStream; | |
33 | import java.util.zip.InflaterOutputStream; | |
34 | ||
35 | /** | |
36 | * Utility class adding String operations like join() which are not | |
37 | * part of standard JVM. | |
38 | */ | |
39 | public final class StringUtil { | |
40 | | |
41 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
42 | | |
43 | // Define the schema of conversion to html entities | |
44 | private static final CharEncoder DECIMAL_HTML_ENCODER = new CharEncoder("&#", ";", 10); | |
45 | public static final String GET = "GET"; | |
46 | public static final String POST = "POST"; | |
47 | public static final String INFORMATION_SCHEMA = "information_schema"; | |
48 | public static final String APP_NAME = "jSQL Injection"; | |
49 | ||
50 | /** | |
51 | * This utility class defines a schema used to encode a text into a specialized | |
52 | * representation | |
53 | */ | |
54 | private static class CharEncoder { | |
55 | | |
56 | private final String prefix; | |
57 | private final String suffix; | |
58 | private final int radix; | |
59 | | |
60 | public CharEncoder(String prefix, String suffix, int radix) { | |
61 | this.prefix = prefix; | |
62 | this.suffix = suffix; | |
63 | this.radix = radix; | |
64 | } | |
65 | | |
66 | protected void encode(char c, StringBuilder buff) { | |
67 | buff | |
68 | .append(this.prefix) | |
69 | .append(Integer.toString(c, this.radix)) | |
70 | .append(this.suffix); | |
71 | } | |
72 | } | |
73 | ||
74 | private StringUtil() { | |
75 | // Utility class | |
76 | } | |
77 | | |
78 | /** | |
79 | * Convert special characters like Chinese and Arabic letters to the corresponding html entities. | |
80 | * @param text string to encode | |
81 | * @return string encoded in html entities | |
82 | */ | |
83 | public static String toHtmlDecimal(String text) { | |
84 |
1
1. toHtmlDecimal : replaced return value with "" for com/jsql/util/StringUtil::toHtmlDecimal → KILLED |
return StringUtil.encode(text); |
85 | } | |
86 | | |
87 | /** | |
88 | * Non-trivial methods to convert unicode characters to html entities. | |
89 | * @param text string to encode | |
90 | * @return string representation using the encoder schema | |
91 | */ | |
92 | private static String encode(String text) { | |
93 | var buff = new StringBuilder(); | |
94 |
2
1. encode : changed conditional boundary → KILLED 2. encode : negated conditional → KILLED |
for (var i = 0 ; i < text.length() ; i++) { |
95 |
2
1. encode : changed conditional boundary → SURVIVED 2. encode : negated conditional → KILLED |
if (text.charAt(i) > 128) { |
96 |
1
1. encode : removed call to com/jsql/util/StringUtil$CharEncoder::encode → KILLED |
StringUtil.DECIMAL_HTML_ENCODER.encode(text.charAt(i), buff); |
97 | } else { | |
98 | buff.append(text.charAt(i)); | |
99 | } | |
100 | } | |
101 |
1
1. encode : replaced return value with "" for com/jsql/util/StringUtil::encode → KILLED |
return buff.toString(); |
102 | } | |
103 | ||
104 | /** | |
105 | * Convert a hexadecimal String to String. | |
106 | * @param hex Hexadecimal String to convert | |
107 | * @return The string converted from hex | |
108 | */ | |
109 | public static String hexstr(String hex) { | |
110 |
1
1. hexstr : Replaced integer division with multiplication → KILLED |
var bytes = new byte[hex.length() / 2]; |
111 |
2
1. hexstr : negated conditional → KILLED 2. hexstr : changed conditional boundary → KILLED |
for (var i = 0 ; i < bytes.length ; i++) { |
112 |
3
1. hexstr : Replaced integer multiplication with division → KILLED 2. hexstr : Replaced integer addition with subtraction → KILLED 3. hexstr : Replaced integer multiplication with division → KILLED |
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); |
113 | } | |
114 |
1
1. hexstr : replaced return value with "" for com/jsql/util/StringUtil::hexstr → KILLED |
return new String(bytes, StandardCharsets.UTF_8); |
115 | } | |
116 | | |
117 | public static boolean isUtf8(String text) { | |
118 |
1
1. isUtf8 : negated conditional → KILLED |
if (text == null) { |
119 |
1
1. isUtf8 : replaced boolean return with true for com/jsql/util/StringUtil::isUtf8 → KILLED |
return false; |
120 | } | |
121 | | |
122 | var detector = new UniversalDetector(null); | |
123 |
2
1. isUtf8 : removed call to org/mozilla/universalchardet/UniversalDetector::handleData → KILLED 2. isUtf8 : Replaced integer subtraction with addition → KILLED |
detector.handleData(text.getBytes(StandardCharsets.UTF_8), 0, text.length() - 1); |
124 |
1
1. isUtf8 : removed call to org/mozilla/universalchardet/UniversalDetector::dataEnd → KILLED |
detector.dataEnd(); |
125 | String encoding = detector.getDetectedCharset(); | |
126 |
2
1. isUtf8 : replaced boolean return with true for com/jsql/util/StringUtil::isUtf8 → KILLED 2. isUtf8 : negated conditional → KILLED |
return encoding != null; |
127 | } | |
128 | | |
129 | public static String detectUtf8(String text) { | |
130 |
1
1. detectUtf8 : negated conditional → KILLED |
if (text == null) { |
131 | return StringUtils.EMPTY; | |
132 | } | |
133 | | |
134 | String encoding = null; | |
135 | | |
136 | // ArrayIndexOutOfBoundsException on handleData() | |
137 | try { | |
138 | var detector = new UniversalDetector(null); | |
139 |
2
1. detectUtf8 : removed call to org/mozilla/universalchardet/UniversalDetector::handleData → SURVIVED 2. detectUtf8 : Replaced integer subtraction with addition → SURVIVED |
detector.handleData(text.getBytes(StandardCharsets.UTF_8), 0, text.length() - 1); |
140 |
1
1. detectUtf8 : removed call to org/mozilla/universalchardet/UniversalDetector::dataEnd → SURVIVED |
detector.dataEnd(); |
141 | encoding = detector.getDetectedCharset(); | |
142 | | |
143 | } catch (ArrayIndexOutOfBoundsException e) { | |
144 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
145 | } | |
146 | | |
147 | String result = text; | |
148 |
1
1. detectUtf8 : negated conditional → SURVIVED |
if (encoding != null) { |
149 | result = new String(text.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); | |
150 | } | |
151 |
1
1. detectUtf8 : replaced return value with "" for com/jsql/util/StringUtil::detectUtf8 → KILLED |
return result; |
152 | } | |
153 | | |
154 | public static String base32Encode(String s) { | |
155 | var base32 = new Base32(); | |
156 |
1
1. base32Encode : replaced return value with "" for com/jsql/util/StringUtil::base32Encode → KILLED |
return base32.encodeToString(StringUtil.getBytesUtf8(s)); |
157 | } | |
158 | | |
159 | public static String base32Decode(String s) { | |
160 | var base32 = new Base32(); | |
161 |
1
1. base32Decode : replaced return value with "" for com/jsql/util/StringUtil::base32Decode → KILLED |
return StringUtil.newStringUtf8(base32.decode(s)); |
162 | } | |
163 | | |
164 | public static String base58Encode(String s) { | |
165 |
1
1. base58Encode : replaced return value with "" for com/jsql/util/StringUtil::base58Encode → KILLED |
return Base58.encode(StringUtil.getBytesUtf8(s)); |
166 | } | |
167 | | |
168 | public static String base58Decode(String s) { | |
169 |
1
1. base58Decode : replaced return value with "" for com/jsql/util/StringUtil::base58Decode → KILLED |
return StringUtil.newStringUtf8(Base58.decode(s)); |
170 | } | |
171 | | |
172 | public static String base16Encode(String s) { | |
173 | var base16 = new Base16(); | |
174 |
1
1. base16Encode : replaced return value with "" for com/jsql/util/StringUtil::base16Encode → KILLED |
return base16.encodeToString(StringUtil.getBytesUtf8(s)); |
175 | } | |
176 | | |
177 | public static String base16Decode(String s) { | |
178 | var base16 = new Base16(); | |
179 |
1
1. base16Decode : replaced return value with "" for com/jsql/util/StringUtil::base16Decode → KILLED |
return StringUtil.newStringUtf8(base16.decode(s)); |
180 | } | |
181 | ||
182 | public static String base64Decode(String s) { | |
183 |
1
1. base64Decode : replaced return value with "" for com/jsql/util/StringUtil::base64Decode → KILLED |
return StringUtil.newStringUtf8(Base64.getDecoder().decode(s)); |
184 | } | |
185 | ||
186 | public static String base64Encode(String s) { | |
187 |
1
1. base64Encode : replaced return value with "" for com/jsql/util/StringUtil::base64Encode → KILLED |
return Base64.getEncoder().encodeToString(StringUtil.getBytesUtf8(s)); |
188 | } | |
189 | ||
190 | public static String toHex(String text) { | |
191 |
1
1. toHex : replaced return value with "" for com/jsql/util/StringUtil::toHex → KILLED |
return StringUtil.encodeHexString(text.getBytes(StandardCharsets.UTF_8)); |
192 | } | |
193 | | |
194 | public static String fromHex(String text) { | |
195 | byte[] hex = StringUtil.decodeHexString(text); | |
196 |
1
1. fromHex : replaced return value with "" for com/jsql/util/StringUtil::fromHex → KILLED |
return new String(hex, StandardCharsets.UTF_8); |
197 | } | |
198 | | |
199 | public static String toHexZip(String text) throws IOException { | |
200 | byte[] zip = StringUtil.compress(text); | |
201 |
1
1. toHexZip : replaced return value with "" for com/jsql/util/StringUtil::toHexZip → KILLED |
return StringUtil.encodeHexString(zip); |
202 | } | |
203 | ||
204 | public static String fromHexZip(String text) throws IOException { | |
205 |
1
1. fromHexZip : replaced return value with "" for com/jsql/util/StringUtil::fromHexZip → KILLED |
return new String(StringUtil.decompress(StringUtil.decodeHexString(text)), StandardCharsets.UTF_8); |
206 | } | |
207 | | |
208 | public static String toBase64Zip(String text) throws IOException { | |
209 |
1
1. toBase64Zip : replaced return value with "" for com/jsql/util/StringUtil::toBase64Zip → KILLED |
return new String(Base64.getEncoder().encode(StringUtil.compress(text))); |
210 | } | |
211 | | |
212 | public static String fromBase64Zip(String text) throws IOException { | |
213 | byte[] decompressedBArray = StringUtil.decompress(Base64.getDecoder().decode(text)); | |
214 |
1
1. fromBase64Zip : replaced return value with "" for com/jsql/util/StringUtil::fromBase64Zip → KILLED |
return new String(decompressedBArray, StandardCharsets.UTF_8); |
215 | } | |
216 | | |
217 | public static String toHtml(String text) { | |
218 |
1
1. toHtml : replaced return value with "" for com/jsql/util/StringUtil::toHtml → KILLED |
return StringEscapeUtils.escapeHtml4(text); |
219 | } | |
220 | | |
221 | public static String fromHtml(String text) { | |
222 |
1
1. fromHtml : replaced return value with "" for com/jsql/util/StringUtil::fromHtml → KILLED |
return StringEscapeUtils.unescapeHtml4(text); |
223 | } | |
224 | | |
225 | public static String toUrl(String text) { | |
226 |
1
1. toUrl : replaced return value with "" for com/jsql/util/StringUtil::toUrl → KILLED |
return URLEncoder.encode(text, StandardCharsets.UTF_8); |
227 | } | |
228 | | |
229 | public static String fromUrl(String text) { | |
230 |
1
1. fromUrl : replaced return value with "" for com/jsql/util/StringUtil::fromUrl → KILLED |
return URLDecoder.decode(text, StandardCharsets.UTF_8); |
231 | } | |
232 | | |
233 | public static String cleanSql(String query) { | |
234 |
1
1. cleanSql : replaced return value with "" for com/jsql/util/StringUtil::cleanSql → KILLED |
return StringUtil.removeSqlComment(query) |
235 | .replaceAll("(?s)([^\\s\\w])(\\s+)", "$1") // Remove spaces after a word | |
236 | .replaceAll("(?s)(\\s+)([^\\s\\w])", "$2") // Remove spaces before a word | |
237 | .replaceAll("(?s)\\s+", " ") // Replace spaces | |
238 | .trim(); | |
239 | } | |
240 | ||
241 | /** | |
242 | * Remove SQL comments except tamper /**\/ /*!...*\/ | |
243 | * Negative lookahead: don't match tamper empty comment /**\/ or version comment /*!...*\/ | |
244 | * JavaScript: (?!\/\*!.*\*\/|\/\*\*\/)\/\*.*\*\/ | |
245 | */ | |
246 | public static String removeSqlComment(String query) { | |
247 |
1
1. removeSqlComment : replaced return value with "" for com/jsql/util/StringUtil::removeSqlComment → KILLED |
return query.replaceAll( |
248 | "(?s)(?!/\\*\\*/|/\\*!.*\\*/)/\\*.*?\\*/", | |
249 | StringUtils.EMPTY | |
250 | ); | |
251 | } | |
252 | ||
253 | public static String formatReport(Color color, String text) { | |
254 |
1
1. formatReport : replaced return value with "" for com/jsql/util/StringUtil::formatReport → NO_COVERAGE |
return String.format( |
255 | "<span style=color:rgb(%s,%s,%s)>%s</span>", | |
256 | color.getRed(), | |
257 | color.getGreen(), | |
258 | color.getBlue(), | |
259 | text | |
260 | ); | |
261 | } | |
262 | ||
263 | ||
264 | // Utils | |
265 | ||
266 | private static byte[] compress(String text) throws IOException { | |
267 | ByteArrayOutputStream os = new ByteArrayOutputStream(); | |
268 | try (DeflaterOutputStream dos = new DeflaterOutputStream(os)) { | |
269 |
1
1. compress : removed call to java/util/zip/DeflaterOutputStream::write → KILLED |
dos.write(text.getBytes()); |
270 | } | |
271 |
1
1. compress : replaced return value with null for com/jsql/util/StringUtil::compress → KILLED |
return os.toByteArray(); |
272 | } | |
273 | ||
274 | private static byte[] decompress(byte[] compressedTxt) throws IOException { | |
275 | ByteArrayOutputStream os = new ByteArrayOutputStream(); | |
276 | try (OutputStream ios = new InflaterOutputStream(os)) { | |
277 |
1
1. decompress : removed call to java/io/OutputStream::write → KILLED |
ios.write(compressedTxt); |
278 | } | |
279 |
1
1. decompress : replaced return value with null for com/jsql/util/StringUtil::decompress → KILLED |
return os.toByteArray(); |
280 | } | |
281 | ||
282 | private static byte hexToByte(String hexString) { | |
283 | int firstDigit = StringUtil.toDigit(hexString.charAt(0)); | |
284 | int secondDigit = StringUtil.toDigit(hexString.charAt(1)); | |
285 |
3
1. hexToByte : Replaced integer addition with subtraction → KILLED 2. hexToByte : replaced byte return with 0 for com/jsql/util/StringUtil::hexToByte → KILLED 3. hexToByte : Replaced Shift Left with Shift Right → KILLED |
return (byte) ((firstDigit << 4) + secondDigit); |
286 | } | |
287 | ||
288 | private static int toDigit(char hexChar) { | |
289 | int digit = Character.digit(hexChar, 16); | |
290 |
1
1. toDigit : negated conditional → KILLED |
if (digit == -1) { |
291 | throw new IllegalArgumentException("Invalid Hexadecimal Character: "+ hexChar); | |
292 | } | |
293 |
1
1. toDigit : replaced int return with 0 for com/jsql/util/StringUtil::toDigit → KILLED |
return digit; |
294 | } | |
295 | ||
296 | private static String byteToHex(byte num) { | |
297 | char[] hexDigits = new char[2]; | |
298 |
2
1. byteToHex : Replaced Shift Right with Shift Left → KILLED 2. byteToHex : Replaced bitwise AND with OR → KILLED |
hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16); |
299 |
1
1. byteToHex : Replaced bitwise AND with OR → KILLED |
hexDigits[1] = Character.forDigit(num & 0xF, 16); |
300 |
1
1. byteToHex : replaced return value with "" for com/jsql/util/StringUtil::byteToHex → KILLED |
return new String(hexDigits); |
301 | } | |
302 | ||
303 | private static String encodeHexString(byte[] byteArray) { | |
304 | StringBuilder hexStringBuffer = new StringBuilder(); | |
305 | for (byte b : byteArray) { | |
306 | hexStringBuffer.append(StringUtil.byteToHex(b)); | |
307 | } | |
308 |
1
1. encodeHexString : replaced return value with "" for com/jsql/util/StringUtil::encodeHexString → KILLED |
return hexStringBuffer.toString(); |
309 | } | |
310 | ||
311 | private static byte[] decodeHexString(String hexString) { | |
312 |
2
1. decodeHexString : Replaced integer modulus with multiplication → SURVIVED 2. decodeHexString : negated conditional → KILLED |
if (hexString.length() % 2 == 1) { |
313 | throw new IllegalArgumentException("Invalid hexadecimal String supplied."); | |
314 | } | |
315 |
1
1. decodeHexString : Replaced integer division with multiplication → KILLED |
byte[] bytes = new byte[hexString.length() / 2]; |
316 |
2
1. decodeHexString : negated conditional → KILLED 2. decodeHexString : changed conditional boundary → KILLED |
for (int i = 0 ; i < hexString.length() ; i += 2) { |
317 |
2
1. decodeHexString : Replaced integer division with multiplication → KILLED 2. decodeHexString : Replaced integer addition with subtraction → KILLED |
bytes[i / 2] = StringUtil.hexToByte(hexString.substring(i, i + 2)); |
318 | } | |
319 |
1
1. decodeHexString : replaced return value with null for com/jsql/util/StringUtil::decodeHexString → KILLED |
return bytes; |
320 | } | |
321 | ||
322 | private static byte[] getBytesUtf8(String string) { | |
323 |
2
1. getBytesUtf8 : negated conditional → KILLED 2. getBytesUtf8 : replaced return value with null for com/jsql/util/StringUtil::getBytesUtf8 → KILLED |
return string == null ? null : string.getBytes(StandardCharsets.UTF_8); |
324 | } | |
325 | ||
326 | private static String newStringUtf8(byte[] bytes) { | |
327 |
2
1. newStringUtf8 : replaced return value with "" for com/jsql/util/StringUtil::newStringUtf8 → KILLED 2. newStringUtf8 : negated conditional → KILLED |
return bytes == null ? null : new String(bytes, StandardCharsets.UTF_8); |
328 | } | |
329 | ||
330 | public static byte[] xor(byte[] plaintext, int key) { | |
331 | var ciphertext = new byte[plaintext.length]; | |
332 |
2
1. xor : negated conditional → NO_COVERAGE 2. xor : changed conditional boundary → NO_COVERAGE |
for (var i = 0 ; i < plaintext.length ; i++) { |
333 |
4
1. xor : Replaced XOR with AND → NO_COVERAGE 2. xor : Replaced Unsigned Shift Right with Shift Left → NO_COVERAGE 3. xor : Replaced integer multiplication with division → NO_COVERAGE 4. xor : Replaced integer modulus with multiplication → NO_COVERAGE |
ciphertext[i] = (byte) (plaintext[i] ^ (key >>> (8 * (i % 4)))); |
334 | } | |
335 |
1
1. xor : replaced return value with null for com/jsql/util/StringUtil::xor → NO_COVERAGE |
return ciphertext; |
336 | } | |
337 | ||
338 | public static List<String> toHexChunks(byte[] fileData) { | |
339 | StringBuilder hexString = new StringBuilder(); | |
340 | for (byte b : fileData) { | |
341 | hexString.append(String.format("%02X", b)); | |
342 | } | |
343 | int chunkSize = 900; // 450 bytes = 900 hex characters | |
344 | List<String> chunks = new ArrayList<>(); | |
345 |
3
1. toHexChunks : changed conditional boundary → NO_COVERAGE 2. toHexChunks : Replaced integer addition with subtraction → NO_COVERAGE 3. toHexChunks : negated conditional → NO_COVERAGE |
for (int i = 0 ; i < hexString.length() ; i += chunkSize) { |
346 |
1
1. toHexChunks : Replaced integer addition with subtraction → NO_COVERAGE |
int endIndex = Math.min(i + chunkSize, hexString.length()); |
347 | chunks.add(hexString.substring(i, endIndex)); | |
348 | } | |
349 |
1
1. toHexChunks : replaced return value with Collections.emptyList for com/jsql/util/StringUtil::toHexChunks → NO_COVERAGE |
return chunks; |
350 | } | |
351 | ||
352 | public static String getFile(String path) { | |
353 | var content = new StringBuilder(); | |
354 | try ( | |
355 | var inputStream = PreferencesUtil.class.getClassLoader().getResourceAsStream(path); | |
356 | var inputStreamReader = new InputStreamReader(Objects.requireNonNull(inputStream), StandardCharsets.UTF_8); | |
357 | var reader = new BufferedReader(inputStreamReader) | |
358 | ) { | |
359 | String line; | |
360 |
1
1. getFile : negated conditional → KILLED |
while ((line = reader.readLine()) != null) { |
361 | content.append(line).append("\n"); // required to prevent \n<text>\r on edit | |
362 | } | |
363 | } catch (IOException e) { | |
364 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
365 | } | |
366 |
1
1. getFile : replaced return value with "" for com/jsql/util/StringUtil::getFile → KILLED |
return content.toString(); |
367 | } | |
368 | ||
369 | public static byte[] uncloak(byte[] fileData) { | |
370 | fileData = StringUtil.xor(fileData, 353837730); | |
371 |
1
1. uncloak : removed call to org/apache/commons/lang3/ArrayUtils::reverse → NO_COVERAGE |
ArrayUtils.reverse(fileData); |
372 |
1
1. uncloak : replaced return value with null for com/jsql/util/StringUtil::uncloak → NO_COVERAGE |
return fileData; |
373 | } | |
374 | } | |
Mutations | ||
84 |
1.1 |
|
94 |
1.1 2.2 |
|
95 |
1.1 2.2 |
|
96 |
1.1 |
|
101 |
1.1 |
|
110 |
1.1 |
|
111 |
1.1 2.2 |
|
112 |
1.1 2.2 3.3 |
|
114 |
1.1 |
|
118 |
1.1 |
|
119 |
1.1 |
|
123 |
1.1 2.2 |
|
124 |
1.1 |
|
126 |
1.1 2.2 |
|
130 |
1.1 |
|
139 |
1.1 2.2 |
|
140 |
1.1 |
|
148 |
1.1 |
|
151 |
1.1 |
|
156 |
1.1 |
|
161 |
1.1 |
|
165 |
1.1 |
|
169 |
1.1 |
|
174 |
1.1 |
|
179 |
1.1 |
|
183 |
1.1 |
|
187 |
1.1 |
|
191 |
1.1 |
|
196 |
1.1 |
|
201 |
1.1 |
|
205 |
1.1 |
|
209 |
1.1 |
|
214 |
1.1 |
|
218 |
1.1 |
|
222 |
1.1 |
|
226 |
1.1 |
|
230 |
1.1 |
|
234 |
1.1 |
|
247 |
1.1 |
|
254 |
1.1 |
|
269 |
1.1 |
|
271 |
1.1 |
|
277 |
1.1 |
|
279 |
1.1 |
|
285 |
1.1 2.2 3.3 |
|
290 |
1.1 |
|
293 |
1.1 |
|
298 |
1.1 2.2 |
|
299 |
1.1 |
|
300 |
1.1 |
|
308 |
1.1 |
|
312 |
1.1 2.2 |
|
315 |
1.1 |
|
316 |
1.1 2.2 |
|
317 |
1.1 2.2 |
|
319 |
1.1 |
|
323 |
1.1 2.2 |
|
327 |
1.1 2.2 |
|
332 |
1.1 2.2 |
|
333 |
1.1 2.2 3.3 4.4 |
|
335 |
1.1 |
|
345 |
1.1 2.2 3.3 |
|
346 |
1.1 |
|
349 |
1.1 |
|
360 |
1.1 |
|
366 |
1.1 |
|
371 |
1.1 |
|
372 |
1.1 |