1414
1515ignoredups = [re .compile (val ) for opt , val in longargs if opt == "--ignoredups" ]
1616
17+ multi_file_validate = True
18+
1719if args :
18- try :
19- os .chdir (args [0 ])
20- except :
21- sys .stderr .write ("could not chdir to %s\n " % args [0 ])
22- sys .stderr .write ("usage: %s directoryname\n " % sys .argv [0 ])
23- sys .exit (2 )
20+ if os .path .isfile (args [0 ]):
21+ multi_file_validate = False
22+ else :
23+ try :
24+ os .chdir (args [0 ])
25+ except :
26+ sys .stderr .write ("could not chdir to %s\n " % args [0 ])
27+ sys .stderr .write ("usage: %s (<directoryname> or <file to validate><directory of all rulesets (optional)>\n " % sys .argv [0 ])
28+ sys .exit (2 )
2429
2530def test_not_anchored (tree ):
2631 # Rules not anchored to the beginning of a line.
@@ -42,19 +47,6 @@ def test_bad_regexp(tree):
4247 return False
4348 return True
4449
45- def test_missing_to (tree ):
46-
47- # Rules that are terminated before setting 'to'.
48- # These cases are probably either due to a misplaced
49- # rule end or intended to be different elements.
50- """Rule is missing a 'to' value."""
51- for rule in tree .xpath ("/ruleset/rule" ):
52- if not rule .get ("to" ):
53- sys .stdout .write ("warning: 'to' attribute missing in %s. " % fi )
54- sys .stdout .write ("Misplaced end or misnamed element?\n " )
55- return False
56- return True
57-
5850def test_unescaped_dots (tree ):
5951 # Rules containing unescaped dots outside of brackets and before slash.
6052 # Note: this is meant to require example\.com instead of example.com,
@@ -95,19 +87,16 @@ def test_unencrypted_to(tree):
9587 # Now warn if the rule author indicates they intended it, with the
9688 # downgrade attribute. Error if this attribute is not present.
9789 """Rule redirects to something other than https."""
98- down_warned = False
9990 for rule in tree .xpath ("/ruleset/rule" ):
10091 to , downgrade = rule .get ("to" ), rule .get ("downgrade" )
10192 if to [:6 ] != "https:" and to [:5 ] != "http:" :
10293 return False
10394 elif to [:5 ] == "http:" and downgrade :
104- if not down_warned :
105- sys .stdout .write ("warning: downgrade rule in %s redirects " % fi )
106- sys .stdout .write ("to http.\n " )
107- down_warned = True
95+ sys .stdout .write ("warning: downgrade rule in %s redirects " % fi )
96+ sys .stdout .write ("to http.\n " )
10897 elif to [:5 ] == "http:" :
109- sys .stdout .write ("error: rule in %s redirects to http and " % fi )
110- sys .stdout .write ("downgrade attribute not specified.\n " )
98+ sys .stdout .write ("error: rule in %s redirects to http and " % fi )
99+ sys .stdout .write ("downgrade attribute not specified.\n " )
111100 return False
112101 return True
113102
@@ -162,7 +151,22 @@ def test_non_ascii(tree):
162151 return False
163152 return True
164153
165- tests = [test_not_anchored , test_bad_regexp , test_unescaped_dots , test_missing_to ,
154+ def get_all_names_and_targets (d ):
155+ names = set ()
156+ targets = set ()
157+ for fi in os .listdir (d ):
158+ try :
159+ tree = etree .parse (fi )
160+ ruleset_name = tree .xpath ("/ruleset/@name" )[0 ]
161+ target_names = tree .xpath ("/ruleset/target/@host" )
162+ except Exception :
163+ continue
164+ names .add (ruleset_name )
165+ for target in target_names :
166+ targets .add (target )
167+ return names , targets
168+
169+ tests = [test_not_anchored , test_bad_regexp , test_unescaped_dots ,
166170 test_space_in_to , test_unencrypted_to , test_backslash_in_to ,
167171 test_no_trailing_slash , test_lacks_target_host , test_bad_target_host ,
168172 test_duplicated_target_host , test_non_ascii ]
@@ -172,25 +176,55 @@ def test_non_ascii(tree):
172176all_targets = set ()
173177all_names = set ()
174178
175- for fi in os .listdir ("." ):
179+ if multi_file_validate :
180+ for fi in os .listdir ("." ):
181+ try :
182+ tree = etree .parse (fi )
183+ if fi [- 4 :] != ".xml" :
184+ if tree .xpath ("/ruleset" ):
185+ sys .stdout .write ("warning: ruleset in file without .xml extension: %s\n " % fi )
186+ else :
187+ continue
188+ seen_file = True
189+ except Exception , oops :
190+ if fi [- 4 :] != ".xml" :
191+ continue
192+ failure = 1
193+ sys .stdout .write ("%s failed XML validity: %s\n " % (fi , oops ))
194+ ruleset_name = tree .xpath ("/ruleset/@name" )[0 ]
195+ if ruleset_name in all_names :
196+ failure = 1
197+ sys .stdout .write ("failure: duplicate ruleset name %s\n " % ruleset_name )
198+ all_names .add (ruleset_name )
199+ for test in tests :
200+ if not test (tree ):
201+ failure = 1
202+ sys .stdout .write ("failure: %s failed test: %s\n " % (fi , test .__doc__ ))
203+ for target in tree .xpath ("/ruleset/target/@host" ):
204+ if target in all_targets and not any (ign .search (target ) for ign in ignoredups ):
205+ # suppress warning about duplicate targets if an --ignoredups
206+ # pattern matches target
207+ sys .stdout .write ("warning: duplicate target: %s\n " % target )
208+ all_targets .add (target )
209+ else :
210+ fi = os .path .basename (args [0 ])
211+ if len (args ) > 1 :
212+ all_names , all_targets = get_all_names_and_targets (args [1 ])
213+ else :
214+ sys .stdout .write ("warning: pass a directory of existing rulesets as the second argument to check for duplicates \n " )
176215 try :
177- tree = etree .parse (fi )
178- if fi [- 4 :] != ".xml" :
179- if tree .xpath ("/ruleset" ):
180- sys .stdout .write ("warning: ruleset in file without .xml extension: %s\n " % fi )
181- else :
182- continue
183- seen_file = True
184- except Exception as oops :
185- if fi [- 4 :] != ".xml" :
186- continue
187- failure = 1
188- sys .stdout .write ("%s failed XML validity: %s\n " % (fi , oops ))
216+ tree = etree .parse (fi )
217+ if fi [- 4 :] != ".xml" :
218+ if tree .xpath ("/ruleset" ):
219+ sys .stdout .write ("warning: ruleset in file without .xml extension: %s\n " % fi )
220+ seen_file = True
221+ except Exception , oops :
222+ failure = 1
223+ sys .stdout .write ("%s failed XML validity: %s\n " % (fi , oops ))
189224 ruleset_name = tree .xpath ("/ruleset/@name" )[0 ]
190225 if ruleset_name in all_names :
191226 failure = 1
192227 sys .stdout .write ("failure: duplicate ruleset name %s\n " % ruleset_name )
193- all_names .add (ruleset_name )
194228 for test in tests :
195229 if not test (tree ):
196230 failure = 1
@@ -200,7 +234,6 @@ def test_non_ascii(tree):
200234 # suppress warning about duplicate targets if an --ignoredups
201235 # pattern matches target
202236 sys .stdout .write ("warning: duplicate target: %s\n " % target )
203- all_targets .add (target )
204237
205238if not seen_file :
206239 which = "specified" if args else "current"
0 commit comments