mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
gp_parse: Add a generalize XML function to the top level parser
In this function we take XML and using the required metadata, we rewrite it into a generic form using entities. ElementTree unfortunately does not allow us to store unescaped entities, and so we must do a textual replace on the output XML. Signed-off-by: Garming Sam <garming@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
57dd88ce5c
commit
abff0c4f4d
@ -19,11 +19,34 @@
|
||||
|
||||
from xml.dom import minidom
|
||||
from io import BytesIO
|
||||
from xml.etree.ElementTree import ElementTree
|
||||
from xml.etree.ElementTree import ElementTree, fromstring, tostring
|
||||
|
||||
|
||||
ENTITY_USER_ID = 0
|
||||
ENTITY_SDDL_ACL = 1
|
||||
ENTITY_NETWORK_PATH = 2
|
||||
|
||||
|
||||
class GPNoParserException(Exception):
|
||||
pass
|
||||
|
||||
class GPGeneralizeException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def entity_type_to_string(ent_type):
|
||||
type_str = None
|
||||
|
||||
if ent_type == ENTITY_USER_ID:
|
||||
type_str = "USER_ID"
|
||||
elif ent_type == ENTITY_SDDL_ACL:
|
||||
type_str = "SDDL_ACL"
|
||||
elif ent_type == ENTITY_NETWORK_PATH:
|
||||
type_str = "NETWORK_PATH"
|
||||
|
||||
return type_str
|
||||
|
||||
|
||||
# [MS-GPIPSEC] (LDAP)
|
||||
# [MS-GPDPC] Deployed Printer Connections (LDAP)
|
||||
# [MS-GPPREF] Preferences Extension (XML)
|
||||
@ -55,3 +78,105 @@ class GPParser(object):
|
||||
xml_declaration=True)
|
||||
minidom_parsed = minidom.parseString(temporary_bytes.getvalue())
|
||||
handle.write(minidom_parsed.toprettyxml(encoding=self.output_encoding))
|
||||
|
||||
def new_xml_entity(self, global_entities, ent_type):
|
||||
identifier = str(len(global_entities)).zfill(4)
|
||||
|
||||
type_str = entity_type_to_string(ent_type)
|
||||
|
||||
if type_str is None:
|
||||
raise GPGeneralizeException("No such entity type")
|
||||
|
||||
# For formattting reasons, align the length of the entities
|
||||
longest = entity_type_to_string(ENTITY_NETWORK_PATH)
|
||||
type_str = type_str.center(len(longest), '_')
|
||||
|
||||
return "&SAMBA__{}__{}__;".format(type_str, identifier)
|
||||
|
||||
def generalize_xml(self, root, out_file, global_entities):
|
||||
entities = []
|
||||
|
||||
# Locate all user_id and all ACLs
|
||||
user_ids = root.findall('.//*[@user_id="TRUE"]')
|
||||
user_ids.sort()
|
||||
|
||||
for elem in user_ids:
|
||||
old_text = elem.text
|
||||
if old_text is None or old_text == '':
|
||||
continue
|
||||
|
||||
if old_text in global_entities:
|
||||
elem.text = global_entities[old_text]
|
||||
entities.append((elem.text, old_text))
|
||||
else:
|
||||
elem.text = self.new_xml_entity(global_entities,
|
||||
ENTITY_USER_ID)
|
||||
|
||||
entities.append((elem.text, old_text))
|
||||
global_entities.update([(old_text, elem.text)])
|
||||
|
||||
acls = root.findall('.//*[@acl="TRUE"]')
|
||||
acls.sort()
|
||||
|
||||
for elem in acls:
|
||||
old_text = elem.text
|
||||
|
||||
if old_text is None or old_text == '':
|
||||
continue
|
||||
|
||||
if old_text in global_entities:
|
||||
elem.text = global_entities[old_text]
|
||||
entities.append((elem.text, old_text))
|
||||
else:
|
||||
elem.text = self.new_xml_entity(global_entities,
|
||||
ENTITY_SDDL_ACL)
|
||||
|
||||
entities.append((elem.text, old_text))
|
||||
global_entities.update([(old_text, elem.text)])
|
||||
|
||||
share_paths = root.findall('.//*[@network_path="TRUE"]')
|
||||
share_paths.sort()
|
||||
|
||||
for elem in share_paths:
|
||||
old_text = elem.text
|
||||
|
||||
if old_text is None or old_text == '':
|
||||
continue
|
||||
|
||||
stripped = old_text.lstrip('\\')
|
||||
file_server = stripped.split('\\')[0]
|
||||
|
||||
server_index = old_text.find(file_server)
|
||||
|
||||
remaining = old_text[server_index + len(file_server):]
|
||||
old_text = old_text[:server_index] + file_server
|
||||
|
||||
if old_text in global_entities:
|
||||
elem.text = global_entities[old_text] + remaining
|
||||
to_put = global_entities[old_text]
|
||||
entities.append((to_put, old_text))
|
||||
else:
|
||||
to_put = self.new_xml_entity(global_entities,
|
||||
ENTITY_NETWORK_PATH)
|
||||
elem.text = to_put + remaining
|
||||
|
||||
entities.append((to_put, old_text))
|
||||
global_entities.update([(old_text, to_put)])
|
||||
|
||||
# Call any file specific customization of entities
|
||||
# (which appear in any subclasses).
|
||||
entities.extend(self.custom_entities(root, global_entities))
|
||||
|
||||
output_xml = tostring(root)
|
||||
|
||||
for ent in entities:
|
||||
output_xml = output_xml.replace(ent[0].replace('&', '&'), ent[0])
|
||||
|
||||
with open(out_file, 'wb') as f:
|
||||
f.write(output_xml)
|
||||
|
||||
return entities
|
||||
|
||||
def custom_entities(self, root, global_entities):
|
||||
# Override this method to do special entity handling
|
||||
return []
|
||||
|
Loading…
Reference in New Issue
Block a user