a little nicer wrt pep8
[sfa.git] / sfatables / runtime.py
1 #!/usr/bin/env python3
2
3 import sys
4 import os
5
6 import libxml2
7 import libxslt
8
9 from sfatables.globals import sfatables_config
10 from sfatables.commands.List import List
11 from sfatables.xmlrule import XMLRule
12
13 class SFATablesRules:
14     def __init__(self, chain_name):
15         self.active_context = {}
16         self.contexts = None # placeholder for rspec_manger
17         self.sorted_rule_list = []
18         self.final_processor = '__sfatables_wrap_up__.xsl'
19         chain_dir_path = os.path.join(sfatables_config,chain_name)
20         rule_list = List().get_rule_list(chain_dir_path)
21         for rule_number in rule_list:
22             self.sorted_rule_list = self.sorted_rule_list + [XMLRule(chain_name, rule_number)]
23         return
24
25     def wrap_up(self, doc):
26         filepath = os.path.join(sfatables_config, 'processors', self.final_processor)
27
28         if not os.path.exists(filepath):
29             raise Exception('Could not find final rule filter')
30
31         styledoc = libxml2.parseFile(filepath)
32         style = libxslt.parseStylesheetDoc(styledoc)
33         result = style.applyStylesheet(doc, None)
34         stylesheet_result = style.saveResultToString(result)
35         style.freeStylesheet()
36         doc.freeDoc()
37         result.freeDoc()
38
39         return stylesheet_result
40
41     def set_context(self, request_context):
42         self.active_context = request_context
43         return
44
45     def create_xml_node(self, name, context_dict):
46         node = libxml2.newNode(name)
47         for k in list(context_dict.keys()):
48             if (type(context_dict[k])==dict):
49                 childNode = self.create_xml_node(k, context_dict[k])
50                 node.addChild(childNode)
51             else:
52                 childNode = libxml2.newNode(k)
53                 childNode.addContent(context_dict[k])
54                 node.addChild(childNode)
55         return node
56                 
57     def add_request_context_to_rspec(self, doc):
58         p = doc.xpathNewContext()
59         context = p.xpathEval("//*")
60         if not context or context[0].name not in ['RSpec', 'rspec']:
61             raise Exception('Request is not an rspec')
62         else:
63             # Add the request context
64             requestNode = self.create_xml_node('request-context',self.active_context)
65             context[0].addChild(requestNode)
66         p.xpathFreeContext()
67         return doc
68
69     
70     def apply(self, rspec):
71         if (self.sorted_rule_list):
72             doc = libxml2.parseDoc(rspec)
73             doc = self.add_request_context_to_rspec(doc)
74
75             intermediate_rspec = doc
76
77             for rule in self.sorted_rule_list:
78                 (matched,intermediate_rspec) = rule.apply_interpreted(intermediate_rspec)
79                 if (rule.terminal and matched):
80                     break
81
82             final_rspec = self.wrap_up(intermediate_rspec) 
83         else:
84             final_rspec = rspec
85
86         return final_rspec
87
88     def print_rules(self):
89         for rule in self.sorted_rule_list:
90             print(rule.processors)
91
92 def main():
93     incoming = SFATablesRules('INCOMING')
94     incoming.set_context({'sfa':{'user':{'hrn':'plc.princeton.sapanb'}}})
95
96     outgoing = SFATablesRules('OUTGOING')
97     print("%d rules loaded for INCOMING chain"%len(incoming.sorted_rule_list))
98     incoming.print_rules()
99
100     print("%d rules loaded for OUTGOING chain"%len(outgoing.sorted_rule_list))
101     outgoing.print_rules()
102
103     rspec = open(sys.argv[1]).read()
104     newrspec = incoming.apply(rspec)
105     print(newrspec)
106     return
107
108 if __name__=="__main__":
109     main()