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