Moved xslt extensions to processors/
[sfa.git] / sfatables / xmlrule.py
1 import libxml2
2 from sfatables.globals import *
3
4 class XMLRule:
5     rule_number = None
6     chain = None
7     xmldoc = None
8     terminal = 0
9
10     arguments = {'match':None,'target':None}
11     processors = {'match':None,'target':None}
12     context = {'match':None,'target':None}
13
14     def apply_processor(self, type, rspec):
15         processor = self.processors[type]
16
17         # XXX TO CLEAN UP
18         filepath = 'processors/' + processor
19         # XXX
20
21         styledoc = libxml2.parseFile(processor)
22         style = libxslt.parseStylesheetDoc(styledoc)
23         doc = libxml2.parseDoc(rspec)
24         result = style.applyStylesheet(doc, None)
25         processed_result = style.saveResultToString(result, 0)
26         style.freeStylesheet()
27         doc.freeDoc()
28         result.freeDoc()
29
30         return stylesheet_result
31
32     def match(self, rspec):
33         match_result = self.apply_processor('match',rspec) 
34         return (match_result=='True')
35
36     def target(self, rspec):
37         target_result = self.apply_processor('target',rspec)
38         return target_result
39
40     def apply_interpreted(self, rspec):
41         # Interpreted
42         #
43         # output =
44         #    if (match(match_args, rspec)
45         #       then target(target_args, rspec)
46         #       else rspec
47
48         if (self.match(rspec)):
49             return self.target(rspec)
50         else:
51             return rspec
52
53
54     def apply_compiled(rspec):
55         # Not supported yet
56         return None
57
58     def load_xml_extension (self, type, chain, rule_number):
59         filename = sfatables_config+"/"+chain+"/"+"sfatables-%d-%s"%(rule_number,type)
60
61         self.xmldoc = libxml2.parseFile(filename)
62         p = self.xmldoc.xpathNewContext()
63
64         context = p.xpathEval('//context/@select')
65         self.context[type] = context[0].content
66
67         processor = p.xpathEval('//processor/@filename')
68
69         context = p.xpathEval('//attributes/attribute[@terminal="yes"]')
70         if (context != []):
71             self.terminal = 1
72         
73         self.processors[type] = processor[0].content
74         self.arguments[type] = p.xpathEval('//rule')
75
76         p.xpathFreeContext()
77
78
79     def wrap_rspec (self, type, rspec):
80         argument = self.arguments[type]
81         p = rspec.xmldoc.xpathNewContext()
82         root_node = p.xpathEval('/RSpec')
83         if (not root_node or not root_node):
84             raise Exception('An evil aggregate manager sent me a malformed RSpec. Please see the stack trace to identify it.')
85
86         root_node.addChild(arguments[type])
87         return rspec
88
89     def __init__(self, chain, rule_number):
90
91         self.load_xml_extension('match', chain, rule_number)
92         self.load_xml_extension('target',chain, rule_number)
93         self.rule_number = rule_number
94         self.chain = chain
95
96         return
97         
98     def free(self):
99         self.xmldoc.freeDoc()