U
    ](U                     @   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 eeZd	Zd
ZdZdZdZdZdd ZdddZeje	jG dd deZdd Zeje	jG dd deZ dd Z!dd Z"dS )zCertbot display.    N)	constants)errors)
interfaces)misc)os)	completerH   okZcancelhelpZesczO- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -c              	   C   s8   |   }g }|D ]}|tj|dddd qd|S )zFormat lines nicely to 80 chars.

    :param str msg: Original message

    :returns: Formatted message respecting newlines in message
    :rtype: str

    P   F)Zbreak_long_wordsZbreak_on_hyphens
)
splitlinesappendtextwrapZfilljoin)msglinesZfixed_lline r   6/usr/lib/python3/dist-packages/certbot/display/util.py_wrap_lines%   s    	
r        @c                 C   s8   | rt j|  t j  t|| }|s.t|dS )a  Get user input with a timeout.

    Behaves the same as six.moves.input, however, an error is raised if
    a user doesn't answer after timeout seconds. The default timeout
    value was chosen to place it just under 12 hours for users following
    our advice and running Certbot twice a day.

    :param str prompt: prompt to provide for input
    :param float timeout: maximum number of seconds to wait for input

    :returns: user response
    :rtype: str

    :raises errors.Error if no answer is given before the timeout

    r   )sysstdoutwriteflushr   Zreadline_with_timeoutEOFErrorrstrip)promptZtimeoutr   r   r   r   input_with_timeout;   s    
r   c                       s   e Zd ZdZ fddZdddZd d	d
Zd!ddZd"ddZd#ddZ	dd Z
dd Zd$ddZdd Zdd Zdd Z  ZS )%FileDisplayzFile-based display.c                    s$   t t|   || _|| _d| _d S )NF)superr    __init__outfileforce_interactiveskipped_interaction)selfr#   r$   	__class__r   r   r"   _   s    zFileDisplay.__init__TFc                 C   sT   |rt |}| jdjdt|d | j  |rP| |rFtd n
t	d dS )a  Displays a notification and waits for user acceptance.

        :param str message: Message to display
        :param bool pause: Whether or not the program should pause for the
            user's confirmation
        :param bool wrap: Whether or not the application should wrap text
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        +{line}{frame}{line}{msg}{line}{frame}{line}r   r   framer   zPress Enter to Continuez!Not pausing for user confirmationN)
r   r#   r   format
SIDE_FRAMEr   _can_interactr   loggerdebug)r&   messagepausewrapr$   r   r   r   notificatione   s      


zFileDisplay.notificationNc	                 K   sB   |  ||||rt|fS | || | t|\}
}|
|d fS )aC  Display a menu.

        .. todo:: This doesn't enable the help label/button (I wasn't sold on
           any interface I came up with for this). It would be a nice feature

        :param str message: title of menu
        :param choices: Menu lines, len must be > 0
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `index`) where
            `code` - str display exit code
            `index` - int index of the user's selection

        :rtype: tuple

           )_return_defaultOK_print_menu_get_valid_int_anslen)r&   r1   choicesok_labelcancel_label
help_labeldefaultcli_flagr$   unused_kwargscode	selectionr   r   r   menu}   s
    zFileDisplay.menuc                 K   sP   |  ||||rt|fS td| d }t|}|dks@|dkrHtdfS t|fS )a  Accept input from the user.

        :param str message: message to display to the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `input`) where
            `code` - str display exit code
            `input` - str of the user's input
        :rtype: tuple

        z%s (Enter 'c' to cancel): cCz-1)r6   r7   r   r   CANCEL)r&   r1   r?   r@   r$   rA   ansr   r   r   input   s    zFileDisplay.inputYesNoc           	      K   s   |  ||||r|S t|}| jdjtjttj |d | j  t	djt
|t
|d}||d  s||d  rdS ||d  s||d  rFdS qFdS )	a  Query the user with a yes/no question.

        Yes and No label must begin with different letters, and must contain at
        least one letter each.

        :param str message: question for the user
        :param str yes_label: Label of the "Yes" parameter
        :param str no_label: Label of the "No" parameter
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: True for "Yes", False for "No"
        :rtype: bool

        z{0}{frame}{msg}{0}{frame})r+   r   z{yes}/{no}: )ZyesZnor   TFN)r6   r   r#   r   r,   r   linesepr-   r   r   _parens_around_char
startswithlowerupper)	r&   r1   	yes_labelno_labelr?   r@   r$   rA   rI   r   r   r   yesno   s*    
  
zFileDisplay.yesnoc                 K   s   |  ||||rt|fS | || | jddd\}}|tkr| shddd tdt|d D }t|}	| 	|	|}
|
r||
fS | j
dtj  | j
  q|g fS qd	S )
aC  Display a checklist.

        :param str message: Message to display to user
        :param list tags: `str` tags to select, len(tags) > 0
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `tags`) where
            `code` - str display exit code
            `tags` - list of selected tags
        :rtype: tuple

        zrSelect the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shownT)r$   rE   c                 s   s   | ]}t |V  qd S Nstr).0xr   r   r   	<genexpr>  s     z(FileDisplay.checklist.<locals>.<genexpr>r5   z!** Error - Invalid selection **%sN)r6   r7   r8   rJ   stripr   ranger:   separate_list_input_scrub_checklist_inputr#   r   r   rM   r   )r&   r1   tagsr?   r@   r$   rA   rB   rI   indicesZselected_tagsr   r   r   	checklist   s$    
"zFileDisplay.checklistc                 C   sT   |  |rdS |dkr>d|}|r2|d|7 }t|ntd|| dS dS )a  Should we return the default instead of prompting the user?

        :param str prompt: prompt for the user
        :param default: default answer to prompt
        :param str cli_flag: command line option for setting an answer
            to this question
        :param bool force_interactive: if interactivity is forced by the
            IDisplay call

        :returns: True if we should return the default without prompting
        :rtype: bool

        FNz-Unable to get an answer for the question:
{0}zA
You can provide an answer on the command line with the {0} flag.z-Falling back to default %s for the prompt:
%sT)r.   r,   r   Errorr/   r0   )r&   r   r?   r@   r$   r   r   r   r   r6     s"    

 zFileDisplay._return_defaultc                 C   s@   | j s|stj r"| j r"dS | js<tdtj	 d| _dS )zCan we safely interact with the user?

        :param bool force_interactive: if interactivity is forced by the
            IDisplay call

        :returns: True if the display can interact with the user
        :rtype: bool

        TzSkipped user interaction because Certbot doesn't appear to be running in a terminal. You should probably include --non-interactive or %s on the command line.F)
r$   r   stdinisattyr#   r%   r/   Zwarningr   ZFORCE_INTERACTIVE_FLAG)r&   r$   r   r   r   r.   +  s    

zFileDisplay._can_interactc              
   K   s0   t   | ||||W  5 Q R  S Q R X dS )a
  Display a directory selection screen.

        :param str message: prompt to give the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of the form (`code`, `string`) where
            `code` - display exit code
            `string` - input entered by the user

        N)r   Z	CompleterrJ   )r&   r1   r?   r@   r$   rA   r   r   r   directory_selectA  s    
zFileDisplay.directory_selectc                    sp   zdd |D }W n t k
r*   g  Y S X tt|}|D ] }|dk sT|t kr<g   S q< fdd|D S )zValidate input and transform indices to appropriate tags.

        :param list indices: input
        :param list tags: Original tags of the checklist

        :returns: valid tags the user selected
        :rtype: :class:`list` of :class:`str`

        c                 S   s   g | ]}t |qS r   )intrX   indexr   r   r   
<listcomp>`  s     z6FileDisplay._scrub_checklist_input.<locals>.<listcomp>r5   c                    s   g | ]} |d   qS )r5   r   rg   r_   r   r   ri   l  s     )
ValueErrorlistsetr:   )r&   r`   r_   rh   r   rj   r   r^   S  s    

z"FileDisplay._scrub_checklist_inputc                 C   s   |r t |d tr dd |D }| jdjtj|d | jttj  t|dD ]4\}}dj||d}| jt	| | jtj qT| jttj  | j
  d	S )
zPrint a menu on the screen.

        :param str message: title of menu
        :param choices: Menu lines
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)

        r   c                 S   s    g | ]}d |d |d f qS )z%s - %sr   r5   r   )rX   rF   r   r   r   ri   y  s     z+FileDisplay._print_menu.<locals>.<listcomp>z{new}{msg}{new})newr   r5   z{num}: {desc})ZnumdescN)
isinstancetupler#   r   r,   r   rM   r-   	enumerater   r   )r&   r1   r;   iro   r   r   r   r   r8   n  s    
zFileDisplay._print_menuc                 C   s   d}|dkrdj |d}nd}|dk rt|}|dsB|drJtdfS z$t|}|dk sd||krld}tW q tk
r   | jd tj	 | j
  Y qX qt|fS )	a5  Get a numerical selection.

        :param int max: The maximum entry (len of choices), must be positive

        :returns: tuple of the form (`code`, `selection`) where
            `code` - str display exit code ('ok' or cancel')
            `selection` - int user's selection
        :rtype: tuple

        r5   zMSelect the appropriate number [1-{max_}] then [enter] (press 'c' to cancel): )max_z@Press 1 [enter] to confirm the selection (press 'c' to cancel): rF   rG   z{0}** Invalid input **{0})r,   r   rO   rH   rf   rk   r#   r   r   rM   r   r7   )r&   ru   rC   Z	input_msgrI   r   r   r   r9     s*    
zFileDisplay._get_valid_int_ans)TTF)NNNNNF)NNF)rK   rL   NNF)NNF)NNF)__name__
__module____qualname____doc__r"   r4   rD   rJ   rT   ra   r6   r.   re   r^   r8   r9   __classcell__r   r   r'   r   r    Y   s@       
       
!    
    
*    
*  
r    c                 C   s4   d | }|r|d |7 }|dk	s0|s0t|dS )aN  Verify that provided arguments is a valid IDisplay call.

    :param str prompt: prompt for the user
    :param default: default answer to prompt
    :param str cli_flag: command line option for setting an answer
        to this question
    :param bool force_interactive: if interactivity is forced by the
        IDisplay call

    z*Invalid IDisplay call for this prompt:
{0}z7
You can set an answer to this prompt with the {0} flagN)r,   AssertionError)r   r?   r@   r$   r   r   r   r   assert_valid_call  s    
r|   c                       sf   e Zd ZdZ fddZdddZdd	d
ZdddZdddZdddZ	dddZ
dddZ  ZS )NoninteractiveDisplayzEAn iDisplay implementation that never asks for interactive user inputc                    s   t t|   || _d S rU   )r!   r}   r"   r#   )r&   r#   Zunused_argsrA   r'   r   r   r"     s    zNoninteractiveDisplay.__init__ c                 C   s<   d}||7 }|r|d| 7 }|r.|d |7 }t|dS )zBError out in case of an attempt to interact in noninteractive modez<Missing command line flag or config entry for this setting:
r   z&

(You can set this with the {0} flag)N)r,   r   ZMissingCommandlineFlag)r&   r1   r@   Zextrar   r   r   r   _interaction_fail  s    z'NoninteractiveDisplay._interaction_failFTc                 K   s4   |rt |}| jdjtjt|d | j  dS )a  Displays a notification without waiting for user acceptance.

        :param str message: Message to display to stdout
        :param bool pause: The NoninteractiveDisplay waits for no keyboard
        :param bool wrap: Whether or not the application should wrap text

        r)   r*   N)r   r#   r   r,   r   rM   r-   r   )r&   r1   r2   r3   rA   r   r   r   r4     s      z"NoninteractiveDisplay.notificationNc           	      K   s&   |dkr|  ||dt|  t|fS )a_  Avoid displaying a menu.

        :param str message: title of menu
        :param choices: Menu lines, len must be > 0
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)
        :param int default: the default choice
        :param dict kwargs: absorbs various irrelevant labelling arguments

        :returns: tuple of (`code`, `index`) where
            `code` - str display exit code
            `index` - int index of the user's selection
        :rtype: tuple
        :raises errors.MissingCommandlineFlag: if there was no default

        Nz	Choices: )r   reprr7   )	r&   r1   r;   r<   r=   r>   r?   r@   rA   r   r   r   rD     s    zNoninteractiveDisplay.menuc                 K   s   |dkr|  || t|fS )aK  Accept input from the user.

        :param str message: message to display to the user

        :returns: tuple of (`code`, `input`) where
            `code` - str display exit code
            `input` - str of the user's input
        :rtype: tuple
        :raises errors.MissingCommandlineFlag: if there was no default

        N)r   r7   r&   r1   r?   r@   rA   r   r   r   rJ     s    zNoninteractiveDisplay.inputc                 K   s   |dkr|  || |S )a+  Decide Yes or No, without asking anybody

        :param str message: question for the user
        :param dict kwargs: absorbs yes_label, no_label

        :raises errors.MissingCommandlineFlag: if there was no default
        :returns: True for "Yes", False for "No"
        :rtype: bool

        N)r   )r&   r1   rR   rS   r?   r@   rA   r   r   r   rT     s    zNoninteractiveDisplay.yesnoc                 K   s$   |dkr|  ||d| t|fS )aj  Display a checklist.

        :param str message: Message to display to user
        :param list tags: `str` tags to select, len(tags) > 0
        :param dict kwargs: absorbs default_status arg

        :returns: tuple of (`code`, `tags`) where
            `code` - str display exit code
            `tags` - list of selected tags
        :rtype: tuple

        Nz? )r   r   r7   )r&   r1   r_   r?   r@   rA   r   r   r   ra     s    zNoninteractiveDisplay.checklistc                 K   s   |  |||S )a  Simulate prompting the user for a directory.

        This function returns default if it is not ``None``, otherwise,
        an exception is raised explaining the problem. If cli_flag is
        not ``None``, the error message will include the flag that can
        be used to set this value with the CLI.

        :param str message: prompt to give the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI

        :returns: tuple of the form (`code`, `string`) where
            `code` - int display exit code
            `string` - input entered by the user

        )rJ   r   r   r   r   re   -  s    z&NoninteractiveDisplay.directory_select)r~   )FT)NNNNN)NN)NNNN)NN)NN)rv   rw   rx   ry   r"   r   r4   rD   rJ   rT   ra   re   rz   r   r   r'   r   r}     s(   


      

    
  
  r}   c                 C   s   |  dd}dd | D S )zSeparate a comma or space separated list.

    :param str input_: input from the user

    :returns: strings
    :rtype: list

    ,rE   c                 S   s   g | ]}t |qS r   rV   )rX   stringr   r   r   ri   N  s     z'separate_list_input.<locals>.<listcomp>)replacesplit)Zinput_Z	no_commasr   r   r   r]   B  s    	r]   c                 C   s   dj | d | dd dS )znPlace parens around first character of label.

    :param str label: Must contain at least one character

    z({first}){rest}r   r5   N)firstrest)r,   )Zlabelr   r   r   rN   Q  s    rN   )Nr   )#ry   Zloggingr   r   Zzope.interfacezopeZcertbotr   r   r   Zcertbot.compatr   r   Zcertbot.displayr   Z	getLoggerrv   r/   ZWIDTHr7   rH   ZHELPZESCr-   r   r   Z	interfaceZimplementerZIDisplayobjectr    r|   r}   r]   rN   r   r   r   r   <module>   s8   

  X