| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python2.4 | |
| 2 # | |
| 3 # Copyright 2009 Google Inc. | |
| 4 # | |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 # you may not use this file except in compliance with the License. | |
| 7 # You may obtain a copy of the License at | |
| 8 # | |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 # | |
| 11 # Unless required by applicable law or agreed to in writing, software | |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 # See the License for the specific language governing permissions and | |
| 15 # limitations under the License. | |
| 16 # ======================================================================== | |
| 17 | |
| 18 """Generates a Group Policy template file for Google Update policies. | |
| 19 | |
| 20 The resulting strings and files use CRLF as required by gpedit.msc. | |
| 21 | |
| 22 To unit test this module, just run the file from the command line. | |
| 23 """ | |
| 24 | |
| 25 import codecs | |
| 26 import filecmp | |
| 27 import os | |
| 28 import sys | |
| 29 | |
| 30 | |
| 31 HORIZONTAL_RULE = ';%s\n' % ('-' * 78) | |
| 32 MAIN_POLICY_KEY = 'Software\Policies\Google\Update' | |
| 33 | |
| 34 # pylint: disable-msg=C6004 | |
| 35 HEADER = """\ | |
| 36 CLASS MACHINE | |
| 37 CATEGORY !!Cat_Google | |
| 38 CATEGORY !!Cat_GoogleUpdate | |
| 39 KEYNAME \"""" + MAIN_POLICY_KEY + """\" | |
| 40 EXPLAIN !!Explain_GoogleUpdate | |
| 41 """ | |
| 42 | |
| 43 PREFERENCES = """ | |
| 44 CATEGORY !!Cat_Preferences | |
| 45 KEYNAME \"""" + MAIN_POLICY_KEY + """\" | |
| 46 EXPLAIN !!Explain_Preferences | |
| 47 | |
| 48 POLICY !!Pol_AutoUpdateCheckPeriod | |
| 49 #if version >= 4 | |
| 50 SUPPORTED !!Sup_GoogleUpdate1_2_145_5 | |
| 51 #endif | |
| 52 EXPLAIN !!Explain_AutoUpdateCheckPeriod | |
| 53 PART !!Part_AutoUpdateCheckPeriod NUMERIC | |
| 54 VALUENAME AutoUpdateCheckPeriodMinutes | |
| 55 DEFAULT 1400 ; 23 hours 20 minutes. | |
| 56 MIN 60 | |
| 57 MAX 43200 ; 30 days. | |
| 58 SPIN 60 ; Increment in hour chunks. | |
| 59 END PART | |
| 60 PART !!Part_DisableAllAutoUpdateChecks CHECKBOX | |
| 61 VALUENAME DisableAutoUpdateChecksCheckboxValue ; Required, unused. | |
| 62 ACTIONLISTON | |
| 63 ; Writes over Part_AutoUpdateCheckPeriod. Assumes this runs last. | |
| 64 VALUENAME AutoUpdateCheckPeriodMinutes VALUE NUMERIC 0 | |
| 65 END ACTIONLISTON | |
| 66 ACTIONLISTOFF | |
| 67 ; Do nothing. Let Part_AutoUpdateCheckPeriod take effect. | |
| 68 END ACTIONLISTOFF | |
| 69 VALUEOFF NUMERIC 0 | |
| 70 VALUEON NUMERIC 1 | |
| 71 END PART | |
| 72 END POLICY | |
| 73 | |
| 74 END CATEGORY ; Preferences | |
| 75 """ | |
| 76 | |
| 77 APPLICATIONS_HEADER = """ | |
| 78 CATEGORY !!Cat_Applications | |
| 79 KEYNAME \"""" + MAIN_POLICY_KEY + """\" | |
| 80 EXPLAIN !!Explain_Applications | |
| 81 """ | |
| 82 | |
| 83 UPDATE_POLICY_ITEMLIST = """\ | |
| 84 ITEMLIST | |
| 85 NAME !!Name_AutomaticUpdates | |
| 86 VALUE NUMERIC 1 | |
| 87 NAME !!Name_ManualUpdates | |
| 88 VALUE NUMERIC 2 | |
| 89 NAME !!Name_UpdatesDisabled | |
| 90 VALUE NUMERIC 0 | |
| 91 END ITEMLIST | |
| 92 REQUIRED""" | |
| 93 | |
| 94 APPLICATION_DEFAULTS = (""" | |
| 95 POLICY !!Pol_DefaultAllowInstallation | |
| 96 #if version >= 4 | |
| 97 SUPPORTED !!Sup_GoogleUpdate1_2_145_5 | |
| 98 #endif | |
| 99 EXPLAIN !!Explain_DefaultAllowInstallation | |
| 100 VALUENAME InstallDefault | |
| 101 VALUEOFF NUMERIC 0 | |
| 102 VALUEON NUMERIC 1 | |
| 103 END POLICY | |
| 104 | |
| 105 POLICY !!Pol_DefaultUpdatePolicy | |
| 106 #if version >= 4 | |
| 107 SUPPORTED !!Sup_GoogleUpdate1_2_145_5 | |
| 108 #endif | |
| 109 EXPLAIN !!Explain_DefaultUpdatePolicy | |
| 110 PART !!Part_UpdatePolicy DROPDOWNLIST | |
| 111 VALUENAME UpdateDefault | |
| 112 """ + | |
| 113 UPDATE_POLICY_ITEMLIST + """ | |
| 114 END PART | |
| 115 END POLICY | |
| 116 """) | |
| 117 | |
| 118 APP_POLICIES_TEMPLATE = (""" | |
| 119 CATEGORY !!Cat_$AppLegalId$ | |
| 120 KEYNAME \"""" + MAIN_POLICY_KEY + """\" | |
| 121 | |
| 122 POLICY !!Pol_AllowInstallation | |
| 123 #if version >= 4 | |
| 124 SUPPORTED !!Sup_GoogleUpdate1_2_145_5 | |
| 125 #endif | |
| 126 EXPLAIN !!Explain_Install$AppLegalId$ | |
| 127 VALUENAME Install$AppGuid$ | |
| 128 VALUEOFF NUMERIC 0 | |
| 129 VALUEON NUMERIC 1 | |
| 130 END POLICY | |
| 131 | |
| 132 POLICY !!Pol_UpdatePolicy | |
| 133 #if version >= 4 | |
| 134 SUPPORTED !!Sup_GoogleUpdate1_2_145_5 | |
| 135 #endif | |
| 136 EXPLAIN !!Explain_AutoUpdate$AppLegalId$ | |
| 137 PART !!Part_UpdatePolicy DROPDOWNLIST | |
| 138 VALUENAME Update$AppGuid$ | |
| 139 """ + | |
| 140 UPDATE_POLICY_ITEMLIST.replace(' ', ' ') + """ | |
| 141 END PART | |
| 142 END POLICY | |
| 143 | |
| 144 END CATEGORY ; $AppName$ | |
| 145 """) | |
| 146 | |
| 147 APPLICATIONS_FOOTER = """ | |
| 148 END CATEGORY ; Applications | |
| 149 | |
| 150 END CATEGORY ; GoogleUpdate | |
| 151 | |
| 152 END CATEGORY ; Google | |
| 153 """ | |
| 154 | |
| 155 # Policy names that are used in multiple locations. | |
| 156 ALLOW_INSTALLATION_POLICY = 'Allow installation' | |
| 157 DEFAULT_ALLOW_INSTALLATION_POLICY = ALLOW_INSTALLATION_POLICY + ' default' | |
| 158 UPDATE_POLICY = 'Update policy override' | |
| 159 DEFAULT_UPDATE_POLICY = UPDATE_POLICY + ' default' | |
| 160 | |
| 161 # Update policy options that are used in multiple locations. | |
| 162 AUTOMATIC_UPDATES = 'Automatic silent updates' | |
| 163 MANUAL_UPDATES = 'Manual updates only' | |
| 164 UPDATES_DISABLED = 'Updates disabled' | |
| 165 | |
| 166 # Category names that are used in multiple locations. | |
| 167 PREFERENCES_CATEGORY = 'Preferences' | |
| 168 APPLICATIONS_CATEGORY = 'Applications' | |
| 169 | |
| 170 # The captions for update policy were selected such that they appear in order of | |
| 171 # decreasing preference when organized alphabetically in gpedit. | |
| 172 STRINGS_HEADER_AND_COMMON = ('\n' + | |
| 173 HORIZONTAL_RULE + | |
| 174 """ | |
| 175 [strings] | |
| 176 Sup_GoogleUpdate1_2_145_5=At least Google Update 1.2.145.5 | |
| 177 | |
| 178 Cat_Google=Google | |
| 179 Cat_GoogleUpdate=Google Update | |
| 180 Cat_Preferences=""" + PREFERENCES_CATEGORY + """ | |
| 181 Cat_Applications=""" + APPLICATIONS_CATEGORY + """ | |
| 182 | |
| 183 Pol_AutoUpdateCheckPeriod=Auto-update check period override | |
| 184 Pol_DefaultAllowInstallation=""" + DEFAULT_ALLOW_INSTALLATION_POLICY + """ | |
| 185 Pol_AllowInstallation=""" + ALLOW_INSTALLATION_POLICY + """ | |
| 186 Pol_DefaultUpdatePolicy=""" + DEFAULT_UPDATE_POLICY + """ | |
| 187 Pol_UpdatePolicy=""" + UPDATE_POLICY + """ | |
| 188 | |
| 189 Part_AutoUpdateCheckPeriod=Minutes between update checks | |
| 190 Part_DisableAllAutoUpdateChecks=Disable all auto-update checks (not recommended) | |
| 191 Part_UpdatePolicy=Policy | |
| 192 | |
| 193 Name_AutomaticUpdates=""" + AUTOMATIC_UPDATES + """ (recommended) | |
| 194 Name_ManualUpdates=""" + MANUAL_UPDATES + """ | |
| 195 Name_UpdatesDisabled=""" + UPDATES_DISABLED + """ | |
| 196 | |
| 197 """) | |
| 198 | |
| 199 STRINGS_APP_NAME_TEMPLATE = """\ | |
| 200 Cat_$AppLegalId$=$AppName$ | |
| 201 """ | |
| 202 | |
| 203 # pylint: disable-msg=C6310 | |
| 204 # pylint: disable-msg=C6013 | |
| 205 | |
| 206 # "application's" should be preceeded by a different word in different contexts. | |
| 207 # The word is specified by replacing the $PreApplicationWord$ token. | |
| 208 STRINGS_UPDATE_POLICY_OPTIONS = """\ | |
| 209 \\n\\nOptions:\\ | |
| 210 \\n - """ + AUTOMATIC_UPDATES + """: Updates are automatically applied when
they are found via the periodic update check.\\ | |
| 211 \\n - """ + MANUAL_UPDATES + """: Updates are only applied when the user doe
s a manual update check. (Not all apps provide an interface for this.)\\ | |
| 212 \\n - """ + UPDATES_DISABLED + """: Never apply updates.\\ | |
| 213 \\n\\nIf you select manual updates, you should periodically check for update
s using $PreApplicationWord$ application's manual update mechanism if available.
If you disable updates, you should periodically check for updates and distribut
e them to users.""" | |
| 214 | |
| 215 STRINGS_COMMON_EXPLANATIONS = (""" | |
| 216 Explain_GoogleUpdate=Policies to control the installation and updating of Google
applications that use Google Update/Google Installer. | |
| 217 | |
| 218 """ + | |
| 219 HORIZONTAL_RULE + | |
| 220 '; ' + PREFERENCES_CATEGORY + '\n' + | |
| 221 HORIZONTAL_RULE + """ | |
| 222 Explain_Preferences=General policies for Google Update. | |
| 223 | |
| 224 Explain_AutoUpdateCheckPeriod=Minimum number of minutes between automatic update
checks. | |
| 225 | |
| 226 """ + | |
| 227 HORIZONTAL_RULE + | |
| 228 '; ' + APPLICATIONS_CATEGORY + '\n' + | |
| 229 HORIZONTAL_RULE + """ | |
| 230 Explain_Applications=Policies for individual applications.\\ | |
| 231 \\n\\nAn updated ADM template will be required to support Google application
s released in the future. | |
| 232 | |
| 233 Explain_DefaultAllowInstallation=Specifies the default behavior for whether Goog
le software can be installed using Google Update/Google Installer.\\ | |
| 234 \\n\\nCan be overridden by the \"""" + ALLOW_INSTALLATION_POLICY + """\" for
individual applications.\\ | |
| 235 \\n\\nOnly affects installation of Google software using Google Update/Googl
e Installer. Cannot prevent running the application installer directly or instal
lation of Google software that does not use Google Update/Google Installer for i
nstallation. | |
| 236 | |
| 237 Explain_DefaultUpdatePolicy=Specifies the default policy for software updates fr
om Google.\\ | |
| 238 \\n\\nCan be overridden by the \"""" + UPDATE_POLICY + """\" for individual
applications.\\ | |
| 239 """ + | |
| 240 STRINGS_UPDATE_POLICY_OPTIONS.replace('$PreApplicationWord$', 'each') + """\\ | |
| 241 \\n\\nOnly affects updates for Google software that uses Google Update for u
pdates. Does not prevent auto-updates of Google software that does not use Googl
e Update for updates.\\ | |
| 242 \\n\\nUpdates for Google Update are not affected by this setting; Google Upd
ate will continue to update itself while it is installed.\\ | |
| 243 \\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. | |
| 244 | |
| 245 """ + | |
| 246 HORIZONTAL_RULE + | |
| 247 '; Individual Applications\n' + | |
| 248 HORIZONTAL_RULE) | |
| 249 | |
| 250 STRINGS_APP_POLICY_EXPLANATIONS_TEMPLATE = (""" | |
| 251 ; $AppName$ | |
| 252 Explain_Install$AppLegalId$=Specifies whether $AppName$ can be installed using G
oogle Update/Google Installer.\\ | |
| 253 \\n\\nIf this policy is not configured, $AppName$ can be installed as specif
ied by \"""" + DEFAULT_ALLOW_INSTALLATION_POLICY + """\". | |
| 254 | |
| 255 Explain_AutoUpdate$AppLegalId$=Specifies how Google Update handles available $Ap
pName$ updates from Google.\\ | |
| 256 \\n\\nIf this policy is not configured, Google Update handles available upda
tes as specified by \"""" + DEFAULT_UPDATE_POLICY + """\".\\ | |
| 257 """ + | |
| 258 STRINGS_UPDATE_POLICY_OPTIONS.replace('$PreApplicationWord$', 'the') + '$AppUpda
teExplainExtra$\n') | |
| 259 | |
| 260 # pylint: enable-msg=C6013 | |
| 261 # pylint: enable-msg=C6310 | |
| 262 # pylint: enable-msg=C6004 | |
| 263 | |
| 264 | |
| 265 def GenerateGroupPolicyTemplate(apps): | |
| 266 # pylint: disable-msg=C6114 | |
| 267 """Generates a Group Policy template (ADM format)for the specified apps. | |
| 268 | |
| 269 Replaces LF in strings above with CRLF as required by gpedit.msc. | |
| 270 When writing the resulting contents to a file, use binary mode to ensure the | |
| 271 CRLFs are preserved. | |
| 272 | |
| 273 Args: | |
| 274 apps: A list of tuples containing information about each app. | |
| 275 Each element of the list is a tuple of: | |
| 276 * app name | |
| 277 * app ID | |
| 278 * optional string to append to the auto-update explanation | |
| 279 - Should start with a space or double new line (\n\n). | |
| 280 | |
| 281 Returns: | |
| 282 String containing the contents of the .ADM file. | |
| 283 """ | |
| 284 # pylint: enable-msg=C6114 | |
| 285 | |
| 286 def _CreateLegalIdentifier(input_string): | |
| 287 """Converts input_string to a legal identifier for ADM files. | |
| 288 | |
| 289 Changes some characters that do not necessarily cause problems and may not | |
| 290 handle all cases. | |
| 291 | |
| 292 Args: | |
| 293 input_string: Text to convert to a legal identifier. | |
| 294 | |
| 295 Returns: | |
| 296 String containing a legal identifier based on input_string. | |
| 297 """ | |
| 298 | |
| 299 # pylint: disable-msg=C6004 | |
| 300 return (input_string.replace(' ', '') | |
| 301 .replace('&', '') | |
| 302 .replace('=', '') | |
| 303 .replace(';', '') | |
| 304 .replace(',', '') | |
| 305 .replace('.', '') | |
| 306 .replace('?', '') | |
| 307 .replace('=', '') | |
| 308 .replace(';', '') | |
| 309 .replace("'", '') | |
| 310 .replace('"', '') | |
| 311 .replace('\\', '') | |
| 312 .replace('/', '') | |
| 313 .replace('(', '') | |
| 314 .replace(')', '') | |
| 315 .replace('[', '') | |
| 316 .replace(']', '') | |
| 317 .replace('{', '') | |
| 318 .replace('}', '') | |
| 319 .replace('-', '') | |
| 320 .replace('!', '') | |
| 321 .replace('@', '') | |
| 322 .replace('#', '') | |
| 323 .replace('$', '') | |
| 324 .replace('%', '') | |
| 325 .replace('^', '') | |
| 326 .replace('*', '') | |
| 327 .replace('+', '') | |
| 328 .replace(u'\u00a9', '') # Copyright (C). | |
| 329 .replace(u'\u00ae', '') # Registered Trademark (R). | |
| 330 .replace(u'\u2122', '')) # Trademark (TM). | |
| 331 | |
| 332 # pylint: enable-msg=C6004 | |
| 333 | |
| 334 def _WriteTemplateForApp(template, app): | |
| 335 """Writes the text for the specified app based on the template. | |
| 336 | |
| 337 Replaces $AppName$, $AppLegalId$, $AppGuid$, and $AppUpdateExplainExtra$. | |
| 338 | |
| 339 Args: | |
| 340 template: text to process and write. | |
| 341 app: tuple containing information about the app. | |
| 342 | |
| 343 Returns: | |
| 344 String containing a copy of the template populated with app-specific | |
| 345 strings. | |
| 346 """ | |
| 347 | |
| 348 (app_name, app_guid, update_explain_extra) = app | |
| 349 # pylint: disable-msg=C6004 | |
| 350 return (template.replace('$AppName$', app_name) | |
| 351 .replace('$AppLegalId$', _CreateLegalIdentifier(app_name)) | |
| 352 .replace('$AppGuid$', app_guid) | |
| 353 .replace('$AppUpdateExplainExtra$', update_explain_extra) | |
| 354 ) | |
| 355 # pylint: enable-msg=C6004 | |
| 356 | |
| 357 def _WriteTemplateForAllApps(template, apps): | |
| 358 """Writes a copy of the template for each of the specified apps. | |
| 359 | |
| 360 Args: | |
| 361 template: text to process and write. | |
| 362 apps: list of tuples containing information about the apps. | |
| 363 | |
| 364 Returns: | |
| 365 String containing concatenated copies of the template for each app in | |
| 366 apps, each populated with the appropriate app-specific strings. | |
| 367 """ | |
| 368 | |
| 369 content = [_WriteTemplateForApp(template, app) for app in apps] | |
| 370 return ''.join(content) | |
| 371 | |
| 372 target_contents = [ | |
| 373 HEADER, | |
| 374 PREFERENCES, | |
| 375 APPLICATIONS_HEADER, | |
| 376 APPLICATION_DEFAULTS, | |
| 377 _WriteTemplateForAllApps(APP_POLICIES_TEMPLATE, apps), | |
| 378 APPLICATIONS_FOOTER, | |
| 379 STRINGS_HEADER_AND_COMMON, | |
| 380 _WriteTemplateForAllApps(STRINGS_APP_NAME_TEMPLATE, apps), | |
| 381 STRINGS_COMMON_EXPLANATIONS, | |
| 382 _WriteTemplateForAllApps(STRINGS_APP_POLICY_EXPLANATIONS_TEMPLATE, apps), | |
| 383 ] | |
| 384 | |
| 385 # Join the sections of content then replace LF with CRLF. | |
| 386 return ''.join(target_contents).replace('\n', '\r\n') | |
| 387 | |
| 388 | |
| 389 def WriteGroupPolicyTemplate(target_path, apps): | |
| 390 """Writes a Group Policy template (ADM format)for the specified apps. | |
| 391 | |
| 392 The file is UTF-16 and contains CRLF on all platforms. | |
| 393 | |
| 394 Args: | |
| 395 target_path: Output path of the .ADM template file. | |
| 396 apps: A list of tuples containing information about each app. | |
| 397 Each element of the list is a tuple of: | |
| 398 * app name | |
| 399 * app ID | |
| 400 * optional string to append to the auto-update explanation | |
| 401 - Should start with a space or double new line (\n\n). | |
| 402 """ # pylint: disable-msg=C6114 | |
| 403 | |
| 404 contents = GenerateGroupPolicyTemplate(apps) | |
| 405 f = codecs.open(target_path, 'wb', 'utf-16') | |
| 406 f.write(contents) | |
| 407 f.close() | |
| 408 | |
| 409 # Run a unit test when the module is run directly. | |
| 410 if __name__ == '__main__': | |
| 411 TEST_APPS = [ | |
| 412 ('Google Test Foo', | |
| 413 '{D6B08267-B440-4c85-9F79-E195E80D9937}', | |
| 414 ' Check http://www.google.com/test_foo/.'), | |
| 415 (u'Google User Test Foo\u00a9\u00ae\u2122', | |
| 416 '{104844D6-7DDA-460b-89F0-FBF8AFDD0A67}', | |
| 417 ' Check http://www.google.com/user_test_foo/.'), | |
| 418 ] | |
| 419 TEST_GOLD_FILENAME = 'test_gold.adm' | |
| 420 TEST_OUTPUT_FILENAME = 'test_out.adm' | |
| 421 | |
| 422 module_dir = os.path.abspath(os.path.dirname(__file__)) | |
| 423 gold_path = os.path.join(module_dir, TEST_GOLD_FILENAME) | |
| 424 output_path = os.path.join(module_dir, TEST_OUTPUT_FILENAME) | |
| 425 | |
| 426 WriteGroupPolicyTemplate(output_path, TEST_APPS) | |
| 427 | |
| 428 if filecmp.cmp(gold_path, output_path, shallow=False): | |
| 429 print 'PASS: Contents equal.' | |
| 430 else: | |
| 431 print 'FAIL: Contents not equal.' | |
| 432 sys.exit(-1) | |
| OLD | NEW |