From 3ef552ffc15478d137beae3fb558592b263a8c9a Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Tue, 10 Feb 2015 09:35:37 +0100
Subject: [PATCH] switch to Python 3, defusedxml and select

- add method handle_xmpp_stanza that uses select to check socket for available
  data and feed the XML parser
- use defusedxml for more robust XML parsing
---
 check_xmpp | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/check_xmpp b/check_xmpp
index 4d43765..8c3c177 100755
--- a/check_xmpp
+++ b/check_xmpp
@@ -1,12 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
 from datetime import datetime
 import socket
-from xml.sax import make_parser
+from select import select
 from xml.sax.handler import ContentHandler, feature_namespaces
 
+from defusedxml.sax import make_parser
 import nagiosplugin
 
 
@@ -47,7 +48,7 @@ class XmppClientServerResponseHandler(ContentHandler):
         if self.inelem[-1] == (NS_XMPP_SASL, 'mechanism'):
             self.mechanisms.append(content)
         else:
-            print self.inelem, content
+            print(self.inelem, content)
 
     def is_valid_start(self):
         return True  # TODO: some real implementation
@@ -107,22 +108,27 @@ class Xmpp(nagiosplugin.Resource):
     def handle_server(self, xmppsocket):
         pass
 
-    def is_valid_client_response(self, xmldata):
-        self.parser.feed(xmldata)
-        return self.contenthandler.is_valid_start()
+    def handle_xmpp_stanza(self, xmppsocket, message_str):
+        xmppsocket.sendall(message_str.encode('utf-8'))
+        while True:
+            rready, wready, xready = select([xmppsocket], [], [], 0.1)
+            if xmppsocket in rready:
+                data = xmppsocket.recv(4096)
+                if not data: break
+                self.parser.feed(data.decode('utf-8'))
+            else:
+                break
 
     def handle_client(self, xmppsocket):
-        xmppsocket.sendall((
+        self.handle_xmpp_stanza(xmppsocket, (
             "<?xml version='1.0' ?><stream:stream to='{servername}' "
             "xmlns='jabber:client' "
             "xmlns:stream='http://etherx.jabber.org/streams' "
             "version='1.0'>"
         ).format(servername=self.servername))
-        if not self.is_valid_client_response(xmppsocket.recv(4096)):
+        if not self.contenthandler.is_valid_start():
             raise XmppException("no valid response to XMPP client request")
-        xmppsocket.sendall("</stream:stream>")
-        self.parser.feed(xmppsocket.recv(4096))
-
+        self.handle_xmpp_stanza(xmppsocket, "</stream:stream>")
 
     def probe(self):
         start = datetime.now()