o
    cď                     @   s^  d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ertddlmZ zddlmZ W n ey   dZY nw eeZG dd dZ de!de!fddZ"de!de!fddZ#defddZ$dS )z@ApacheParser is a member object of the ApacheConfigurator class.    N)
Collection)Dict)Iterable)List)Mapping)Optional)Pattern)Set)Tuple)TYPE_CHECKING)Union)errors)os)apache_util)	constants)ApacheConfigurator)Augeasc                   @   s  e Zd ZU dZedZeed< h dZ	e
e ed< 	dydedd	d
edeedf ddf
ddZdeddfddZdeeee f fddZde
e fddZdzddZdee ddfddZdee ddfddZd ed!eddfd"d#Zd$eddfd%d&Zdzd'd(Zdzd)d*Zdzd+d,Zdzd-d.Zdzd/d0Zdzd1d2Z d3ed4edee fd5d6Z!d7ed8ed4ee ddfd9d:Z"d7ed;edefd<d=Z#d7ed;edefd>d?Z$d7e%e d8e%e d4eee ef ddfd@dAZ&d7e%e dBed4eee ef ddfdCdDZ'd7edEeddfdFdGZ(d{dHedIe%e dee fdJdKZ)		Ld|d8edHe%e dIe%e dMedee f
dNdOZ*dPede%e fdQdRZ+defdSdTZ,d3ee dee fdUdVZ-dPedWeee.e f defdXdYZ/dHedefdZd[Z0dHe%e de%e fd\d]Z1d^edefd_d`Z2daeddfdbdcZ3dde%e defdedfZ4dde%e defdgdhZ5ddedie6eee f defdjdkZ7daedeeef fdldmZ8daeddfdndoZ9dpeddfdqdrZ:dzdsdtZ;de<eef fdudvZ=defdwdxZ>dS )}ApacheParsera  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,

    z\$\{[^ \}]*}arg_var_interpreter>   *?[\]fnmatch_chars      rootconfiguratorr   	vhostrootversion.returnNc                 C   s   || _ t | _|  stdi | _i | _i | _t	j
|| _d|  i| _| | jd  |   |   |   | j|   t| j| _|r^| t	j
|d | j jj  d S d S )NzApache plugin support requires libaugeas0 and augeas-lenses version 1.2.0 or higher, please make sure you have you have those installed.r   /)r   init_augeasaugcheck_aug_versionr   NotSupportedErrormodulesparser_paths	variablesr   pathabspathr   _find_config_rootloc
parse_fileupdate_runtime_variablesstandardize_exclparse_modulesupdate_set_locationscopydeepcopyexisting_pathsoptionsvhost_files)selfr   r   r    r!    r;   L/opt/certbot/lib/python3.10/site-packages/certbot_apache/_internal/parser.py__init__2   s,   
zApacheParser.__init__lensc              	   C   sv   | j d}|D ]0}| j |d }|r8||v r8d|dt|d  | j |d | j |d }t|qdS )	zVerify Augeas can parse all of the lens files.

        :param str lens: lens to check for errors

        :raises .errors.PluginError: If there has been an error in parsing with
            the specified lens.

        /augeas//errorz/lensz@There has been an error in parsing the file {0} on line {1}: {2}      z/line/messageN)r%   matchgetformatlenr   PluginError)r:   r>   error_filesr+   	lens_pathmsgr;   r;   r<   check_parsing_errorsa   s   	
z!ApacheParser.check_parsing_errorsc                 C   sP   | j dd z| j d}W n ty   | j d Y dS w | j d |S )z Checks that we have recent enough version of libaugeas.
        If augeas version is recent enough, it will support case insensitive
        regexp matchingz/test/path/testing/argaRgUMeNTz,/test//*[self::arg=~regexp('argument', 'i')]z
/test/pathF)r%   setrC   RuntimeErrorremove)r:   matchesr;   r;   r<   r&   {   s   zApacheParser.check_aug_versionc              	   C   s   | j d}| j dd | j d}z| j   W n ttfy1   | | d| j_	t
dw | j d| | j d}t }|rV|D ]}|| j |dd  qF|S )	a  Lists files that have modified Augeas DOM but the changes have not
        been written to the filesystem yet, used by `self.save()` and
        ApacheConfigurator to check the file state.

        :raises .errors.PluginError: If there was an error in Augeas, in
            an attempt to save the configuration, or an error creating a
            checkpoint

        :returns: `set` of unsaved files
        z/augeas/savenoopr?    z-Error saving files, check logs for more info.z/augeas/events/savedrA   N)r%   rD   rM   rC   saverN   IOError_log_save_errorsr   
save_notesr   rG   add)r:   
save_stateex_errs
save_paths
save_filesr+   r;   r;   r<   unsaved_files   s&   
zApacheParser.unsaved_filesc                 C   s*   |   r| j jd7  _| j  dS dS )zMakes sure that all Augeas dom changes are written to files to avoid
        loss of configuration directives when doing additional augeas parsing,
        causing a possible augeas.load() resulting dom reset
        z
(autosave)N)r\   r   rV   rS   r:   r;   r;   r<   ensure_augeas_state   s   z ApacheParser.ensure_augeas_stater[   c                 C   sn   d| j _| jd}z| j  W n ty   | |  w |r5|D ]
}| jd|  q#| j  dS dS )zSaves all changes to the configuration files.

        save() is called from ApacheConfigurator to handle the parser specific
        tasks of saving.

        :param list save_files: list of strings of file paths that we need to save.

        rR   r?   z/files/N)	r   rV   r%   rC   rS   rT   rU   rO   load)r:   r[   rY   sfr;   r;   r<   rS      s   	
zApacheParser.saverY   c              
      s    fdd| j dD }|D ]}td| j ||dt|d  | j | d qtdd	d
d |D | jj	rGd| jj	  dS d dS )zfLog errors due to bad Augeas save.

        :param list ex_errs: Existing errors before save

        c                    s   g | ]}| vr|qS r;   r;   ).0erY   r;   r<   
<listcomp>   s    z1ApacheParser._log_save_errors.<locals>.<listcomp>r?   zError %s saving %s: %sr@   rA   rB   zUnable to save files: %s.%sz, c                 s   s$    | ]}|d t |d  V  qdS )r@   rA   N)rF   )ra   errr;   r;   r<   	<genexpr>   s   " z0ApacheParser._log_save_errors.<locals>.<genexpr>z Save Notes: rR   N)
r%   rC   loggerdebugrD   rF   errorjoinr   rV   )r:   rY   new_errsre   r;   rc   r<   rU      s   zApacheParser._log_save_errorsmain_configinc_pathc                 C   sh   |  td|s2td|t| | t|d| tj|}tj	|}| j
|g | dS dS )zAdd 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

        IncludezAdding Include %s to %sN)find_dircase_irg   rh   get_aug_pathadd_dirr   r+   dirnamebasenamer7   
setdefaultappend)r:   rl   rm   new_dirnew_filer;   r;   r<   add_include   s   zApacheParser.add_includemod_namec                 C   sH   |d | j vrd| j |d < d| d | j vr"d| j d| d < dS dS )z%Shortcut for updating parser modules._moduleNmod_z.c)r(   )r:   rz   r;   r;   r<   add_mod   s
   zApacheParser.add_modc                 C   s   i | _ |   |   dS )zgReset the loaded modules list. This is called from cleanup to clear
        temporarily loaded modules.N)r(   update_modulesr2   r]   r;   r;   r<   reset_modules   s   zApacheParser.reset_modulesc           	      C   s   i }|  d}t|}d}t||krRt|}t||D ]/\}}| |}| |}|rA|rA|||< ||tj|dd d < qt	d|dd  qt||ks| j
| dS )zIterates 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.

        
LoadModuleNcz8Could not read LoadModule directive from Augeas path: %srA   )ro   iterrF   zipget_argr   r+   rt   rg   rh   r(   r3   )	r:   modsrP   iterator	prev_size
match_namematch_filenamerz   mod_filenamer;   r;   r<   r2     s&   



zApacheParser.parse_modulesc                 C   s   |    |   |   dS )zAUpdate Includes, Defines and Includes from httpd config dump dataN)update_definesupdate_includesr~   r]   r;   r;   r<   r0   "  s   z%ApacheParser.update_runtime_variablesc                 C   s   t | jjj| _dS )z>Updates the dictionary of known variables in the configurationN)r   parse_definesr   r8   get_defines_cmdr*   r]   r;   r;   r<   r   )  s   zApacheParser.update_definesc                 C   sD   |  d}t| jjj}|r|D ]}| |s| | qdS dS )z>Get includes from httpd process, and add them to DOM if neededrn   N)ro   r   parse_includesr   r8   get_includes_cmdparsed_in_currentr/   )r:   _rP   ir;   r;   r<   r   -  s   


zApacheParser.update_includesc                 C   s,   t | jjj}|D ]	}| |  q
dS )z:Get loaded modules from httpd process, and add them to DOMN)r   r2   r   r8   get_modules_cmdr}   strip)r:   rP   modr;   r;   r<   r~   ;  s   zApacheParser.update_modulesrP   argsc                 C   s   g }|dkr!t |D ]\}}|dr||| dd  q
|S t |D ]0\}}|d| rU|t|d ksE||d  d|d  sU||| dtd|    q%|S )a  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 str 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)

           /argN/arg[%d])	enumerateendswithrv   rF   )r:   rP   r   filteredr   rC   r;   r;   r<   filter_args_numB  s"   
 zApacheParser.filter_args_numaug_conf_path	directivec                 C   s   |  |d}| j|d dd |d }| j|| t|dkr.| j|d |d  d
S t|D ]\}}| jd	||d f | q2d
S )a  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; list of str (eg. ["443"])
        :type args: list

        z	mod_ssl.cargr   Fzdirective[1]r   r   r   z
%s/arg[%d]N)	get_ifmodr%   insertrM   rF   r   )r:   r   r   r   if_mod_pathnvh_pathr   r   r;   r;   r<   add_dir_to_ifmodssla  s   z ApacheParser.add_dir_to_ifmodsslr   c                 C   s6   | j d||f }|s| ||S |d dd S )a  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
        :param bool beginning: If the IfModule should be created to the beginning
            of augeas path DOM tree.

        :returns: Augeas path of the requested IfModule directive that pre-existed
            or was created during the process. The path may be dynamic,
            i.e. .../IfModule[last()]
        :rtype: str

        z%s/IfModule/*[self::arg='%s']r   r   )r%   rC   create_ifmod
rpartition)r:   r   r   if_modsr;   r;   r<   r   {  s   zApacheParser.get_ifmodc                 C   s>   d |}d |}| j|d d |}| j|| |S )a>  Creates a new <IfMod mod> and returns its path.

        :param str aug_conf_path: Augeas configuration path
        :param str mod: module ie. mod_ssl.c

        :returns: Augeas path of the newly created IfModule directive.
            The path may be dynamic, i.e. .../IfModule[last()]
        :rtype: str

        z{}/IfModule[last() + 1]z{}/IfModule[last()]/argrR   z{}/IfModule[last()]/)rE   r%   rM   )r:   r   r   c_path
c_path_argretpathr;   r;   r<   r     s   


zApacheParser.create_ifmodc                 C   sl   |r|nd}| j |d | t|tr+t|dD ]\}}| j d||f | qdS | j |d | dS )a  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

        rR   z/directive[last() + 1]r   z%s/directive[last()]/arg[%d]z/directive[last()]/argN)r%   rM   
isinstancelistr   )r:   r   r   r   r   valuer;   r;   r<   rr     s   
zApacheParser.add_dirrs   c                 C   s   |r|nd}|d }| j |r| j |dd n| j |d | j || t|trCt|dD ]\}}| j |d|  | q1dS | j |d | dS )	a)  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
        rR   z/directive[1]r   Tr   r   r   N)r%   rD   r   rM   r   r   r   )r:   r   rs   r   	first_dirr   r   r;   r;   r<   add_dir_beginning  s   	
zApacheParser.add_dir_beginningcommentc                 C   s   | j |d | dS )zAdds the comment to the augeas path

        :param str aug_conf_path: Augeas configuration path to add directive
        :param str comment: Comment content

        z/#comment[last() + 1]N)r%   rM   )r:   r   r   r;   r;   r<   add_comment  s   zApacheParser.add_commentr   startc                 C   sR   |st | j}| jd| }g }|D ]}| j|}|r&||v r&|| q|S )a  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

        z%s//*[label() = '#comment'])rq   r   r%   rC   rD   rv   )r:   r   r   commentsresultsr   	c_contentr;   r;   r<   find_comments  s   


zApacheParser.find_commentsTexcludec                 C   s   |s	t | jd }dt|tdtdf }| jd||f }|r'| |}|du r.d}ndt| }g }|D ]2}	| j|	 }
|
d	v rY|| 	||| 
| |	d | |
| krj|| j|	|  q8|S )
a  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

        :rtype list

        r   z(%s)|(%s)|(%s)rn   IncludeOptionalz$%s//*[self::directive=~regexp('%s')]Nr   z/*[self::arg=~regexp('%s')])includeincludeoptional)rq   r.   rp   r%   rC   exclude_dirsrD   lowerextendro   _get_include_pathr   )r:   r   r   r   r   regexrP   
arg_suffixordered_matchesrC   dir_r;   r;   r<   ro     s6   !

zApacheParser.find_dirrC   c              	   C   sr   | j |}|s
dS |d}tj|}|D ]}z||| j|dd  }W q ty6   t	
d| w |S )zUses augeas.get to get argument value and interprets result.

        This also converts all variables and parameters appropriately.

        N'"r   r   zError Parsing variable: %s)r%   rD   r   r   r   findallreplacer*   KeyErrorr   rG   )r:   rC   r   r*   varr;   r;   r<   r   ?  s   
zApacheParser.get_argc                 C   s   t | jd S )z@
        Returns the Augeas path of root configuration.
        r   )rq   r.   r]   r;   r;   r<   get_root_augpath\  s   zApacheParser.get_root_augpathc                 C   sN   d| j  fd| jfg}g }|D ]}|D ]
}| ||s nq|| q|S )z>Exclude directives that are not loaded into the configuration.ifmoduleifdefine)r(   keysr*   _pass_filterrv   )r:   rP   filtersvalid_matchesrC   filter_r;   r;   r<   r   b  s   
zApacheParser.exclude_dirsr   c                 C   s   |  }||d }|dkrG|d|}| j|d| d }|dr3|dd |d v r2dS n||d vr;dS ||d |}|dksd	S )
zDetermine 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)]

        r   r   r#   Nr   !r   FT)r   findr%   rD   
startswith)r:   rC   r   match_llast_match_idx	end_of_if
expressionr;   r;   r<   r   p  s   
zApacheParser._pass_filterc                 C   s@   | d}|dstjtj| j|}|S tj|}|S )zEnsure paths are consistent and absolute

        :param str arg: Argument of directive

        :returns: Standardized argument path
        :rtype: str
        r   r#   )r   r   r   r+   normpathrj   r   )r:   r   r;   r;   r<   standard_path_from_server_root  s   
	
z+ApacheParser.standard_path_from_server_rootc                 C   s   |du rdS |  |}tj|r| tj|d n| | |d}t|D ]\}}tdd |D r@d| 	| ||< q*d|}t
|S )a@  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

        Nr   r#   c                 s   s    | ]}|t jv V  qd S N)r   r   )ra   charr;   r;   r<   rf     s    z1ApacheParser._get_include_path.<locals>.<genexpr>z* [label()=~regexp('%s')])r   r   r+   isdirr/   rj   splitr   anyfnmatch_to_rerq   )r:   r   	split_argidxr   r;   r;   r<   r     s   



zApacheParser._get_include_pathclean_fn_matchc                 C   s   t |dd S )a  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

        :param str clean_fn_match: Apache style filename match, like globs

        :returns: regex suitable for augeas
        :rtype: str

        r   )fnmatch	translate)r:   r   r;   r;   r<   r     s   zApacheParser.fnmatch_to_refilepathc                 C   s\   |  |\}}|   |r*| jd| }|s,|r| | | | | j  dS dS dS )zParse 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

        z&/augeas/load/Httpd['%s' =~ glob(incl)]N)_check_path_actionsr^   r%   rC   _remove_httpd_transform_add_httpd_transformr_   )r:   r   use_new
remove_oldinc_testr;   r;   r<   r/     s   	

zApacheParser.parse_filefilepc                 C      |sdS |  || jS )a<  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
        F)_parsed_by_parser_pathsr)   r:   r   r;   r;   r<   r        
zApacheParser.parsed_in_currentc                 C   r   )a[  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
        F)r   r7   r   r;   r;   r<   parsed_in_original  r   zApacheParser.parsed_in_originalpathsc              	   C   s:   |D ]}|| D ]}t  |tj||r  dS qqdS )znHelper function that searches through provided paths and returns
        True if file path is found in the setTF)r   r   r+   rj   )r:   r   r   	directoryfilenamer;   r;   r<   r     s   z$ApacheParser._parsed_by_parser_pathsc                 C   sd   z!t j|}| jt j| }d|v rd}nd}|dk}W ||fS  ty1   d}d}Y ||fS w )aL  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

        r   FT)r   r+   rt   r)   rs   r   )r:   r   new_file_matchexisting_matchesr   r   r;   r;   r<   r     s   
z ApacheParser._check_path_actionsc                 C   sd   | j tj| }tj|}|D ]}|d | }| jd| }| j|d  q| j | dS )z[Remove path from Augeas transform

        :param str filepath: filepath to remove
        r#   z!/augeas/load/Httpd/incl [. ='%s']r   N)r)   r   r+   rs   r%   rC   rO   pop)r:   r   remove_basenamesremove_dirnamenameremove_path
remove_incr;   r;   r<   r   8  s   z$ApacheParser._remove_httpd_transforminclc                 C   s   | j d}|r| j |d dd | j d| n| j dd | j d| z| jtj| tj	| W d	S  t
yS   tj	|g| jtj|< Y d	S w )
a"  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

        z /augeas/load/Httpd/incl [last()]r   r  Fz/augeas/load/Httpd/incl[last()]z/augeas/load/Httpd/lensz	Httpd.lnsz/augeas/load/Httpd/inclN)r%   rC   r   rM   r)   r   r+   rs   rv   rt   r   )r:   r  last_includer;   r;   r<   r   G  s   



z!ApacheParser._add_httpd_transformc                 C   sz   ddddddddd	| j d
 | j d | j d | j d | j d | j d g}t|dD ]\}}| jd| | q(| j  dS )aa  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.

        z*.augnewz	*.augsavez*.dpkg-distz
*.dpkg-bakz
*.dpkg-newz
*.dpkg-oldz	*.rpmsavez*.rpmnewz*~z
/*.augsavez/*~z/*/*augsavez/*/*~z/*/*/*.augsavez/*/*/*~r   z/augeas/load/Httpd/excl[%d]N)r   r   r%   rM   r_   )r:   exclr   excludedr;   r;   r<   r1   c  s   
zApacheParser.standardize_exclc                 C   sD   | j d }tj| jd}tj|r|}|}n|}|}|||dS )zSet default location for directives.

        Locations are given as file_paths
        .. todo:: Make sure that files are included

        r   z
ports.conf)defaultlistenr   )r.   r   r+   rj   r   isfile)r:   r  tempr  r   r;   r;   r<   r4     s   
zApacheParser._set_locationsc                 C   sH   g d}|D ]}t jt j| j|rt j| j|  S qtd)z(Find the Apache Configuration Root file.)zapache2.confz
httpd.confzconf/httpd.confz!Could not find configuration root)r   r+   r  rj   r   r   NoInstallationError)r:   locationr   r;   r;   r<   r-     s   
zApacheParser._find_config_root)r   )r"   Nr   )NNT)?__name__
__module____qualname____doc__recompiler   r   __annotations__r   r	   strr
   intr=   rK   r   boolr   r&   r\   r^   r   rS   rU   ry   r}   r   r2   r0   r   r   r~   r   r   r   r   r   rr   r   r   r   ro   r   r   r   r   r   r   r   r   r/   r   r   r   r   r   r   r   r1   r   r4   r-   r;   r;   r;   r<   r   "   s   
 

/
'








 	
O"."	
 r   stringr"   c                 C   s   d dd t| D S )a`  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

    rR   c                 s   s4    | ]}|  rd |  |  d n|V  qdS )r   r   N)isalphaupperr   )ra   r   r;   r;   r<   rf     s    
zcase_i.<locals>.<genexpr>)rj   r  escape)r  r;   r;   r<   rp     s   
rp   	file_pathc                 C   s   d|  S )zTReturn augeas path for full filepath.

    :param str file_path: Full filepath

    z/files%sr;   )r  r;   r;   r<   rq     s   rq   c                   C   s*   t stdt tjt jt jB t jB dS )z' Initialize the actual Augeas instance zProblem in Augeas installation)loadpathflags)r   r   r
  r   AUGEAS_LENS_DIRNONENO_MODL_AUTOLOADENABLE_SPANr;   r;   r;   r<   r$     s   
r$   )%r  r5   r   loggingr  typingr   r   r   r   r   r   r   r	   r
   r   r   certbotr   certbot.compatr   certbot_apache._internalr   r   %certbot_apache._internal.configuratorr   augeasr   ImportError	getLoggerr  rg   r   r  rp   rq   r$   r;   r;   r;   r<   <module>   sN    
       	