blob: 2707a0c14642fed2112264e9e318a5cb940f07a3 [file]
#!/usr/bin/python2.4
#
# Copyright 2009 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========================================================================
"""Generates a Group Policy template file for Google Update policies.
This script only works on Windows because gpedit.msc requires Windows-style
line endings (\r\n).
To unit test this module, just run the file from the command line.
"""
import filecmp
import os
import sys
HORIZONTAL_RULE = ';%s\n' % ('-' * 78)
# pylint: disable-msg=C6004
HEADER = """\
CLASS MACHINE
CATEGORY !!Cat_Google
CATEGORY !!Cat_GoogleUpdate
KEYNAME !!Key_BaseName
EXPLAIN !!Explain_GoogleUpdate
"""
PREFERENCES = """
CATEGORY !!Cat_Preferences
KEYNAME !!Key_BaseName
EXPLAIN !!Explain_Preferences
POLICY !!Pol_AutoUpdateCheckPeriod
EXPLAIN !!Explain_AutoUpdateCheckPeriod
PART !!Part_AutoUpdateCheckPeriod NUMERIC
VALUENAME AutoUpdateCheckPeriodMinutes
DEFAULT 1400 ; 23 hours 20 minutes.
MIN 30
MAX 65535 ; 45.5 days.
SPIN 60 ; Increment in hour chunks.
END PART
END POLICY
END CATEGORY ; Preferences
"""
APPLICATIONS_HEADER = """
CATEGORY !!Cat_Applications
KEYNAME !!Key_BaseName
EXPLAIN !!Explain_Applications
"""
UPDATE_POLICY_ITEMLIST = """\
ITEMLIST
NAME !!Name_AutomaticUpdates
VALUE NUMERIC 1
NAME !!Name_ManualUpdates
VALUE NUMERIC 2
NAME !!Name_UpdatesDisabled
VALUE NUMERIC 0
END ITEMLIST
REQUIRED"""
APPLICATION_DEFAULTS = ("""
POLICY !!Pol_DefaultAllowInstallation
EXPLAIN !!Explain_DefaultAllowInstallation
VALUENAME InstallDefault
VALUEOFF NUMERIC 0
VALUEON NUMERIC 1
END POLICY
POLICY !!Pol_DefaultUpdatePolicy
EXPLAIN !!Explain_DefaultUpdatePolicy
PART !!Part_UpdatePolicy DROPDOWNLIST
VALUENAME UpdateDefault
""" +
UPDATE_POLICY_ITEMLIST + """
END PART
END POLICY
""")
APP_POLICIES_TEMPLATE = ("""
CATEGORY !!Cat_$AppLegalId$
KEYNAME !!Key_BaseName
POLICY !!Pol_AllowInstallation
EXPLAIN !!Explain_Install$AppLegalId$
VALUENAME Install$AppGuid$
VALUEOFF NUMERIC 0
VALUEON NUMERIC 1
END POLICY
POLICY !!Pol_UpdatePolicy
EXPLAIN !!Explain_AutoUpdate$AppLegalId$
PART !!Part_UpdatePolicy DROPDOWNLIST
VALUENAME Update$AppGuid$
""" +
UPDATE_POLICY_ITEMLIST.replace(' ', ' ') + """
END PART
END POLICY
END CATEGORY ; $AppName$
""")
APPLICATIONS_FOOTER = """
END CATEGORY ; Applications
END CATEGORY ; GoogleUpdate
END CATEGORY ; Google
"""
# Policy names that are used in multiple locations.
ALLOW_INSTALLATION_POLICY = 'Allow installation'
DEFAULT_ALLOW_INSTALLATION_POLICY = ALLOW_INSTALLATION_POLICY + ' default'
UPDATE_POLICY = 'Update policy override'
DEFAULT_UPDATE_POLICY = UPDATE_POLICY + ' default'
# Update policy options that are used in multiple locations.
AUTOMATIC_UPDATES = 'Automatic silent updates'
MANUAL_UPDATES = 'Manual updates only'
UPDATES_DISABLED = 'Updates disabled'
# Category names that are used in multiple locations.
PREFERENCES_CATEGORY = 'Preferences'
APPLICATIONS_CATEGORY = 'Applications'
# The captions for update policy were selected such that they appear in order of
# decreasing preference when organized alphabetically in gpedit.
STRINGS_HEADER_AND_COMMON = ('\n' +
HORIZONTAL_RULE +
"""
[strings]
Key_BaseName=Software\\Policies\\Google\\Update
Cat_Google=Google
Cat_GoogleUpdate=Google Update
Cat_Preferences=""" + PREFERENCES_CATEGORY + """
Cat_Applications=""" + APPLICATIONS_CATEGORY + """
Pol_AutoUpdateCheckPeriod=Auto-update check period override
Pol_DefaultAllowInstallation=""" + DEFAULT_ALLOW_INSTALLATION_POLICY + """
Pol_AllowInstallation=""" + ALLOW_INSTALLATION_POLICY + """
Pol_DefaultUpdatePolicy=""" + DEFAULT_UPDATE_POLICY + """
Pol_UpdatePolicy=""" + UPDATE_POLICY + """
Part_AutoUpdateCheckPeriod=Minutes between update checks
Part_UpdatePolicy=Policy
Name_AutomaticUpdates=""" + AUTOMATIC_UPDATES + """ (recommended)
Name_ManualUpdates=""" + MANUAL_UPDATES + """
Name_UpdatesDisabled=""" + UPDATES_DISABLED + """
""")
STRINGS_APP_NAME_TEMPLATE = """\
Cat_$AppLegalId$=$AppName$
"""
# pylint: disable-msg=C6310
# pylint: disable-msg=C6013
# "application's" should be preceeded by a different word in different contexts.
# The word is specified by replacing the $PreApplicationWord$ token.
STRINGS_UPDATE_POLICY_OPTIONS = """\
\\n\\nOptions:\\
\\n - """ + AUTOMATIC_UPDATES + """: Updates are automatically applied when they are found via the periodic update check.\\
\\n - """ + MANUAL_UPDATES + """: Updates are only applied when the user does a manual update check. (Not all apps provide an interface for this.)\\
\\n - """ + UPDATES_DISABLED + """: Never apply updates.\\
\\n\\nIf you select manual updates, you should periodically check for updates using $PreApplicationWord$ application's manual update mechanism if available. If you disable updates, you should periodically check for updates and distribute them to users."""
STRINGS_COMMON_EXPLANATIONS = ("""
Explain_GoogleUpdate=Policies to control the installation and updating of Google applications that use Google Update/Google Installer.
""" +
HORIZONTAL_RULE +
'; ' + PREFERENCES_CATEGORY + '\n' +
HORIZONTAL_RULE + """
Explain_Preferences=General policies for Google Update.
Explain_AutoUpdateCheckPeriod=Minimum number of minutes between automatic update checks.
""" +
HORIZONTAL_RULE +
'; ' + APPLICATIONS_CATEGORY + '\n' +
HORIZONTAL_RULE + """
Explain_Applications=Policies for individual applications.\\
\\n\\nAn updated ADM template will be required to support Google applications released in the future.
Explain_DefaultAllowInstallation=Specifies the default behavior for whether Google software can be installed using Google Update/Google Installer.\\
\\n\\nCan be overridden by the \"""" + ALLOW_INSTALLATION_POLICY + """\" for individual applications.\\
\\n\\nOnly affects installation of Google software using Google Update/Google Installer. Cannot prevent running the application installer directly or installation of Google software that does not use Google Update/Google Installer for installation.
Explain_DefaultUpdatePolicy=Specifies the default policy for software updates from Google.\\
\\n\\nCan be overridden by the \"""" + UPDATE_POLICY + """\" for individual applications.\\
""" +
STRINGS_UPDATE_POLICY_OPTIONS.replace('$PreApplicationWord$', 'each') + """\\
\\n\\nOnly affects updates for Google software that uses Google Update for updates. Does not prevent auto-updates of Google software that does not use Google Update for updates.\\
\\n\\nUpdates for Google Update are not affected by this setting; Google Update will continue to update itself while it is installed.\\
\\n\\nWARNING: Disabing updates will also prevent updates of any new Google applications released in the future, possibly including dependencies for future versions of installed applications.
""" +
HORIZONTAL_RULE +
'; Individual Applications\n' +
HORIZONTAL_RULE)
STRINGS_APP_POLICY_EXPLANATIONS_TEMPLATE = ("""
; $AppName$
Explain_Install$AppLegalId$=Specifies whether $AppName$ can be installed using Google Update/Google Installer.\\
\\n\\nIf this policy is not configured, $AppName$ can be installed as specified by \"""" + DEFAULT_ALLOW_INSTALLATION_POLICY + """\".
Explain_AutoUpdate$AppLegalId$=Specifies how Google Update handles available $AppName$ updates from Google.\\
\\n\\nIf this policy is not configured, Google Update handles available updates as specified by \"""" + DEFAULT_UPDATE_POLICY + """\".\\
""" +
STRINGS_UPDATE_POLICY_OPTIONS.replace('$PreApplicationWord$', 'the') + '$AppUpdateExplainExtra$\n')
# pylint: enable-msg=C6013
# pylint: enable-msg=C6310
# pylint: enable-msg=C6004
def GenerateGroupPolicyTemplate(apps):
"""Generates a Group Policy template (ADM format)for the specified apps.
Args:
apps: A list of tuples containing information about each app.
Each element of the list is a tuple of:
* app name
* app ID
* optional string to append to the auto-update explanation
- Should start with a space or double new line (\n\n).
target_path: Output path of the .ADM template file.
Returns:
String containing the contents of the .ADM file.
"""
def _CreateLegalIdentifier(input_string):
"""Converts input_string to a legal identifier for ADM files.
Changes some characters that do not necessarily cause problems and may not
handle all cases.
Args:
input_string: Text to convert to a legal identifier.
Returns:
String containing a legal identifier based on input_string.
"""
# pylint: disable-msg=C6004
return (input_string.replace(' ', '')
.replace('&', '')
.replace('=', '')
.replace(';', '')
.replace(',', '')
.replace('.', '')
.replace('?', '')
.replace('=', '')
.replace(';', '')
.replace("'", '')
.replace('"', '')
.replace('\\', '')
.replace('/', '')
.replace('(', '')
.replace(')', '')
.replace('[', '')
.replace(']', '')
.replace('{', '')
.replace('}', '')
.replace('-', '')
.replace('!', '')
.replace('@', '')
.replace('#', '')
.replace('$', '')
.replace('%', '')
.replace('^', '')
.replace('*', '')
.replace('+', ''))
# pylint: enable-msg=C6004
def _WriteTemplateForApp(template, app):
"""Writes the text for the specified app based on the template.
Replaces $AppName$, $AppLegalId$, $AppGuid$, and $AppUpdateExplainExtra$.
Args:
template: text to process and write.
app: tuple containing information about the app.
Returns:
String containing a copy of the template populated with app-specific
strings.
"""
(app_name, app_guid, update_explain_extra) = app
# pylint: disable-msg=C6004
return (template.replace('$AppName$', app_name)
.replace('$AppLegalId$', _CreateLegalIdentifier(app_name))
.replace('$AppGuid$', app_guid)
.replace('$AppUpdateExplainExtra$', update_explain_extra)
)
# pylint: enable-msg=C6004
def _WriteTemplateForAllApps(template, apps):
"""Writes a copy of the template for each of the specified apps.
Args:
template: text to process and write.
apps: list of tuples containing information about the apps.
Returns:
String containing concatenated copies of the template for each app in
apps, each populated with the appropriate app-specific strings.
"""
content = [_WriteTemplateForApp(template, app) for app in apps]
return ''.join(content)
target_contents = [
HEADER,
PREFERENCES,
APPLICATIONS_HEADER,
APPLICATION_DEFAULTS,
_WriteTemplateForAllApps(APP_POLICIES_TEMPLATE, apps),
APPLICATIONS_FOOTER,
STRINGS_HEADER_AND_COMMON,
_WriteTemplateForAllApps(STRINGS_APP_NAME_TEMPLATE, apps),
STRINGS_COMMON_EXPLANATIONS,
_WriteTemplateForAllApps(STRINGS_APP_POLICY_EXPLANATIONS_TEMPLATE, apps),
]
return ''.join(target_contents)
# Run a unit test when the module is run directly.
if __name__ == '__main__':
TEST_APPS = [
('Google Chrome',
'{8A69D345-D564-463C-AFF1-A69D9E530F96}',
' Check http://www.google.com/chrome/.'),
('Google Earth',
'{74AF07D8-FB8F-4D51-8AC7-927721D56EBB}',
' Check http://earth.google.com/.'),
]
TEST_GOLD_FILENAME = 'test_gold.adm'
TEST_OUTPUT_FILENAME = 'test_out.adm'
module_dir = os.path.abspath(os.path.dirname(__file__))
gold_path = os.path.join(module_dir, TEST_GOLD_FILENAME)
output_path = os.path.join(module_dir, TEST_OUTPUT_FILENAME)
test_target_contents = GenerateGroupPolicyTemplate(TEST_APPS)
target = open(output_path, 'wt')
target.write(test_target_contents)
target.close()
if filecmp.cmp(gold_path, output_path, shallow=False):
print 'PASS: Contents equal.'
else:
print 'FAIL: Contents not equal.'
sys.exit(-1)