Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'certbot-apache/certbot_apache/parser.py')
-rw-r--r--certbot-apache/certbot_apache/parser.py822
1 files changed, 0 insertions, 822 deletions
diff --git a/certbot-apache/certbot_apache/parser.py b/certbot-apache/certbot_apache/parser.py
deleted file mode 100644
index 148f052d0..000000000
--- a/certbot-apache/certbot_apache/parser.py
+++ /dev/null
@@ -1,822 +0,0 @@
-"""ApacheParser is a member object of the ApacheConfigurator class."""
-import copy
-import fnmatch
-import logging
-import os
-import re
-import subprocess
-import sys
-
-import six
-
-from acme.magic_typing import Dict, List, Set # pylint: disable=unused-import, no-name-in-module
-from certbot import errors
-
-logger = logging.getLogger(__name__)
-
-
-class ApacheParser(object):
- # pylint: disable=too-many-public-methods
- """Class handles the fine details of parsing the Apache Configuration.
-
- .. todo:: Make parsing general... remove sites-available etc...
-
- :ivar str root: Normalized absolute path to the server root
- directory. Without trailing slash.
- :ivar set modules: All module names that are currently enabled.
- :ivar dict loc: Location to place directives, root - configuration origin,
- default - user config file, name - NameVirtualHost,
-
- """
- arg_var_interpreter = re.compile(r"\$\{[^ \}]*}")
- fnmatch_chars = set(["*", "?", "\\", "[", "]"])
-
- def __init__(self, aug, root, vhostroot=None, version=(2, 4),
- configurator=None):
- # Note: Order is important here.
-
- # Needed for calling save() with reverter functionality that resides in
- # AugeasConfigurator superclass of ApacheConfigurator. This resolves
- # issues with aug.load() after adding new files / defines to parse tree
- self.configurator = configurator
-
- self.modules = set() # type: Set[str]
- self.parser_paths = {} # type: Dict[str, List[str]]
- self.variables = {} # type: Dict[str, str]
-
- self.aug = aug
- # Find configuration root and make sure augeas can parse it.
- self.root = os.path.abspath(root)
- self.loc = {"root": self._find_config_root()}
- self.parse_file(self.loc["root"])
-
- if version >= (2, 4):
- # Look up variables from httpd and add to DOM if not already parsed
- self.update_runtime_variables()
-
- # This problem has been fixed in Augeas 1.0
- self.standardize_excl()
-
- # Parse LoadModule directives from configuration files
- self.parse_modules()
-
- # Set up rest of locations
- self.loc.update(self._set_locations())
-
- # list of the active include paths, before modifications
- self.existing_paths = copy.deepcopy(self.parser_paths)
-
- # Must also attempt to parse additional virtual host root
- if vhostroot:
- self.parse_file(os.path.abspath(vhostroot) + "/" +
- self.configurator.option("vhost_files"))
-
- # check to see if there were unparsed define statements
- if version < (2, 4):
- if self.find_dir("Define", exclude=False):
- raise errors.PluginError("Error parsing runtime variables")
-
- def add_include(self, main_config, inc_path):
- """Add Include for a new configuration file if one does not exist
-
- :param str main_config: file path to main Apache config file
- :param str inc_path: path of file to include
-
- """
- if len(self.find_dir(case_i("Include"), inc_path)) == 0:
- logger.debug("Adding Include %s to %s",
- inc_path, get_aug_path(main_config))
- self.add_dir(
- get_aug_path(main_config),
- "Include", inc_path)
-
- # Add new path to parser paths
- new_dir = os.path.dirname(inc_path)
- new_file = os.path.basename(inc_path)
- if new_dir in self.existing_paths.keys():
- # Add to existing path
- self.existing_paths[new_dir].append(new_file)
- else:
- # Create a new path
- self.existing_paths[new_dir] = [new_file]
-
- def add_mod(self, mod_name):
- """Shortcut for updating parser modules."""
- if mod_name + "_module" not in self.modules:
- self.modules.add(mod_name + "_module")
- if "mod_" + mod_name + ".c" not in self.modules:
- self.modules.add("mod_" + mod_name + ".c")
-
- def reset_modules(self):
- """Reset the loaded modules list. This is called from cleanup to clear
- temporarily loaded modules."""
- self.modules = set()
- self.update_modules()
- self.parse_modules()
-
- def parse_modules(self):
- """Iterates on the configuration until no new modules are loaded.
-
- ..todo:: This should be attempted to be done with a binary to avoid
- the iteration issue. Else... parse and enable mods at same time.
-
- """
- mods = set() # type: Set[str]
- matches = self.find_dir("LoadModule")
- iterator = iter(matches)
- # Make sure prev_size != cur_size for do: while: iteration
- prev_size = -1
-
- while len(mods) != prev_size:
- prev_size = len(mods)
-
- for match_name, match_filename in six.moves.zip(
- iterator, iterator):
- mod_name = self.get_arg(match_name)
- mod_filename = self.get_arg(match_filename)
- if mod_name and mod_filename:
- mods.add(mod_name)
- mods.add(os.path.basename(mod_filename)[:-2] + "c")
- else:
- logger.debug("Could not read LoadModule directive from " +
- "Augeas path: {0}".format(match_name[6:]))
- self.modules.update(mods)
-
- def update_runtime_variables(self):
- """Update Includes, Defines and Includes from httpd config dump data"""
- self.update_defines()
- self.update_includes()
- self.update_modules()
-
- def update_defines(self):
- """Get Defines from httpd process"""
-
- variables = dict()
- define_cmd = [self.configurator.option("ctl"), "-t", "-D",
- "DUMP_RUN_CFG"]
- matches = self.parse_from_subprocess(define_cmd, r"Define: ([^ \n]*)")
- try:
- matches.remove("DUMP_RUN_CFG")
- except ValueError:
- return
-
- for match in matches:
- if match.count("=") > 1:
- logger.error("Unexpected number of equal signs in "
- "runtime config dump.")
- raise errors.PluginError(
- "Error parsing Apache runtime variables")
- parts = match.partition("=")
- variables[parts[0]] = parts[2]
-
- self.variables = variables
-
- def update_includes(self):
- """Get includes from httpd process, and add them to DOM if needed"""
-
- # Find_dir iterates over configuration for Include and IncludeOptional
- # directives to make sure we see the full include tree present in the
- # configuration files
- _ = self.find_dir("Include")
-
- inc_cmd = [self.configurator.option("ctl"), "-t", "-D",
- "DUMP_INCLUDES"]
- matches = self.parse_from_subprocess(inc_cmd, r"\(.*\) (.*)")
- if matches:
- for i in matches:
- if not self.parsed_in_current(i):
- self.parse_file(i)
-
- def update_modules(self):
- """Get loaded modules from httpd process, and add them to DOM"""
-
- mod_cmd = [self.configurator.option("ctl"), "-t", "-D",
- "DUMP_MODULES"]
- matches = self.parse_from_subprocess(mod_cmd, r"(.*)_module")
- for mod in matches:
- self.add_mod(mod.strip())
-
- def parse_from_subprocess(self, command, regexp):
- """Get values from stdout of subprocess command
-
- :param list command: Command to run
- :param str regexp: Regexp for parsing
-
- :returns: list parsed from command output
- :rtype: list
-
- """
- stdout = self._get_runtime_cfg(command)
- return re.compile(regexp).findall(stdout)
-
- def _get_runtime_cfg(self, command): # pylint: disable=no-self-use
- """Get runtime configuration info.
- :param command: Command to run
-
- :returns: stdout from command
-
- """
- try:
- proc = subprocess.Popen(
- command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- universal_newlines=True)
- stdout, stderr = proc.communicate()
-
- except (OSError, ValueError):
- logger.error(
- "Error running command %s for runtime parameters!%s",
- command, os.linesep)
- raise errors.MisconfigurationError(
- "Error accessing loaded Apache parameters: %s",
- command)
- # Small errors that do not impede
- if proc.returncode != 0:
- logger.warning("Error in checking parameter list: %s", stderr)
- raise errors.MisconfigurationError(
- "Apache is unable to check whether or not the module is "
- "loaded because Apache is misconfigured.")
-
- return stdout
-
- def filter_args_num(self, matches, args): # pylint: disable=no-self-use
- """Filter out directives with specific number of arguments.
-
- This function makes the assumption that all related arguments are given
- in order. Thus /files/apache/directive[5]/arg[2] must come immediately
- after /files/apache/directive[5]/arg[1]. Runs in 1 linear pass.
-
- :param string matches: Matches of all directives with arg nodes
- :param int args: Number of args you would like to filter
-
- :returns: List of directives that contain # of arguments.
- (arg is stripped off)
-
- """
- filtered = []
- if args == 1:
- for i in range(len(matches)):
- if matches[i].endswith("/arg"):
- filtered.append(matches[i][:-4])
- else:
- for i in range(len(matches)):
- if matches[i].endswith("/arg[%d]" % args):
- # Make sure we don't cause an IndexError (end of list)
- # Check to make sure arg + 1 doesn't exist
- if (i == (len(matches) - 1) or
- not matches[i + 1].endswith("/arg[%d]" %
- (args + 1))):
- filtered.append(matches[i][:-len("/arg[%d]" % args)])
-
- return filtered
-
- def add_dir_to_ifmodssl(self, aug_conf_path, directive, args):
- """Adds directive and value to IfMod ssl block.
-
- Adds given directive and value along configuration path within
- an IfMod mod_ssl.c block. If the IfMod block does not exist in
- the file, it is created.
-
- :param str aug_conf_path: Desired Augeas config path to add directive
- :param str directive: Directive you would like to add, e.g. Listen
- :param args: Values of the directive; str "443" or list of str
- :type args: list
-
- """
- # TODO: Add error checking code... does the path given even exist?
- # Does it throw exceptions?
- if_mod_path = self._get_ifmod(aug_conf_path, "mod_ssl.c")
- # IfModule can have only one valid argument, so append after
- self.aug.insert(if_mod_path + "arg", "directive", False)
- nvh_path = if_mod_path + "directive[1]"
- self.aug.set(nvh_path, directive)
- if len(args) == 1:
- self.aug.set(nvh_path + "/arg", args[0])
- else:
- for i, arg in enumerate(args):
- self.aug.set("%s/arg[%d]" % (nvh_path, i + 1), arg)
-
- def _get_ifmod(self, aug_conf_path, mod):
- """Returns the path to <IfMod mod> and creates one if it doesn't exist.
-
- :param str aug_conf_path: Augeas configuration path
- :param str mod: module ie. mod_ssl.c
-
- """
- if_mods = self.aug.match(("%s/IfModule/*[self::arg='%s']" %
- (aug_conf_path, mod)))
- if len(if_mods) == 0:
- self.aug.set("%s/IfModule[last() + 1]" % aug_conf_path, "")
- self.aug.set("%s/IfModule[last()]/arg" % aug_conf_path, mod)
- if_mods = self.aug.match(("%s/IfModule/*[self::arg='%s']" %
- (aug_conf_path, mod)))
- # Strip off "arg" at end of first ifmod path
- return if_mods[0][:len(if_mods[0]) - 3]
-
- def add_dir(self, aug_conf_path, directive, args):
- """Appends directive to the end fo the file given by aug_conf_path.
-
- .. note:: Not added to AugeasConfigurator because it may depend
- on the lens
-
- :param str aug_conf_path: Augeas configuration path to add directive
- :param str directive: Directive to add
- :param args: Value of the directive. ie. Listen 443, 443 is arg
- :type args: list or str
-
- """
- self.aug.set(aug_conf_path + "/directive[last() + 1]", directive)
- if isinstance(args, list):
- for i, value in enumerate(args, 1):
- self.aug.set(
- "%s/directive[last()]/arg[%d]" % (aug_conf_path, i), value)
- else:
- self.aug.set(aug_conf_path + "/directive[last()]/arg", args)
-
- def add_dir_beginning(self, aug_conf_path, dirname, args):
- """Adds the directive to the beginning of defined aug_conf_path.
-
- :param str aug_conf_path: Augeas configuration path to add directive
- :param str dirname: Directive to add
- :param args: Value of the directive. ie. Listen 443, 443 is arg
- :type args: list or str
- """
- first_dir = aug_conf_path + "/directive[1]"
- self.aug.insert(first_dir, "directive", True)
- self.aug.set(first_dir, dirname)
- if isinstance(args, list):
- for i, value in enumerate(args, 1):
- self.aug.set(first_dir + "/arg[%d]" % (i), value)
- else:
- self.aug.set(first_dir + "/arg", args)
-
- def add_comment(self, aug_conf_path, comment):
- """Adds the comment to the augeas path
-
- :param str aug_conf_path: Augeas configuration path to add directive
- :param str comment: Comment content
-
- """
- self.aug.set(aug_conf_path + "/#comment[last() + 1]", comment)
-
- def find_comments(self, arg, start=None):
- """Finds a comment with specified content from the provided DOM path
-
- :param str arg: Comment content to search
- :param str start: Beginning Augeas path to begin looking
-
- :returns: List of augeas paths containing the comment content
- :rtype: list
-
- """
- if not start:
- start = get_aug_path(self.root)
-
- comments = self.aug.match("%s//*[label() = '#comment']" % start)
-
- results = []
- for comment in comments:
- c_content = self.aug.get(comment)
- if c_content and arg in c_content:
- results.append(comment)
- return results
-
- def find_dir(self, directive, arg=None, start=None, exclude=True):
- """Finds directive in the configuration.
-
- Recursively searches through config files to find directives
- Directives should be in the form of a case insensitive regex currently
-
- .. todo:: arg should probably be a list
- .. todo:: arg search currently only supports direct matching. It does
- not handle the case of variables or quoted arguments. This should
- be adapted to use a generic search for the directive and then do a
- case-insensitive self.get_arg filter
-
- Note: Augeas is inherently case sensitive while Apache is case
- insensitive. Augeas 1.0 allows case insensitive regexes like
- regexp(/Listen/, "i"), however the version currently supported
- by Ubuntu 0.10 does not. Thus I have included my own case insensitive
- transformation by calling case_i() on everything to maintain
- compatibility.
-
- :param str directive: Directive to look for
- :param arg: Specific value directive must have, None if all should
- be considered
- :type arg: str or None
-
- :param str start: Beginning Augeas path to begin looking
- :param bool exclude: Whether or not to exclude directives based on
- variables and enabled modules
-
- """
- # Cannot place member variable in the definition of the function so...
- if not start:
- start = get_aug_path(self.loc["root"])
-
- # No regexp code
- # if arg is None:
- # matches = self.aug.match(start +
- # "//*[self::directive='" + directive + "']/arg")
- # else:
- # matches = self.aug.match(start +
- # "//*[self::directive='" + directive +
- # "']/* [self::arg='" + arg + "']")
-
- # includes = self.aug.match(start +
- # "//* [self::directive='Include']/* [label()='arg']")
-
- regex = "(%s)|(%s)|(%s)" % (case_i(directive),
- case_i("Include"),
- case_i("IncludeOptional"))
- matches = self.aug.match(
- "%s//*[self::directive=~regexp('%s')]" % (start, regex))
-
- if exclude:
- matches = self._exclude_dirs(matches)
-
- if arg is None:
- arg_suffix = "/arg"
- else:
- arg_suffix = "/*[self::arg=~regexp('%s')]" % case_i(arg)
-
- ordered_matches = [] # type: List[str]
-
- # TODO: Wildcards should be included in alphabetical order
- # https://httpd.apache.org/docs/2.4/mod/core.html#include
- for match in matches:
- dir_ = self.aug.get(match).lower()
- if dir_ == "include" or dir_ == "includeoptional":
- ordered_matches.extend(self.find_dir(
- directive, arg,
- self._get_include_path(self.get_arg(match + "/arg")),
- exclude))
- # This additionally allows Include
- if dir_ == directive.lower():
- ordered_matches.extend(self.aug.match(match + arg_suffix))
-
- return ordered_matches
-
- def get_arg(self, match):
- """Uses augeas.get to get argument value and interprets result.
-
- This also converts all variables and parameters appropriately.
-
- """
- value = self.aug.get(match)
-
- # No need to strip quotes for variables, as apache2ctl already does
- # this, but we do need to strip quotes for all normal arguments.
-
- # Note: normal argument may be a quoted variable
- # e.g. strip now, not later
- if not value:
- return None
- else:
- value = value.strip("'\"")
-
- variables = ApacheParser.arg_var_interpreter.findall(value)
-
- for var in variables:
- # Strip off ${ and }
- try:
- value = value.replace(var, self.variables[var[2:-1]])
- except KeyError:
- raise errors.PluginError("Error Parsing variable: %s" % var)
-
- return value
-
- def _exclude_dirs(self, matches):
- """Exclude directives that are not loaded into the configuration."""
- filters = [("ifmodule", self.modules), ("ifdefine", self.variables)]
-
- valid_matches = []
-
- for match in matches:
- for filter_ in filters:
- if not self._pass_filter(match, filter_):
- break
- else:
- valid_matches.append(match)
- return valid_matches
-
- def _pass_filter(self, match, filter_):
- """Determine if directive passes a filter.
-
- :param str match: Augeas path
- :param list filter: list of tuples of form
- [("lowercase if directive", set of relevant parameters)]
-
- """
- match_l = match.lower()
- last_match_idx = match_l.find(filter_[0])
-
- while last_match_idx != -1:
- # Check args
- end_of_if = match_l.find("/", last_match_idx)
- # This should be aug.get (vars are not used e.g. parser.aug_get)
- expression = self.aug.get(match[:end_of_if] + "/arg")
-
- if expression.startswith("!"):
- # Strip off "!"
- if expression[1:] in filter_[1]:
- return False
- else:
- if expression not in filter_[1]:
- return False
-
- last_match_idx = match_l.find(filter_[0], end_of_if)
-
- return True
-
- def _get_include_path(self, arg):
- """Converts an Apache Include directive into Augeas path.
-
- Converts an Apache Include directive argument into an Augeas
- searchable path
-
- .. todo:: convert to use os.path.join()
-
- :param str arg: Argument of Include directive
-
- :returns: Augeas path string
- :rtype: str
-
- """
- # Check to make sure only expected characters are used <- maybe remove
- # validChars = re.compile("[a-zA-Z0-9.*?_-/]*")
- # matchObj = validChars.match(arg)
- # if matchObj.group() != arg:
- # logger.error("Error: Invalid regexp characters in %s", arg)
- # return []
-
- # Remove beginning and ending quotes
- arg = arg.strip("'\"")
-
- # Standardize the include argument based on server root
- if not arg.startswith("/"):
- # Normpath will condense ../
- arg = os.path.normpath(os.path.join(self.root, arg))
- else:
- arg = os.path.normpath(arg)
-
- # Attempts to add a transform to the file if one does not already exist
- if os.path.isdir(arg):
- self.parse_file(os.path.join(arg, "*"))
- else:
- self.parse_file(arg)
-
- # Argument represents an fnmatch regular expression, convert it
- # Split up the path and convert each into an Augeas accepted regex
- # then reassemble
- split_arg = arg.split("/")
- for idx, split in enumerate(split_arg):
- if any(char in ApacheParser.fnmatch_chars for char in split):
- # Turn it into a augeas regex
- # TODO: Can this instead be an augeas glob instead of regex
- split_arg[idx] = ("* [label()=~regexp('%s')]" %
- self.fnmatch_to_re(split))
- # Reassemble the argument
- # Note: This also normalizes the argument /serverroot/ -> /serverroot
- arg = "/".join(split_arg)
-
- return get_aug_path(arg)
-
- def fnmatch_to_re(self, clean_fn_match): # pylint: disable=no-self-use
- """Method converts Apache's basic fnmatch to regular expression.
-
- Assumption - Configs are assumed to be well-formed and only writable by
- privileged users.
-
- https://apr.apache.org/docs/apr/2.0/apr__fnmatch_8h_source.html
- http://apache2.sourcearchive.com/documentation/2.2.16-6/apr__fnmatch_8h_source.html
-
- :param str clean_fn_match: Apache style filename match, like globs
-
- :returns: regex suitable for augeas
- :rtype: str
-
- """
- if sys.version_info < (3, 6):
- # This strips off final /Z(?ms)
- return fnmatch.translate(clean_fn_match)[:-7]
- else: # pragma: no cover
- # Since Python 3.6, it returns a different pattern like (?s:.*\.load)\Z
- return fnmatch.translate(clean_fn_match)[4:-3]
-
- def parse_file(self, filepath):
- """Parse file with Augeas
-
- Checks to see if file_path is parsed by Augeas
- If filepath isn't parsed, the file is added and Augeas is reloaded
-
- :param str filepath: Apache config file path
-
- """
- use_new, remove_old = self._check_path_actions(filepath)
- # Ensure that we have the latest Augeas DOM state on disk before
- # calling aug.load() which reloads the state from disk
- if self.configurator:
- self.configurator.ensure_augeas_state()
- # Test if augeas included file for Httpd.lens
- # Note: This works for augeas globs, ie. *.conf
- if use_new:
- inc_test = self.aug.match(
- "/augeas/load/Httpd['%s' =~ glob(incl)]" % filepath)
- if not inc_test:
- # Load up files
- # This doesn't seem to work on TravisCI
- # self.aug.add_transform("Httpd.lns", [filepath])
- if remove_old:
- self._remove_httpd_transform(filepath)
- self._add_httpd_transform(filepath)
- self.aug.load()
-
- def parsed_in_current(self, filep):
- """Checks if the file path is parsed by current Augeas parser config
- ie. returns True if the file is found on a path that's found in live
- Augeas configuration.
-
- :param str filep: Path to match
-
- :returns: True if file is parsed in existing configuration tree
- :rtype: bool
- """
- return self._parsed_by_parser_paths(filep, self.parser_paths)
-
- def parsed_in_original(self, filep):
- """Checks if the file path is parsed by existing Apache config.
- ie. returns True if the file is found on a path that matches Include or
- IncludeOptional statement in the Apache configuration.
-
- :param str filep: Path to match
-
- :returns: True if file is parsed in existing configuration tree
- :rtype: bool
- """
- return self._parsed_by_parser_paths(filep, self.existing_paths)
-
- def _parsed_by_parser_paths(self, filep, paths):
- """Helper function that searches through provided paths and returns
- True if file path is found in the set"""
- for directory in paths.keys():
- for filename in paths[directory]:
- if fnmatch.fnmatch(filep, os.path.join(directory, filename)):
- return True
- return False
-
- def _check_path_actions(self, filepath):
- """Determine actions to take with a new augeas path
-
- This helper function will return a tuple that defines
- if we should try to append the new filepath to augeas
- parser paths, and / or remove the old one with more
- narrow matching.
-
- :param str filepath: filepath to check the actions for
-
- """
-
- try:
- new_file_match = os.path.basename(filepath)
- existing_matches = self.parser_paths[os.path.dirname(filepath)]
- if "*" in existing_matches:
- use_new = False
- else:
- use_new = True
- if new_file_match == "*":
- remove_old = True
- else:
- remove_old = False
- except KeyError:
- use_new = True
- remove_old = False
- return use_new, remove_old
-
- def _remove_httpd_transform(self, filepath):
- """Remove path from Augeas transform
-
- :param str filepath: filepath to remove
- """
-
- remove_basenames = self.parser_paths[os.path.dirname(filepath)]
- remove_dirname = os.path.dirname(filepath)
- for name in remove_basenames:
- remove_path = remove_dirname + "/" + name
- remove_inc = self.aug.match(
- "/augeas/load/Httpd/incl [. ='%s']" % remove_path)
- self.aug.remove(remove_inc[0])
- self.parser_paths.pop(remove_dirname)
-
- def _add_httpd_transform(self, incl):
- """Add a transform to Augeas.
-
- This function will correctly add a transform to augeas
- The existing augeas.add_transform in python doesn't seem to work for
- Travis CI as it loads in libaugeas.so.0.10.0
-
- :param str incl: filepath to include for transform
-
- """
- last_include = self.aug.match("/augeas/load/Httpd/incl [last()]")
- if last_include:
- # Insert a new node immediately after the last incl
- self.aug.insert(last_include[0], "incl", False)
- self.aug.set("/augeas/load/Httpd/incl[last()]", incl)
- # On first use... must load lens and add file to incl
- else:
- # Augeas uses base 1 indexing... insert at beginning...
- self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns")
- self.aug.set("/augeas/load/Httpd/incl", incl)
- # Add included path to paths dictionary
- try:
- self.parser_paths[os.path.dirname(incl)].append(
- os.path.basename(incl))
- except KeyError:
- self.parser_paths[os.path.dirname(incl)] = [
- os.path.basename(incl)]
-
- def standardize_excl(self):
- """Standardize the excl arguments for the Httpd lens in Augeas.
-
- Note: Hack!
- Standardize the excl arguments for the Httpd lens in Augeas
- Servers sometimes give incorrect defaults
- Note: This problem should be fixed in Augeas 1.0. Unfortunately,
- Augeas 0.10 appears to be the most popular version currently.
-
- """
- # attempt to protect against augeas error in 0.10.0 - ubuntu
- # *.augsave -> /*.augsave upon augeas.load()
- # Try to avoid bad httpd files
- # There has to be a better way... but after a day and a half of testing
- # I had no luck
- # This is a hack... work around... submit to augeas if still not fixed
-
- excl = ["*.augnew", "*.augsave", "*.dpkg-dist", "*.dpkg-bak",
- "*.dpkg-new", "*.dpkg-old", "*.rpmsave", "*.rpmnew",
- "*~",
- self.root + "/*.augsave",
- self.root + "/*~",
- self.root + "/*/*augsave",
- self.root + "/*/*~",
- self.root + "/*/*/*.augsave",
- self.root + "/*/*/*~"]
-
- for i, excluded in enumerate(excl, 1):
- self.aug.set("/augeas/load/Httpd/excl[%d]" % i, excluded)
-
- self.aug.load()
-
- def _set_locations(self):
- """Set default location for directives.
-
- Locations are given as file_paths
- .. todo:: Make sure that files are included
-
- """
- default = self.loc["root"]
-
- temp = os.path.join(self.root, "ports.conf")
- if os.path.isfile(temp):
- listen = temp
- name = temp
- else:
- listen = default
- name = default
-
- return {"default": default, "listen": listen, "name": name}
-
- def _find_config_root(self):
- """Find the Apache Configuration Root file."""
- location = ["apache2.conf", "httpd.conf", "conf/httpd.conf"]
- for name in location:
- if os.path.isfile(os.path.join(self.root, name)):
- return os.path.join(self.root, name)
- raise errors.NoInstallationError("Could not find configuration root")
-
-
-def case_i(string):
- """Returns case insensitive regex.
-
- Returns a sloppy, but necessary version of a case insensitive regex.
- Any string should be able to be submitted and the string is
- escaped and then made case insensitive.
- May be replaced by a more proper /i once augeas 1.0 is widely
- supported.
-
- :param str string: string to make case i regex
-
- """
- return "".join(["[" + c.upper() + c.lower() + "]"
- if c.isalpha() else c for c in re.escape(string)])
-
-
-def get_aug_path(file_path):
- """Return augeas path for full filepath.
-
- :param str file_path: Full filepath
-
- """
- return "/files%s" % file_path