troubadix 25.10.7__py3-none-any.whl → 25.10.9__py3-none-any.whl

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.
troubadix/__version__.py CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  # THIS IS AN AUTOGENERATED FILE. DO NOT TOUCH!
4
4
 
5
- __version__ = "25.10.7"
5
+ __version__ = "25.10.9"
@@ -1,62 +1,78 @@
1
1
  # Copyright (C) 2022 Greenbone AG
2
- #
3
2
  # SPDX-License-Identifier: GPL-3.0-or-later
4
- #
5
- # This program is free software: you can redistribute it and/or modify
6
- # it under the terms of the GNU General Public License as published by
7
- # the Free Software Foundation, either version 3 of the License, or
8
- # (at your option) any later version.
9
- #
10
- # This program is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- # GNU General Public License for more details.
14
- #
15
- # You should have received a copy of the GNU General Public License
16
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
3
 
18
- import re
19
- from pathlib import Path
20
- from typing import Iterable, Iterator
4
+ from typing import Iterator
21
5
 
22
- import charset_normalizer
6
+ import magic
23
7
 
24
- from troubadix.plugin import LineContentPlugin, LinterError, LinterResult
8
+ from troubadix.plugin import (
9
+ FilePlugin,
10
+ LinterError,
11
+ LinterResult,
12
+ )
25
13
 
26
- # Only the ASCII and extended ASCII for now... # https://www.ascii-code.com/
27
- # CHAR_SET = r"[^\x00-\xFF]"
28
- # Temporary only check for chars in between 7f-9f, like in the old Feed-QA...
29
- INVALID_CHAR_PATTERN = re.compile(r"[\x7F-\x9F]")
14
+ # OpenVAS decodes NASL files using ISO-8859-1 (Latin-1).
15
+ # Files saved in other encodings (like UTF-8)
16
+ # will be misinterpreted and cause errors or garbled text.
17
+ # US-ASCII is also allowed since it's a subset of ISO-8859-1.
18
+ ALLOWED_ENCODINGS = ["iso-8859-1", "us-ascii"]
30
19
 
31
- ALLOWED_ENCODINGS = ["ascii", "latin_1"]
32
20
 
21
+ class CheckEncoding(FilePlugin):
22
+ """
23
+ Check if the encoding of the NASL file is ISO-8859-1 (Latin-1) encoded.
24
+ Finds UTF-8 multibyte sequences that are composed of individually valid Latin-1 bytes,
25
+ but result in garbled text.
26
+ """
33
27
 
34
- class CheckEncoding(LineContentPlugin):
35
28
  name = "check_encoding"
36
29
 
37
- def check_lines(
38
- self,
39
- nasl_file: Path,
40
- lines: Iterable[str],
41
- ) -> Iterator[LinterResult]:
42
- match = charset_normalizer.from_path(
43
- nasl_file, threshold=0.4, cp_isolation=ALLOWED_ENCODINGS
44
- ).best()
30
+ def run(self) -> Iterator[LinterResult]:
31
+ with open(self.context.nasl_file, "rb") as f:
32
+ raw = f.read()
45
33
 
46
- if not match:
34
+ # Use magic to detect encoding
35
+ detected_encoding = magic.Magic(mime_encoding=True).from_buffer(raw)
36
+
37
+ if detected_encoding not in ALLOWED_ENCODINGS:
47
38
  yield LinterError(
48
- f"VT uses a wrong encoding. "
49
- f"Allowed encodings are {', '.join(ALLOWED_ENCODINGS)}.",
50
- file=nasl_file,
39
+ f"Detected encoding '{detected_encoding.upper()}' is not Latin-1 compatible.",
40
+ file=self.context.nasl_file,
51
41
  plugin=self.name,
52
42
  )
53
43
 
54
- for index, line in enumerate(lines, 1):
55
- encoding = INVALID_CHAR_PATTERN.search(line)
56
- if encoding:
44
+ def has_utf8_multibyte(data: bytes) -> bool:
45
+ """
46
+ Function to detect UTF-8 multibyte sequences by checking the first two bytes.
47
+ UTF-8 multibyte sequences start with a lead byte followed by continuation bytes.
48
+
49
+ Lead byte ranges:
50
+ - 2-byte: 0xC2–0xDF (110xxxxx, excluding 0xC0–0xC1 to avoid overlongs)
51
+ - 3-byte: 0xE0–0xEF (1110xxxx)
52
+ - 4-byte: 0xF0–0xF4 (11110xxx)
53
+ These ranges are continuous, so we can check 0xC2–0xF4 as a single range.
54
+ 11000010 C2 -- F4 11110111
55
+
56
+ Continuation bytes: 0x80–0xBF (10yyyyyy)
57
+ 10000000 80 -- BF 10111111
58
+
59
+ Lead and continuation byte values are either not valid Latin-1 or special symbols
60
+ that are unlikely to be following each other in normal use.
61
+ """
62
+
63
+ for i in range(len(data) - 1):
64
+ first = data[i]
65
+ second = data[i + 1]
66
+ if 0xC2 <= first <= 0xF4 and 0x80 <= second <= 0xBF:
67
+ return True
68
+ return False
69
+
70
+ lines = raw.split(b"\n")
71
+ for i, line_bytes in enumerate(lines, start=1):
72
+ if has_utf8_multibyte(line_bytes):
57
73
  yield LinterError(
58
- f"Found invalid character in line: {index}",
59
- file=nasl_file,
74
+ f"Likely UTF-8 multibyte sequence found in line {i}",
75
+ file=self.context.nasl_file,
60
76
  plugin=self.name,
61
- line=index,
77
+ line=i,
62
78
  )
@@ -56,7 +56,7 @@ exceptions = [
56
56
  r"these\s+error\s+(messages|reports|conditions)", re.IGNORECASE
57
57
  ),
58
58
  PatternCheck(
59
- r"these\s+file\s+(permissions|overwrites|names|includes|systems)",
59
+ r"these\s+file\s+(permissions|overwrites|names|includes|systems|formats)",
60
60
  re.IGNORECASE,
61
61
  ),
62
62
  # nb: Valid sentence
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: troubadix
3
- Version: 25.10.7
3
+ Version: 25.10.9
4
4
  Summary: A linting and QA check tool for NASL files
5
5
  License: GPL-3.0-or-later
6
6
  License-File: LICENSE
@@ -1,5 +1,5 @@
1
1
  troubadix/__init__.py,sha256=K7sIXXDrC7YRb7BvIpdQ6ZfG_QkT0qUH_wAlHROVRfM,716
2
- troubadix/__version__.py,sha256=URKTfluCYWyv6hpNgwKzTwfbDB-zbsbURt4HvY-BXM4,104
2
+ troubadix/__version__.py,sha256=5vWilWzDGYBXmf8qR5PG3cr7jcf2aD3Xeu9CIBn01Ms,104
3
3
  troubadix/argparser.py,sha256=-H07Jhqh68_M4Mbjq9qJjTr3MShy_N2pxl2qHA6cfRU,7481
4
4
  troubadix/codespell/codespell.additions,sha256=SJPlIo8vEKEOTftY6ZBSXzcfyv6y9aFAXl9FdpcMxD0,561
5
5
  troubadix/codespell/codespell.exclude,sha256=W1dHEbKuXZbiLMRLhUPIzhCV1ptHqPLuaB6VsJLxn64,147965
@@ -27,10 +27,10 @@ troubadix/plugins/deprecated_functions.py,sha256=6e46woXd-3hUBnnuIXLlaqlcP6F7c99
27
27
  troubadix/plugins/double_end_points.py,sha256=1TLVc8HFYEKS870zaIoKmsAjBsRU9WZpaMKReRDUoLo,2509
28
28
  troubadix/plugins/duplicate_oid.py,sha256=lemYl3CUoOMFtRTLnlfjwPptnN51sQby3D9YjFtOv2Q,2652
29
29
  troubadix/plugins/duplicated_script_tags.py,sha256=UPBR2jbU15JLKJlVk1e2GFREH5Wj5Ax2yDFrmRKq74Y,3123
30
- troubadix/plugins/encoding.py,sha256=zNzqNpP39TUwOklnc8OJ3OIUelAN_hvnuBYoa3Pz764,2104
30
+ troubadix/plugins/encoding.py,sha256=Ow_ZpyjtL2_nqhbukY_3EUhiR0agfSxMxJ4IcMSGsT4,2768
31
31
  troubadix/plugins/forking_nasl_functions.py,sha256=IUtCrTK_sGDx79jAPS8lF_aN8zSG2AkzfC6duTMvJOw,6069
32
32
  troubadix/plugins/get_kb_on_services.py,sha256=oFmcjiF7ZD3x5tEbJEoZNn80y1qUzNgeSZNsogSqaZ0,3401
33
- troubadix/plugins/grammar.py,sha256=hd5Qqamem9Iy64UMmdv5lEIfinS1vGDw_1CYNPmOsvg,10231
33
+ troubadix/plugins/grammar.py,sha256=-53McZsKFuEavIS8-8CG7fUbW8VO3FuZv0PXenD42Bk,10239
34
34
  troubadix/plugins/http_links_in_tags.py,sha256=F4fm74M3CbmWOJoCyDdEO-bKQahFsHL6vs4ZynhHEkc,7325
35
35
  troubadix/plugins/if_statement_syntax.py,sha256=5BRJwCCghvZn1AfvYzmk8l9S7aRqbVaLHhSKod_Q9zw,1429
36
36
  troubadix/plugins/illegal_characters.py,sha256=B6q_RU85AxCjLry56Oc-RhMSpnJU8mTrxclRzi1FVFU,4406
@@ -108,8 +108,8 @@ troubadix/standalone_plugins/no_solution.py,sha256=p_-az9Igl4GH6HnhLLYbYlWIiEP64
108
108
  troubadix/standalone_plugins/util.py,sha256=JTXGmi-_BJouTNe6QzEosLlXUt9jKW-3fz4db05RJJw,696
109
109
  troubadix/standalone_plugins/version_updated.py,sha256=6YHF0OjL5NWszQdsSh7XzlSji1e6Uaqwu_Y6m3R0mvI,4203
110
110
  troubadix/troubadix.py,sha256=5__Jz3bYSrya4aG6RCBWxqnsDepXfwXZ3v0bjCzEFi0,6039
111
- troubadix-25.10.7.dist-info/METADATA,sha256=BXZnOZiPoSlgxZB2ig4wxRvucT7ehJ-0tSynVzr2np4,4536
112
- troubadix-25.10.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
113
- troubadix-25.10.7.dist-info/entry_points.txt,sha256=ETEPBi4fKv3o7hzkzceX4838G6g5_5wRdEddYot8N6A,920
114
- troubadix-25.10.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
115
- troubadix-25.10.7.dist-info/RECORD,,
111
+ troubadix-25.10.9.dist-info/METADATA,sha256=vqH-RyAUMdTGfE_TiQ1WAsxQrsyXNm5LSD4xuf7l7G8,4536
112
+ troubadix-25.10.9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
113
+ troubadix-25.10.9.dist-info/entry_points.txt,sha256=ETEPBi4fKv3o7hzkzceX4838G6g5_5wRdEddYot8N6A,920
114
+ troubadix-25.10.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
115
+ troubadix-25.10.9.dist-info/RECORD,,