HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.104.1.lve.el8.x86_64 #1 SMP Tue Feb 10 20:07:30 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/__pycache__/win_pkg.cpython-310.pyc
o

�N�g�Z�@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z
ddlmZddl
ZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZmZmZddlmZe� e!�Z"dZ#dd�Z$d	d
�Z%dd�Z&dBdd�Z'dd�Z(dd�Z)	
dCdd�Z*dDdd�Z+dd�Z,dd�Z-dd�Z.dd �Z/	!dEd"d#�Z0dBd$d%�Z1d&d'�Z2d(d)�Z3dFd*d+�Z4d,d-�Z5dGd.d/�Z6dGd0d1�Z7dEd2d3�Z8dEd4d5�Z9dEd6d7�Z:dEd8d9�Z;d:d;�Z<d<d=�Z=dHd@dA�Z>dS)Ia�
A module to manage software on Windows

.. important::
    If you feel that Salt should be using this module to manage packages on a
    minion, and it is using a different module (or gives an error similar to
    *'pkg.install' is not available*), see :ref:`here
    <module-provider-override>`.

The following functions require the existence of a :ref:`windows repository
<windows-package-manager>` metadata DB, typically created by running
:py:func:`pkg.refresh_db <salt.modules.win_pkg.refresh_db>`:

- :py:func:`pkg.get_repo_data <salt.modules.win_pkg.get_repo_data>`
- :py:func:`pkg.install <salt.modules.win_pkg.install>`
- :py:func:`pkg.latest_version <salt.modules.win_pkg.latest_version>`
- :py:func:`pkg.list_available <salt.modules.win_pkg.list_available>`
- :py:func:`pkg.list_pkgs <salt.modules.win_pkg.list_pkgs>`
- :py:func:`pkg.list_upgrades <salt.modules.win_pkg.list_upgrades>`
- :py:func:`pkg.remove <salt.modules.win_pkg.remove>`

If a metadata DB does not already exist and one of these functions is run, then
one will be created from the repo SLS files that are present.

As the creation of this metadata can take some time, the
:conf_minion:`winrepo_cache_expire_min` minion config option can be used to
suppress refreshes when the metadata is less than a given number of seconds
old.

.. note::
    Version numbers can be ``version number string``, ``latest`` and ``Not
    Found``, where ``Not Found`` means this module was not able to determine
    the version of the software installed, it can also be used as the version
    number in sls definitions file in these cases. Versions numbers are sorted
    in order of 0, ``Not Found``, ``order version numbers``, ..., ``latest``.

�N)�
cmp_to_key)�CommandExecutionError�MinionError�SaltInvocationError�SaltRenderError��LooseVersion�pkgcCstjj��rtSdS)z9
    Set the virtual pkg module if the os is Windows
    )Fz4Module win_pkg: module only works on Windows systems)�salt�utils�platformZ
is_windows�__virtualname__�rr�H/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/win_pkg.py�__virtual__Lsrc
	OsT|sdSi}|D]}d||<q|�dd�}tjj�|�dd��}td||d�}t�d|�|D]l}d}||vrbt�d	|�zt||t	t
�d
���}WntyZt�
d|�Ynwt�d||�t||d
�}t�d||�t|�}	|	r�t�d||	�tt|	�dt|�d�r�t�d|||	�|	||<q/t�d||�q/t|�dkr�||dS|S)a�
    Return the latest version of the named package available for upgrade or
    installation. If more than one package name is specified, a dict of
    name/version pairs is returned.

    If the latest version of a given package is already installed, an empty
    string will be returned for that package.

    .. note::
        Since this is looking for the latest version available, a refresh_db
        will be triggered by default. This can take some time. To avoid this set
        ``refresh`` to ``False``.

    Args:
        names (str): A single or multiple names to lookup

    Kwargs:
        saltenv (str): Salt environment. Default ``base``
        refresh (bool): Refresh package metadata. Default ``True``

    Returns:
        dict: A dictionary of packages with the latest version available

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.latest_version <package name>
        salt '*' pkg.latest_version <package1> <package2> <package3> ...
    ��saltenv�base�refreshT)�versions_as_listrrzList of installed packages: %s�0z*Determining latest installed version of %s��keyzN%s was empty in pkg.list_pkgs return data, this is probably a bug in list_pkgsz$Latest installed version of %s is %s�rz!Raw winrepo pkg_info for %s is %sz,Latest available version of package %s is %s�>�Zver1ZoperZver2z(Upgrade of %s from %s to %s is availablez+No newer version than %s of %s is available�r)�getr
r�data�is_true�	list_pkgs�log�trace�sortedr�_reverse_cmp_pkg_versions�pop�
IndexError�warning�debug�_get_package_info�_get_latest_pkg_version�compare_versions�str�len)
�names�kwargs�ret�namerr�installed_pkgsZlatest_installed�pkg_infoZlatest_availablerrr�latest_versionUsp
��������
��r4cKs4|�dd�}tjj�|�dd��}t|||d�dkS)a�
    Check whether or not an upgrade is available for a given package

    Args:
        name (str): The name of a single package

    Kwargs:
        refresh (bool): Refresh package metadata. Default ``True``
        saltenv (str): The salt environment. Default ``base``

    Returns:
        bool: True if new version available, otherwise False

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.upgrade_available <package name>
    rrrT�rrr)rr
rrrr4)r1r/rrrrr�upgrade_available�sr6TcKst|�dd�}tjj�|�}t||d�td|d�}t|��d�}i}|D]}||vr7t|d|d�}|r7|||<q$|S)an
    List all available package upgrades on this system

    Args:
        refresh (bool): Refresh package metadata. Default ``True``

    Kwargs:
        saltenv (str): Salt environment. Default ``base``

    Returns:
        dict: A dictionary of packages with available upgrades

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_upgrades
    rr��forceF)rr�repo)	rr
rrr�_refresh_db_conditionalr �
get_repo_datar4)rr/rr2Zavailable_pkgs�pkgsr	Z
latest_verrrr�
list_upgrades�s�r=c	Os�|sdS|�dd�}tjj�|�dd��}t||d�tjj�|�dd��}t|�dkrH|sHt|d	|d
�}|s:dStt	|�
��tt�d�}|Si}|D]}t||d
�}|sWqLt|r`t	|�
��ngtt�d�}|||<qL|S)a�
    Return a list of available versions of the specified package.

    Args:
        names (str): One or more package names

    Kwargs:

        saltenv (str): The salt environment to use. Default ``base``.

        refresh (bool): Refresh package metadata. Default ``False``.

        return_dict_always (bool):
            Default ``False`` dict when a single package name is queried.

    Returns:
        dict: The package name with its available versions

    .. code-block:: cfg

        {'<package name>': ['<version>', '<version>', ]}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_available <package name> return_dict_always=True
        salt '*' pkg.list_available <package name01> <package name02>
    rrrrFr7�return_dict_alwaysrrrr)
rr
rrrr:r-r)r#�list�keysrr$)	r.r/rrr>�pkginfo�versionsr1Zverlistrrr�list_availables6
����
rCcOs^|�dd�}t||�dd�d�}t|�dkr|�|dd�Si}|D]
}|�|d�||<q"|S)	a2
    Returns a string representing the package version or an empty string if not
    installed. If more than one package name is specified, a dict of
    name/version pairs is returned.

    Args:
        name (str): One or more package names

    Kwargs:
        saltenv (str): The salt environment to use. Default ``base``.
        refresh (bool): Refresh package metadata. Default ``False``.

    Returns:
        str: version string when a single package is specified.
        dict: The package name(s) with the installed versions.

    .. code-block:: cfg

        {['<version>', '<version>', ]} OR
        {'<package name>': ['<version>', '<version>', ]}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.version <package name>
        salt '*' pkg.version <package name01> <package name02>

    rrrFr5rrr)rr r-)r.r/rr2r0r1rrr�versionBs&rDFcs"tjj�|�}t�fdd�dD��riS��dd�}tjj���dd��}t||d�i}t|�}t||d	��	�D]G\}}	||vrq||}
|	D](}|d
krgt
|
|d�}|sVqG|��D]}
||
d|krf|
}qZtd
||
|�qGq9|}
|	D]
}td
||
|�quq9td|�|s�td|�|S)a�
    List the packages currently installed.

    .. note::
        To view installed software as displayed in the Add/Remove Programs, set
        ``include_components`` and ``include_updates`` to False.

    Args:

        versions_as_list (bool):
            Returns the versions as a list

        include_components (bool):
            Include sub components of installed software. Default is ``True``

        include_updates (bool):
            Include software updates and Windows updates. Default is ``True``

    Kwargs:

        saltenv (str):
            The salt environment to use. Default ``base``

        refresh (bool):
            Refresh package metadata. Default ``False``

    Returns:
        dict: A dictionary of installed software with versions installed

    .. code-block:: cfg

        {'<package_name>': '<version>'}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_pkgs
        salt '*' pkg.list_pkgs versions_as_list=True
    cs g|]}tjj���|���qSr)r
rrrr)�.0�x�r/rr�
<listcomp>�s zlist_pkgs.<locals>.<listcomp>)ZremovedZ
purge_desiredrrrFr7)�include_components�include_updates�	Not Foundr�	full_namezpkg_resource.add_pkgzpkg_resource.sort_pkglist�pkg_resource.stringify)
r
rrr�anyrr:�
_get_name_map�_get_reg_software�itemsr)r@�__salt__)rrIrJr/rrr0�name_map�pkg_nameZval_listr�valr3Zpkg_verrrGrr tsH+��
����r cs�i��fdd�}dd�}dd�}�fdd�}d	d
�}��fdd�}d
ddd�}tdd#i|��D]5}	|	|d<|d#i|��r>q0|d#i|��rFq0|d#i|��rNq0|d#i|��rVq0|d#i|��r^q0|d#i|��q0d|d<|�dd�tdd#i|��D]5}	|	|d<|d#i|��r�qy|d#i|��r�qy|d#i|��r�qy|d#i|��r�qy|d#i|��r�qy|d#i|��qyd
ddd�}d}
tdd#i|��D]-}	td|d|
�d|	��d�s�q�|	|d<|d#i|��r�q�|d#i|��r�q�|d#i|��q�d}d}d}
d}td|d�D]�}||�|�dd�}tdd#i|���r\tdd#i|��D]@}	|	|d<|d#i|���r+�q|d#i|���r5�q|d#i|���r?�q|d#i|���rI�q|d#i|���rS�q|d#i|���q||
�|�dd�}tdd#i|���r�tdd#i|��D],}	d
|�||	�dd�}tdd#i|���r�d |d<|d#i|���r��qx|d#i|���qxq�td|dd!�D]�}||�|�dd�}tdd#i|���r
tdd#i|��D]@}	|	|d<|d#i|���rܐq�|d#i|���r�q�|d#i|���r�q�|d#i|���r��q�|d#i|���r�q�|d#i|���q�||
�|�dd�}tdd#i|���rVtdd#i|��D],}d
|�||�dd�}tdd#i|���rTd |d<|d#i|���rM�q)|d#i|���q)�q��S)$a<
    This searches the uninstall keys in the registry to find a match in the sub
    keys, it will return a dict with the display name as the key and the
    version as the value

    Args:

        include_components (bool):
            Include sub components of installed software. Default is ``True``

        include_updates (bool):
            Include software updates and Windows updates. Default is ``True``

    Returns:
        dict: A dictionary of installed software with versions installed

    .. code-block:: cfg

        {'<package_name>': '<version>'}
    csT�rdStd||�d|��d|d�r(td||�d|��d|d�ddkr(d	SdS)
a2
        'SystemComponent' must be either absent or present with a value of 0,
        because this value is usually set on programs that have been installed
        via a Windows Installer Package (MSI).

        Returns:
            bool: True if the package needs to be skipped, otherwise False
        F�reg.value_exists�\ZSystemComponent��hiverZvname�use_32bit_registry�reg.read_value�vdatarT��	__utils__�rYr�sub_keyrZ)rIrr�skip_component�s(	����z)_get_reg_software.<locals>.skip_componentcSsvd}td||�d|��d|d�r9td||�d|��d|d�ddkr9tjj�|�}td	d
|�|�|d�s9dSd
S)a�
        'WindowsInstaller' must be either absent or present with a value of 0.
        If the value is set to 1, then the application is included in the list
        if and only if the corresponding compressed guid is also present in
        HKLM:\Software\Classes\Installer\Products

        Returns:
            bool: True if the package needs to be skipped, otherwise False
        z'Software\Classes\Installer\Products\{0}rVrWZWindowsInstallerrXr[r\r�reg.key_exists�HKLM�rYrrZTF)r^r
rZ
win_functionsZ
guid_to_squid�format)rYrr`rZZproducts_keyZsquidrrr�skip_win_installer�s2
�����z-_get_reg_software.<locals>.skip_win_installercSsntd||�d|��d|d�r$td||�d|��d|d�ddkr$dStd||�d|��d	|d�s5d
SdS)a
        `UninstallString` must be present, because it stores the command line
        that gets executed by Add/Remove programs, when the user tries to
        uninstall a program. Skip those, unless `NoRemove` contains a non-zero
        value in which case there is no `UninstallString` value.

        We want to display these in case we're trying to install software that
        will set the `NoRemove` option.

        Returns:
            bool: True if the package needs to be skipped, otherwise False
        rVrWZNoRemoverXr[r\rFZUninstallStringTr]r_rrr�skip_uninstall_string s2�����z0_get_reg_software.<locals>.skip_uninstall_stringcs\�rdSgd�}td||�d|��d|d�r,td||�d|��d|d�d|vr,d	SdS)
a<
        'ReleaseType' must either be absent or if present must not have a
        value set to 'Security Update', 'Update Rollup', or 'Hotfix', because
        that indicates it's an update to an existing program.

        Returns:
            bool: True if the package needs to be skipped, otherwise False
        F)ZHotfixzSecurity Updatez
Update RolluprVrWZReleaseTyperXr[r\Tr])rYrr`rZZ
skip_types)rJrr�skip_release_typeGs*	����z,_get_reg_software.<locals>.skip_release_typecSs&td||�d|��d|d�rdSdS)z�
        'ParentKeyName' must NOT be present, because that indicates it's an
        update to the parent program.

        Returns:
            bool: True if the package needs to be skipped, otherwise False
        rVrWZ
ParentKeyNamerXTFr]r_rrr�skip_parent_keyes�z*_get_reg_software.<locals>.skip_parent_keycs�td||�d|��d|d�}|dr|ddvs|dd	vr!d
S|d}�s/t�d|�r/d
Std||�d|��d|d�}d
}|drf|ddvrft|dt�rXt|d�}n|drf|ddkrf|d}��|g��|�d
S)a
        'DisplayName' must be present with a valid value, as this is reflected
        as the software name returned by pkg.list_pkgs. Also, its value must
        not start with 'KB' followed by 6 numbers - as that indicates a
        Windows update.
        r[rWZDisplayNamerX�successZvtype)�REG_SZ�
REG_EXPAND_SZr\)�(value not set)NFNz^KB[0-9]{6}ZDisplayVersionrK)rkrlZ	REG_DWORDrm)r^�re�match�
isinstance�intr,�
setdefault�append)rYrr`rZZd_name_regdataZd_nameZd_vers_regdataZd_vers)rJ�reg_softwarerr�add_softwarews<����z'_get_reg_software.<locals>.add_softwarercz3Software\Microsoft\Windows\CurrentVersion\UninstallFrdz
reg.list_keysr`TrZz#Software\Classes\Installer\ProductszNSoftware\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\ProductsrbrYrW)rYrZHKUz7{0}\Software\Microsoft\Windows\CurrentVersion\Uninstallz){0}\Software\Microsoft\Installer\ProductszMSoftware\Microsoft\Windows\CurrentVersion\Installer\UserData\{0}\Products\{1})rYZInstallProperties)rYrZNr)r^r%re)rIrJrarfrgrhrirur/r`Zuserdata_keyZhive_hkuZ
uninstall_keyZproduct_keyZ
user_data_keyZ	user_guidZ	sub_key_2r)rIrJrtrrP�s#'3�������
����
��rPc	Ks�tjj�|�dd��}tjj�|�dd��}td}td}t|�}|r7|dkr7|j|kr7t�	d|j|�d}|sC|jdksC|j|krEd	nd}|sWt�
d
|tj|jd��d	S|jdkrbt�
d|�t
|d|d
�}z
t|�dd��WSty}YdSw)a�
    Internal use only in this module, has a different set of defaults and
    returns True or False. And supports checking the age of the existing
    generated metadata db, as well as ensure metadata db exists to begin with

    Args:
        saltenv (str): Salt environment

    Kwargs:

        force (bool):
            Force a refresh if the minimum age has been reached. Default is
            False.

        failhard (bool):
            If ``True``, an error will be raised if any repo SLS files failed to
            process.

    Returns:
        bool: True Fetched or Cache uptodate, False to indicate an issue

    :codeauthor: Damon Atkins <https://github.com/damon-atkins>
    r8F�failhardZwinrepo_cache_expire_maxZwinrepo_cache_expire_minrzcRefresh skipped, age of winrepo metadata in seconds (%s) is less than winrepo_cache_expire_min (%s)���Tz;Using existing pkg metadata db for saltenv '%s' (age is %s)��secondsz:No winrepo.p cache file for saltenv '%s', creating one now�r�verboserv�failed)r
rrrr%�__opts__�_get_repo_details�winrepo_ager!�infor(�datetime�	timedelta�
refresh_db�boolr�AttributeError)	rr/r8rvZexpired_maxZexpired_min�repo_detailsr�resultsrrrr:BsD��

���
�r:cKs�tjj�t�|�dd�}tjj�|�dd��}tjj�|�dd��}t�dd�t	|�}t
�d	|tj
|jd
��t
�d|j�g}tjjj|jdd�D]B\}}}|D]:}	|	�d
�r�tj�||	�}
zt�|
�WqSty�}z|jtjkr�t
�d|
|�|�|
�WYd}~qSd}~wwqSqL|r�tdd|id��tj�t�}|dd�}
|j|
d�t
�d|j �z
t!d|j |ddd�Wnt"y�}zt
j#d|j |d�WYd}~nd}~wwt$|||d�S)aE

    Generates the local software metadata database (`winrepo.p`) on the minion.
    The database is stored in a serialized format located by default at the
    following location:

    ``C:\ProgramData\Salt Project\Salt\var\cache\salt\minion\files\base\win\repo-ng\winrepo.p``

    This module performs the following steps to generate the software metadata
    database:

    - Fetch the package definition files (.sls) from `winrepo_source_dir`
      (default `salt://win/repo-ng`) and cache them in
      `<cachedir>\files\<saltenv>\<winrepo_source_dir>`
      (default: ``C:\ProgramData\Salt Project\Salt\var\cache\salt\minion\files\base\win\repo-ng``)
    - Call :py:func:`pkg.genrepo <salt.modules.win_pkg.genrepo>` to parse the
      package definition files and generate the repository metadata database
      file (`winrepo.p`)
    - Return the report received from
      :py:func:`pkg.genrepo <salt.modules.win_pkg.genrepo>`

    The default winrepo directory on the master is `/srv/salt/win/repo-ng`. All
    files that end with `.sls` in this and all subdirectories will be used to
    generate the repository metadata database (`winrepo.p`).

    .. note::
        - Hidden directories (directories beginning with '`.`', such as
          '`.git`') will be ignored.

    .. note::
        There is no need to call `pkg.refresh_db` every time you work with the
        pkg module. Automatic refresh will occur based on the following minion
        configuration settings:

        - `winrepo_cache_expire_min`
        - `winrepo_cache_expire_max`

        However, if the package definition files have changed, as would be the
        case if you are developing a new package definition, this function
        should be called to ensure the minion has the latest information about
        packages available to it.

    .. warning::
        Directories and files fetched from <winrepo_source_dir>
        (`/srv/salt/win/repo-ng`) will be processed in alphabetical order. If
        two or more software definition files contain the same name, the last
        one processed replaces all data from the files processed before it.

    For more information see
    :ref:`Windows Software Repository <windows-package-manager>`

    Arguments:

    saltenv (str): Salt environment. Default: ``base``

    verbose (bool):
        Return a verbose data structure which includes 'success_list', a
        list of all sls files and the package names contained within.
        Default is 'False'

    failhard (bool):
        If ``True``, an error will be raised if any repo SLS files fails to
        process. If ``False``, no error will be raised, and a dictionary
        containing the full results will be returned.

    Returns:
        dict: A dictionary containing the results of the database refresh.

    .. note::
        A result with a `total: 0` generally means that the files are in the
        wrong location on the master. Try running the following command on the
        minion: `salt-call -l debug pkg.refresh saltenv=base`

    .. warning::
        When calling this command from a state using `module.run` be sure to
        pass `failhard: False`. Otherwise, the state will report failure if it
        encounters a bad software definition file.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.refresh_db
        salt '*' pkg.refresh_db saltenv=base
    rrr{FrvT�winrepo.dataNzLRefreshing pkg metadata db for saltenv '%s' (age of existing metadata is %s)rxz#Removing all *.sls files under '%s'��followlinks�.slszFailed to remove %s: %sz/Failed to clear one or more winrepo cache filesr|�r�)rZ	fsbackend)�loadzFetching *.sls files from %s�cp.cache_dirz*.slszE@\/\..*?\/)�pathr�include_pat�exclude_pat�Failed to cache %s��exc_inforz)%r
rr	Z
clear_rtagr}r%rr�__context__r~r!r(r�r�rr��
local_destr��os_walk�endswith�os�join�remove�OSError�errno�ENOENT�errorrsr�
fileserverZ
FileserverZclear_file_list_cache�winrepo_source_dirrRr�	exception�genrepo)r/rr{rvr�r|�root�_�filesr1Z
full_filename�excr�r�rrrr��sfV��

����	�

����r�c

Csd|��}|tvrt|\}}}nptd}tdd|g}tj�|�}|�|j�|�|j�	d��
d��tj�
|�}tj�
|d�}tjdtdtjd	�sVtj�
|td�}nt�d
td�tj�dd�}tjjj|d
�
|dg�d�sztd�|���|||ft|<zt�|�Wn"ty�}z|jtjkr�td|�d|����WYd}~nd}~wwd}	zt�|�}
|
j}t � �|}	Wn?ty�}z|jtj!kr�td|�d|����WYd}~n"d}~wt"y�t�#d|
�Ynt$y�t�#d||�Ynwt%�&dd�}|||||	�S)zG
    Return repo details for the specified saltenv as a namedtuple
    zwinrepo._get_repo_details.r�Zcachedirr��/z	winrepo.pz[\/:*?"<>|]Zwinrepo_cachefile��flagsz�minion configuration option 'winrepo_cachefile' has been ignored as its value (%s) is invalid. Please ensure this option is set to a valid filename.Z
SystemRootz
C:\WindowsrWZTEMP)r�Z
allow_pathz>Attempting to delete files from a possibly unsafe location: {}zFailed to create z: NrwzFailed to get age of z$st_mtime missing from stat result %sz#mtime of %s (%s) is an invalid typeZRepoDetails)r�r��winrepo_filer)'r�r}�urllib�parse�urlparsers�netloc�extendr��strip�splitr��sepr�rn�search�
IGNORECASEr!r��environrr
rZ	safe_pathrre�makedirsr�r�ZEEXIST�stat�st_mtime�timer�r�r'�	TypeError�collections�
namedtuple)
rZ
contextkeyr�r�r��dirsZ	url_partsZsystem_rootr�r�stat_result�mtimer�rrrr~sp
��	������
����r~c	Ks�|�dd�}tjj�|�dd��}tjj�|�dd��}i}i}d}i|d<i|d	<t|�}tjjj|jdd
�D]A\}}	}
t	�
d|�rJt�d|�q8t
j�||j�}|d
krXd}|
D]}|�d�rx|d7}tt
j�||�t
j�||�|||d�qZq8tjj�|jd��}
|
�tj�|��Wd�n1s�wYt|�}t|d	�}|r�|||||d	d�}n|dkr�||||d	d�}n|||d�}|dkr�|r�td|d��|S)a�
    Generate package metadata db based on files within the winrepo_source_dir

    Kwargs:

        saltenv (str): Salt environment. Default: ``base``

        verbose (bool):
            Return verbose data structure which includes 'success_list', a list
            of all sls files and the package names contained within.
            Default ``False``.

        failhard (bool):
            If ``True``, an error will be raised if any repo SLS files failed
            to process. If ``False``, no error will be raised, and a dictionary
            containing the full results will be returned.

    .. note::
        - Hidden directories (directories beginning with '`.`', such as
          '`.git`') will be ignored.

    Returns:
        dict: A dictionary of the results of the command

    CLI Example:

    .. code-block:: bash

        salt-run pkg.genrepo
        salt -G 'os:windows' pkg.genrepo verbose=true failhard=false
        salt -G 'os:windows' pkg.genrepo saltenv=base
    rrr{FrvTrr9�errorsr�z	[\\/]\..*zSkipping files in directory: %s�.rr�r)�filename�short_path_namer0�successful_verboser�wbN)�totalrjr|Zsuccess_list�failed_list)r�rjr|r�)r�rjr|z'Error occurred while generating repo dbr�)r%r
rrrr~r�r�r�rnr�r!r(r��relpathr��_repo_process_pkg_slsr�r��fopenr��write�payload�dumpsr-r)r/rr{rvr0r�Ztotal_files_processedr�r�r�r�Z
short_pathr1Z
repo_cacheZsuccessful_countZerror_countr�rrrr�^sr!�
��������r�rc
s�tj�tt�}��fdd�}ztjj||tdt�dd�t�dd�|d�}Wn-ty=}z|d|�WYd}~Sd}~wt	yS}z|d	|�WYd}~Sd}~ww|r�t
|t�r�i}	g}
|��D]Y\}}|�d
vrt
�d|��|
�d|�d
��n>|��D]8\}
}t
|
t�s�t
�d|�|
�|
�d�||
��q�t
|t�s�t
�d|�|
�|
�d�||
��q�||	|d<q�qc|
r�|
��di��<dS��d
i��|���di��|	�t|���|�<dS|r�|dd�St
�d��g|�<dS)Ncs2t�d|�|�|�d|�d�g��di��<dS)Nz%s '%s': %s�, � r�F)r!r�rr)Z
prefix_msgZ	error_msg�r0r�rr�_failed_compile�sz._repo_process_pkg_sls.<locals>._failed_compileZrendererZrenderer_blacklistrZrenderer_whitelistrzFailed to compilezFailed to readr9z2package '%s' within '%s' already defined, skippingz	package 'z' already definedz<package '%s' within '%s', version number %s' is not a stringz/package '{}', version number {} is not a stringzXpackage '%s' within '%s', repo data for version number %s is not defined as a dictionaryzLpackage '{}', repo data for version number {} is not defined as a dictionaryrLr�rSzCompiled contentsznot a dictionary/hashz$No data within '%s' after processing)r
�loaderZrenderr}rR�templateZcompile_templaterr�	Exceptionrp�dictrQr!r�rsr,rerr�updater?r@r()r�r�r0r�rZ	renderersr�Zconfigr�Zrevmapr��pkgnameZversion_listZversion_str�repodatarr�rr��s�


�����
���
���� 
r�c
Cs�t�}d}d�|�}t|�}tj�|�j}||vrWztd|||dd�}Wnty:}	z	t	j
d||	d��d}	~	ww|sEtd	|�d
���td|d|�}|durUt|��|S|�
d
d�}
t|
�dkrpd�|d�|��}t|��dd�|
D�\|d<|d<|S)zV
    Extract the hash sum, whether it is in a remote hash file, or just a string.
    )r
�http�https�ftpZswiftZs3�filezOSource hash '{}' format is invalid. It must be in the format <hash type>=<hash>�
cp.cache_fileT)r�
verify_ssl�use_etagr�r�NzSource hash file z
 not foundzfile.extract_hashr�=r�z*{}, or it must be a supported protocol: {}r�css�|]	}|����VqdS�N)r��lower)rE�itemrrr�	<genexpr>?s�z"_get_source_sum.<locals>.<genexpr>�	hash_type�hsum)r�rer,r�r�r��schemerRrr!r�rrr�r-r�)�source_hashZ	file_pathrr�r0ZschemesZinvalid_hash_msgZsource_hash_schemeZcached_hash_filer�rQrrr�_get_source_sums>�
���
�
�r�cCsJ|durdSt|t�rtj�|�rd|fSt�d|�d}|dur#dSdS)zJ
    Return if msiexec.exe will be used and the command to invoke it.
    F)FrTzDmsiexec path '%s' not found. Using system registered msiexec instead)T�msiexecN)rpr,r�r��isfiler!r')�use_msiexecrrr�_get_msiexecDs
��r�cCs|S)ak
    Nothing to do on Windows. We need this function so that Salt doesn't go
    through every module looking for ``pkg.normalize_name``.

    .. versionadded:: 3006.0

    Args:
        name (str): The name of the package

    Returns:
        str: The name of the package

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.normalize_name git
    r�r1rrr�normalize_nameWsr�c(Kshi}|�dd�}tjj�|�}|s|sdStd||fi|��d}t|�dkr4|�d�dur4t�	d	�|D]
}d
||i||<q6|sJt�
d�iS|s`t|�dkr`||�d
�|�d�d�i}nt|�dkrutt|��}|�d�||d<t
||d
d�}g}	|��D�]�\}
}t|
|d�}|s�t�
d|
�d|
��||
<q�|�d
�}
t|
t�s�|
dur�t|
�}
|
s�|
|vr�t�d|
||
d�q�t|�}
|
dkr�d|vr�t|�}
|
|�|
g�vr�t�d|
|
�q�|
dkr�|
|vr�t�
d|
|
�d|
i||
<q�||
�dd�}||
�dd�}||
�dd�}|�s t�
d|
|
�d|
i||
<q�td||�}t|t��r2|d}nd}td|��rP|�r�|�d ��r�tj�|�\}}t�d!|�z
td"||ddd#d$�Wn(t�y�}zd%|��}tj||d&�|�d'|��WYd}~Sd}~ww|�r�|�d ��r�td||�}t�d(|�ztd)||||�d*d
�d+�}Wn(t�y�}zd%|��}tj||d&�|�d'|��WYd}~Sd}~ww|�s�t�
d,|�d-|i||
<q�d}|
dk�r�|�d ��s�td.||�}|�sOt�d(|�ztd)||||�d*d
�d
d/�}Wn(t�y=}zd%|��}tj||d&�|�d'|��WYd}~Sd}~ww|�sOt�
d0||�d1|i||
<q�n|}|�d2d3�}tj�|�}||
�d4d�}|�r�t||||�d*d
�d5�}t�d6|d7|d�tjj�||d7�}t�d8|d7|�|d|k�r�t d9�!|d|���t�d:�||
�d;d�}|�r�|�d��r�d<�!||�dd��}t"||
�d=d��\}}t�#d>d?�!t�#d@���} |�r�dA|�dB|�dA�}!||
�dCd
��r�|!�dD�}!ndA|�dA�}!|�r|!�dE|��}!t�dF| |!�t�dG|�||
�dHd��r�tdIdJdKd
dL| dM|!�dA�|dNdOdPdddQ�t$j%dR|
t$j&t$j'dS�du�r�dTdUi||
<tdVdJdW��s]t�
dX|
�dTdYi||
<q�t(�(�dZ}"t(�(�|"k�r�t(�)d[�td\dJ�d]k}#|#�r{nt(�(�|"k�sj|#�s�t�
dX|
�dTdYi||
<q�td^dJdW��s�t�
dX|
�dTdYi||
<q�td_dA| �d`|!�dA�|dadd
db�}$t�dc|$dd�|$dd�s�dTdei||
<|	�*|
�q�|$dddfk�r�|�dgd
�}%|%�r�tdh�dTdii||
<|	�*|
�q�|$dddjk�rdTdki||
<|	�*|
�q�t�
dl|
|$dd|$dm�dTdYi||
<q�t
|ddn�}&tdo|�tjj�+||&�}'|�,|'�|S)pa�
    Install the passed package(s) on the system using winrepo

    Args:

        name (str):
            The name of a single package, or a comma-separated list of packages
            to install. (no spaces after the commas)

        refresh (bool):
            Boolean value representing whether or not to refresh the winrepo db.
            Default ``False``.

        pkgs (list):
            A list of packages to install from a software repository. All
            packages listed under ``pkgs`` will be installed via a single
            command.

            You can specify a version by passing the item as a dict:

            CLI Example:

            .. code-block:: bash

                # will install the latest version of foo and bar
                salt '*' pkg.install pkgs='["foo", "bar"]'

                # will install the latest version of foo and version 1.2.3 of bar
                salt '*' pkg.install pkgs='["foo", {"bar": "1.2.3"}]'

    Kwargs:

        version (str):
            The specific version to install. If omitted, the latest version will
            be installed. Recommend for use when installing a single package.

            If passed with a list of packages in the ``pkgs`` parameter, the
            version will be ignored.

            CLI Example:

             .. code-block:: bash

                # Version is ignored
                salt '*' pkg.install pkgs="['foo', 'bar']" version=1.2.3

            If passed with a comma separated list in the ``name`` parameter, the
            version will apply to all packages in the list.

            CLI Example:

             .. code-block:: bash

                # Version 1.2.3 will apply to packages foo and bar
                salt '*' pkg.install foo,bar version=1.2.3

        extra_install_flags (str):
            Additional install flags that will be appended to the
            ``install_flags`` defined in the software definition file. Only
            applies when single package is passed.

        saltenv (str):
            Salt environment. Default 'base'

        report_reboot_exit_codes (bool):
            If the installer exits with a recognized exit code indicating that
            a reboot is required, the module function

               *win_system.set_reboot_required_witnessed*

            will be called, preserving the knowledge of this event for the
            remainder of the current boot session. For the time being, 3010 is
            the only recognized exit code. The value of this param defaults to
            True.

            .. versionadded:: 2016.11.0

    Returns:
        dict: Return a dict containing the new package names and versions. If
        the package is already installed, an empty dict is returned.

        If the package is installed by ``pkg.install``:

        .. code-block:: cfg

            {'<package>': {'old': '<old-version>',
                           'new': '<new-version>'}}

    The following example will refresh the winrepo and install a single
    package, 7zip.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.install 7zip refresh=True

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.install 7zip
        salt '*' pkg.install 7zip,filezilla
        salt '*' pkg.install pkgs='["7zip","filezilla"]'

    WinRepo Definition File Examples:

    The following example demonstrates the use of ``cache_file``. This would be
    used if you have multiple installers in the same directory that use the
    same ``install.ini`` file and you don't want to download the additional
    installers.

    .. code-block:: bash

        ntp:
          4.2.8:
            installer: 'salt://win/repo/ntp/ntp-4.2.8-win32-setup.exe'
            full_name: Meinberg NTP Windows Client
            locale: en_US
            reboot: False
            cache_file: 'salt://win/repo/ntp/install.ini'
            install_flags: '/USEFILE=C:\salt\var\cache\salt\minion\files\base\win\repo\ntp\install.ini'
            uninstaller: 'NTP/uninst.exe'

    The following example demonstrates the use of ``cache_dir``. It assumes a
    file named ``install.ini`` resides in the same directory as the installer.

    .. code-block:: bash

        ntp:
          4.2.8:
            installer: 'salt://win/repo/ntp/ntp-4.2.8-win32-setup.exe'
            full_name: Meinberg NTP Windows Client
            locale: en_US
            reboot: False
            cache_dir: True
            install_flags: '/USEFILE=C:\salt\var\cache\salt\minion\files\base\win\repo\ntp\install.ini'
            uninstaller: 'NTP/uninst.exe'
    rr�0Must pass a single package or a list of packages�pkg_resource.parse_targetsrr�extra_install_flagsNzK'extra_install_flags' argument will be ignored for multiple package targetsrDzNo package definition found)rDr�T�rrrrzUnable to locate package %s�Unable to locate package z3pkg.install: '%s' version '%s' is already installed�latestz#Version %s not found for package %sz	not found�	installerr�	cache_dirF�
cache_filez4No installer configured for version %s of package %szno installer�cp.hash_filer��config.valid_fileproto�salt:zPKG: Caching directory: %sr��E@init.sls$�r�rZ
include_emptyr�r��Failed to cache r��
�PKG: Caching file: %sr�r�)rr�r��Unable to cache %szfailed to cache cache_file�cp.is_cached�rr�r�r�z(Unable to cache file %s from saltenv: %s�unable to cacher�rWr�)rr�zpkg.install: Source %s hash: %sr�z pkg.install: Package %s hash: %sz1Source hash '{}' does not match package hash '{}'z.pkg.install: Source hash matches package hash.�
install_flags�{} {}r��ComSpec�{}\system32\cmd.exe�WINDIR�"z" /I "Zallusersz ALLUSERS=1r��PKG : cmd: %s /c %s�
PKG : pwd: %s�
use_scheduler�task.create_task�update-salt-software�System�Execute�/c "�Once�
1975-01-01�01:00�r1Z	user_namer8Zaction_type�cmd�	argumentsZstart_inZtrigger_typeZ
start_dateZ
start_timeZac_onlyZstop_if_on_batterieszsalt[\s_.-]*minionr�zinstall statusztask startedztask.runr�z2Scheduled Task failed to run. Failed to install %sr|�g�?ztask.statusZRunning�
task.run_wait�cmd.run_all�" /c "r"�Zoutput_loglevelZpython_shell�redirect_stderr�PKG : retcode: %s�retcoderj���report_reboot_exit_codes�$system.set_reboot_required_witnessed�success, reboot required�i�success, reboot initiatedz7Failed to install %s; retcode: %s; installer output: %s�stdoutr5rM)-r%r
rrrrRr-rr!r'r��next�iterr rQr)rpr,r(r*r��
startswithr�r�r�rr��replace�dirnamer�Z	hashutilsZget_hashrrer��getenvrnr�r��UNICODEr��sleeprs�
compare_dictsr�)(r1rr<r/r0r�
pkg_paramsr	�old�changedrT�optionsrA�version_numr�r�r�Zinstaller_hashr�r�r��msgZcache_file_hashZcached_file�
cached_pkg�
cache_pathr�Z
source_sumZcached_pkg_sumrr�r��	cmd_shellrZt_endZtask_running�resultr$�new�
differencerrr�installms
�
��

���

�
��

�
��

�
����
������
��
�
����
�������

�
r?cKs>t�d�tjj�|�dd��}|�dd�}t�d||�iS)a�
    Upgrade all software. Currently not implemented

    Kwargs:
        saltenv (str): The salt environment to use. Default ``base``.
        refresh (bool): Refresh package metadata. Default ``True``.

    .. note::
        This feature is not yet implemented for Windows.

    Returns:
        dict: Empty dict, until implemented

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.upgrade
    z*pkg.upgrade not implemented on Windows yetrTrrz@pkg.upgrade not implemented on Windows yet refresh:%s saltenv:%s)r!r'r
rrrr)r/rrrrr�upgradeps
�	r@c"s�|�dd�}tjj�|�dd��}i}|s|sdStd||fi|��d}t||dd	�}g}|��D�]�\}	}
t|	|d
�}|sOd|	��}t	�
|�|||	<q3|	|vret	�d|	|
r[|
nd
�ddi||	<q3g}
|
durot|
�}
|
dur�||	D]}||vr�d|vr�t	�d|	|
�|
�
d�qw|
�
|�qwn1|
|vr�|
||	vr�|
�
|
�n!t	�d|	|
�d|
�d�i||	<q3d|vr�t	�d|	|
�|
�
d�|
s�t	�
d|	|
�d|
�d�i||	<q3|
D�]}||�dd
�}||�dd�}||�dd
�}|�s|�r||�dd
�}|�st	�
d|	�d|i||	<q�td||�}t|t��r&|d}nd}td|��r�|�r~|�d��r~tj�|�\}}t	�d |�z
td!||ddd"d#�Wn*t�y}}zd$|��}t	j||d%�|�d&|��WYd}~Sd}~wwtd'||�}|�s�t	�d(|�ztd)||||�d*d�dd+�}Wn*t�y�}zd$|��}t	j||d%�|�d&|��WYd}~Sd}~ww|�s�t	�
d,|�d-|i||	<q�ntj�|�}|�d.d/�}tj�|�\}}|�d0��r�d1�||�d0d
��}t||�d2d��\}}t�d3d4�t�d5���}|�r$d6|�d7|�d6�}nd6|�d6�}|�r4|�d8|��}|�
|	�t	�d9||�t	�d:|�||�d;d��rztd<d=d>dd?|d@|�d6�|dAdBdCdddD�tdEd=dF��syt	�
dG|	�dHdIi||	<q�tdJd6|�dK|�d6�dLdddM�}t	�dN|dO�|dO�s�dHdPi||	<|�
|	�q�|dOdQk�r�|�dRd�}|�r�tdS�dHdTi||	<|�
|	�q�|dOdUk�r�dHdVi||	<|�
|	�q�t	�
dW|	|dO|dX�dHdIi||	<q�q3t|ddY�}tdZ|�tjj�||��t�fd[d\�|D��} t��d]}!| �sCt��|!k�rCt�d^�t|ddY�}tjj�||��t�fd_d\�|D��} | �sCt��|!k�s| �sKt	� d`�|�!��|S)aa�
    Remove the passed package(s) from the system using winrepo

    .. versionadded:: 0.16.0

    Args:
        name (str):
            The name(s) of the package(s) to be uninstalled. Can be a
            single package or a comma delimited list of packages, no spaces.

        pkgs (list):
            A list of packages to delete. Must be passed as a python list. The
            ``name`` parameter will be ignored if this option is passed.

    Kwargs:

        version (str):
            The version of the package to be uninstalled. If this option is
            used to to uninstall multiple packages, then this version will be
            applied to all targeted packages. Recommended using only when
            uninstalling a single package. If this parameter is omitted, the
            latest version will be uninstalled.

        saltenv (str): Salt environment. Default ``base``
        refresh (bool): Refresh package metadata. Default ``False``

    Returns:
        dict: Returns a dict containing the changes.

        If the package is removed by ``pkg.remove``:

            {'<package>': {'old': '<old-version>',
                           'new': '<new-version>'}}

        If the package is already uninstalled:

            {'<package>': {'current': 'not installed'}}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.remove <package name>
        salt '*' pkg.remove <package1>,<package2>,<package3>
        salt '*' pkg.remove pkgs='["foo", "bar"]'
    rrrFr�r�rTr�rr�z%s %s not installedr�currentz
not installedNr�z-%s %s using package latest entry to to removez not installedz*%s %s no definition to remove this versionz no definition, cannot removed�uninstallerr��uninstall_flagsr�z5No installer or uninstaller configured for package %szno uninstaller definedr�r�r�r�zPKG: Caching dir: %sr�r�r�rr�rrrr�r�rrrr�rWZextra_uninstall_flagsrr�r	r
rrz" /X "r�r
rrrrrrrrrrrrr�z1Scheduled Task failed to run. Failed to remove %szuninstall statusr|rrr"rr!r"rjr#r$r%r&r'r(z8Failed to remove %s; retcode: %s; uninstaller output: %sr)r5rMc3��|]}|�vVqdSr�r�rEr1�r>rrr����zremove.<locals>.<genexpr>�g�?c3rDr�rrErFrrr��rGz:Expected changes for package removal may not have occurred)"rr
rrrrRr rQr)r!r�r(r,rsrpr�r,r�r�r�rr��
expandvarsr-rer�r/r%r2�allr�r1r'r�)"r1r<r/rrr0r3r4r5r�r7rAr8Zremoval_targetsZver_install�targetrBr�rCZuninstaller_hashr�r�r�r9r:r�r�r;rr<r$r=Z
found_chgsZend_trrFrr��s�/

����
�
�

�
"��

�
"�����

����
�
���0
�

r�cKstd||d�|��S)a�
    Package purges are not supported on Windows, this function is identical to
    ``remove()``.

    .. note::
        At some point in the future, ``pkg.purge`` may direct the installer to
        remove all configs and settings for software packages that support that
        option.

    .. versionadded:: 0.16.0

    Args:

        name (str): The name of the package to be deleted.

        version (str):
            The version of the package to be deleted. If this option is
            used in combination with the ``pkgs`` option below, then this
            version will be applied to all targeted packages.

        pkgs (list):
            A list of packages to delete. Must be passed as a python
            list. The ``name`` parameter will be ignored if this option is
            passed.

    Kwargs:
        saltenv (str): Salt environment. Default ``base``
        refresh (bool): Refresh package metadata. Default ``False``

    Returns:
        dict: A dict containing the changes.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.purge <package name>
        salt '*' pkg.purge <package1>,<package2>,<package3>
        salt '*' pkg.purge pkgs='["foo", "bar"]'
    )r1r<Nr)r�)r1r<r/rrr�purge�s)rLcCs*t|�}|jdkrt�d�t|d�dtvr t�d�tdSt�d�zUtjj	�
|jd��A}ztjj�
tj�|���p>i�}|td<|WWd�WStyo}zt�|�iWYd}~Wd�WSd}~ww1sswYWdSty�}zt�d	|�iWYd}~Sd}~ww)
aV
    Returns the existing package metadata db. Will create it, if it does not
    exist, however will not refresh it.

    Args:
        saltenv (str): Salt environment. Default ``base``

    Returns:
        dict: A dict containing contents of metadata db.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.get_repo_data
    rwz,No winrepo.p cache file. Refresh pkg db now.rr�z0get_repo_data returning results from __context__z&get_repo_data called reading from disk�rbNzNot able to read repo file: %s)r~rr!r(r�r�r"r
rr�r�r�r�decoder��loads�readr�r�r�)rr�Zrepofiler�r�rrrr;	s:




��
���
��r;cCsi}t|��di�}|S)zT
    Return a reverse map of full pkg names to the names recognized by winrepo.
    rS�r;r)rZ
u_name_maprSrrrrO9	srOcCst||d�S)a
    Get information about the package as found in the winrepo database

    Args:

        name (str): The name of the package

        saltenv (str): The salt environment to use. Default is "base"

    Returns:
        dict: A dictionary of package info, empty if package not available

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.get_package_info chrome

    �r1r)r)rRrrr�get_package_infoB	srScCst|��di��|i�S)zj
    Return package info. Returns empty map if package not available
    TODO: Add option for version
    r9rQrRrrrr)Y	sr)cCst|�t|�kr
dSdS)z+
    Compare software package versions
    rrwr)Zpkg1Zpkg2rrrr$a	sr$cCsHt|�dkrtt|����Szt|tt�d���WSty#YdSw)z�
    Returns the latest version of the package.
    Will return 'latest' or version number string, and
    'Not Found' if 'Not Found' is the only entry.
    rrr)	r-r*r+r@r#rr$r%r&)rArrrr*h	s�r*r�==cCsj|std��|std��|dkrttj�}|dkrttj�}|dkr$d}|dkr*d}tjjj|||dd�S)a�
    Compare software package versions. Made public for use with Jinja

    Args:
        ver1 (str): A software version to compare
        oper (str): The operand to use to compare
        ver2 (str): A software version to compare

    Returns:
        bool: True if the comparison is valid, otherwise False

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.compare_versions 1.2 >= 1.3
    zcompare_version, ver1 is blankzcompare_version, ver2 is blankr�rKz	0.0.0.0.0T)Zignore_epoch)rr,�sys�maxsizer
rrBZcomparerrrrr+v	s

r+)T)FTT)TT)r)NFN)NN)rrTr)?�__doc__r�r�r��loggingr�rnrUr��urllib.parser��	functoolsrZsalt.fileserverr
Zsalt.payloadZ
salt.syspathsZsalt.utils.argsZsalt.utils.dataZsalt.utils.filesZsalt.utils.hashutilsZsalt.utils.pathZsalt.utils.pkgZsalt.utils.platformZsalt.utils.versionsZsalt.utils.win_functionsZsalt.exceptionsrrrrr�	getLogger�__name__r!r
rr4r6r=rCrDr rPr:r�r~r�r�r�r�r�r?r@r�rLr;rOrSr)r$r*r+rrrr�<module>s�&
	k
(<3
�
QG
Ii
�
R,

#
K
,
1