diff --git a/certbot-apache/certbot_apache/apacheparser.py b/certbot-apache/certbot_apache/apacheparser.py index 4a29d2954..993c41035 100644 --- a/certbot-apache/certbot_apache/apacheparser.py +++ b/certbot-apache/certbot_apache/apacheparser.py @@ -78,6 +78,13 @@ class ApacheDirectiveNode(ApacheParserNode): self.enabled = enabled self.include = None + # Loadmodule processing + if self.name and self.name.lower() in ["loadmodule"]: + if "modules_loaded" not in self.metadata: + self.metadata["modules_loaded"] = [set(), set()] + self.metadata["modules_loaded"][0].add(self.parameters[0]) + self.metadata["modules_loaded"][1].add(self.parameters[1]) + # Include processing if self.name and self.name.lower() in ["include", "includeoptional"]: value = self.parameters[0] @@ -134,21 +141,23 @@ def _parameters_from_string(text): return tuple(words) -def _recursive_generator(node, files_visited=None): +def _recursive_generator(node, exclude=True, files_visited=None): # iterator through children, and recursively expands through blocks and includes if not files_visited: files_visited = set([node.filepath]) for child in node.children: + if exclude and not isinstance(child, ApacheCommentNode) and not child.enabled: + continue yield child if isinstance(child, ApacheBlockNode): - for subchild in _recursive_generator(child, files_visited): + for subchild in _recursive_generator(child, exclude, files_visited): yield subchild if isinstance(child, ApacheDirectiveNode) and child.include: for filename in child.include: if filename not in files_visited: files_visited.add(filename) file_ast = node.metadata['parsed_files'][filename] - for subchild in _recursive_generator(file_ast, files_visited): + for subchild in _recursive_generator(file_ast, exclude, files_visited): yield subchild @@ -159,6 +168,16 @@ class ApacheBlockNode(ApacheDirectiveNode): super(ApacheBlockNode, self).__init__(**kwargs) self._raw_children = self._raw children = [] + if self.name and self.name.lower() == "ifmodule": + module_name = self.parameters[0] + expect_loaded = not module_name.startswith("!") + module_name = module_name.strip("!") + loaded = False + if "modules_loaded" in self.metadata: + loaded = (module_name in self.metadata["modules_loaded"][0] or + module_name in self.metadata["modules_loaded"][1]) + self.enabled = self.enabled and expect_loaded == loaded + for raw_node in self._raw_children: metadata = self.metadata.copy() metadata['ac_ast'] = raw_node @@ -170,14 +189,14 @@ class ApacheBlockNode(ApacheDirectiveNode): parameters = _parameters_from_string(raw_node.arguments) node = ApacheBlockNode(name=raw_node.tag, parameters=parameters, metadata=metadata, ancestor=self, - filepath=self.filepath) + filepath=self.filepath, enabled = self.enabled) else: parameters = () if raw_node.value: parameters = _parameters_from_string(raw_node.value) node = ApacheDirectiveNode(name=raw_node.name, parameters=parameters, metadata=metadata, - ancestor=self, filepath=self.filepath) + ancestor=self, filepath=self.filepath, enabled=self.enabled) children.append(node) self.children = tuple(children) @@ -250,7 +269,7 @@ class ApacheBlockNode(ApacheDirectiveNode): def find_blocks(self, name, exclude=True): # pylint: disable=unused-argument """Recursive search of BlockNodes from the sequence of children""" blocks = [] - for child in _recursive_generator(self): + for child in _recursive_generator(self, exclude=exclude): if isinstance(child, ApacheBlockNode) and child.name.lower() == name.lower(): blocks.append(child) return blocks @@ -258,7 +277,7 @@ class ApacheBlockNode(ApacheDirectiveNode): def find_directives(self, name, exclude=True): # pylint: disable=unused-argument """Recursive search of DirectiveNodes from the sequence of children""" directives = [] - for child in _recursive_generator(self): + for child in _recursive_generator(self, exclude=exclude): if isinstance(child, ApacheDirectiveNode) and child.name.lower() == name.lower(): directives.append(child) return directives diff --git a/certbot-apache/certbot_apache/dualparser.py b/certbot-apache/certbot_apache/dualparser.py index 24c385504..1626e39f9 100644 --- a/certbot-apache/certbot_apache/dualparser.py +++ b/certbot-apache/certbot_apache/dualparser.py @@ -239,8 +239,7 @@ class DualBlockNode(DualNodeBase): raise AssertionError("Could not find a matching node.") return matched - # TODO: Re-set default "exclude" to True when apacheconfig version is implemented. - def find_blocks(self, name, exclude=False): + def find_blocks(self, name, exclude=True): """ Performs a search for BlockNodes using both implementations and does simple checks for results. This is built upon the assumption that unimplemented @@ -252,7 +251,7 @@ class DualBlockNode(DualNodeBase): return self._find_helper(DualBlockNode, "find_blocks", name, exclude=exclude) - def find_directives(self, name, exclude=False): + def find_directives(self, name, exclude=True): """ Performs a search for DirectiveNodes using both implementations and checks the results. This is built upon the assumption that unimplemented diff --git a/certbot-apache/certbot_apache/tests/augeasnode_test.py b/certbot-apache/certbot_apache/tests/augeasnode_test.py index 95fb736ba..4f20e8ace 100644 --- a/certbot-apache/certbot_apache/tests/augeasnode_test.py +++ b/certbot-apache/certbot_apache/tests/augeasnode_test.py @@ -74,7 +74,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- def test_find_directive_found(self): directives = self.config.parser_root.find_directives("Listen") - self.assertEqual(len(directives), 3) + self.assertEqual(len(directives), 1) self.assertTrue(directives[0].filepath.endswith("/apache2/ports.conf")) self.assertEqual(directives[0].parameters, (u'80',)) @@ -116,7 +116,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- def test_set_parameters_atinit(self): from certbot_apache.augeasparser import AugeasDirectiveNode - servernames = self.config.parser_root.find_directives("servername", exclude=False) + servernames = self.config.parser_root.find_directives("servername") setparam = "certbot_apache.augeasparser.AugeasDirectiveNode.set_parameters" with mock.patch(setparam) as mock_set: AugeasDirectiveNode(