diff options
author | Rob Austein <sra@hactrn.net> | 2014-07-07 23:13:35 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2014-07-07 23:13:35 +0000 |
commit | 13a65b463cd0acedd3bc36c9437d5ee8b2e26b60 (patch) | |
tree | d129b276d8e77591943d03f1995ac76c3eb6d5f8 /rpki/xml_utils.py | |
parent | bfba2f0ce8f8416b9e5f91542068d0d6470bc19f (diff) |
Checkpoint of SQL-based publish and withdraw processing. Doesn't
handle publish-with-overwrite correctly yet, not generating RRDP files
yet, but passes "make test" without doing anything obviously insane.
svn path=/branches/tk705/; revision=5887
Diffstat (limited to 'rpki/xml_utils.py')
-rw-r--r-- | rpki/xml_utils.py | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/rpki/xml_utils.py b/rpki/xml_utils.py index 1574cd9e..11c2180e 100644 --- a/rpki/xml_utils.py +++ b/rpki/xml_utils.py @@ -56,6 +56,7 @@ class sax_handler(xml.sax.handler.ContentHandler): """ Initialize SAX handler. """ + xml.sax.handler.ContentHandler.__init__(self) self.text = "" self.stack = [] @@ -64,18 +65,21 @@ class sax_handler(xml.sax.handler.ContentHandler): """ Redirect startElementNS() events to startElement(). """ + return self.startElement(name[1], attrs) def endElementNS(self, name, qname): """ Redirect endElementNS() events to endElement(). """ + return self.endElement(name[1]) def characters(self, content): """ Accumulate a chuck of element content (text). """ + self.text += content def startElement(self, name, attrs): @@ -111,6 +115,7 @@ class sax_handler(xml.sax.handler.ContentHandler): Handle endElement() events. Mostly this means handling any accumulated element text. """ + text = self.text.encode("ascii").strip() self.text = "" self.stack[-1].endElement(self.stack, name, text) @@ -120,6 +125,7 @@ class sax_handler(xml.sax.handler.ContentHandler): """ Create a one-off SAX parser, parse an ETree, return the result. """ + self = cls() lxml.sax.saxify(elt, self) return self.result @@ -128,6 +134,7 @@ class sax_handler(xml.sax.handler.ContentHandler): """ Handle top-level PDU for this protocol. """ + assert name == self.name and attrs["version"] == self.version return self.pdu() @@ -154,6 +161,7 @@ class base_elt(object): """ Default startElement() handler: just process attributes. """ + if name not in self.elements: assert name == self.element_name, "Unexpected name %s, stack %s" % (name, stack) self.read_attrs(attrs) @@ -162,6 +170,7 @@ class base_elt(object): """ Default endElement() handler: just pop the stack. """ + assert name == self.element_name, "Unexpected name %s, stack %s" % (name, stack) stack.pop() @@ -169,12 +178,14 @@ class base_elt(object): """ Default toXML() element generator. """ + return self.make_elt() def read_attrs(self, attrs): """ Template-driven attribute reader. """ + for key in self.attributes: val = attrs.get(key, None) if isinstance(val, str) and val.isdigit() and not key.endswith("_handle"): @@ -187,6 +198,7 @@ class base_elt(object): """ XML element constructor. """ + elt = lxml.etree.Element("{%s}%s" % (self.xmlns, self.element_name), nsmap = self.nsmap) for key in self.attributes: val = getattr(self, key, None) @@ -201,6 +213,7 @@ class base_elt(object): """ Constructor for Base64-encoded subelement. """ + if value is not None and not value.empty(): lxml.etree.SubElement(elt, "{%s}%s" % (self.xmlns, name), nsmap = self.nsmap).text = value.get_Base64() @@ -208,6 +221,7 @@ class base_elt(object): """ Convert a base_elt object to string format. """ + return lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "us-ascii") @classmethod @@ -215,6 +229,7 @@ class base_elt(object): """ Generic PDU constructor. """ + self = cls() for k, v in kargs.items(): if isinstance(v, bool): @@ -235,6 +250,7 @@ class text_elt(base_elt): """ Extract text from parsed XML. """ + base_elt.endElement(self, stack, name, text) setattr(self, self.text_attribute, text) @@ -242,6 +258,7 @@ class text_elt(base_elt): """ Insert text into generated XML. """ + elt = self.make_elt() elt.text = getattr(self, self.text_attribute) or None return elt @@ -258,6 +275,7 @@ class data_elt(base_elt): that sub-elements are Base64-encoded using the sql_template mechanism. """ + if name in self.elements: elt_type = self.sql_template.map.get(name) assert elt_type is not None, "Couldn't find element type for %s, stack %s" % (name, stack) @@ -271,6 +289,7 @@ class data_elt(base_elt): Default element generator for SQL-based objects. This assumes that sub-elements are Base64-encoded DER objects. """ + elt = self.make_elt() for i in self.elements: self.make_b64elt(elt, i, getattr(self, i, None)) @@ -280,6 +299,7 @@ class data_elt(base_elt): """ Construct a reply PDU. """ + if r_pdu is None: r_pdu = self.__class__() self.make_reply_clone_hook(r_pdu) @@ -297,6 +317,7 @@ class data_elt(base_elt): """ Overridable hook. """ + pass def serve_fetch_one(self): @@ -304,6 +325,7 @@ class data_elt(base_elt): Find the object on which a get, set, or destroy method should operate. """ + r = self.serve_fetch_one_maybe() if r is None: raise rpki.exceptions.NotFound @@ -313,12 +335,14 @@ class data_elt(base_elt): """ Overridable hook. """ + cb() def serve_post_save_hook(self, q_pdu, r_pdu, cb, eb): """ Overridable hook. """ + cb() def serve_create(self, r_msg, cb, eb): @@ -371,6 +395,7 @@ class data_elt(base_elt): """ Handle a get action. """ + r_pdu = self.serve_fetch_one() self.make_reply(r_pdu) r_msg.append(r_pdu) @@ -380,6 +405,7 @@ class data_elt(base_elt): """ Handle a list action for non-self objects. """ + for r_pdu in self.serve_fetch_all(): self.make_reply(r_pdu) r_msg.append(r_pdu) @@ -389,12 +415,14 @@ class data_elt(base_elt): """ Overridable hook. """ + cb() def serve_destroy(self, r_msg, cb, eb): """ Handle a destroy action. """ + def done(): db_pdu.sql_delete() r_msg.append(self.make_reply()) @@ -406,6 +434,7 @@ class data_elt(base_elt): """ Action dispatch handler. """ + dispatch = { "create" : self.serve_create, "set" : self.serve_set, "get" : self.serve_get, @@ -419,6 +448,7 @@ class data_elt(base_elt): """ Uniform handling for unimplemented control operations. """ + unimplemented = [x for x in controls if getattr(self, x, False)] if unimplemented: raise rpki.exceptions.NotImplementedYet("Unimplemented control %s" % ", ".join(unimplemented)) @@ -432,6 +462,7 @@ class msg(list): """ Handle top-level PDU. """ + if name == "msg": assert self.version == int(attrs["version"]) self.type = attrs["type"] @@ -445,6 +476,7 @@ class msg(list): """ Handle top-level PDU. """ + assert name == "msg", "Unexpected name %s, stack %s" % (name, stack) assert len(stack) == 1 stack.pop() @@ -453,12 +485,14 @@ class msg(list): """ Convert msg object to string. """ + return lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "us-ascii") def toXML(self): """ Generate top-level PDU. """ + elt = lxml.etree.Element("{%s}msg" % (self.xmlns), nsmap = self.nsmap, version = str(self.version), type = self.type) elt.extend(i.toXML() for i in self) return elt @@ -468,6 +502,7 @@ class msg(list): """ Create a query PDU. """ + self = cls(args) self.type = "query" return self @@ -477,6 +512,7 @@ class msg(list): """ Create a reply PDU. """ + self = cls(args) self.type = "reply" return self @@ -485,10 +521,12 @@ class msg(list): """ Is this msg a query? """ + return self.type == "query" def is_reply(self): """ Is this msg a reply? """ + return self.type == "reply" |