From 09f905cbdca7006597137f9fc2466abebfae578f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Mon, 30 Mar 2026 14:39:29 -0400 Subject: [PATCH 001/184] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 51be1ff60..8d8490736 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -21,19 +21,19 @@ class DirStream(): """ def __init__(self: T, project: VbaProject) -> None: - self.project = project + self._project = project self._include_compat = project.compat def to_bytes(self: T) -> bytes: information = self._load_information() - endien = self.project.endien - cp_name = self.project.codepage_name + endien = self._project.endien + cp_name = self._project.codepage_name pack_symbol = '<' if endien == 'little' else '>' # should be 0xFFFF - cookie_value = self.project.project_cookie + cookie_value = self._project.project_cookie self.project_cookie = IdSizeField(19, 2, cookie_value) - references = self.project.references - modules = self.project.modules + references = self._project.references + modules = self._project.modules output = b'' for record in information: output += record.pack(endien, cp_name) @@ -70,7 +70,7 @@ def _load_information(self: T) -> List: project_name = IdSizeField(4, 10, "VBAProject") docstring = DoubleEncodedString([5, 0x0040], "") helpfile = DoubleEncodedString([6, 0x003D], "") - help_context = IdSizeField(7, 4, 0) + help_context = IdSizeField(7, 4, self._project.help_context_id) lib_flags = IdSizeField(8, 4, 0) version = IdSizeField(9, 4, 0x65BE0257) minor_version = PackedData("H", 17) From afc66642439aa5a8423fe3490ecbb324402d1f8a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Mon, 30 Mar 2026 14:41:23 -0400 Subject: [PATCH 002/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index fde3b35b0..18e01de51 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -12,7 +12,7 @@ class Project: The Project data view for the vbaProject """ def __init__(self: T, project: VbaProject) -> None: - self.project = project + self._project = project # Attributes # A list of attributes and values @@ -27,14 +27,14 @@ def add_attribute(self: T, name: str, value: str) -> None: def __str__(self: T) -> str: # Use \x0D0A line endings. - project = self.project + project = self._project project_id = project.project_id result = [f'ID="{project_id}"'] modules = project.modules for module in modules: result += [module.to_project_module_string()] result += ['Name="VBAProject"'] - result += ['HelpContextID="0"'] + result += ['HelpContextID="' + str(project.help_context_id) + '"'] for name, value in self.attributes.items(): result += [f'{name}="{value}"'] cmg = MsOvbaCrypto.encrypt(project_id, project.protection_state) @@ -56,7 +56,7 @@ def __str__(self: T) -> str: return "\r\n".join(result) + "\r\n" def to_bytes(self: T) -> bytes: - codepage_name = self.project.codepage_name + codepage_name = self._project.codepage_name return bytes(str(self), codepage_name) def write_file(self: T) -> None: From d5c9d2952ef58d34a8ecf06ca1529ff20af60b57 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Mon, 30 Mar 2026 14:42:01 -0400 Subject: [PATCH 003/184] Update vbaProject.py --- src/ms_ovba/vbaProject.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/vbaProject.py b/src/ms_ovba/vbaProject.py index 81bcd5d20..ff631318d 100644 --- a/src/ms_ovba/vbaProject.py +++ b/src/ms_ovba/vbaProject.py @@ -31,6 +31,7 @@ def __init__(self: T) -> None: self._license_records: list[LicenseInfo] = [] # Attributes and values + self.help_context_id = 0 self.attributes: dict[str, str] = {} self._project_cookie = 0xFFFF From a181fe703f498c2de6bfdc8b362993552b59ada1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Mon, 30 Mar 2026 14:43:33 -0400 Subject: [PATCH 004/184] Update test_project.py --- tests/Unit/Views/test_project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index d3c486a0d..c81777353 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -52,6 +52,7 @@ def __init__(self: T) -> None: self.password = b'\x00' self.visibility_state = b'\xFF' self.attributes = {} + self.help_context_id = 0 @unittest.mock.patch('random.randint', NotSoRandom.randint) From e40b368ab6e01e2dc1d026186a6da7948c3dc4e6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 08:14:39 -0400 Subject: [PATCH 005/184] Update project.py --- src/ms_ovba/Views/project.py | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 18e01de51..1aa99f679 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -1,4 +1,5 @@ import binascii +import re from ms_ovba_crypto import MsOvbaCrypto from ms_ovba.vbaProject import VbaProject from typing import TypeVar @@ -63,3 +64,51 @@ def write_file(self: T) -> None: bin_f = open("project.bin", "wb") bin_f.write(self.to_bytes()) bin_f.close() + + def is_valid(self: T, file: str) -> bool: + # get codepage + # verify that characterset is mbcs with the codepage + # verify EOL is eithe \r\n or \n\r + valid = True + lines = file.splitlines(True) + for line in lines + if line[-2:] not in ["\r\n", "\n\r"]: + return False + i = 0 + if not self._valid_project_id_line(lines[i]): + return False + i += 1 + while self._project_item_line(line[i]): + if not self._valid_project_item_line(lines[i]): + return False + i += 1 + if self._help_file_line(lines[i]): + i += 1 + if not self._valid_help_file_line(lines[i]): + return False + if self._exe_line(lines[i]): + i += 1 + if not self._valid_exe_line(lines[i]): + return False + if not self._valid_name_line(lines[i]): + return False + i += 1 + if not self._valid_help_id_line(lines[i]): + return False + i += 1 + return valid + + def _valid_project_id_line(self: T, line) -> bool: + if line[:3] != 'ID="': + return False + if line[26:] != '"'\r\n': + return False + guid = line[4:24] + hd = '[0-9a-fA-F]' + pattern = ( + r'^\{' + hd + '{8}-' + + hd + '{4}-' + hd + '{4}-' + + hd + '{4}-' + hd + r'{12}\}$' + ) + # Use re.fullmatch to ensure the entire string is evaluated + return bool(re.fullmatch(pattern, guid)) From 02570efa179ad14f1a2a8dc4d032f70fbfbc8fe9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 08:54:04 -0400 Subject: [PATCH 006/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1aa99f679..00a7c6921 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -71,7 +71,7 @@ def is_valid(self: T, file: str) -> bool: # verify EOL is eithe \r\n or \n\r valid = True lines = file.splitlines(True) - for line in lines + for line in lines: if line[-2:] not in ["\r\n", "\n\r"]: return False i = 0 From 14a642ca42f14c8da6a506ad92d057ff7cd8f0f3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 09:26:19 -0400 Subject: [PATCH 007/184] Update project.py --- src/ms_ovba/Views/project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 00a7c6921..64dc490c0 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -74,6 +74,7 @@ def is_valid(self: T, file: str) -> bool: for line in lines: if line[-2:] not in ["\r\n", "\n\r"]: return False + lines = file.splitlines(False) i = 0 if not self._valid_project_id_line(lines[i]): return False @@ -101,7 +102,7 @@ def is_valid(self: T, file: str) -> bool: def _valid_project_id_line(self: T, line) -> bool: if line[:3] != 'ID="': return False - if line[26:] != '"'\r\n': + if line[26:] != '"': return False guid = line[4:24] hd = '[0-9a-fA-F]' From 3f776ea6492330803a2832a436a378e76cebcda5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 09:56:58 -0400 Subject: [PATCH 008/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 64dc490c0..9a38232e1 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -99,7 +99,7 @@ def is_valid(self: T, file: str) -> bool: i += 1 return valid - def _valid_project_id_line(self: T, line) -> bool: + def _valid_project_id_line(self: T, line: str) -> bool: if line[:3] != 'ID="': return False if line[26:] != '"': From 864b2f668178d53e835343605341c9751f8bd68e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 10:01:46 -0400 Subject: [PATCH 009/184] Update project.py --- src/ms_ovba/Views/project.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 9a38232e1..1733d7ec7 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -65,25 +65,24 @@ def write_file(self: T) -> None: bin_f.write(self.to_bytes()) bin_f.close() - def is_valid(self: T, file: str) -> bool: + def is_valid(self: T, filename: str) -> bool: # get codepage # verify that characterset is mbcs with the codepage - # verify EOL is eithe \r\n or \n\r - valid = True - lines = file.splitlines(True) - for line in lines: - if line[-2:] not in ["\r\n", "\n\r"]: + + with open(filename, 'r') as file: + for line in file: + if line[-2:] not in ["\r\n", "\n\r"]: + return False + with open(filename, 'r') as file: + line = file.readline().strip() + if not self._valid_project_id_line(line): return False - lines = file.splitlines(False) - i = 0 - if not self._valid_project_id_line(lines[i]): - return False - i += 1 - while self._project_item_line(line[i]): - if not self._valid_project_item_line(lines[i]): - return False - i += 1 - if self._help_file_line(lines[i]): + line = file.readline().strip() + while self._project_item_line(line[i]): + if not self._valid_project_item_line(line): + return False + line = file.readline().strip() + if self._help_file_line(line): i += 1 if not self._valid_help_file_line(lines[i]): return False From 24b874f7b0d67bb721de0a8b3ff975b9dcfbd2e2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 10:17:39 -0400 Subject: [PATCH 010/184] Update project.py --- src/ms_ovba/Views/project.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1733d7ec7..1dc5cb7b4 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -78,25 +78,22 @@ def is_valid(self: T, filename: str) -> bool: if not self._valid_project_id_line(line): return False line = file.readline().strip() - while self._project_item_line(line[i]): + while self._project_item_line(line): if not self._valid_project_item_line(line): return False line = file.readline().strip() if self._help_file_line(line): - i += 1 - if not self._valid_help_file_line(lines[i]): + if not self._valid_help_file_line(line): + return False + if self._exe_line(line): + if not self._valid_exe_line(line): + return False + if not self._valid_name_line(line): return False - if self._exe_line(lines[i]): - i += 1 - if not self._valid_exe_line(lines[i]): + line = file.readline().strip() + if not self._valid_help_id_line(lines[i]): return False - if not self._valid_name_line(lines[i]): - return False - i += 1 - if not self._valid_help_id_line(lines[i]): - return False - i += 1 - return valid + return True def _valid_project_id_line(self: T, line: str) -> bool: if line[:3] != 'ID="': From d1123c8d12ba5ee149aee36b3e5a6c30005b151c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 10:27:05 -0400 Subject: [PATCH 011/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1dc5cb7b4..b1d5ba0ce 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -68,7 +68,7 @@ def write_file(self: T) -> None: def is_valid(self: T, filename: str) -> bool: # get codepage # verify that characterset is mbcs with the codepage - + with open(filename, 'r') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: @@ -91,7 +91,7 @@ def is_valid(self: T, filename: str) -> bool: if not self._valid_name_line(line): return False line = file.readline().strip() - if not self._valid_help_id_line(lines[i]): + if not self._valid_help_id_line(line): return False return True From cf874be398b60fb0eba50ce924741afec6d28d0e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 10:28:01 -0400 Subject: [PATCH 012/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index b1d5ba0ce..1e53c2ee7 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -94,7 +94,7 @@ def is_valid(self: T, filename: str) -> bool: if not self._valid_help_id_line(line): return False return True - + def _valid_project_id_line(self: T, line: str) -> bool: if line[:3] != 'ID="': return False From 46b0774932ea196ca2a82f7fa115f5018459a280 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 10:52:13 -0400 Subject: [PATCH 013/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1e53c2ee7..0d36633cc 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -109,3 +109,7 @@ def _valid_project_id_line(self: T, line: str) -> bool: ) # Use re.fullmatch to ensure the entire string is evaluated return bool(re.fullmatch(pattern, guid)) + + @staticmethod + def _project_item_line(line) -> bool: + From e2194622edc9e98d43d9b35b9fc1ef74d8afa180 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 11:20:34 -0400 Subject: [PATCH 014/184] Update project.py --- src/ms_ovba/Views/project.py | 37 +++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 0d36633cc..97b334489 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -96,11 +96,38 @@ def is_valid(self: T, filename: str) -> bool: return True def _valid_project_id_line(self: T, line: str) -> bool: - if line[:3] != 'ID="': + pieces = line.split('=') + if pieces[0] != 'ID': return False - if line[26:] != '"': + value = pieces[1] + if value[1] != '"' and value[-1] != '"': return False - guid = line[4:24] + return self._valid_guid(value[1:-1]) + + @staticmethod + def _project_item_line(line: str) -> bool: + options = ['Doc', 'Mod', 'Cla', 'Bas', 'Pac'] + return line[:3] in options + + def _valid_project_item_line(line: str) -> bool: + # split at the equalsS + pieces = line.split('=') + # Verify the name. + if pieces[0] == 'Document': + rerurn self._valid_guid(pieces[1]) + elif pieces[0] == 'Package': + pass + elif pieces[0] in ['Module', 'Class', 'BaseClass'] + return self._valid_modulename(pieces[1]) + else: + return False + + @staticmethod + def _valid_modulename(name: str) -> bool: + return len(name) <= 31 + + @staticmethod + def _valid_guid(guid: str) -> bool: hd = '[0-9a-fA-F]' pattern = ( r'^\{' + hd + '{8}-' + @@ -109,7 +136,3 @@ def _valid_project_id_line(self: T, line: str) -> bool: ) # Use re.fullmatch to ensure the entire string is evaluated return bool(re.fullmatch(pattern, guid)) - - @staticmethod - def _project_item_line(line) -> bool: - From 597f83d859280102c611622d4d01023efeec34cf Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 11:22:15 -0400 Subject: [PATCH 015/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 97b334489..524848c13 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -102,7 +102,7 @@ def _valid_project_id_line(self: T, line: str) -> bool: value = pieces[1] if value[1] != '"' and value[-1] != '"': return False - return self._valid_guid(value[1:-1]) + return Project._valid_guid(value[1:-1]) @staticmethod def _project_item_line(line: str) -> bool: @@ -114,7 +114,7 @@ def _valid_project_item_line(line: str) -> bool: pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': - rerurn self._valid_guid(pieces[1]) + rerurn Project._valid_guid(pieces[1]) elif pieces[0] == 'Package': pass elif pieces[0] in ['Module', 'Class', 'BaseClass'] From e67a50239db9e563d09f42042e1d38f7ae8661ac Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 11:32:22 -0400 Subject: [PATCH 016/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 524848c13..ae7d1395a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -102,7 +102,7 @@ def _valid_project_id_line(self: T, line: str) -> bool: value = pieces[1] if value[1] != '"' and value[-1] != '"': return False - return Project._valid_guid(value[1:-1]) + return self._valid_guid(value[1:-1]) @staticmethod def _project_item_line(line: str) -> bool: @@ -114,7 +114,7 @@ def _valid_project_item_line(line: str) -> bool: pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': - rerurn Project._valid_guid(pieces[1]) + return self._valid_guid(pieces[1]) elif pieces[0] == 'Package': pass elif pieces[0] in ['Module', 'Class', 'BaseClass'] From df2db42254bb6d67fbf30f02d785e1382eb983ae Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 11:36:03 -0400 Subject: [PATCH 017/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index ae7d1395a..e17e33696 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -117,7 +117,7 @@ def _valid_project_item_line(line: str) -> bool: return self._valid_guid(pieces[1]) elif pieces[0] == 'Package': pass - elif pieces[0] in ['Module', 'Class', 'BaseClass'] + elif pieces[0] in ['Module', 'Class', 'BaseClass']: return self._valid_modulename(pieces[1]) else: return False From fdbad538e753e847ea2d9b25bfd55b15a4e11c79 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 11:43:39 -0400 Subject: [PATCH 018/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index e17e33696..ad2b879e3 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -103,13 +103,13 @@ def _valid_project_id_line(self: T, line: str) -> bool: if value[1] != '"' and value[-1] != '"': return False return self._valid_guid(value[1:-1]) - + @staticmethod def _project_item_line(line: str) -> bool: options = ['Doc', 'Mod', 'Cla', 'Bas', 'Pac'] return line[:3] in options - def _valid_project_item_line(line: str) -> bool: + def _valid_project_item_line(self: T, line: str) -> bool: # split at the equalsS pieces = line.split('=') # Verify the name. From dcc71b8633c9594a2c5bb0789d7a7d341e09c085 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:34:25 -0400 Subject: [PATCH 019/184] Update project.py --- src/ms_ovba/Views/project.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index ad2b879e3..d2099fc7a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -109,8 +109,12 @@ def _project_item_line(line: str) -> bool: options = ['Doc', 'Mod', 'Cla', 'Bas', 'Pac'] return line[:3] in options + @staticmethod + def _help_file_line(line: str) -> bool: + return line[0:5] == 'HelpF' + def _valid_project_item_line(self: T, line: str) -> bool: - # split at the equalsS + # Split at the equals. pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': @@ -118,10 +122,19 @@ def _valid_project_item_line(self: T, line: str) -> bool: elif pieces[0] == 'Package': pass elif pieces[0] in ['Module', 'Class', 'BaseClass']: + # ToDo: append name to an array for validation + # against dir-stream return self._valid_modulename(pieces[1]) else: return False + @staticmethod + def _valid_help_file_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "HelpFile": + return self._valid_path(pieces[1]) + return False + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 @@ -136,3 +149,17 @@ def _valid_guid(guid: str) -> bool: ) # Use re.fullmatch to ensure the entire string is evaluated return bool(re.fullmatch(pattern, guid)) + + @staticmethod + def _valid_path(path: str) -> bool: + # 259 is max plus two double quotes + if len(path) > 261: + return False + if path[1] != '"' and path[-1] != '"': + return False + path = path[1:-1] + # Dquot must be paired + path.replace('""', " ") + path.replace('\t', " ") + path.replace('"', '\x19') + return all( 32 <= ord(char) <= 255 for char in path) From 295b3261727c91e445ad04bd39f12de3e3345085 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:35:49 -0400 Subject: [PATCH 020/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index d2099fc7a..f1532fe68 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -132,9 +132,9 @@ def _valid_project_item_line(self: T, line: str) -> bool: def _valid_help_file_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "HelpFile": - return self._valid_path(pieces[1]) + return Project._valid_path(pieces[1]) return False - + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 From 8fe09fe3bfa6df60d5d68ec78ce32c2368b3017e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:37:03 -0400 Subject: [PATCH 021/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index f1532fe68..8be48a1a6 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -162,4 +162,4 @@ def _valid_path(path: str) -> bool: path.replace('""', " ") path.replace('\t', " ") path.replace('"', '\x19') - return all( 32 <= ord(char) <= 255 for char in path) + return all(32 <= ord(char) <= 255 for char in path) From 79562f3ef787c207e4e02551eab22ba29f3c85ea Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:40:51 -0400 Subject: [PATCH 022/184] Update project.py --- src/ms_ovba/Views/project.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8be48a1a6..08af0defc 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -113,6 +113,10 @@ def _project_item_line(line: str) -> bool: def _help_file_line(line: str) -> bool: return line[0:5] == 'HelpF' + @staticmethod + def _exe_line(line: str) -> bool: + return line[0:3] == 'Exe' + def _valid_project_item_line(self: T, line: str) -> bool: # Split at the equals. pieces = line.split('=') @@ -135,6 +139,13 @@ def _valid_help_file_line(line: str) -> bool: return Project._valid_path(pieces[1]) return False + @staticmethod + def _valid_exe_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "ExeName32": + return Project._valid_path(pieces[1]) + return False + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 From 283ba8945fb9612ad9c31fb04ca394340bf309c4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:55:26 -0400 Subject: [PATCH 023/184] Update project.py --- src/ms_ovba/Views/project.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 08af0defc..3a838fac9 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -146,6 +146,12 @@ def _valid_exe_line(line: str) -> bool: return Project._valid_path(pieces[1]) return False + def _valid_name_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "Name": + return Project._valid_quoted_string(path, 1, 128) + return False + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 @@ -163,14 +169,17 @@ def _valid_guid(guid: str) -> bool: @staticmethod def _valid_path(path: str) -> bool: - # 259 is max plus two double quotes - if len(path) > 261: + return Project._valid_quoted_string(path, 0, 259) + + @staticmethod + def _valid_quoted_string(string: str, min: int, max: int) -> bool: + if not (min + 2 <= len(path) <= max + 2): return False - if path[1] != '"' and path[-1] != '"': + if string[1] != '"' and string[-1] != '"': return False - path = path[1:-1] + string = string[1:-1] # Dquot must be paired - path.replace('""', " ") - path.replace('\t', " ") - path.replace('"', '\x19') - return all(32 <= ord(char) <= 255 for char in path) + string.replace('""', " ") + string.replace('\t', " ") + string.replace('"', '\x19') + return all(32 <= ord(char) <= 255 for char in string) From e678102ae7f7ccfc25d67bdace401906ee58d1a1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:57:50 -0400 Subject: [PATCH 024/184] Update project.py --- src/ms_ovba/Views/project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 3a838fac9..c04cbfeba 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -146,10 +146,11 @@ def _valid_exe_line(line: str) -> bool: return Project._valid_path(pieces[1]) return False + @staticmethod def _valid_name_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "Name": - return Project._valid_quoted_string(path, 1, 128) + return Project._valid_quoted_string(piece[1], 1, 128) return False @staticmethod From 65832a4a3562fe7ff7b945ff536648bdd3f7dcc8 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 12:58:16 -0400 Subject: [PATCH 025/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index c04cbfeba..bba5bef14 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -152,7 +152,7 @@ def _valid_name_line(line: str) -> bool: if pieces[0] == "Name": return Project._valid_quoted_string(piece[1], 1, 128) return False - + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 From cd26b7752ceb153fd48ec41cf472b07f20f283d6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:00:56 -0400 Subject: [PATCH 026/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index bba5bef14..92149d6d9 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -150,7 +150,7 @@ def _valid_exe_line(line: str) -> bool: def _valid_name_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "Name": - return Project._valid_quoted_string(piece[1], 1, 128) + return Project._valid_quoted_string(pieces[1], 1, 128) return False @staticmethod @@ -174,7 +174,7 @@ def _valid_path(path: str) -> bool: @staticmethod def _valid_quoted_string(string: str, min: int, max: int) -> bool: - if not (min + 2 <= len(path) <= max + 2): + if not (min + 2 <= len(string) <= max + 2): return False if string[1] != '"' and string[-1] != '"': return False From 652557b4003be7cb7971e79f0533b629faa65744 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:13:46 -0400 Subject: [PATCH 027/184] Update project.py --- src/ms_ovba/Views/project.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 92149d6d9..700f617d8 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -153,6 +153,22 @@ def _valid_name_line(line: str) -> bool: return Project._valid_quoted_string(pieces[1], 1, 128) return False + @staticmethod + def _valid_help_id_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "HelpContextID": + string = pieces[1] + if string[1] != '"' and string[-1] != '"': + return False + candidate = string[1:-1] + try: + int(candidate) + return True + except ValueError: + return False + return False + + # Data Type Validators @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 From 83b1eae663fd4916342c1c9bc70ef2f6923573fd Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:15:44 -0400 Subject: [PATCH 028/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 700f617d8..07a17243b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -100,7 +100,7 @@ def _valid_project_id_line(self: T, line: str) -> bool: if pieces[0] != 'ID': return False value = pieces[1] - if value[1] != '"' and value[-1] != '"': + if value[1] != '"' or value[-1] != '"': return False return self._valid_guid(value[1:-1]) @@ -158,8 +158,8 @@ def _valid_help_id_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "HelpContextID": string = pieces[1] - if string[1] != '"' and string[-1] != '"': - return False + if string[1] != '"' or string[-1] != '"': + return False candidate = string[1:-1] try: int(candidate) @@ -192,7 +192,7 @@ def _valid_path(path: str) -> bool: def _valid_quoted_string(string: str, min: int, max: int) -> bool: if not (min + 2 <= len(string) <= max + 2): return False - if string[1] != '"' and string[-1] != '"': + if string[1] != '"' or string[-1] != '"': return False string = string[1:-1] # Dquot must be paired From 2363f4f00f3bec112956480b24d3ec84cfa553af Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:16:33 -0400 Subject: [PATCH 029/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 07a17243b..1f0514425 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -167,7 +167,7 @@ def _valid_help_id_line(line: str) -> bool: except ValueError: return False return False - + # Data Type Validators @staticmethod def _valid_modulename(name: str) -> bool: From fc60a5dcd8bd0ef6c146e5e95c2625125dd47e11 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:18:20 -0400 Subject: [PATCH 030/184] Update project.py --- src/ms_ovba/Views/project.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1f0514425..8a56226a6 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -129,8 +129,7 @@ def _valid_project_item_line(self: T, line: str) -> bool: # ToDo: append name to an array for validation # against dir-stream return self._valid_modulename(pieces[1]) - else: - return False + return False @staticmethod def _valid_help_file_line(line: str) -> bool: From d07ffe1d9a446a9b1ef9a7665f0638f197f16bc3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:31:55 -0400 Subject: [PATCH 031/184] Update test_fullFile.py --- tests/Functional/test_fullFile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Functional/test_fullFile.py b/tests/Functional/test_fullFile.py index 109743429..58ddec2f9 100644 --- a/tests/Functional/test_fullFile.py +++ b/tests/Functional/test_fullFile.py @@ -321,6 +321,7 @@ def create_cache(proj_cookie: int, modules: list) -> bytes: def create_doc_module(project: VbaProject, name: str, cookie: int, guid_s: str, path: str) -> DocModule: mod = DocModule(name) + mod.add_workspace(0, 0, 0, 0, 'C') mod.cookie = cookie guid = uuid.UUID(guid_s) mod.add_guid(guid) From 7b2ecf2e73d5d3bcc2592796fff69bf670daac01 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:35:52 -0400 Subject: [PATCH 032/184] Update module_base.py --- src/ms_ovba/Models/Entities/module_base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Models/Entities/module_base.py b/src/ms_ovba/Models/Entities/module_base.py index 1f8d734e5..8aad9c9a3 100644 --- a/src/ms_ovba/Models/Entities/module_base.py +++ b/src/ms_ovba/Models/Entities/module_base.py @@ -4,7 +4,7 @@ ) from ms_ovba.Models.Fields.packed_data import PackedData from ms_ovba.Models.Fields.idSizeField import IdSizeField -from typing import TypeVar +from typing import Literal, TypeVar T = TypeVar('T', bound='ModuleBase') @@ -24,7 +24,7 @@ def __init__(self: T, name: str) -> None: # self.readonly = SimpleRecord(0x001E, 4, helpContext) # self.private = SimpleRecord(0x001E, 4, helpContext) self._cache = b'' - self.workspace = [0, 0, 0, 0, 'C'] + self.workspace: tuple[int, int, int, int, Literal['C', 'I', 'Z']] self.type = '' self.created = 0 self.modified = 0 @@ -77,7 +77,7 @@ def bin_path(self: T) -> str: def add_workspace(self: T, val1: int, val2: int, val3: int, val4: int, val5: int) -> None: - self.workspace = [val1, val2, val3, val4, val5] + self.workspace = (val1, val2, val3, val4, val5) def pack(self: T, endien: str, cp_name: str) -> bytes: """ From 9b94737686e435ca97b79aba7b9c8975423957ad Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:38:54 -0400 Subject: [PATCH 033/184] Update project.py --- src/ms_ovba/Views/project.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8a56226a6..a005f146b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -47,13 +47,17 @@ def __str__(self: T) -> str: result += [''] result += ['[Host Extender Info]'] result += [self.hostExtenderInfo] - result += [''] - result += ['[Workspace]'] + workspace_started = False + for module in modules: - separator = ", " - joined = module.modName.value + '=' - joined += separator.join(map(str, module.workspace)) - result += [joined] + if module.workspace is not None: + if not workspace_started: + result += [''] + result += ['[Workspace]'] + separator = ", " + joined = module.modName.value + '=' + joined += separator.join(map(str, module.workspace)) + result += [joined] return "\r\n".join(result) + "\r\n" def to_bytes(self: T) -> bytes: From 90f7dbced439b28a485f04ce758a5e328bfd06c7 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:39:55 -0400 Subject: [PATCH 034/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a005f146b..0dafdfd10 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -48,7 +48,7 @@ def __str__(self: T) -> str: result += ['[Host Extender Info]'] result += [self.hostExtenderInfo] workspace_started = False - + for module in modules: if module.workspace is not None: if not workspace_started: From a766ef5d6ded0e0e3470711539a61c50020c2c19 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:43:16 -0400 Subject: [PATCH 035/184] Update module_base.py --- src/ms_ovba/Models/Entities/module_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/module_base.py b/src/ms_ovba/Models/Entities/module_base.py index 8aad9c9a3..6064cf8c3 100644 --- a/src/ms_ovba/Models/Entities/module_base.py +++ b/src/ms_ovba/Models/Entities/module_base.py @@ -76,7 +76,7 @@ def bin_path(self: T) -> str: return self._file_path + ".bin" def add_workspace(self: T, val1: int, val2: int, - val3: int, val4: int, val5: int) -> None: + val3: int, val4: int, val5: Literal['C', 'I', 'Z']) -> None: self.workspace = (val1, val2, val3, val4, val5) def pack(self: T, endien: str, cp_name: str) -> bytes: From 0cd72ffc84b182ae6f85f0ab2ab59ad4219c8060 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:44:28 -0400 Subject: [PATCH 036/184] Update module_base.py --- src/ms_ovba/Models/Entities/module_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/module_base.py b/src/ms_ovba/Models/Entities/module_base.py index 6064cf8c3..9ad4d059b 100644 --- a/src/ms_ovba/Models/Entities/module_base.py +++ b/src/ms_ovba/Models/Entities/module_base.py @@ -76,7 +76,8 @@ def bin_path(self: T) -> str: return self._file_path + ".bin" def add_workspace(self: T, val1: int, val2: int, - val3: int, val4: int, val5: Literal['C', 'I', 'Z']) -> None: + val3: int, val4: int, val5: Literal['C', 'I', 'Z'] + ) -> None: self.workspace = (val1, val2, val3, val4, val5) def pack(self: T, endien: str, cp_name: str) -> bytes: From 67b240e5f3d96817650eae4c5c8f439e3287fc2c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:49:17 -0400 Subject: [PATCH 037/184] Update module_base.py --- src/ms_ovba/Models/Entities/module_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Models/Entities/module_base.py b/src/ms_ovba/Models/Entities/module_base.py index 9ad4d059b..82dd6f691 100644 --- a/src/ms_ovba/Models/Entities/module_base.py +++ b/src/ms_ovba/Models/Entities/module_base.py @@ -76,8 +76,8 @@ def bin_path(self: T) -> str: return self._file_path + ".bin" def add_workspace(self: T, val1: int, val2: int, - val3: int, val4: int, val5: Literal['C', 'I', 'Z'] - ) -> None: + val3: int, val4: int, + val5: Literal['C', 'I', 'Z']) -> None: self.workspace = (val1, val2, val3, val4, val5) def pack(self: T, endien: str, cp_name: str) -> bytes: From c2210ea8acaff155bd6c8ac026e9efd2f88659a1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:51:19 -0400 Subject: [PATCH 038/184] Update project.py --- src/ms_ovba/Views/project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 0dafdfd10..a91badbb1 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -52,6 +52,7 @@ def __str__(self: T) -> str: for module in modules: if module.workspace is not None: if not workspace_started: + workspace_started = True result += [''] result += ['[Workspace]'] separator = ", " From 70ca2c5a49db7015ff7d0f2a7d2f25c255777c02 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 13:56:57 -0400 Subject: [PATCH 039/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index c81777353..e56e4be68 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -73,3 +73,8 @@ def test_blank() -> None: expected += file.read(0x0152) assert project.to_bytes() == expected + + +def test_valid() -> None: + path = 'tests/blank/PROJECT' + assert Project.is_valid(path) From 96c992a8b1bb43d15f60f0c9eafc4b492c787dee Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:00:51 -0400 Subject: [PATCH 040/184] Update project.py --- src/ms_ovba/Views/project.py | 39 ++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a91badbb1..9422d0cd1 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -70,9 +70,12 @@ def write_file(self: T) -> None: bin_f.write(self.to_bytes()) bin_f.close() - def is_valid(self: T, filename: str) -> bool: - # get codepage - # verify that characterset is mbcs with the codepage + @staticmethod + def is_valid(filename: str) -> bool: + """ + Validate the structure of the file. This method does + not test if data values match between streams. + """ with open(filename, 'r') as file: for line in file: @@ -80,34 +83,35 @@ def is_valid(self: T, filename: str) -> bool: return False with open(filename, 'r') as file: line = file.readline().strip() - if not self._valid_project_id_line(line): + if not Project._valid_project_id_line(line): return False line = file.readline().strip() - while self._project_item_line(line): - if not self._valid_project_item_line(line): + while Project._project_item_line(line): + if not Project._valid_project_item_line(line): return False line = file.readline().strip() - if self._help_file_line(line): - if not self._valid_help_file_line(line): + if Project._help_file_line(line): + if not Project._valid_help_file_line(line): return False - if self._exe_line(line): - if not self._valid_exe_line(line): + if Project._exe_line(line): + if not Project._valid_exe_line(line): return False - if not self._valid_name_line(line): + if not Project._valid_name_line(line): return False line = file.readline().strip() - if not self._valid_help_id_line(line): + if not Project._valid_help_id_line(line): return False return True - def _valid_project_id_line(self: T, line: str) -> bool: + @staticmethod + def _valid_project_id_line(line: str) -> bool: pieces = line.split('=') if pieces[0] != 'ID': return False value = pieces[1] if value[1] != '"' or value[-1] != '"': return False - return self._valid_guid(value[1:-1]) + return Project._valid_guid(value[1:-1]) @staticmethod def _project_item_line(line: str) -> bool: @@ -122,18 +126,19 @@ def _help_file_line(line: str) -> bool: def _exe_line(line: str) -> bool: return line[0:3] == 'Exe' - def _valid_project_item_line(self: T, line: str) -> bool: + @staticmethod + def _valid_project_item_line(line: str) -> bool: # Split at the equals. pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': - return self._valid_guid(pieces[1]) + return Project._valid_guid(pieces[1]) elif pieces[0] == 'Package': pass elif pieces[0] in ['Module', 'Class', 'BaseClass']: # ToDo: append name to an array for validation # against dir-stream - return self._valid_modulename(pieces[1]) + return Project._valid_modulename(pieces[1]) return False @staticmethod From 23aa3400664c35214af6a5f1dad6f2daa1c13c6d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:04:11 -0400 Subject: [PATCH 041/184] Update project.py --- src/ms_ovba/Views/project.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 9422d0cd1..8943b154b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -2,7 +2,7 @@ import re from ms_ovba_crypto import MsOvbaCrypto from ms_ovba.vbaProject import VbaProject -from typing import TypeVar +from typing import Any, TypeVar T = TypeVar('T', bound='Project') @@ -71,7 +71,7 @@ def write_file(self: T) -> None: bin_f.close() @staticmethod - def is_valid(filename: str) -> bool: + def is_valid(filename: str) -> Any: """ Validate the structure of the file. This method does not test if data values match between streams. @@ -80,27 +80,27 @@ def is_valid(filename: str) -> bool: with open(filename, 'r') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return False + return 1 with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): - return False + return 2 line = file.readline().strip() while Project._project_item_line(line): if not Project._valid_project_item_line(line): - return False + return 3 line = file.readline().strip() if Project._help_file_line(line): if not Project._valid_help_file_line(line): - return False + return 4 if Project._exe_line(line): if not Project._valid_exe_line(line): - return False + return 5 if not Project._valid_name_line(line): - return False + return 6 line = file.readline().strip() if not Project._valid_help_id_line(line): - return False + return 7 return True @staticmethod From ee848aaf53b65ddffed5c47b43d4d97ee58e6474 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:06:15 -0400 Subject: [PATCH 042/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8943b154b..5e4780e90 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -101,7 +101,7 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() if not Project._valid_help_id_line(line): return 7 - return True + return 0 @staticmethod def _valid_project_id_line(line: str) -> bool: From b4fcb8472ad5eae5624eb6729aba2bef5c2c197a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:06:35 -0400 Subject: [PATCH 043/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index e56e4be68..70a9d015c 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -77,4 +77,4 @@ def test_blank() -> None: def test_valid() -> None: path = 'tests/blank/PROJECT' - assert Project.is_valid(path) + assert Project.is_valid(path) == 0 From 976f80f51c469ed5a9538332075a16f9c4f31081 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:09:00 -0400 Subject: [PATCH 044/184] CRLF --- tests/blank/PROJECT | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/blank/PROJECT b/tests/blank/PROJECT index 38b200edd..f90b6a608 100644 --- a/tests/blank/PROJECT +++ b/tests/blank/PROJECT @@ -1,18 +1,18 @@ -ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" -Document=ThisWorkbook/&H00000000 -Document=Sheet1/&H00000000 -Module=Module1 -Name="VBAProject" -HelpContextID="0" -VersionCompatible32="393222000" -CMG="41435A5A5E5A5E5A5E5A5E" -DPB="BCBEA7A2591C5A1C5A1C" -GC="37352C2BDCDD56DE56DEA9" - -[HostExtender Info] -&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 - -[Workspace] -ThisWorkbook=0, 0, 0, 0, C -Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z From af0ddd74e0f89a75f668f637743f968c90291274 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:12:48 -0400 Subject: [PATCH 045/184] Update project.py --- src/ms_ovba/Views/project.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 5e4780e90..f2bf0318a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -78,9 +78,11 @@ def is_valid(filename: str) -> Any: """ with open(filename, 'r') as file: + i = 1 for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return 1 + return i + i += 1 with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): From c5f43a1e0172730616da64668c5088c01a992750 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:16:05 -0400 Subject: [PATCH 046/184] Update project.py --- src/ms_ovba/Views/project.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index f2bf0318a..3b4cab44a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -78,11 +78,9 @@ def is_valid(filename: str) -> Any: """ with open(filename, 'r') as file: - i = 1 for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return i - i += 1 + return line[-2:].encode("utf-8") with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): From f880ff62a629fab1e247ee5db9b570b33784e4f8 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:20:43 -0400 Subject: [PATCH 047/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 3b4cab44a..a272eec0c 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -77,7 +77,7 @@ def is_valid(filename: str) -> Any: not test if data values match between streams. """ - with open(filename, 'r') as file: + with open(filename, 'r', newline='') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: return line[-2:].encode("utf-8") From ecb04e03e0248c9b164eefa18f3190fbd702d444 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:23:27 -0400 Subject: [PATCH 048/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a272eec0c..325d60a17 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -80,7 +80,7 @@ def is_valid(filename: str) -> Any: with open(filename, 'r', newline='') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return line[-2:].encode("utf-8") + return False with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): From b13f64ccc2613ad448b5ded331717b15faabcc29 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:29:19 -0400 Subject: [PATCH 049/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 70a9d015c..1fd26bf6e 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -75,6 +75,11 @@ def test_blank() -> None: assert project.to_bytes() == expected +def test_guid_valid() -> None: + guid = "{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" + assert Project._valid_guid(guid) + + def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) == 0 From b5172c45d55f81816024357d09577e2ab02b17d6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:31:59 -0400 Subject: [PATCH 050/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 1fd26bf6e..a43ad63ce 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -80,6 +80,11 @@ def test_guid_valid() -> None: assert Project._valid_guid(guid) +def test_project_line_valid() -> None: + line = 'ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}"' + assert Project._valid_project_id_line(line) + + def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) == 0 From a485704a62bacd0f3346ef423dfabf9ef69cf192 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:33:48 -0400 Subject: [PATCH 051/184] Update project.py --- src/ms_ovba/Views/project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 325d60a17..cc5cbdc4a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -104,13 +104,13 @@ def is_valid(filename: str) -> Any: return 0 @staticmethod - def _valid_project_id_line(line: str) -> bool: + def _valid_project_id_line(line: str) -> Any: pieces = line.split('=') if pieces[0] != 'ID': - return False + return 1 value = pieces[1] if value[1] != '"' or value[-1] != '"': - return False + return 2 return Project._valid_guid(value[1:-1]) @staticmethod From a48bea7c2d262de5148ae0ceb118bc0e851501e3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:34:11 -0400 Subject: [PATCH 052/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index a43ad63ce..5c93f0d49 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -82,7 +82,7 @@ def test_guid_valid() -> None: def test_project_line_valid() -> None: line = 'ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}"' - assert Project._valid_project_id_line(line) + assert Project._valid_project_id_line(line) == 0 def test_valid() -> None: From 760dbf04fa4fd6c3819045cf06cdad3d4a26259f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:36:36 -0400 Subject: [PATCH 053/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index cc5cbdc4a..2ef3222a1 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -84,7 +84,7 @@ def is_valid(filename: str) -> Any: with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): - return 2 + return False line = file.readline().strip() while Project._project_item_line(line): if not Project._valid_project_item_line(line): From 018e58830ec1d229f69913e36390d6320056170c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:37:45 -0400 Subject: [PATCH 054/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 2ef3222a1..8c19de064 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -107,10 +107,10 @@ def is_valid(filename: str) -> Any: def _valid_project_id_line(line: str) -> Any: pieces = line.split('=') if pieces[0] != 'ID': - return 1 + return False value = pieces[1] - if value[1] != '"' or value[-1] != '"': - return 2 + if value[0] != '"' or value[-1] != '"': + return False return Project._valid_guid(value[1:-1]) @staticmethod @@ -167,7 +167,7 @@ def _valid_help_id_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "HelpContextID": string = pieces[1] - if string[1] != '"' or string[-1] != '"': + if string[0] != '"' or string[-1] != '"': return False candidate = string[1:-1] try: From d6fb5d547155a15dad8f29e993003e8dd66ad06e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:38:57 -0400 Subject: [PATCH 055/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8c19de064..a4b20e9e6 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -201,7 +201,7 @@ def _valid_path(path: str) -> bool: def _valid_quoted_string(string: str, min: int, max: int) -> bool: if not (min + 2 <= len(string) <= max + 2): return False - if string[1] != '"' or string[-1] != '"': + if string[0] != '"' or string[-1] != '"': return False string = string[1:-1] # Dquot must be paired From 4d8b02f809c5017999220789ce5287469cf16ab2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:39:30 -0400 Subject: [PATCH 056/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 5c93f0d49..a43ad63ce 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -82,7 +82,7 @@ def test_guid_valid() -> None: def test_project_line_valid() -> None: line = 'ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}"' - assert Project._valid_project_id_line(line) == 0 + assert Project._valid_project_id_line(line) def test_valid() -> None: From 2b5f9b4615ea520122c16492a5d52a5be4e1d2be Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:47:59 -0400 Subject: [PATCH 057/184] Update project.py --- src/ms_ovba/Views/project.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a4b20e9e6..4802fa451 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -132,7 +132,11 @@ def _valid_project_item_line(line: str) -> bool: pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': - return Project._valid_guid(pieces[1]) + doc_string = pieces[1].split('/') + return ( + Project._valid_modulename(doc_string[0]) and + Project._valid_hex(doc_string[1]) + ) elif pieces[0] == 'Package': pass elif pieces[0] in ['Module', 'Class', 'BaseClass']: @@ -178,6 +182,10 @@ def _valid_help_id_line(line: str) -> bool: return False # Data Type Validators + @staticmethod + def _valid_hex(hex: str) -> bool: + pass + @staticmethod def _valid_modulename(name: str) -> bool: return len(name) <= 31 From 2e0d242d8732a95814ce35ccc796198310178a8b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 14:49:11 -0400 Subject: [PATCH 058/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 4802fa451..05b120654 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -184,7 +184,7 @@ def _valid_help_id_line(line: str) -> bool: # Data Type Validators @staticmethod def _valid_hex(hex: str) -> bool: - pass + return hex[:2] == "&H" @staticmethod def _valid_modulename(name: str) -> bool: From 27b8b10af3af8797be6009bdc082afbf2ba4f590 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:00:40 -0400 Subject: [PATCH 059/184] Update project.py --- src/ms_ovba/Views/project.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 05b120654..6cf86c560 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -88,20 +88,20 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() while Project._project_item_line(line): if not Project._valid_project_item_line(line): - return 3 + return False line = file.readline().strip() if Project._help_file_line(line): if not Project._valid_help_file_line(line): - return 4 + return False if Project._exe_line(line): if not Project._valid_exe_line(line): - return 5 + return False if not Project._valid_name_line(line): - return 6 + return False line = file.readline().strip() if not Project._valid_help_id_line(line): - return 7 - return 0 + return False + return True @staticmethod def _valid_project_id_line(line: str) -> Any: @@ -183,8 +183,12 @@ def _valid_help_id_line(line: str) -> bool: # Data Type Validators @staticmethod - def _valid_hex(hex: str) -> bool: - return hex[:2] == "&H" + def _valid_hex32(hex: str) -> bool: + prefix = hex[:2] + value = int(hex[2:], 16) + min = -2147483648 + max = 2147483647 + return prefix == "&H" and (min <= value <= max) @staticmethod def _valid_modulename(name: str) -> bool: From 3c57e3ce3b43ff69ab050513a3e05d0b1ac477b4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:01:48 -0400 Subject: [PATCH 060/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 6cf86c560..086fbfa59 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -135,7 +135,7 @@ def _valid_project_item_line(line: str) -> bool: doc_string = pieces[1].split('/') return ( Project._valid_modulename(doc_string[0]) and - Project._valid_hex(doc_string[1]) + Project._valid_hex32(doc_string[1]) ) elif pieces[0] == 'Package': pass From d90ec7cbc8c8ee8c9b4eacafa0bb32e90e1a8a34 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:03:00 -0400 Subject: [PATCH 061/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index a43ad63ce..d0767ac9c 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -87,4 +87,4 @@ def test_project_line_valid() -> None: def test_valid() -> None: path = 'tests/blank/PROJECT' - assert Project.is_valid(path) == 0 + assert Project.is_valid(path) From d81f64c59de01109f141ce6f4dfe8684e1fb1e39 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:04:06 -0400 Subject: [PATCH 062/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index d0767ac9c..eb65cf6ad 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -80,6 +80,11 @@ def test_guid_valid() -> None: assert Project._valid_guid(guid) +def test_guid_invalid() -> None: + guid = "{9E394C0Z-697E-4AEE-9FA6-446F51FB30DC}" + assert not Project._valid_guid(guid) + + def test_project_line_valid() -> None: line = 'ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}"' assert Project._valid_project_id_line(line) From 87c8de7b69d9142b388af2a662e4c63158612810 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:04:50 -0400 Subject: [PATCH 063/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index eb65cf6ad..5a77ef5c2 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -90,6 +90,11 @@ def test_project_line_valid() -> None: assert Project._valid_project_id_line(line) +def test_project_line_invalid() -> None: + line = 'ID={9E394C0B-697E-4AEE-9FA6-446F51FB30DC}' + assert not Project._valid_project_id_line(line) + + def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) From ce57fd47e780fb5054ee1478dbf09ca6764100b5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 15:16:30 -0400 Subject: [PATCH 064/184] Update project.py --- src/ms_ovba/Views/project.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 086fbfa59..edd9eb2be 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -93,14 +93,37 @@ def is_valid(filename: str) -> Any: if Project._help_file_line(line): if not Project._valid_help_file_line(line): return False + line = file.readline().strip() if Project._exe_line(line): if not Project._valid_exe_line(line): return False + line = file.readline().strip() if not Project._valid_name_line(line): return False line = file.readline().strip() if not Project._valid_help_id_line(line): return False + line = file.readline().strip() + # if Project._description_line(line): + # if not Project._valid_description_line(line): + # return False + # line = file.readline().strip() + # if Project._version_line(line): + # if not Project._valid_version_line(line): + # return False + # line = file.readline().strip() + # if not Project._valid_protection_line(line): + # return False + # line = file.readline().strip() + # if not Project._valid_password_line(line): + # return False + # line = file.readline().strip() + # if not Project._valid_visibility_line(line): + # return False + # line = file.readline().strip() + # if line != "": + # return False + return True @staticmethod From 28f0ad63e7e9d1ccae8717f692480dcc0678fb47 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 16:50:23 -0400 Subject: [PATCH 065/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index edd9eb2be..3bd37271f 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -123,7 +123,7 @@ def is_valid(filename: str) -> Any: # line = file.readline().strip() # if line != "": # return False - + return True @staticmethod From ac4ed76cb75b828d66f912bfd8bf649c126d17e3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 16:55:16 -0400 Subject: [PATCH 066/184] Update project.py --- src/ms_ovba/Views/project.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 3bd37271f..958d3dff3 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -104,10 +104,10 @@ def is_valid(filename: str) -> Any: if not Project._valid_help_id_line(line): return False line = file.readline().strip() - # if Project._description_line(line): - # if not Project._valid_description_line(line): - # return False - # line = file.readline().strip() + if Project._description_line(line): + if not Project._valid_description_line(line): + return False + line = file.readline().strip() # if Project._version_line(line): # if not Project._valid_version_line(line): # return False @@ -149,6 +149,10 @@ def _help_file_line(line: str) -> bool: def _exe_line(line: str) -> bool: return line[0:3] == 'Exe' + @staticmethod + def _description_line(line: str) -> bool: + return line[0:3] == 'Des' + @staticmethod def _valid_project_item_line(line: str) -> bool: # Split at the equals. @@ -204,6 +208,13 @@ def _valid_help_id_line(line: str) -> bool: return False return False + @staticmethod + def _valid_description_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "Description": + return Project._valid_quoted_string(pieces[1], 0, 2000) + return False + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From f4eb07da7f0d50d3757fa8878eab983b98fa47fc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 16:57:14 -0400 Subject: [PATCH 067/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 958d3dff3..27c904535 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -153,6 +153,10 @@ def _exe_line(line: str) -> bool: def _description_line(line: str) -> bool: return line[0:3] == 'Des' + @staticmethod + def _version_line(line: str) -> bool: + return line[0:3] == 'Ver' + @staticmethod def _valid_project_item_line(line: str) -> bool: # Split at the equals. From cfed947c482b0666202e2fad5742311b3143c5e5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 17:02:11 -0400 Subject: [PATCH 068/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 27c904535..458efff2f 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -123,7 +123,7 @@ def is_valid(filename: str) -> Any: # line = file.readline().strip() # if line != "": # return False - + return True @staticmethod @@ -218,7 +218,7 @@ def _valid_description_line(line: str) -> bool: if pieces[0] == "Description": return Project._valid_quoted_string(pieces[1], 0, 2000) return False - + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 562167dbfb5a2c3c76a70ed26fdaa5accbb45d91 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 17:14:42 -0400 Subject: [PATCH 069/184] Update project.py --- src/ms_ovba/Views/project.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 458efff2f..df4c6643a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -219,6 +219,13 @@ def _valid_description_line(line: str) -> bool: return Project._valid_quoted_string(pieces[1], 0, 2000) return False + @staticmethod + def _valid_version_line(line) -> bool: + pieces = line.split('=') + if pieces[0] == "VersionCompatible32": + return Project._valid_quoted_string(pieces[1], 0, 2000) + return False + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 467fb60013f22d58cadba0b8da4648ec814a2e6a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 17:20:59 -0400 Subject: [PATCH 070/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index df4c6643a..cf973e691 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -223,7 +223,7 @@ def _valid_description_line(line: str) -> bool: def _valid_version_line(line) -> bool: pieces = line.split('=') if pieces[0] == "VersionCompatible32": - return Project._valid_quoted_string(pieces[1], 0, 2000) + return pieces[1] == '"393222000"' return False # Data Type Validators From 965547e8b8e520acd19eca629ece403e3add38fa Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 17:24:05 -0400 Subject: [PATCH 071/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index cf973e691..48142bfda 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -108,10 +108,10 @@ def is_valid(filename: str) -> Any: if not Project._valid_description_line(line): return False line = file.readline().strip() - # if Project._version_line(line): - # if not Project._valid_version_line(line): - # return False - # line = file.readline().strip() + if Project._version_line(line): + if not Project._valid_version_line(line): + return False + line = file.readline().strip() # if not Project._valid_protection_line(line): # return False # line = file.readline().strip() From eda7a9e0622021f6f97f36a1d9be2f5f4caa3b98 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 20:39:47 -0400 Subject: [PATCH 072/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 48142bfda..398178c05 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -220,12 +220,12 @@ def _valid_description_line(line: str) -> bool: return False @staticmethod - def _valid_version_line(line) -> bool: + def _valid_version_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "VersionCompatible32": return pieces[1] == '"393222000"' return False - + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 72f0c088bdd95e44dd3b099a373a34e603cc87b0 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 20:50:31 -0400 Subject: [PATCH 073/184] Update project.py --- src/ms_ovba/Views/project.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 398178c05..8eb7e4f24 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -226,6 +226,13 @@ def _valid_version_line(line: str) -> bool: return pieces[1] == '"393222000"' return False + @staticmethod + def _valid_protection_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "CMG": + return pieces[1] == Project._valid_quoted_hex(pieces[1], 22, 28) + return False + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: @@ -266,3 +273,12 @@ def _valid_quoted_string(string: str, min: int, max: int) -> bool: string.replace('\t', " ") string.replace('"', '\x19') return all(32 <= ord(char) <= 255 for char in string) + + @staticmethod + def _valid_quoted_hex(string: str, min: int, max: int) -> bool: + if not (min + 2 <= len(string) <= max + 2): + return False + if string[0] != '"' or string[-1] != '"': + return False + string = string[1:-1] + return all(((48 <= ord(char) <= 57) or (65 <= ord(char) <= 70)) for char in string) From 6835aabf633f828d4c12c36dfd94bd7b10d91129 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 20:52:29 -0400 Subject: [PATCH 074/184] Update project.py --- src/ms_ovba/Views/project.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8eb7e4f24..3cae6e92e 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -281,4 +281,7 @@ def _valid_quoted_hex(string: str, min: int, max: int) -> bool: if string[0] != '"' or string[-1] != '"': return False string = string[1:-1] - return all(((48 <= ord(char) <= 57) or (65 <= ord(char) <= 70)) for char in string) + return all( + ((48 <= ord(char) <= 57) or (65 <= ord(char) <= 70)) + for char in string + ) From eaba5a5b84150ff3ebc0bb02793038b598d3e218 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:13:11 -0400 Subject: [PATCH 075/184] Update project.py --- src/ms_ovba/Views/project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 3cae6e92e..fe8f1c8a0 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -112,9 +112,9 @@ def is_valid(filename: str) -> Any: if not Project._valid_version_line(line): return False line = file.readline().strip() - # if not Project._valid_protection_line(line): - # return False - # line = file.readline().strip() + if not Project._valid_protection_line(line): + return False + line = file.readline().strip() # if not Project._valid_password_line(line): # return False # line = file.readline().strip() From bc98a45bc1b3ad76565cf92e9241ff5b460fe843 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:21:53 -0400 Subject: [PATCH 076/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index fe8f1c8a0..f3e68021f 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -230,7 +230,7 @@ def _valid_version_line(line: str) -> bool: def _valid_protection_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "CMG": - return pieces[1] == Project._valid_quoted_hex(pieces[1], 22, 28) + return Project._valid_quoted_hex(pieces[1], 22, 28) return False # Data Type Validators From f5b85952559df7e5892020598d0d609f7141da6e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:32:46 -0400 Subject: [PATCH 077/184] Update project.py --- src/ms_ovba/Views/project.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index f3e68021f..5d02f2358 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -115,9 +115,9 @@ def is_valid(filename: str) -> Any: if not Project._valid_protection_line(line): return False line = file.readline().strip() - # if not Project._valid_password_line(line): - # return False - # line = file.readline().strip() + if not Project._valid_password_line(line): + return False + line = file.readline().strip() # if not Project._valid_visibility_line(line): # return False # line = file.readline().strip() @@ -233,6 +233,14 @@ def _valid_protection_line(line: str) -> bool: return Project._valid_quoted_hex(pieces[1], 22, 28) return False + @staticmethod + def _valid_password_line(line: str) -> bool + pieces = line.split('=') + if pieces[0] == "DPB": + return Project._valid_quoted_hex(pieces[1], 16, 16) + return False + + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 4e095241dc2e86951840d27fd464524b8fd2df94 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:35:39 -0400 Subject: [PATCH 078/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 5d02f2358..509038003 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -234,7 +234,7 @@ def _valid_protection_line(line: str) -> bool: return False @staticmethod - def _valid_password_line(line: str) -> bool + def _valid_password_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "DPB": return Project._valid_quoted_hex(pieces[1], 16, 16) From 1459cb8cdc600448797c212501d2b52ddd1b3045 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:37:58 -0400 Subject: [PATCH 079/184] Update project.py --- src/ms_ovba/Views/project.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 509038003..6758394da 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -239,7 +239,6 @@ def _valid_password_line(line: str) -> bool: if pieces[0] == "DPB": return Project._valid_quoted_hex(pieces[1], 16, 16) return False - # Data Type Validators @staticmethod From b995774e6b5d4f8180eee61aa1d60879975e392e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:40:36 -0400 Subject: [PATCH 080/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 6758394da..8d9a8143f 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -239,7 +239,7 @@ def _valid_password_line(line: str) -> bool: if pieces[0] == "DPB": return Project._valid_quoted_hex(pieces[1], 16, 16) return False - + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From b62881c4c8588060ee118b7c73caee29d94c08f6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:50:04 -0400 Subject: [PATCH 081/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 5a77ef5c2..0e41238b0 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -90,6 +90,11 @@ def test_project_line_valid() -> None: assert Project._valid_project_id_line(line) +def test_password_line_valid() -> None + line = 'DPB="BCBEA7A2591C5A1C5A1C"' + assert Project._valid_password_line(line) + + def test_project_line_invalid() -> None: line = 'ID={9E394C0B-697E-4AEE-9FA6-446F51FB30DC}' assert not Project._valid_project_id_line(line) From a2e26aa44ac341563ef4f68d39d0f3469f28c54d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 21:55:14 -0400 Subject: [PATCH 082/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 0e41238b0..2f4e21f53 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -90,7 +90,7 @@ def test_project_line_valid() -> None: assert Project._valid_project_id_line(line) -def test_password_line_valid() -> None +def test_password_line_valid() -> None: line = 'DPB="BCBEA7A2591C5A1C5A1C"' assert Project._valid_password_line(line) From 45b7e8ff6819512d290bac99834e834960dee54f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Tue, 31 Mar 2026 22:10:36 -0400 Subject: [PATCH 083/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8d9a8143f..85176573b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -237,7 +237,7 @@ def _valid_protection_line(line: str) -> bool: def _valid_password_line(line: str) -> bool: pieces = line.split('=') if pieces[0] == "DPB": - return Project._valid_quoted_hex(pieces[1], 16, 16) + return Project._valid_quoted_hex(pieces[1], 16, 2000) return False # Data Type Validators From 2ed2bc22069a57d831e51e589b49d60355f0787e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 07:52:43 -0400 Subject: [PATCH 084/184] Update project.py --- src/ms_ovba/Views/project.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 85176573b..f14f500c1 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -118,11 +118,11 @@ def is_valid(filename: str) -> Any: if not Project._valid_password_line(line): return False line = file.readline().strip() - # if not Project._valid_visibility_line(line): - # return False - # line = file.readline().strip() - # if line != "": - # return False + if not Project._valid_visibility_line(line): + return False + line = file.readline().strip() + if line != "": + return False return True @@ -240,6 +240,13 @@ def _valid_password_line(line: str) -> bool: return Project._valid_quoted_hex(pieces[1], 16, 2000) return False + @staticmethod + def _valid_visibility_line(line: str) -> bool: + pieces = line.split('=') + if pieces[0] == "GC": + return Project._valid_quoted_hex(pieces[1], 16, 22) + return False + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 74a737b988bc5cfa36bb18c259ea879b8fd6fa30 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 07:57:35 -0400 Subject: [PATCH 085/184] Update project.py --- src/ms_ovba/Views/project.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index f14f500c1..1397f1358 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -123,7 +123,13 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() if line != "": return False - + line = file.readline().strip() + if line != "[Host Extender Info]": + return False + while Project._host_extender_line(line): + if not Project._valid_host_extender_line(line): + return False + line = file.readline().strip() return True @staticmethod @@ -152,11 +158,15 @@ def _exe_line(line: str) -> bool: @staticmethod def _description_line(line: str) -> bool: return line[0:3] == 'Des' - + @staticmethod def _version_line(line: str) -> bool: return line[0:3] == 'Ver' + @staticmethod + def _host_extender_line(line: str) -> bool: + return line[0:2] == '&H' + @staticmethod def _valid_project_item_line(line: str) -> bool: # Split at the equals. @@ -247,6 +257,10 @@ def _valid_visibility_line(line: str) -> bool: return Project._valid_quoted_hex(pieces[1], 16, 22) return False + @staticmethod + def _valid_host_extender_line(line: str) -> bool: + return True + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From 5ad50a37084eaa05aba744ff973f7351ede77ed9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:06:56 -0400 Subject: [PATCH 086/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1397f1358..c90cd31c6 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -158,7 +158,7 @@ def _exe_line(line: str) -> bool: @staticmethod def _description_line(line: str) -> bool: return line[0:3] == 'Des' - + @staticmethod def _version_line(line: str) -> bool: return line[0:3] == 'Ver' @@ -260,7 +260,7 @@ def _valid_visibility_line(line: str) -> bool: @staticmethod def _valid_host_extender_line(line: str) -> bool: return True - + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: From f4433cdff0f9625d482d62bb296b8f58536a34b9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:13:20 -0400 Subject: [PATCH 087/184] Update project.py --- src/ms_ovba/Views/project.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index c90cd31c6..8bcc650a9 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -259,7 +259,14 @@ def _valid_visibility_line(line: str) -> bool: @staticmethod def _valid_host_extender_line(line: str) -> bool: - return True + pieces = line.split('=') + ref = pieces[1].split(";") + return ( + Project._valid_hex32(pieces[0]) and + Project._valid_guid(ref[0]) and + ref[0] == "VBE" and + Project._valid_hex32(ref[2]) + ) # Data Type Validators @staticmethod From 89013760954a5561ba551c1a097f5788137b53e3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:17:05 -0400 Subject: [PATCH 088/184] Update project.py --- src/ms_ovba/Views/project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8bcc650a9..20664a65b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -263,8 +263,9 @@ def _valid_host_extender_line(line: str) -> bool: ref = pieces[1].split(";") return ( Project._valid_hex32(pieces[0]) and + len(ref) == 3 and Project._valid_guid(ref[0]) and - ref[0] == "VBE" and + (ref[0] == "VBE" or all(0x21 <= ord(char) <= 0xff for char in ref[0])) and Project._valid_hex32(ref[2]) ) From efe9d94f67144a64bf7bf1ddf18fa78b7377b05f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:23:41 -0400 Subject: [PATCH 089/184] Update project.py --- src/ms_ovba/Views/project.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 20664a65b..ecc0ad8cb 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -265,7 +265,10 @@ def _valid_host_extender_line(line: str) -> bool: Project._valid_hex32(pieces[0]) and len(ref) == 3 and Project._valid_guid(ref[0]) and - (ref[0] == "VBE" or all(0x21 <= ord(char) <= 0xff for char in ref[0])) and + ( + ref[0] == "VBE" or + all(0x21 <= ord(char) <= 0xff for char in ref[0]) + ) and Project._valid_hex32(ref[2]) ) From 7c7a644ac1df68a166c83b54060f6fba50784aef Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:26:49 -0400 Subject: [PATCH 090/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 2f4e21f53..ab4dfe4f4 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -100,6 +100,11 @@ def test_project_line_invalid() -> None: assert not Project._valid_project_id_line(line) +def test_host_extender_line() -> None: + line = "&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000" + assert Project._valid_host_extender_line(line) + + def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) From 88ef1aee5b7e5524410f31b811c74ab496c3231b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:29:40 -0400 Subject: [PATCH 091/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index ecc0ad8cb..d53db2bbf 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -266,7 +266,7 @@ def _valid_host_extender_line(line: str) -> bool: len(ref) == 3 and Project._valid_guid(ref[0]) and ( - ref[0] == "VBE" or + ref[0] == "VBE" or all(0x21 <= ord(char) <= 0xff for char in ref[0]) ) and Project._valid_hex32(ref[2]) From fc1799e1dc838a3feab8b7cdf3ab1dc7c3deffa5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:31:14 -0400 Subject: [PATCH 092/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index d53db2bbf..1aa7783f2 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -266,8 +266,8 @@ def _valid_host_extender_line(line: str) -> bool: len(ref) == 3 and Project._valid_guid(ref[0]) and ( - ref[0] == "VBE" or - all(0x21 <= ord(char) <= 0xff for char in ref[0]) + ref[1] == "VBE" or + all(0x21 <= ord(char) <= 0xff for char in ref[1]) ) and Project._valid_hex32(ref[2]) ) From d4ce0586703aa73e0231d9a96b66b7d5ec7ae320 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:33:07 -0400 Subject: [PATCH 093/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1aa7783f2..a0f2efe6a 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -122,15 +122,15 @@ def is_valid(filename: str) -> Any: return False line = file.readline().strip() if line != "": - return False + return 1 line = file.readline().strip() if line != "[Host Extender Info]": - return False + return 2 while Project._host_extender_line(line): if not Project._valid_host_extender_line(line): - return False + return 3 line = file.readline().strip() - return True + return 0 @staticmethod def _valid_project_id_line(line: str) -> Any: From 1b9e925e9723fdfb5137660143ba2a8583d34500 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:33:20 -0400 Subject: [PATCH 094/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index ab4dfe4f4..0d4dccee9 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -107,4 +107,4 @@ def test_host_extender_line() -> None: def test_valid() -> None: path = 'tests/blank/PROJECT' - assert Project.is_valid(path) + assert Project.is_valid(path) == 0 From 489f2e4b87f467cf4b362b8bc836e2f24779c9e0 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:35:24 -0400 Subject: [PATCH 095/184] Update project.py --- src/ms_ovba/Views/project.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a0f2efe6a..0d1dcc27d 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -122,15 +122,15 @@ def is_valid(filename: str) -> Any: return False line = file.readline().strip() if line != "": - return 1 + return False line = file.readline().strip() - if line != "[Host Extender Info]": - return 2 + if line != "[HostExtender Info]": + return False while Project._host_extender_line(line): if not Project._valid_host_extender_line(line): - return 3 + return False line = file.readline().strip() - return 0 + return True @staticmethod def _valid_project_id_line(line: str) -> Any: From 749e9aca297a601c129c0f3c9521da25709c62b8 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:35:33 -0400 Subject: [PATCH 096/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 0d4dccee9..ab4dfe4f4 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -107,4 +107,4 @@ def test_host_extender_line() -> None: def test_valid() -> None: path = 'tests/blank/PROJECT' - assert Project.is_valid(path) == 0 + assert Project.is_valid(path) From 80dad6446a0e3ace6eafccbd5e54e067fd8bb812 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:55:54 -0400 Subject: [PATCH 097/184] Update project.py --- src/ms_ovba/Views/project.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 0d1dcc27d..1e28e4eef 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -126,10 +126,23 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() if line != "[HostExtender Info]": return False + line = file.readline().strip() while Project._host_extender_line(line): if not Project._valid_host_extender_line(line): return False line = file.readline().strip() + if line != "": + return False + line = file.readline() + if line != '': + line = line.strip() + if line != "[Workspace]": + return False + line = file.readline().strip() + while line != '': + if not Project._valid_workspace_line(line): + return False + line = file.readline().strip() return True @staticmethod @@ -272,6 +285,17 @@ def _valid_host_extender_line(line: str) -> bool: Project._valid_hex32(ref[2]) ) + @staticmethod + def ._valid_workspace_line(line: str) -> bool: + pieces = line.split('=') + data = pieces[1].split(", ") + return ( + Project._valid_modulename(pieces[0]) and + len(data) == 5 and + all(Project._valid_int32(num) for num in data[:4]) and + data[4] in ['C', 'I', 'Z'] + ) + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: @@ -324,3 +348,13 @@ def _valid_quoted_hex(string: str, min: int, max: int) -> bool: ((48 <= ord(char) <= 57) or (65 <= ord(char) <= 70)) for char in string ) + + @staticmethod + def valid_int32(string: str) -> bool: + try: + value = int(candidate) + min = -2147483648 + max = 2147483647 + return min <= value <= max + except ValueError: + return False From 2cb523fa01b99914c7dbb5298766a72fd47c78fc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:56:39 -0400 Subject: [PATCH 098/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1e28e4eef..3b86637ef 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -286,7 +286,7 @@ def _valid_host_extender_line(line: str) -> bool: ) @staticmethod - def ._valid_workspace_line(line: str) -> bool: + def _valid_workspace_line(line: str) -> bool: pieces = line.split('=') data = pieces[1].split(", ") return ( From f09511fb22124fd56c6536af6a87dffb35f072fe Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:57:33 -0400 Subject: [PATCH 099/184] Update project.py --- src/ms_ovba/Views/project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 3b86637ef..40dd8c6a9 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -353,8 +353,8 @@ def _valid_quoted_hex(string: str, min: int, max: int) -> bool: def valid_int32(string: str) -> bool: try: value = int(candidate) - min = -2147483648 - max = 2147483647 - return min <= value <= max + min = -2147483648 + max = 2147483647 + return min <= value <= max except ValueError: return False From 7c841c96ccf83887b9e82fd143180167cf71741a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 09:58:32 -0400 Subject: [PATCH 100/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 40dd8c6a9..e7b29f3e2 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -295,7 +295,7 @@ def _valid_workspace_line(line: str) -> bool: all(Project._valid_int32(num) for num in data[:4]) and data[4] in ['C', 'I', 'Z'] ) - + # Data Type Validators @staticmethod def _valid_hex32(hex: str) -> bool: @@ -352,7 +352,7 @@ def _valid_quoted_hex(string: str, min: int, max: int) -> bool: @staticmethod def valid_int32(string: str) -> bool: try: - value = int(candidate) + value = int(string) min = -2147483648 max = 2147483647 return min <= value <= max From 35a29341fbfc56ac1ac4332fb186c855c544e3a8 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 10:03:17 -0400 Subject: [PATCH 101/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index e7b29f3e2..eefc3f952 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -350,7 +350,7 @@ def _valid_quoted_hex(string: str, min: int, max: int) -> bool: ) @staticmethod - def valid_int32(string: str) -> bool: + def _valid_int32(string: str) -> bool: try: value = int(string) min = -2147483648 From 606a17d60199394d0b2b0479d8d830fa3604ab5f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 11:33:54 -0400 Subject: [PATCH 102/184] Create PROJECT_bad --- tests/test_files/PROJECT_bad | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/test_files/PROJECT_bad diff --git a/tests/test_files/PROJECT_bad b/tests/test_files/PROJECT_bad new file mode 100644 index 000000000..38b200edd --- /dev/null +++ b/tests/test_files/PROJECT_bad @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z From e23270fab634af7765dcbcb3895bf9c435899a8e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 12:58:39 -0400 Subject: [PATCH 103/184] Update test_project.py --- tests/Unit/Views/test_project.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index ab4dfe4f4..ed088f72a 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -108,3 +108,7 @@ def test_host_extender_line() -> None: def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) + +def test_invalid() -> None: + path = 'test_files/PROJECT_bad' + assert not Project.is_valid(path) From 1b525c648615b981354eb7c9ce678c763b985260 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:00:07 -0400 Subject: [PATCH 104/184] Update test_project.py --- tests/Unit/Views/test_project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index ed088f72a..43ca3eb29 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -109,6 +109,7 @@ def test_valid() -> None: path = 'tests/blank/PROJECT' assert Project.is_valid(path) -def test_invalid() -> None: + +def test_incorrect_line_endings() -> None: path = 'test_files/PROJECT_bad' assert not Project.is_valid(path) From 3b0262cbd7a11dffba02ade565c2fb862d2fc1e5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:00:36 -0400 Subject: [PATCH 105/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 43ca3eb29..ef902face 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -111,5 +111,5 @@ def test_valid() -> None: def test_incorrect_line_endings() -> None: - path = 'test_files/PROJECT_bad' + path = 'tests/test_files/PROJECT_bad' assert not Project.is_valid(path) From aed905c45ce99f76ad0132d09ee9761901d84f13 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:03:47 -0400 Subject: [PATCH 106/184] Create PROJECT_line1 --- tests/test_files/PROJECT_line1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/test_files/PROJECT_line1 diff --git a/tests/test_files/PROJECT_line1 b/tests/test_files/PROJECT_line1 new file mode 100644 index 000000000..7e9deda01 --- /dev/null +++ b/tests/test_files/PROJECT_line1 @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z From 2e3b65df045f0c84f2cc5a4099c89fe3b83ef95f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:06:49 -0400 Subject: [PATCH 107/184] Added test files --- tests/test_files/PROJECT_line1 | 36 +++++++++++++++++----------------- tests/test_files/PROJECT_line2 | 18 +++++++++++++++++ tests/test_files/PROJECT_line3 | 18 +++++++++++++++++ tests/test_files/PROJECT_line4 | 18 +++++++++++++++++ tests/test_files/PROJECT_line5 | 18 +++++++++++++++++ 5 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 tests/test_files/PROJECT_line2 create mode 100644 tests/test_files/PROJECT_line3 create mode 100644 tests/test_files/PROJECT_line4 create mode 100644 tests/test_files/PROJECT_line5 diff --git a/tests/test_files/PROJECT_line1 b/tests/test_files/PROJECT_line1 index 7e9deda01..7938cfbed 100644 --- a/tests/test_files/PROJECT_line1 +++ b/tests/test_files/PROJECT_line1 @@ -1,18 +1,18 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" -Document=ThisWorkbook/&H00000000 -Document=Sheet1/&H00000000 -Module=Module1 -Name="VBAProject" -HelpContextID="0" -VersionCompatible32="393222000" -CMG="41435A5A5E5A5E5A5E5A5E" -DPB="BCBEA7A2591C5A1C5A1C" -GC="37352C2BDCDD56DE56DEA9" - -[HostExtender Info] -&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 - -[Workspace] -ThisWorkbook=0, 0, 0, 0, C -Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line2 b/tests/test_files/PROJECT_line2 new file mode 100644 index 000000000..254b6042b --- /dev/null +++ b/tests/test_files/PROJECT_line2 @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line3 b/tests/test_files/PROJECT_line3 new file mode 100644 index 000000000..fa47b9cbe --- /dev/null +++ b/tests/test_files/PROJECT_line3 @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H100000000000000000000 +Module=Module1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line4 b/tests/test_files/PROJECT_line4 new file mode 100644 index 000000000..28ed9a4fd --- /dev/null +++ b/tests/test_files/PROJECT_line4 @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Mod ule1 +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line5 b/tests/test_files/PROJECT_line5 new file mode 100644 index 000000000..a310a1977 --- /dev/null +++ b/tests/test_files/PROJECT_line5 @@ -0,0 +1,18 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +Name=VBAProject +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z From 7c9f8857d7058283dd94539bd46e6e10c3688a07 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:12:00 -0400 Subject: [PATCH 108/184] Update test_project.py --- tests/Unit/Views/test_project.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index ef902face..538f0a2cc 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -113,3 +113,18 @@ def test_valid() -> None: def test_incorrect_line_endings() -> None: path = 'tests/test_files/PROJECT_bad' assert not Project.is_valid(path) + + +file_numbers = [ + ("1"), + ("2"), + ("3"), + ("4"), + ("5"), +] + + +@pytest.mark.parametrize("input, expected", file_numbers) +def test_incorrect_lines(number: str) -> None: + path = 'tests/test_files/PROJECT_line' + number + assert not Project.is_valid(path) From 8034711f1ffe48a64d5a55f8f2aa46d3f0dc9534 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:12:53 -0400 Subject: [PATCH 109/184] Update test_project.py --- tests/Unit/Views/test_project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 538f0a2cc..15330e7a9 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -1,3 +1,4 @@ +import pytest import unittest.mock from ms_ovba.Views.project import Project from typing import Type, TypeVar From 9358f2a841770311172930763de850e1be9cecb0 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:18:37 -0400 Subject: [PATCH 110/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 15330e7a9..750c85b31 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -125,7 +125,7 @@ def test_incorrect_line_endings() -> None: ] -@pytest.mark.parametrize("input, expected", file_numbers) +@pytest.mark.parametrize("input", file_numbers) def test_incorrect_lines(number: str) -> None: path = 'tests/test_files/PROJECT_line' + number assert not Project.is_valid(path) From 7df7b94e5af401fde621aa11311a88ba7e0bd416 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:20:58 -0400 Subject: [PATCH 111/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 750c85b31..8a22bde77 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -125,7 +125,7 @@ def test_incorrect_line_endings() -> None: ] -@pytest.mark.parametrize("input", file_numbers) +@pytest.mark.parametrize("number", file_numbers) def test_incorrect_lines(number: str) -> None: path = 'tests/test_files/PROJECT_line' + number assert not Project.is_valid(path) From aacdfa4cade7ed436ef6dd56eae1aff109bf1bb1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:47:06 -0400 Subject: [PATCH 112/184] Update project.py --- src/ms_ovba/Views/project.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index eefc3f952..604a2c4ff 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -145,15 +145,6 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() return True - @staticmethod - def _valid_project_id_line(line: str) -> Any: - pieces = line.split('=') - if pieces[0] != 'ID': - return False - value = pieces[1] - if value[0] != '"' or value[-1] != '"': - return False - return Project._valid_guid(value[1:-1]) @staticmethod def _project_item_line(line: str) -> bool: @@ -180,9 +171,17 @@ def _version_line(line: str) -> bool: def _host_extender_line(line: str) -> bool: return line[0:2] == '&H' + @staticmethod + def _valid_project_id_line(line: str) -> Any: + pieces = line.split('=') + return ( + len(pieces) == 2 and pieces[0] == 'ID' and + pieces[1][0] == '"' and pieces[1][-1] == '"' and + Project._valid_guid(pieces[1][1:-1]) + ) + @staticmethod def _valid_project_item_line(line: str) -> bool: - # Split at the equals. pieces = line.split('=') # Verify the name. if pieces[0] == 'Document': @@ -202,9 +201,10 @@ def _valid_project_item_line(line: str) -> bool: @staticmethod def _valid_help_file_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "HelpFile": - return Project._valid_path(pieces[1]) - return False + return ( + len(pieces) == 2 and pieces[0] == "HelpFile" and + Project._valid_path(pieces[1]) + ) @staticmethod def _valid_exe_line(line: str) -> bool: From 688648af35948123b01493fbfa361dc5c733148b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:48:02 -0400 Subject: [PATCH 113/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 604a2c4ff..ff9b1be08 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -171,7 +171,7 @@ def _version_line(line: str) -> bool: def _host_extender_line(line: str) -> bool: return line[0:2] == '&H' - @staticmethod + @staticmethod def _valid_project_id_line(line: str) -> Any: pieces = line.split('=') return ( From f847065bdb55f5066a601818f3041b36ff3d122d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 13:48:57 -0400 Subject: [PATCH 114/184] Update project.py --- src/ms_ovba/Views/project.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index ff9b1be08..8193b3052 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -145,7 +145,6 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() return True - @staticmethod def _project_item_line(line: str) -> bool: options = ['Doc', 'Mod', 'Cla', 'Bas', 'Pac'] From d5a7e5198b5b28ba593e6f8e94545fd2f1cbf3be Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 14:12:54 -0400 Subject: [PATCH 115/184] added test cases --- tests/test_files/PROJECT_good | 21 +++++++++++++++++++++ tests/test_files/PROJECT_line5 | 3 ++- tests/test_files/PROJECT_line6 | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/test_files/PROJECT_good create mode 100644 tests/test_files/PROJECT_line6 diff --git a/tests/test_files/PROJECT_good b/tests/test_files/PROJECT_good new file mode 100644 index 000000000..92f99803b --- /dev/null +++ b/tests/test_files/PROJECT_good @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464" +Name="VBAProject" +HelpContextID="0" +Description="Can description contain an equals sign?" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line5 b/tests/test_files/PROJECT_line5 index a310a1977..eeb45a980 100644 --- a/tests/test_files/PROJECT_line5 +++ b/tests/test_files/PROJECT_line5 @@ -2,7 +2,8 @@ ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 -Name=VBAProject +HelpFile="foo"124.exe" +Name="VBAProject" HelpContextID="0" VersionCompatible32="393222000" CMG="41435A5A5E5A5E5A5E5A5E" diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 new file mode 100644 index 000000000..668f1c496 --- /dev/null +++ b/tests/test_files/PROJECT_line6 @@ -0,0 +1,20 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file From de66925d232820ac502c3ab218b696254da5a4b2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 14:13:57 -0400 Subject: [PATCH 116/184] more tests --- tests/test_files/PROJECT_line7 | 20 ++++++++++++++++++++ tests/test_files/PROJECT_line8 | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/test_files/PROJECT_line7 create mode 100644 tests/test_files/PROJECT_line8 diff --git a/tests/test_files/PROJECT_line7 b/tests/test_files/PROJECT_line7 new file mode 100644 index 000000000..80b5a0ea1 --- /dev/null +++ b/tests/test_files/PROJECT_line7 @@ -0,0 +1,20 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name=VBAProject +HelpContextID="0" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line8 b/tests/test_files/PROJECT_line8 new file mode 100644 index 000000000..8f54eb78d --- /dev/null +++ b/tests/test_files/PROJECT_line8 @@ -0,0 +1,20 @@ +ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file From 80c5ddb82743cf92eeebcd69da0c0f46e668ad61 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 14:14:55 -0400 Subject: [PATCH 117/184] Update test_project.py --- tests/Unit/Views/test_project.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 8a22bde77..4e22ffce4 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -106,9 +106,9 @@ def test_host_extender_line() -> None: assert Project._valid_host_extender_line(line) -def test_valid() -> None: - path = 'tests/blank/PROJECT' - assert Project.is_valid(path) +def test_valid_file() -> None: + path = 'tests/test_files/PROJECT_good' + assert not Project.is_valid(path) def test_incorrect_line_endings() -> None: @@ -122,6 +122,9 @@ def test_incorrect_line_endings() -> None: ("3"), ("4"), ("5"), + ("6"), + ("7"), + ("8"), ] From 1cfbf53213e8e00b60f237df8b79f7c7a8f7c6f9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 20:10:29 -0400 Subject: [PATCH 118/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 4e22ffce4..a573bf9e7 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -108,7 +108,7 @@ def test_host_extender_line() -> None: def test_valid_file() -> None: path = 'tests/test_files/PROJECT_good' - assert not Project.is_valid(path) + assert Project.is_valid(path) def test_incorrect_line_endings() -> None: From 3bdc7622e118d1471887bab3ef0f18aae6d6674b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:17:08 -0400 Subject: [PATCH 119/184] added dash --- tests/test_files/PROJECT_good | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_good b/tests/test_files/PROJECT_good index 92f99803b..e1ab7935c 100644 --- a/tests/test_files/PROJECT_good +++ b/tests/test_files/PROJECT_good @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 From cbb4e2ef919d9171670bb259dcf28c427e9f56f1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:18:48 -0400 Subject: [PATCH 120/184] Update PROJECT_line2 --- tests/test_files/PROJECT_line2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line2 b/tests/test_files/PROJECT_line2 index 254b6042b..00398df95 100644 --- a/tests/test_files/PROJECT_line2 +++ b/tests/test_files/PROJECT_line2 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/H00000000 Document=Sheet1/&H00000000 Module=Module1 From e134ab1aa0a48398b7d21a338c9cd6369b2f3806 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:25:54 -0400 Subject: [PATCH 121/184] Update PROJECT_line3 --- tests/test_files/PROJECT_line3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line3 b/tests/test_files/PROJECT_line3 index fa47b9cbe..cb9a92d5a 100644 --- a/tests/test_files/PROJECT_line3 +++ b/tests/test_files/PROJECT_line3 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H100000000000000000000 Module=Module1 From 5e4c9a3dbf44489461ab11956ae54b78a78c0b71 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:26:10 -0400 Subject: [PATCH 122/184] Update PROJECT_line4 --- tests/test_files/PROJECT_line4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line4 b/tests/test_files/PROJECT_line4 index 28ed9a4fd..6fdc5a309 100644 --- a/tests/test_files/PROJECT_line4 +++ b/tests/test_files/PROJECT_line4 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Mod ule1 From 7b8fe433316f0afc37e9ab150c8f4021ecf556b6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:26:25 -0400 Subject: [PATCH 123/184] Update PROJECT_line5 --- tests/test_files/PROJECT_line5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line5 b/tests/test_files/PROJECT_line5 index eeb45a980..23640bad4 100644 --- a/tests/test_files/PROJECT_line5 +++ b/tests/test_files/PROJECT_line5 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 From 5ba0188e1505633513829e58584e1aef787e4db7 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:26:40 -0400 Subject: [PATCH 124/184] Update PROJECT_line6 --- tests/test_files/PROJECT_line6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 index 668f1c496..aa62995b5 100644 --- a/tests/test_files/PROJECT_line6 +++ b/tests/test_files/PROJECT_line6 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z From 73e371aeea91acc60ede5506caac5873b03ac416 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:26:56 -0400 Subject: [PATCH 125/184] Update PROJECT_line7 --- tests/test_files/PROJECT_line7 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_files/PROJECT_line7 b/tests/test_files/PROJECT_line7 index 80b5a0ea1..00d3834be 100644 --- a/tests/test_files/PROJECT_line7 +++ b/tests/test_files/PROJECT_line7 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z From 8b583e6502bcc08162ce0c65afce261afa1e7a00 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:27:11 -0400 Subject: [PATCH 126/184] Update PROJECT_line8 --- tests/test_files/PROJECT_line8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_files/PROJECT_line8 b/tests/test_files/PROJECT_line8 index 8f54eb78d..6964e0e90 100644 --- a/tests/test_files/PROJECT_line8 +++ b/tests/test_files/PROJECT_line8 @@ -1,4 +1,4 @@ -ID="{9E394C0B-697E-4AEE-9FA6446F51FB30DC}" +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z From 49480315d467102761be6357c8d7cbdd45e07a5c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Wed, 1 Apr 2026 22:36:51 -0400 Subject: [PATCH 127/184] Update PROJECT_line4 --- tests/test_files/PROJECT_line4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line4 b/tests/test_files/PROJECT_line4 index 6fdc5a309..117bdfaf1 100644 --- a/tests/test_files/PROJECT_line4 +++ b/tests/test_files/PROJECT_line4 @@ -1,7 +1,7 @@ ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 -Module=Mod ule1 +Module=Mod ule1-;:()&@2836:).!,)37yshebxieushdjsiejxhsusndjejdnxj Name="VBAProject" HelpContextID="0" VersionCompatible32="393222000" From b960bade0bf47a986091d885047ede78df0b142f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 06:19:35 -0400 Subject: [PATCH 128/184] Update project.py --- src/ms_ovba/Views/project.py | 48 ++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 8193b3052..0ab34027d 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -208,16 +208,18 @@ def _valid_help_file_line(line: str) -> bool: @staticmethod def _valid_exe_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "ExeName32": - return Project._valid_path(pieces[1]) - return False + return ( + pieces[0] == "ExeName32" and + Project._valid_path(pieces[1]) + ) @staticmethod def _valid_name_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "Name": - return Project._valid_quoted_string(pieces[1], 1, 128) - return False + return ( + pieces[0] == "Name" and + Project._valid_quoted_string(pieces[1], 1, 128) + ) @staticmethod def _valid_help_id_line(line: str) -> bool: @@ -237,37 +239,41 @@ def _valid_help_id_line(line: str) -> bool: @staticmethod def _valid_description_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "Description": - return Project._valid_quoted_string(pieces[1], 0, 2000) - return False + return ( + pieces[0] == "Description" and + Project._valid_quoted_string(pieces[1], 0, 2000) + ) @staticmethod def _valid_version_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "VersionCompatible32": - return pieces[1] == '"393222000"' - return False + return ( + line == 'VersionCompatible32="393222000" + ) @staticmethod def _valid_protection_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "CMG": - return Project._valid_quoted_hex(pieces[1], 22, 28) - return False + return ( + pieces[0] == "CMG" and + Project._valid_quoted_hex(pieces[1], 22, 28) + ) @staticmethod def _valid_password_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "DPB": - return Project._valid_quoted_hex(pieces[1], 16, 2000) - return False + return ( + pieces[0] == "DPB" and + Project._valid_quoted_hex(pieces[1], 16, 2000) + ) @staticmethod def _valid_visibility_line(line: str) -> bool: pieces = line.split('=') - if pieces[0] == "GC": - return Project._valid_quoted_hex(pieces[1], 16, 22) - return False + return ( + pieces[0] == "GC" and + Project._valid_quoted_hex(pieces[1], 16, 22) + ) @staticmethod def _valid_host_extender_line(line: str) -> bool: From 548557fa80d6be8d20b14f26cbde786de3f90f57 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:44:54 -0400 Subject: [PATCH 129/184] Update PROJECT_line6 --- tests/test_files/PROJECT_line6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 index aa62995b5..df9f03842 100644 --- a/tests/test_files/PROJECT_line6 +++ b/tests/test_files/PROJECT_line6 @@ -3,7 +3,7 @@ Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 HelpFile="foo""124.exe" -ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +ExeName32="123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122" Name="VBAProject" HelpContextID="0" VersionCompatible32="393222000" From d11fbf04881614c7246174aeb80a93d425d2f171 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:45:57 -0400 Subject: [PATCH 130/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 0ab34027d..9a46a41d6 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -248,7 +248,7 @@ def _valid_description_line(line: str) -> bool: def _valid_version_line(line: str) -> bool: pieces = line.split('=') return ( - line == 'VersionCompatible32="393222000" + line == 'VersionCompatible32="393222000"' ) @staticmethod From d2ae5b6427261f484e201493ff5aa65e4a307c3d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:51:02 -0400 Subject: [PATCH 131/184] Update project.py --- src/ms_ovba/Views/project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 9a46a41d6..b8b14ba7b 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -337,9 +337,9 @@ def _valid_quoted_string(string: str, min: int, max: int) -> bool: return False string = string[1:-1] # Dquot must be paired - string.replace('""', " ") - string.replace('\t', " ") - string.replace('"', '\x19') + string = string.replace('""', " ") + string = string.replace('\t', " ") + string = string.replace('"', '\x19') return all(32 <= ord(char) <= 255 for char in string) @staticmethod From 22c537484ecdf87e60473178965e3e3f2f35429a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:51:57 -0400 Subject: [PATCH 132/184] Update project.py --- src/ms_ovba/Views/project.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index b8b14ba7b..bb9333b40 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -246,7 +246,6 @@ def _valid_description_line(line: str) -> bool: @staticmethod def _valid_version_line(line: str) -> bool: - pieces = line.split('=') return ( line == 'VersionCompatible32="393222000"' ) @@ -263,7 +262,7 @@ def _valid_protection_line(line: str) -> bool: def _valid_password_line(line: str) -> bool: pieces = line.split('=') return ( - pieces[0] == "DPB" and + pieces[0] == "DPB" and Project._valid_quoted_hex(pieces[1], 16, 2000) ) From 9fa22e50a836cf051681462796768e4bc91c9683 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:54:30 -0400 Subject: [PATCH 133/184] Update test_project.py --- tests/Unit/Views/test_project.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index a573bf9e7..a6ab2342c 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -106,6 +106,13 @@ def test_host_extender_line() -> None: assert Project._valid_host_extender_line(line) +def test_invalid_quoted_string() -> None: + string = "abcde" + min = 0 + max = 2 + assert not Project_valid_quoted_string(string, min, max) + + def test_valid_file() -> None: path = 'tests/test_files/PROJECT_good' assert Project.is_valid(path) From e8dc783c7f9df355e4f1e96f1a4b70e2db7ede3d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:56:50 -0400 Subject: [PATCH 134/184] Update test_project.py --- tests/Unit/Views/test_project.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index a6ab2342c..4a884cc0d 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -106,11 +106,15 @@ def test_host_extender_line() -> None: assert Project._valid_host_extender_line(line) -def test_invalid_quoted_string() -> None: - string = "abcde" - min = 0 - max = 2 - assert not Project_valid_quoted_string(string, min, max) +invalid_quoted_string = [ + ("abcde", 0, 2, "Too Long"), + ("abcde", 10, 12, "Too Short"), +] + + +@pytest.mark.parametrize("string, min, max, msg", invalid_quoted_strings) +def test_invalid_quoted_string(string: str, min: int, max: int, msg: str) -> None: + assert not Project_valid_quoted_string(string, min, max), msg def test_valid_file() -> None: From 87eb61768b797f3555d089e9c5546ede3d341eb9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:57:24 -0400 Subject: [PATCH 135/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 4a884cc0d..319b25d79 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -114,7 +114,7 @@ def test_host_extender_line() -> None: @pytest.mark.parametrize("string, min, max, msg", invalid_quoted_strings) def test_invalid_quoted_string(string: str, min: int, max: int, msg: str) -> None: - assert not Project_valid_quoted_string(string, min, max), msg + assert not Project._valid_quoted_string(string, min, max), msg def test_valid_file() -> None: From e7d4dfb95d6b5c404486c5ef0a54893c3c54f974 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 07:58:37 -0400 Subject: [PATCH 136/184] Update test_project.py --- tests/Unit/Views/test_project.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 319b25d79..0d029251c 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -106,14 +106,15 @@ def test_host_extender_line() -> None: assert Project._valid_host_extender_line(line) -invalid_quoted_string = [ +invalid_quoted_strings = [ ("abcde", 0, 2, "Too Long"), ("abcde", 10, 12, "Too Short"), ] @pytest.mark.parametrize("string, min, max, msg", invalid_quoted_strings) -def test_invalid_quoted_string(string: str, min: int, max: int, msg: str) -> None: +def test_invalid_quoted_string(string: str, + min: int, max: int, msg: str) -> None: assert not Project._valid_quoted_string(string, min, max), msg From bc240ec6e6f237d0ed40bc310d671960d9ff8458 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:03:01 -0400 Subject: [PATCH 137/184] Update test_project.py --- tests/Unit/Views/test_project.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 0d029251c..68040d48c 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -101,6 +101,17 @@ def test_project_line_invalid() -> None: assert not Project._valid_project_id_line(line) +def test_invalid_exe_line() -> None: + line = ( + 'ExeName32="12345678910111213141516171819202122232425262728293031' + + '3233343536373839404142434445464748495051525354555657585960616263' + + '6465666768697071727374757677787980818283848586878889909192939495' + + '9697989910010110210310410510610710810911011111211311411511611711' + + '8119120121122"' + ) + assert not Project._valid_exe_line(line) + + def test_host_extender_line() -> None: line = "&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000" assert Project._valid_host_extender_line(line) From 1b96829f751db10f22d428ecd9e9587df31eb7d9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:05:07 -0400 Subject: [PATCH 138/184] Update test_project.py --- tests/Unit/Views/test_project.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 68040d48c..d4cdecfb9 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -129,6 +129,18 @@ def test_invalid_quoted_string(string: str, assert not Project._valid_quoted_string(string, min, max), msg +invalid_quoted_strings = [ + ("abcde", 0, 20), + ("abcde", 5, 12), + ("a=b", 0, 20) +] + + +@pytest.mark.parametrize("string, min, max", valid_quoted_strings) +def test_valid_quoted_string(string: str, min: int, max: int) -> None: + assert Project._valid_quoted_string(string, min, max) + + def test_valid_file() -> None: path = 'tests/test_files/PROJECT_good' assert Project.is_valid(path) From f560213efe081afa0004551b038b26cd84e48a78 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:07:29 -0400 Subject: [PATCH 139/184] final line --- tests/test_files/PROJECT_line6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 index df9f03842..e5d707391 100644 --- a/tests/test_files/PROJECT_line6 +++ b/tests/test_files/PROJECT_line6 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z +Module1=26, 26, 1349, 522, Z \ No newline at end of file From 353f5a4d9547483637951e867502fed17e913baa Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:08:02 -0400 Subject: [PATCH 140/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index d4cdecfb9..034298770 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -129,7 +129,7 @@ def test_invalid_quoted_string(string: str, assert not Project._valid_quoted_string(string, min, max), msg -invalid_quoted_strings = [ +valid_quoted_strings = [ ("abcde", 0, 20), ("abcde", 5, 12), ("a=b", 0, 20) From 0f76d1e502f5f1ce268eac8b41aeb847ab80db78 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:16:48 -0400 Subject: [PATCH 141/184] Update project.py --- src/ms_ovba/Views/project.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index bb9333b40..e4e4dd9b0 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -330,16 +330,15 @@ def _valid_path(path: str) -> bool: @staticmethod def _valid_quoted_string(string: str, min: int, max: int) -> bool: - if not (min + 2 <= len(string) <= max + 2): - return False - if string[0] != '"' or string[-1] != '"': - return False - string = string[1:-1] - # Dquot must be paired - string = string.replace('""', " ") - string = string.replace('\t', " ") - string = string.replace('"', '\x19') - return all(32 <= ord(char) <= 255 for char in string) + substring = string[1:-1] + substring = substring.replace('""', " ") + substring = substring.replace('\t', " ") + substring = substring.replace('"', '\x19') + return( + (min <= len(substring) <= max) and + string[0] == '"' and string[-1] == '"' and + all(32 <= ord(char) <= 255 for char in string) + ) @staticmethod def _valid_quoted_hex(string: str, min: int, max: int) -> bool: From 875d674d45f403c563127e00e42550f80edb226d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:17:45 -0400 Subject: [PATCH 142/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index e4e4dd9b0..2bfc4fe7c 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -334,7 +334,7 @@ def _valid_quoted_string(string: str, min: int, max: int) -> bool: substring = substring.replace('""', " ") substring = substring.replace('\t', " ") substring = substring.replace('"', '\x19') - return( + return ( (min <= len(substring) <= max) and string[0] == '"' and string[-1] == '"' and all(32 <= ord(char) <= 255 for char in string) From 5a41125251501ebbc7b0efe38d322b0201a85604 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:19:05 -0400 Subject: [PATCH 143/184] Update test_project.py --- tests/Unit/Views/test_project.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 034298770..c10d2572f 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -118,8 +118,9 @@ def test_host_extender_line() -> None: invalid_quoted_strings = [ - ("abcde", 0, 2, "Too Long"), - ("abcde", 10, 12, "Too Short"), + ('"abcde"', 0, 2, "Too Long"), + ('"abcde"', 10, 12, "Too Short"), + ('abcde', 5, 12, "Not Quoted"), ] @@ -130,9 +131,9 @@ def test_invalid_quoted_string(string: str, valid_quoted_strings = [ - ("abcde", 0, 20), - ("abcde", 5, 12), - ("a=b", 0, 20) + ('"abcde"', 0, 20), + ('"abcde"', 5, 12), + ('"a=b"', 0, 20) ] From 62e1c7fafcd7dd4ff2b02a0f6833b9963f3ceb2a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:22:05 -0400 Subject: [PATCH 144/184] Update test_project.py --- tests/Unit/Views/test_project.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index c10d2572f..d71379c62 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -121,6 +121,7 @@ def test_host_extender_line() -> None: ('"abcde"', 0, 2, "Too Long"), ('"abcde"', 10, 12, "Too Short"), ('abcde', 5, 12, "Not Quoted"), + ('"a"b"', 0, 20, "Unpaired DQUOT") ] @@ -133,7 +134,8 @@ def test_invalid_quoted_string(string: str, valid_quoted_strings = [ ('"abcde"', 0, 20), ('"abcde"', 5, 12), - ('"a=b"', 0, 20) + ('"a=b"', 0, 20), + ('"a""b"', 0, 20) ] From c799f753e960c2b34a4ffb5bcc21e4834b9ea145 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:25:24 -0400 Subject: [PATCH 145/184] Update project.py --- src/ms_ovba/Views/project.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 2bfc4fe7c..d70234463 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -330,6 +330,8 @@ def _valid_path(path: str) -> bool: @staticmethod def _valid_quoted_string(string: str, min: int, max: int) -> bool: + if len(str) < 2: + return False substring = string[1:-1] substring = substring.replace('""', " ") substring = substring.replace('\t', " ") @@ -337,7 +339,7 @@ def _valid_quoted_string(string: str, min: int, max: int) -> bool: return ( (min <= len(substring) <= max) and string[0] == '"' and string[-1] == '"' and - all(32 <= ord(char) <= 255 for char in string) + all((32 <= ord(char) <= 255) for char in string) ) @staticmethod From 5aa684ee81ad78edd2e6e5b98cd9e65af13a6874 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:26:45 -0400 Subject: [PATCH 146/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index d70234463..bbe4217d0 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -339,7 +339,7 @@ def _valid_quoted_string(string: str, min: int, max: int) -> bool: return ( (min <= len(substring) <= max) and string[0] == '"' and string[-1] == '"' and - all((32 <= ord(char) <= 255) for char in string) + all(32 <= ord(char) <= 255 for char in substring) ) @staticmethod From 244644f4c276e6018c9357d385914a2c164b989c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:29:22 -0400 Subject: [PATCH 147/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index bbe4217d0..925148136 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -330,7 +330,7 @@ def _valid_path(path: str) -> bool: @staticmethod def _valid_quoted_string(string: str, min: int, max: int) -> bool: - if len(str) < 2: + if len(string) < 2: return False substring = string[1:-1] substring = substring.replace('""', " ") From e3e4a76fe1ff5f8c1a43ce4c6c8a1edc5c22a600 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:34:59 -0400 Subject: [PATCH 148/184] Update test_project.py --- tests/Unit/Views/test_project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index d71379c62..863d2d6af 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -118,8 +118,8 @@ def test_host_extender_line() -> None: invalid_quoted_strings = [ - ('"abcde"', 0, 2, "Too Long"), - ('"abcde"', 10, 12, "Too Short"), + ('"abc"', 0, 2, "Too Long"), + ('"abcde"', 6, 12, "Too Short"), ('abcde', 5, 12, "Not Quoted"), ('"a"b"', 0, 20, "Unpaired DQUOT") ] From bf316b52ce6c52e8e429f1083aa392b4d1a7e311 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:37:19 -0400 Subject: [PATCH 149/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 863d2d6af..87728ce58 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -107,7 +107,7 @@ def test_invalid_exe_line() -> None: '3233343536373839404142434445464748495051525354555657585960616263' + '6465666768697071727374757677787980818283848586878889909192939495' + '9697989910010110210310410510610710810911011111211311411511611711' + - '8119120121122"' + '8119120121122123"' ) assert not Project._valid_exe_line(line) From 282958600c245ec3d1f5dd53df14897fbbaba9e5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:37:59 -0400 Subject: [PATCH 150/184] increased length --- tests/test_files/PROJECT_line6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 index e5d707391..b61a4f197 100644 --- a/tests/test_files/PROJECT_line6 +++ b/tests/test_files/PROJECT_line6 @@ -3,7 +3,7 @@ Document=ThisWorkbook/&H00000000 Document=Sheet1/&H00000000 Module=Module1 HelpFile="foo""124.exe" -ExeName32="123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122" +ExeName32="123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123" Name="VBAProject" HelpContextID="0" VersionCompatible32="393222000" From 4e3d30f6f287d859fa4a3568f6d47053869b8931 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 08:39:40 -0400 Subject: [PATCH 151/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 87728ce58..5e46af0e7 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -145,7 +145,7 @@ def test_valid_quoted_string(string: str, min: int, max: int) -> None: def test_valid_file() -> None: - path = 'tests/test_files/PROJECT_good' + path = 'tests/blank/PROJECT' assert Project.is_valid(path) From b2fa66845961d1a44eb87bab52c5522988f69513 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 10:25:57 -0400 Subject: [PATCH 152/184] Update project.py --- src/ms_ovba/Views/project.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 925148136..9cc02282c 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -80,37 +80,37 @@ def is_valid(filename: str) -> Any: with open(filename, 'r', newline='') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return False + return 1 with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): - return False + return 2 line = file.readline().strip() while Project._project_item_line(line): if not Project._valid_project_item_line(line): - return False + return 3 line = file.readline().strip() if Project._help_file_line(line): if not Project._valid_help_file_line(line): - return False + return 4 line = file.readline().strip() if Project._exe_line(line): if not Project._valid_exe_line(line): - return False + return 5 line = file.readline().strip() if not Project._valid_name_line(line): - return False + return 6 line = file.readline().strip() if not Project._valid_help_id_line(line): - return False + return 7 line = file.readline().strip() if Project._description_line(line): if not Project._valid_description_line(line): - return False + return 8 line = file.readline().strip() if Project._version_line(line): if not Project._valid_version_line(line): - return False + return 9 line = file.readline().strip() if not Project._valid_protection_line(line): return False @@ -143,7 +143,7 @@ def is_valid(filename: str) -> Any: if not Project._valid_workspace_line(line): return False line = file.readline().strip() - return True + return 0 @staticmethod def _project_item_line(line: str) -> bool: From 3f471834a3296a0e46f497118be5f637f4dac6e2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 10:27:15 -0400 Subject: [PATCH 153/184] Update test_project.py --- tests/Unit/Views/test_project.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 5e46af0e7..b751c81cf 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -155,18 +155,18 @@ def test_incorrect_line_endings() -> None: file_numbers = [ - ("1"), - ("2"), - ("3"), - ("4"), - ("5"), - ("6"), - ("7"), - ("8"), + ("1", 1), + ("2", 2), + ("3", 2), + ("4", 2), + ("5", 3), + ("6", 4), + ("7", 5), + ("8", 6), ] -@pytest.mark.parametrize("number", file_numbers) -def test_incorrect_lines(number: str) -> None: +@pytest.mark.parametrize("number, result", file_numbers) +def test_incorrect_lines(number: str, result: int) -> None: path = 'tests/test_files/PROJECT_line' + number - assert not Project.is_valid(path) + assert not Project.is_valid(path) == result From 07f582ef4893cb361ff8e747450931dfe679a2b2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 10:35:36 -0400 Subject: [PATCH 154/184] Update project.py --- src/ms_ovba/Views/project.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 9cc02282c..1d9411fe8 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -80,37 +80,37 @@ def is_valid(filename: str) -> Any: with open(filename, 'r', newline='') as file: for line in file: if line[-2:] not in ["\r\n", "\n\r"]: - return 1 + return False with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): - return 2 + return False line = file.readline().strip() while Project._project_item_line(line): if not Project._valid_project_item_line(line): - return 3 + return False line = file.readline().strip() if Project._help_file_line(line): if not Project._valid_help_file_line(line): - return 4 + return False line = file.readline().strip() if Project._exe_line(line): if not Project._valid_exe_line(line): - return 5 + return False line = file.readline().strip() if not Project._valid_name_line(line): - return 6 + return False line = file.readline().strip() if not Project._valid_help_id_line(line): - return 7 + return False line = file.readline().strip() if Project._description_line(line): if not Project._valid_description_line(line): - return 8 + return False line = file.readline().strip() if Project._version_line(line): if not Project._valid_version_line(line): - return 9 + return False line = file.readline().strip() if not Project._valid_protection_line(line): return False From 618042760b416ad3dfaac7238749958240afe3d6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 10:36:28 -0400 Subject: [PATCH 155/184] Update test_project.py --- tests/Unit/Views/test_project.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index b751c81cf..a938f75d9 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -155,18 +155,18 @@ def test_incorrect_line_endings() -> None: file_numbers = [ - ("1", 1), - ("2", 2), - ("3", 2), - ("4", 2), - ("5", 3), - ("6", 4), - ("7", 5), - ("8", 6), + ("1"), + ("2"), + ("3"), + ("4"), + ("5"), + ("6"), + ("7"), + ("8"), ] @pytest.mark.parametrize("number, result", file_numbers) def test_incorrect_lines(number: str, result: int) -> None: path = 'tests/test_files/PROJECT_line' + number - assert not Project.is_valid(path) == result + assert not Project.is_valid(path) From 401c681cd715054cd393c42df3a0d269ce60a09a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 10:37:41 -0400 Subject: [PATCH 156/184] Update test_project.py --- tests/Unit/Views/test_project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index a938f75d9..5e46af0e7 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -166,7 +166,7 @@ def test_incorrect_line_endings() -> None: ] -@pytest.mark.parametrize("number, result", file_numbers) -def test_incorrect_lines(number: str, result: int) -> None: +@pytest.mark.parametrize("number", file_numbers) +def test_incorrect_lines(number: str) -> None: path = 'tests/test_files/PROJECT_line' + number assert not Project.is_valid(path) From f13a3bdc3c92dd23c392466adfd718f9b982298d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 11:01:14 -0400 Subject: [PATCH 157/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 1d9411fe8..925148136 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -143,7 +143,7 @@ def is_valid(filename: str) -> Any: if not Project._valid_workspace_line(line): return False line = file.readline().strip() - return 0 + return True @staticmethod def _project_item_line(line: str) -> bool: From e23df5304b9a9049d31ede705223d0e6afca37af Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 11:37:52 -0400 Subject: [PATCH 158/184] Added more tests --- tests/test_files/PROJECT_line10 | 21 +++++++++++++++++++++ tests/test_files/PROJECT_line11 | 21 +++++++++++++++++++++ tests/test_files/PROJECT_line12 | 21 +++++++++++++++++++++ tests/test_files/PROJECT_line13 | 21 +++++++++++++++++++++ tests/test_files/PROJECT_line14 | 20 ++++++++++++++++++++ tests/test_files/PROJECT_line9 | 21 +++++++++++++++++++++ 6 files changed, 125 insertions(+) create mode 100644 tests/test_files/PROJECT_line10 create mode 100644 tests/test_files/PROJECT_line11 create mode 100644 tests/test_files/PROJECT_line12 create mode 100644 tests/test_files/PROJECT_line13 create mode 100644 tests/test_files/PROJECT_line14 create mode 100644 tests/test_files/PROJECT_line9 diff --git a/tests/test_files/PROJECT_line10 b/tests/test_files/PROJECT_line10 new file mode 100644 index 000000000..78b2e81be --- /dev/null +++ b/tests/test_files/PROJECT_line10 @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description="" +VersionCompatible32="1.0" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line11 b/tests/test_files/PROJECT_line11 new file mode 100644 index 000000000..cb3cc55e4 --- /dev/null +++ b/tests/test_files/PROJECT_line11 @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description="" +VersionCompatible32="1.0" +GMC="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line12 b/tests/test_files/PROJECT_line12 new file mode 100644 index 000000000..c4c7f4d04 --- /dev/null +++ b/tests/test_files/PROJECT_line12 @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description="" +VersionCompatible32="1.0" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line13 b/tests/test_files/PROJECT_line13 new file mode 100644 index 000000000..a8ae9c53c --- /dev/null +++ b/tests/test_files/PROJECT_line13 @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description="" +VersionCompatible32="1.0" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GCC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line14 b/tests/test_files/PROJECT_line14 new file mode 100644 index 000000000..9084c4061 --- /dev/null +++ b/tests/test_files/PROJECT_line14 @@ -0,0 +1,20 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description="" +VersionCompatible32="1.0" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file diff --git a/tests/test_files/PROJECT_line9 b/tests/test_files/PROJECT_line9 new file mode 100644 index 000000000..f7cbf0bbf --- /dev/null +++ b/tests/test_files/PROJECT_line9 @@ -0,0 +1,21 @@ +ID="{9E394C0B-697E-4AEE-9FA6-446F51FB30DC}" +Document=ThisWorkbook/&H00000000 +Document=Sheet1/&H00000000 +Module=Module1 +HelpFile="foo""124.exe" +ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" +Name="VBAProject" +HelpContextID="X" +Description=" +VersionCompatible32="393222000" +CMG="41435A5A5E5A5E5A5E5A5E" +DPB="BCBEA7A2591C5A1C5A1C" +GC="37352C2BDCDD56DE56DEA9" + +[HostExtender Info] +&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 + +[Workspace] +ThisWorkbook=0, 0, 0, 0, C +Sheet1=0, 0, 0, 0, C +Module1=26, 26, 1349, 522, Z \ No newline at end of file From 893c818891121823b31abc7fecd3fcb1c6d53aed Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 11:38:37 -0400 Subject: [PATCH 159/184] Update test_project.py --- tests/Unit/Views/test_project.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 5e46af0e7..4fdfbea89 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -163,6 +163,12 @@ def test_incorrect_line_endings() -> None: ("6"), ("7"), ("8"), + ("9"), + ("10"), + ("11"), + ("12"), + ("13"), + ("14"), ] From 986a0a0230fce14f090c6a8c38557e854ed47863 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 11:53:19 -0400 Subject: [PATCH 160/184] Update test_project.py --- tests/Unit/Views/test_project.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 4fdfbea89..26bcc9064 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -155,11 +155,11 @@ def test_incorrect_line_endings() -> None: file_numbers = [ - ("1"), - ("2"), - ("3"), - ("4"), - ("5"), +# ("1"), +# ("2"), +# ("3"), +# ("4"), +# ("5"), ("6"), ("7"), ("8"), @@ -168,7 +168,7 @@ def test_incorrect_line_endings() -> None: ("11"), ("12"), ("13"), - ("14"), + ("14") ] From 8144e03b63b835c52058fef09e90dd163670217d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 11:57:46 -0400 Subject: [PATCH 161/184] Update project.py --- src/ms_ovba/Views/project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 925148136..2e1f75a97 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -95,7 +95,8 @@ def is_valid(filename: str) -> Any: return False line = file.readline().strip() if Project._exe_line(line): - if not Project._valid_exe_line(line): + if not Project._valid_exe_line(1"), + raise Exception("found bad exe") return False line = file.readline().strip() if not Project._valid_name_line(line): From 4aa4a3b1e2989fb6ef2b3e5c2754c8146b960f58 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:07:42 -0400 Subject: [PATCH 162/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 2e1f75a97..325d6c787 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -95,7 +95,7 @@ def is_valid(filename: str) -> Any: return False line = file.readline().strip() if Project._exe_line(line): - if not Project._valid_exe_line(1"), + if not Project._valid_exe_line(line): raise Exception("found bad exe") return False line = file.readline().strip() From 69d060be6b00788e1662e90ae43c47a4f53018e9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:17:50 -0400 Subject: [PATCH 163/184] Update project.py --- src/ms_ovba/Views/project.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 325d6c787..d79b3585c 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -1,5 +1,6 @@ import binascii import re +import warnings from ms_ovba_crypto import MsOvbaCrypto from ms_ovba.vbaProject import VbaProject from typing import Any, TypeVar @@ -78,9 +79,15 @@ def is_valid(filename: str) -> Any: """ with open(filename, 'r', newline='') as file: + i = 1 for line in file: if line[-2:] not in ["\r\n", "\n\r"]: + warnings.warn( + ("Incorrect Line ending: " + + filename + "line: " + i), + SyntaxWarning) return False + line += 1 with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): From b15e4ce974f19f8836fd2bdde9ea454670b7bcf0 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:19:51 -0400 Subject: [PATCH 164/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index d79b3585c..7affcb184 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -84,7 +84,7 @@ def is_valid(filename: str) -> Any: if line[-2:] not in ["\r\n", "\n\r"]: warnings.warn( ("Incorrect Line ending: " + - filename + "line: " + i), + filename + "line: " + str(i)), SyntaxWarning) return False line += 1 From f4ddeb2399f6838280252a56e9ae3aae0b0e3edc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:20:26 -0400 Subject: [PATCH 165/184] Update test_project.py --- tests/Unit/Views/test_project.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 26bcc9064..ba10679c6 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -155,11 +155,11 @@ def test_incorrect_line_endings() -> None: file_numbers = [ -# ("1"), -# ("2"), -# ("3"), -# ("4"), -# ("5"), + ("1"), + ("2"), + ("3"), + ("4"), + ("5"), ("6"), ("7"), ("8"), From 599194435f4359495bd267f214383115c2c14674 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:22:02 -0400 Subject: [PATCH 166/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 7affcb184..5073c9a22 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -87,7 +87,7 @@ def is_valid(filename: str) -> Any: filename + "line: " + str(i)), SyntaxWarning) return False - line += 1 + i += 1 with open(filename, 'r') as file: line = file.readline().strip() if not Project._valid_project_id_line(line): From 1bc9d7e5f010327fb01f725af337c6b94a09b929 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:24:19 -0400 Subject: [PATCH 167/184] Update test_project.py --- tests/Unit/Views/test_project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index ba10679c6..5c5d334a4 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -151,7 +151,8 @@ def test_valid_file() -> None: def test_incorrect_line_endings() -> None: path = 'tests/test_files/PROJECT_bad' - assert not Project.is_valid(path) + with pytest.warns(SyntaxWarning, match="my message"): + assert not Project.is_valid(path) file_numbers = [ From 99b8ce933f936ef960065d2657897f974eb75fd1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:27:25 -0400 Subject: [PATCH 168/184] Update test_project.py --- tests/Unit/Views/test_project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 5c5d334a4..1a9ea384a 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -151,6 +151,7 @@ def test_valid_file() -> None: def test_incorrect_line_endings() -> None: path = 'tests/test_files/PROJECT_bad' + msg = "Incorrect Line ending: " + path + "line: 1" with pytest.warns(SyntaxWarning, match="my message"): assert not Project.is_valid(path) From a153e80476466fe21a292dccaa3794ba949c11bc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:33:06 -0400 Subject: [PATCH 169/184] Update test_project.py --- tests/Unit/Views/test_project.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 1a9ea384a..8fcf66da6 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -152,8 +152,10 @@ def test_valid_file() -> None: def test_incorrect_line_endings() -> None: path = 'tests/test_files/PROJECT_bad' msg = "Incorrect Line ending: " + path + "line: 1" - with pytest.warns(SyntaxWarning, match="my message"): + with pytest.warns() as record: assert not Project.is_valid(path) + assert len(record) == 1 + assert record[0].message.args[0] == msg file_numbers = [ From 66e93c24a16faa34596d90724bf793d3732d518a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:38:20 -0400 Subject: [PATCH 170/184] Update project.py --- src/ms_ovba/Views/project.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 5073c9a22..a3f97ad2d 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -90,22 +90,38 @@ def is_valid(filename: str) -> Any: i += 1 with open(filename, 'r') as file: line = file.readline().strip() + i = 1 if not Project._valid_project_id_line(line): + warnings.warn( + ("Ivalid Data: " + filename + "line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 while Project._project_item_line(line): if not Project._valid_project_item_line(line): + warnings.warn( + ("Ivalid Data: " + filename + "line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if Project._help_file_line(line): if not Project._valid_help_file_line(line): + warnings.warn( + ("Ivalid Data: " + filename + "line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if Project._exe_line(line): if not Project._valid_exe_line(line): - raise Exception("found bad exe") + warnings.warn( + ("Ivalid Data: " + filename + "line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if not Project._valid_name_line(line): return False line = file.readline().strip() From 6a462f0c11fb63ce4496d035955204607f09fe4d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:41:11 -0400 Subject: [PATCH 171/184] Update test_project.py --- tests/Unit/Views/test_project.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 8fcf66da6..9b55c3565 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -179,4 +179,9 @@ def test_incorrect_line_endings() -> None: @pytest.mark.parametrize("number", file_numbers) def test_incorrect_lines(number: str) -> None: path = 'tests/test_files/PROJECT_line' + number - assert not Project.is_valid(path) + msg = f"Incorrect Line ending: {path} line: {number}" + with pytest.warns() as record: + assert not Project.is_valid(path) + assert len(record) == 1 + assert record[0].message.args[0] == msg + From 14fd5ee5598a26c3f146bae2600bf8164d98f2e1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:42:14 -0400 Subject: [PATCH 172/184] Update test_project.py --- tests/Unit/Views/test_project.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 9b55c3565..1740dbe2d 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -184,4 +184,3 @@ def test_incorrect_lines(number: str) -> None: assert not Project.is_valid(path) assert len(record) == 1 assert record[0].message.args[0] == msg - From 41286561c73486baece2eccc6248ccb118fc2e5f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 12:43:59 -0400 Subject: [PATCH 173/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 1740dbe2d..95b07e788 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -179,7 +179,7 @@ def test_incorrect_line_endings() -> None: @pytest.mark.parametrize("number", file_numbers) def test_incorrect_lines(number: str) -> None: path = 'tests/test_files/PROJECT_line' + number - msg = f"Incorrect Line ending: {path} line: {number}" + msg = f"Invalid Data: {path} line: {number}" with pytest.warns() as record: assert not Project.is_valid(path) assert len(record) == 1 From e100618c9a533b81c8b1c1a2532bb87f65eb6d46 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 14:00:58 -0400 Subject: [PATCH 174/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index a3f97ad2d..fc0a6d806 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -93,7 +93,7 @@ def is_valid(filename: str) -> Any: i = 1 if not Project._valid_project_id_line(line): warnings.warn( - ("Ivalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + "line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -101,7 +101,7 @@ def is_valid(filename: str) -> Any: while Project._project_item_line(line): if not Project._valid_project_item_line(line): warnings.warn( - ("Ivalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + "line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -109,7 +109,7 @@ def is_valid(filename: str) -> Any: if Project._help_file_line(line): if not Project._valid_help_file_line(line): warnings.warn( - ("Ivalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + "line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -117,7 +117,7 @@ def is_valid(filename: str) -> Any: if Project._exe_line(line): if not Project._valid_exe_line(line): warnings.warn( - ("Ivalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + "line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() From 17a0588d2c51d71f61aca5f7715ecb8818fb34d9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 14:02:14 -0400 Subject: [PATCH 175/184] Update project.py --- src/ms_ovba/Views/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index fc0a6d806..48addbfe0 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -93,7 +93,7 @@ def is_valid(filename: str) -> Any: i = 1 if not Project._valid_project_id_line(line): warnings.warn( - ("Invalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + " line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -101,7 +101,7 @@ def is_valid(filename: str) -> Any: while Project._project_item_line(line): if not Project._valid_project_item_line(line): warnings.warn( - ("Invalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + " line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -109,7 +109,7 @@ def is_valid(filename: str) -> Any: if Project._help_file_line(line): if not Project._valid_help_file_line(line): warnings.warn( - ("Invalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + " line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() @@ -117,7 +117,7 @@ def is_valid(filename: str) -> Any: if Project._exe_line(line): if not Project._valid_exe_line(line): warnings.warn( - ("Invalid Data: " + filename + "line: " + + ("Invalid Data: " + filename + " line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() From f08a29afaeeec6735f48706dc54c42ffb4f98120 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:20:16 -0400 Subject: [PATCH 176/184] Update project.py --- src/ms_ovba/Views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index 48addbfe0..cbb46c583 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -84,7 +84,7 @@ def is_valid(filename: str) -> Any: if line[-2:] not in ["\r\n", "\n\r"]: warnings.warn( ("Incorrect Line ending: " + - filename + "line: " + str(i)), + filename + " line: " + str(i)), SyntaxWarning) return False i += 1 From 6555faf315662ef79297fe29c3a0d3e87415bfa4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:23:42 -0400 Subject: [PATCH 177/184] Update project.py --- src/ms_ovba/Views/project.py | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index cbb46c583..b219b76c8 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -123,50 +123,102 @@ def is_valid(filename: str) -> Any: line = file.readline().strip() i += 1 if not Project._valid_name_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if not Project._valid_help_id_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if Project._description_line(line): if not Project._valid_description_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if Project._version_line(line): if not Project._valid_version_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if not Project._valid_protection_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if not Project._valid_password_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if not Project._valid_visibility_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if line != "": + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if line != "[HostExtender Info]": + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 while Project._host_extender_line(line): if not Project._valid_host_extender_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 if line != "": + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline() + i += 1 if line != '': line = line.strip() if line != "[Workspace]": + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 while line != '': if not Project._valid_workspace_line(line): + warnings.warn( + ("Invalid Data: " + filename + " line: " + + str(i)), SyntaxWarning) return False line = file.readline().strip() + i += 1 return True @staticmethod From 69c89c4c41433a0bfc8e11d4459f2140b240fff2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:25:57 -0400 Subject: [PATCH 178/184] Update project.py --- src/ms_ovba/Views/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/project.py b/src/ms_ovba/Views/project.py index b219b76c8..08653ce98 100644 --- a/src/ms_ovba/Views/project.py +++ b/src/ms_ovba/Views/project.py @@ -214,8 +214,8 @@ def is_valid(filename: str) -> Any: while line != '': if not Project._valid_workspace_line(line): warnings.warn( - ("Invalid Data: " + filename + " line: " + - str(i)), SyntaxWarning) + ("Invalid Data: " + filename + + " line: " + str(i)), SyntaxWarning) return False line = file.readline().strip() i += 1 From f9281a453c173994a397bcccf64f136b3a288664 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:27:06 -0400 Subject: [PATCH 179/184] Update test_project.py --- tests/Unit/Views/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_project.py b/tests/Unit/Views/test_project.py index 95b07e788..b971157b5 100644 --- a/tests/Unit/Views/test_project.py +++ b/tests/Unit/Views/test_project.py @@ -151,7 +151,7 @@ def test_valid_file() -> None: def test_incorrect_line_endings() -> None: path = 'tests/test_files/PROJECT_bad' - msg = "Incorrect Line ending: " + path + "line: 1" + msg = "Incorrect Line ending: " + path + " line: 1" with pytest.warns() as record: assert not Project.is_valid(path) assert len(record) == 1 From bbc4d9256656ec02420c1ceda8ad09b2ccf63b45 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:29:07 -0400 Subject: [PATCH 180/184] added last line ending --- tests/test_files/PROJECT_line6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line6 b/tests/test_files/PROJECT_line6 index b61a4f197..6249d8069 100644 --- a/tests/test_files/PROJECT_line6 +++ b/tests/test_files/PROJECT_line6 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z From 7b7ae8d3655aab6500a40e5c5658223b7a34ff46 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:49:20 -0400 Subject: [PATCH 181/184] extra line --- tests/test_files/PROJECT_line10 | 2 +- tests/test_files/PROJECT_line11 | 2 +- tests/test_files/PROJECT_line12 | 2 +- tests/test_files/PROJECT_line13 | 2 +- tests/test_files/PROJECT_line14 | 2 +- tests/test_files/PROJECT_line9 | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_files/PROJECT_line10 b/tests/test_files/PROJECT_line10 index 78b2e81be..ffceefec8 100644 --- a/tests/test_files/PROJECT_line10 +++ b/tests/test_files/PROJECT_line10 @@ -18,4 +18,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line11 b/tests/test_files/PROJECT_line11 index cb3cc55e4..39831d9fc 100644 --- a/tests/test_files/PROJECT_line11 +++ b/tests/test_files/PROJECT_line11 @@ -18,4 +18,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line12 b/tests/test_files/PROJECT_line12 index c4c7f4d04..dc7dfa4a0 100644 --- a/tests/test_files/PROJECT_line12 +++ b/tests/test_files/PROJECT_line12 @@ -18,4 +18,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line13 b/tests/test_files/PROJECT_line13 index a8ae9c53c..8003970ec 100644 --- a/tests/test_files/PROJECT_line13 +++ b/tests/test_files/PROJECT_line13 @@ -18,4 +18,4 @@ GCC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line14 b/tests/test_files/PROJECT_line14 index 9084c4061..41947c4b9 100644 --- a/tests/test_files/PROJECT_line14 +++ b/tests/test_files/PROJECT_line14 @@ -17,4 +17,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z diff --git a/tests/test_files/PROJECT_line9 b/tests/test_files/PROJECT_line9 index f7cbf0bbf..3356acdf4 100644 --- a/tests/test_files/PROJECT_line9 +++ b/tests/test_files/PROJECT_line9 @@ -18,4 +18,4 @@ GC="37352C2BDCDD56DE56DEA9" [Workspace] ThisWorkbook=0, 0, 0, 0, C Sheet1=0, 0, 0, 0, C -Module1=26, 26, 1349, 522, Z \ No newline at end of file +Module1=26, 26, 1349, 522, Z From a54d41079e33a0b57bf3e1f8d68d8158417e6d6b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:52:24 -0400 Subject: [PATCH 182/184] fixed bug --- tests/test_files/PROJECT_line9 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_files/PROJECT_line9 b/tests/test_files/PROJECT_line9 index 3356acdf4..dbd28ff0c 100644 --- a/tests/test_files/PROJECT_line9 +++ b/tests/test_files/PROJECT_line9 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description=" VersionCompatible32="393222000" CMG="41435A5A5E5A5E5A5E5A5E" From 03b3510aa512dd617bc228b5736f8caafcbf9a5a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:53:05 -0400 Subject: [PATCH 183/184] fixed bug --- tests/test_files/PROJECT_line10 | 2 +- tests/test_files/PROJECT_line11 | 2 +- tests/test_files/PROJECT_line12 | 2 +- tests/test_files/PROJECT_line13 | 2 +- tests/test_files/PROJECT_line14 | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_files/PROJECT_line10 b/tests/test_files/PROJECT_line10 index ffceefec8..c534fe68a 100644 --- a/tests/test_files/PROJECT_line10 +++ b/tests/test_files/PROJECT_line10 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description="" VersionCompatible32="1.0" CMG="41435A5A5E5A5E5A5E5A5E" diff --git a/tests/test_files/PROJECT_line11 b/tests/test_files/PROJECT_line11 index 39831d9fc..5219073d9 100644 --- a/tests/test_files/PROJECT_line11 +++ b/tests/test_files/PROJECT_line11 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description="" VersionCompatible32="1.0" GMC="41435A5A5E5A5E5A5E5A5E" diff --git a/tests/test_files/PROJECT_line12 b/tests/test_files/PROJECT_line12 index dc7dfa4a0..b01645506 100644 --- a/tests/test_files/PROJECT_line12 +++ b/tests/test_files/PROJECT_line12 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description="" VersionCompatible32="1.0" CMG="41435A5A5E5A5E5A5E5A5E" diff --git a/tests/test_files/PROJECT_line13 b/tests/test_files/PROJECT_line13 index 8003970ec..6be0462b2 100644 --- a/tests/test_files/PROJECT_line13 +++ b/tests/test_files/PROJECT_line13 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description="" VersionCompatible32="1.0" CMG="41435A5A5E5A5E5A5E5A5E" diff --git a/tests/test_files/PROJECT_line14 b/tests/test_files/PROJECT_line14 index 41947c4b9..19143e569 100644 --- a/tests/test_files/PROJECT_line14 +++ b/tests/test_files/PROJECT_line14 @@ -5,7 +5,7 @@ Module=Module1 HelpFile="foo""124.exe" ExeName32="12345678910111213141516171819202122232425262728293031323343536373839404142434445464748945051525354555657585960616263646566" Name="VBAProject" -HelpContextID="X" +HelpContextID="0" Description="" VersionCompatible32="1.0" CMG="41435A5A5E5A5E5A5E5A5E" From 07e0c9e45f8925ade5ce59ddeaae2782729bd68e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 2 Apr 2026 15:54:39 -0400 Subject: [PATCH 184/184] bugs --- tests/test_files/PROJECT_line11 | 2 +- tests/test_files/PROJECT_line12 | 2 +- tests/test_files/PROJECT_line13 | 2 +- tests/test_files/PROJECT_line14 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_files/PROJECT_line11 b/tests/test_files/PROJECT_line11 index 5219073d9..228368467 100644 --- a/tests/test_files/PROJECT_line11 +++ b/tests/test_files/PROJECT_line11 @@ -7,7 +7,7 @@ ExeName32="123456789101112131415161718192021222324252627282930313233435363738394 Name="VBAProject" HelpContextID="0" Description="" -VersionCompatible32="1.0" +VersionCompatible32="393222000" GMC="41435A5A5E5A5E5A5E5A5E" DPB="BCBEA7A2591C5A1C5A1C" GC="37352C2BDCDD56DE56DEA9" diff --git a/tests/test_files/PROJECT_line12 b/tests/test_files/PROJECT_line12 index b01645506..e58170710 100644 --- a/tests/test_files/PROJECT_line12 +++ b/tests/test_files/PROJECT_line12 @@ -7,7 +7,7 @@ ExeName32="123456789101112131415161718192021222324252627282930313233435363738394 Name="VBAProject" HelpContextID="0" Description="" -VersionCompatible32="1.0" +VersionCompatible32="393222000" CMG="41435A5A5E5A5E5A5E5A5E" DPB="BCBEA7A2591C5A" GC="37352C2BDCDD56DE56DEA9" diff --git a/tests/test_files/PROJECT_line13 b/tests/test_files/PROJECT_line13 index 6be0462b2..b47c82c5a 100644 --- a/tests/test_files/PROJECT_line13 +++ b/tests/test_files/PROJECT_line13 @@ -7,7 +7,7 @@ ExeName32="123456789101112131415161718192021222324252627282930313233435363738394 Name="VBAProject" HelpContextID="0" Description="" -VersionCompatible32="1.0" +VersionCompatible32="393222000" CMG="41435A5A5E5A5E5A5E5A5E" DPB="BCBEA7A2591C5A1C5A1C" GCC="37352C2BDCDD56DE56DEA9" diff --git a/tests/test_files/PROJECT_line14 b/tests/test_files/PROJECT_line14 index 19143e569..d99e9e3aa 100644 --- a/tests/test_files/PROJECT_line14 +++ b/tests/test_files/PROJECT_line14 @@ -7,7 +7,7 @@ ExeName32="123456789101112131415161718192021222324252627282930313233435363738394 Name="VBAProject" HelpContextID="0" Description="" -VersionCompatible32="1.0" +VersionCompatible32="393222000" CMG="41435A5A5E5A5E5A5E5A5E" DPB="BCBEA7A2591C5A1C5A1C" GC="37352C2BDCDD56DE56DEA9"