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 |