def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	answers = []
	query_for_SRV_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_SRV_record = resolver.query(srv_name+domain_url, dns.rdatatype.SRV)

	except (NXDOMAIN, NoAnswer, Timeout):

		return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

	except Exception, e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

		status = 2
		briefing = "A problem happened while searching for the %s:" % srv_description
		briefing += " <strong>" + srv_name + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the %s:" % srv_description
		message += " <strong>" + srv_name + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so." 
		return (status, briefing, message, None)
def classifyDomainByRecord(domain):

    resolver = dns.resolver.Resolver()
    resolver.lifetime = 5
    try:
        nameserver = getAuthoritativeNameserver(domain)
        if nameserver:
            resolver.nameservers = [nameserver]
        addresses = resolver.query(domain, dns.rdatatype.CNAME)
        return {"type": "CNAME", "domain": domain, "addresses": addresses}

    except dns.resolver.NXDOMAIN:
        pass
    except dns.resolver.NoAnswer:
        pass
    except Exception as e:
        return {"type": "PROBLEM", "name": "CNAME record", "value": str(e)}

    try:
        addresses = resolver.query(domain, dns.rdatatype.A)
        return {"type": "A", "domain": domain, "addresses": addresses}

    except (NXDOMAIN, NoAnswer):
        return {"type": "NONEXISTENT", "domain": domain, "addresses": []}
    except Exception as e:
        return {"type": "PROBLEM", "name": "A record", "value": str(e)}
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if ( nameserver ):
            resolver.nameservers = [ nameserver ]
        answer = resolver.query("_buddycloud-api._tcp."+domain_url,
            dns.rdatatype.TXT)
    except Exception as e:
        return no_record(view)

    else:

        txt_answer = answer[0].to_text()
        view["record"] = txt_answer

        for test in record_well_formedness_tests:
            if ( not test[0](txt_answer) ):
                view["error"] = code("TXT record") + " is malformed! " + test[1]
                return record_error(view)

        domain =  txt_answer[txt_answer.find("host=")+5:
            txt_answer.find(" ", txt_answer.find("host=")+5)]
        port = txt_answer[txt_answer.find("port=")+5:
            txt_answer.find(" ", txt_answer.find("port=")+5)]
        path = txt_answer[txt_answer.find("path=")+5:
            txt_answer.find(" ", txt_answer.find("path=")+5)]
        protocol = txt_answer[txt_answer.find("protocol=")+9:
            txt_answer.find(" ", txt_answer.find("protocol=")+9)]

        if ( protocol.lower() != "https" ):
            view["error"] = code("TXT record") + "\'s " + bold("protocol") + "\
                attribute must have value set to " + code("https") + "!"
            return record_error(view)

        output = {
            'protocol' : protocol,
            'domain' : domain,
            'port' : port,
            'path' : path
        }
        return record_correct(view, output)
예제 #4
0
def classifyDomainByRecord(domain):

		resolver = dns.resolver.Resolver()
		resolver.lifetime = 5
		try:
			resolver.nameservers = [ getAuthoritativeNameserver(domain) ]
			addresses = resolver.query(domain, dns.rdatatype.CNAME)
			return { 'type' : 'CNAME',
				 'domain' : domain, 
				 'addresses' : addresses
			}
		
		except dns.resolver.NXDOMAIN:
			pass
		except dns.resolver.NoAnswer:
			pass
		except Exception as e:
			return { 'type' : 'PROBLEM',
				 'name' : 'CNAME record',
				 'value' : str(e)
			}

		try:
			addresses = resolver.query(domain, dns.rdatatype.A)
			return { 'type' : 'A',
				 'domain' : domain,
				 'addresses' : addresses
			}

		except (NXDOMAIN, NoAnswer):
			return { 'type' : 'NONEXISTENT',
				 'domain' : domain,
				 'addresses' : []
			}
		except Exception as e:
			return { 'type' : 'PROBLEM',
				 'name' : 'A record',
				 'value' : str(e)
			}
예제 #5
0
def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    answers = []
    query_for_SRV_record = None

    try:

        resolver = dns.resolver.Resolver()
        resolver.nameservers = [getAuthoritativeNameserver(domain_url)]
        resolver.lifetime = 5
        query_for_SRV_record = resolver.query(srv_name + domain_url,
                                              dns.rdatatype.SRV)

    except (NXDOMAIN, NoAnswer, Timeout):

        return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

    except Exception, e:

        if (str(e) == "" or str(e) == ("%s. does not exist." % domain_url)):
            return no_SRV_record(domain_url, srv_name, srv_description,
                                 srv_port)

        status = 2
        briefing = "A problem happened while searching for the %s:" % srv_description
        briefing += " <strong>" + srv_name + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the %s:" % srv_description
        message += " <strong>" + srv_name + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)
예제 #6
0
def testFunction(domain_url):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    query_for_TXT_record = None

    try:

        resolver = dns.resolver.Resolver()
        resolver.nameservers = [getAuthoritativeNameserver(domain_url)]
        resolver.lifetime = 5
        query_for_TXT_record = resolver.query(
            "_buddycloud-api._tcp." + domain_url, dns.rdatatype.TXT)

    except (NXDOMAIN, NoAnswer):

        return noTXTRecord(domain_url)

    except Exception as e:

        if (str(e) == "" or str(e) == ("%s. does not exist." % domain_url)):
            return noTXTRecord(domain_url)

        status = 2
        briefing = "A problem happened while searching for the API server TXT record:"
        briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the API server TXT record:"
        message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)

    classified_records = {}

    for answer in query_for_TXT_record:

        classified = classifyTXTRecord(str(answer))

        if not classified['type'] in classified_records:
            classified_records[classified['type']] = []
        classified_records[classified['type']].append(classified)

    if (len(classified_records.get('INFO_MISSING', [])) != 0
            or len(classified_records.get('MALFORMED', [])) != 0
            or len(classified_records.get('NOT_HTTPS', [])) != 0):

        status = 1
        briefing = "We detected incorrect API server TXT records at domain"
        briefing += " <strong>%s</strong>." % domain_url
        message = "We detected you set up the following incorrect API"
        message += " server TXT records.<br/>"
        message += "You must have just one correct API server SRV record.<br/>"
        message += "These are the SRV records we found and their problems: <br/><br/>"

        for record in classified_records.get('INFO_MISSING', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        for record in classified_records.get('MALFORMED', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        if (len(classified_records.get('MALFORMED', [])) != 0):

            message += "The API server TXT record must always have a <em>version</em>, <em>host</em>,"
            message += " <em>protocol</em>, <em>path</em> and <em>port</em>.<br/>"
            message += "<strong>Each of these properties must be defined within double quotes and separated by spaces only</strong>.<br/>"
            message += "For example, assuming that the server running buddycloud will be named: <strong><em>buddycloud."
            message += domain_url + "</em></strong>,"
            message += "<br/>here you are a TXT record that should work:<br/>"
            message += "<strong>_buddycloud-api._tcp." + domain_url + "\tIN TXT \"v=1.0\" \"host=buddycloud."
            message += domain_url + "\" \"protocol=https\" \"path=/api\" \"port=433\"</strong><br/>"
            message += "<br/>Please not that your API server TXT record won't be correct until it contains proper"
            message += " information regarding the <em>version</em>, <em>host</em>, <em>protocol<em/>, <em>path</em> and <em>port</em>.<br/>"

        for record in classified_records.get('NOT_HTTPS', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        if (len(classified_records.get('NOT_HTTPS', [])) != 0):

            message += "Please ensure your API server will run with HTTPS enabled.<br/>"

        message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
        message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
        return (status, briefing, message, None)

    elif len(classified_records.get('CORRECT', [])) == 0:

        status = 1
        briefing = "No correct API server TXT record found at "
        briefing += "domain <strong>%s</strong>!<br/>" % domain_url
        message = briefing + "<br/>"
        message += "You must have one correct API server SRV record.<br/>"
        message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
        message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
        return (status, briefing, message, None)

    elif len(classified_records.get('CORRECT', [])) > 1:

        status = 1
        briefing = "We found multiple correct API server TXT records!"
        message = briefing + "<br/>"
        message += "But really, you should have just one.<br/>"
        message += "These are the records we found: <br/><br/>"

    else:

        status = 0
        briefing = "API server TXT record found: "
        briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0][
            'record']
        message = "Congratulations! You have set up your API server "
        message += "TXT record correctly.<br/><br/>"

    for record in classified_records.get('CORRECT', []):

        message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>" %
                    (record['protocol'], record['domain'], record['port'],
                     record['path'], record['record']))

    r = classified_records['CORRECT'][0]

    return (status, briefing, message, {
        'protocol': r['protocol'],
        'domain': r['domain'],
        'port': r['port'],
        'path': r['path']
    })
def testFunction(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	query_for_TXT_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_TXT_record = resolver.query("_buddycloud-api._tcp."+domain_url, dns.rdatatype.TXT)

	except (NXDOMAIN, NoAnswer):

		return noTXTRecord(domain_url)

	except Exception as e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return noTXTRecord(domain_url)

		status = 2
		briefing = "A problem happened while searching for the API server TXT record:"
		briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the API server TXT record:"
		message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so." 
		return (status, briefing, message, None)

	classified_records = {}

	for answer in query_for_TXT_record:

		classified = classifyTXTRecord(str(answer))

		if not classified['type'] in classified_records:
			classified_records[classified['type']] = []
		classified_records[classified['type']].append(classified)

	if ( len(classified_records.get('INFO_MISSING', [])) != 0
	  or len(classified_records.get('MALFORMED', [])) != 0
	  or len(classified_records.get('NOT_HTTPS', [])) != 0 ):

		status = 1
		briefing = "We detected incorrect API server TXT records at domain"
		briefing += " <strong>%s</strong>." % domain_url
		message = "We detected you set up the following incorrect API"
		message += " server TXT records.<br/>"
		message += "You must have just one correct API server SRV record.<br/>"
		message += "These are the SRV records we found and their problems: <br/><br/>"

		for record in classified_records.get('INFO_MISSING', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('MALFORMED', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('MALFORMED', [])) != 0 ):

			message += "The API server TXT record must always have a <em>version</em>, <em>host</em>,"
			message += " <em>protocol</em>, <em>path</em> and <em>port</em>.<br/>"
			message += "<strong>Each of these properties must be defined within double quotes and separated by spaces only</strong>.<br/>"
			message += "For example, assuming that the server running buddycloud will be named: <strong><em>buddycloud."
			message += domain_url + "</em></strong>," 
			message += "<br/>here you are a TXT record that should work:<br/>"
			message += "<strong>_buddycloud-api._tcp." + domain_url + "\tIN TXT \"v=1.0\" \"host=buddycloud."
			message += domain_url + "\" \"protocol=https\" \"path=/api\" \"port=433\"</strong><br/>"
			message += "<br/>Please not that your API server TXT record won't be correct until it contains proper"
			message += " information regarding the <em>version</em>, <em>host</em>, <em>protocol<em/>, <em>path</em> and <em>port</em>.<br/>"

		for record in classified_records.get('NOT_HTTPS', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('NOT_HTTPS', [])) != 0 ):

			message += "Please ensure your API server will run with HTTPS enabled.<br/>"

		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) == 0:

		status = 1
		briefing = "No correct API server TXT record found at "
		briefing += "domain <strong>%s</strong>!<br/>" % domain_url
		message = briefing + "<br/>"
		message += "You must have one correct API server SRV record.<br/>"
		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) > 1:

		status = 1
		briefing = "We found multiple correct API server TXT records!"
		message = briefing + "<br/>"
		message += "But really, you should have just one.<br/>"
		message += "These are the records we found: <br/><br/>"

	else:

		status = 0
		briefing = "API server TXT record found: "
		briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0]['record']
		message = "Congratulations! You have set up your API server "
		message += "TXT record correctly.<br/><br/>"

	for record in classified_records.get('CORRECT', []):

		message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>"
				% (record['protocol'],
				   record['domain'],
				   record['port'],
				   record['path'],
				   record['record']))

	r = classified_records['CORRECT'][0]

	return (status, briefing, message, {
			'protocol' : r['protocol'],
			'domain' : r['domain'],
			'port' : r['port'],
			'path' : r['path']
		})
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    (status, b, m, answers) = xmppServerServiceRecordLookup(domain_url)
    if ( status != 0 ):
        wiew["warning"] = "XMPP Server of domain %s not found!" % (domain_url)
        return warning(view)

    xmpp = sleekxmpp.ClientXMPP("*****@*****.**", "ei3tseq")

    situation = {}

    for answer in answers:

        conn_address = answer["domain"], answer["port"]
        view["xmpp_server"] = conn_address[0]

        if ( not xmpp.connect(conn_address, reattempt=False, use_ssl=False, use_tls=False) ):
             situation[conn_address] = make_output_builder(view,
                 xmpp_connection_problem)
             continue

        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                ito=domain_url, ifrom=xmpp.boundjid)

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=5)
            except Exception as e:
                if ( str(e) != "" ):
                    view["error"] = str(e)
                situation[conn_address] = make_output_builder(view,
                    xmpp_disco_query_send_error)
                continue

            if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                situation[conn_address] = make_output_builder(view,
                    xmpp_server_error)
                continue

            its = response.xml.findall(
                "{%s}query/{%s}item" % ((DISCO_ITEMS_NS,)*2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                    ito=item_jid, ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    response = iq.send(block=True, timeout=5)
                except Exception as e:
                    if ( str(e) != "" ):
                        view["error"] = str(e)
                    situation[conn_address] = make_output_builder(view,
                        xmpp_disco_query_send_error)
                    continue

                if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                    view["error"] = response.xml.findall("iq[@type='error']")[0]
                    situation[conn_address] = make_output_builder(view,
                        xmpp_server_error)
                    continue

                ids = response.xml.findall(
                    "{%s}query/{%s}identity" % ((DISCO_INFO_NS,)*2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    view["discovery"] = True
                    view["channel_server"] = item_jid
                    if ( identity_category == 'pubsub'
                        and identity_type == 'channels' ):

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            resolver.nameservers = [nameserver]
                            resolver.lifetime = 5
                            PTR_name = "_buddycloud-server._tcp." + domain_url
                            answer = resolver.query(PTR_name, dns.rdatatype.PTR)
                        except Exception:
                            pass
                        else:
                            #TODO check if PTR record and DISCO are pointing
                            # to the same place -- they must!
                            view["ptr_record"] = True
                        return is_buddycloud_enabled(view)

            if not conn_address in situation:
                situation[conn_address] = make_output_builder(view,
                    not_buddycloud_enabled)

        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        resolver.nameservers = [nameserver]
        resolver.lifetime = 5
        PTR_name = "_buddycloud-server._tcp." + domain_url
        answer = resolver.query(PTR_name, dns.rdatatype.PTR)
    except (NXDOMAIN, NoAnswer, Timeout):
        pass
    except Exception:
        pass
    else:
        view["ptr_record"] = True
        #view["channel_server"] = answer
        return is_buddycloud_enabled(view)

    if ( len(situation) == 1 ):
       return situation[situation.keys()[0]]() 

    view["xmpp_servers"] = []

    status = 2
    for xmpp_server in situation:
        output = situation[xmpp_server]()
        if ( output[0] == 1 ):
            status = 1
        view["xmpp_servers"].append({
            "name" : "%s through port %s" %(xmpp_server),
            "error" : output[2]
        })

    view["status"] = status

    return multiple_problems(view)
예제 #9
0
def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if status != 0:
        return (status, briefing, message, None)

    answers = []
    query_for_SRV_record = None

    try:

        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if nameserver:
            resolver.nameservers = [nameserver]
        query_for_SRV_record = resolver.query(srv_name + domain_url, dns.rdatatype.SRV)

    except (NXDOMAIN, NoAnswer, Timeout):

        return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

    except Exception as e:

        if str(e) == "" or str(e) == ("%s. does not exist." % domain_url):
            return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

        status = 2
        briefing = "A problem happened while searching for the %s:" % srv_description
        briefing += " <strong>" + srv_name + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the %s:" % srv_description
        message += " <strong>" + srv_name + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)

    for answer in query_for_SRV_record:

        try:

            domain = answer.target.to_text()[:-1]
            port = str(answer.port)

            answers.append({"domain": domain, "port": port, "priority": answer.priority, "weight": answer.weight})

        except Exception:
            continue

    SRV_records = []
    for i in range(len(answers)):
        SRV_record = srv_name + domain_url + " IN SRV "
        SRV_record += answers[i]["port"] + " " + str(answers[i]["domain"])
        SRV_records.append(SRV_record)

    status = 0
    briefing = srv_description + "s found: <strong>" + string.join(SRV_records, " | ") + "</strong>"
    message = "Congratulations! You have set up your SRV records correctly."
    message += "<br/>These were the %ss we found:<br/>" % srv_description
    message += "<strong><br/>" + string.join(SRV_records, "<br/>") + "<br/></strong>"
    message += "<br/>Now, we expect that at least one of them is pointing to an A record"
    message += " that will ultimately guide us to your buddycloud server."
    return (status, briefing, message, answers)
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    xmpp = create_xmpp_client()
    conn_address = 'crater.buddycloud.org', 5222

    disco_situation = None

    if ( not xmpp.connect(conn_address) ):
        disco_situation = make_output_builder(view, xmpp_connection_problem)

    else:
        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                ito=domain_url, ifrom=xmpp.boundjid)

            class DiscoItemsFailedException(Exception):
                pass

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=config.IQ_TIMEOUT)
            except Exception as e:
                if ( str(e) != "" ):
                    view["error"] = str(e)
                disco_situation = make_output_builder(view,
                    xmpp_disco_query_send_error)
                raise DiscoItemsFailedException()

            if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                disco_situation = make_output_builder(view,
                    xmpp_server_error)
                raise DiscoItemsFailedException()

            its = response.xml.findall(
                "{%s}query/{%s}item" % ((DISCO_ITEMS_NS,)*2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                    ito=item_jid, ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    view["xmpp_server"] = item_jid
                    response = iq.send(block=True, timeout=config.IQ_TIMEOUT)
                except Exception as e:
                    if ( str(e) != "" ):
                        view["error"] = str(e)
                    disco_situation = make_output_builder(view,
                        xmpp_disco_query_send_error)
                    continue

                if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                    view["error"] = response.xml.findall("iq[@type='error']")[0]
                    disco_situation = make_output_builder(view,
                        xmpp_server_error)
                    continue

                ids = response.xml.findall(
                    "{%s}query/{%s}identity" % ((DISCO_INFO_NS,)*2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    if ( identity_category == 'pubsub'
                        and identity_type == 'channels' ):

                        view["discovery"] = True
                        view["channel_server"] = item_jid

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            if ( nameserver ):
                                resolver.nameservers = [nameserver]
                            TXT_name = "_bcloud-server._tcp." + domain_url
                            answer = resolver.query(TXT_name, dns.rdatatype.TXT)
                        except Exception:
                            pass
                        else:
                            view["txt_record"] = True
                            txt_answer = answer[0].to_text()
                            if ( len(txt_answer) == 0 ):
                                txt_answer = "(Blank record)"
                            view["record"] = txt_answer

                            for test in record_well_formedness_tests:
                                if ( not test[0](txt_answer) ):
                                    view["error"] = code("TXT record") + " is malformed! " + test[1]
                                    return record_error(view)

                            answer_jid =  txt_answer[txt_answer.find("server=")+7:txt_answer.find(" ", txt_answer.find("server=")+7)]

                            if ( item_jid != answer_jid ):
                                view["channel_server2"] = answer_jid
                                return buddycloud_enabled_with_conflict(view)

                        return is_buddycloud_enabled(view)

            if disco_situation == None:
                disco_situation = make_output_builder(view,
                    not_buddycloud_enabled)

        except DiscoItemsFailedException:
            pass
        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if ( nameserver ):
            resolver.nameservers = [nameserver]
        TXT_name = "_bcloud-server._tcp." + domain_url
        answer = resolver.query(TXT_name, dns.rdatatype.TXT)
    except Exception:
        return disco_situation() 
    else:
        view["txt_record"] = True
        txt_answer = answer[0].to_text()
        if ( len(txt_answer) == 0 ):
            txt_answer = "(Blank record)"
        view["record"] = txt_answer

        for test in record_well_formedness_tests:
            if ( not test[0](txt_answer) ):
                view["error"] = code("TXT record") + " is malformed! " + test[1]
                return record_error(view)

        answer_jid =  txt_answer[txt_answer.find("server=")+7:txt_answer.find(" ", txt_answer.find("server=")+7)]

        view["channel_server"] = answer_jid
        return is_buddycloud_enabled(view)
def testFunction(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	query_for_TXT_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_TXT_record = resolver.query("_buddycloud-api._tcp."+domain_url, dns.rdatatype.TXT)

	except (NXDOMAIN, NoAnswer):

		return noTXTRecord(domain_url)

	except Exception as e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return noTXTRecord(domain_url)

		status = 2
		briefing = "A problem happened while searching for the API server TXT record:"
		briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the API server TXT record:"
		message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <email> if you think so." 
		return (status, briefing, message, None)

	classified_records = {}

	for answer in query_for_TXT_record:

		classified = classifyTXTRecord(str(answer))

		if not classified['type'] in classified_records:
			classified_records[classified['type']] = []
		classified_records[classified['type']].append(classified)


	if ( len(classified_records.get('INFO_MISSING', [])) != 0
	  or len(classified_records.get('MALFORMED', [])) != 0
	  or len(classified_records.get('NOT_HTTPS', [])) != 0 ):

		status = 1
		briefing = "We detected incorrect API server TXT records at domain"
		briefing += " <strong>%s</strong>." % domain_url
		message = "We detected you set up the following incorrect API"
		message += " server TXT records.<br/>"
		message += "Really you must have just one correct API server SRV record.<br/>"
		message += "These are the SRV records we found and their problems: <br/><br/>"

		for record in classified_records.get('INFO_MISSING', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('MALFORMED', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('NOT_HTTPS', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('NOT_HTTPS', [])) != 0 ):

			message += "Please ensure your API server will run with HTTPS enabled.<br/>"

		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) == 0:

		status = 1
		briefing = "No correct API server TXT record found at "
		briefing += "domain <strong>%s</strong>!<br/>" % domain_url
		message = briefing + "<br/>"
		message += "You must have one correct API server SRV record.<br/>"
		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) > 1:

		status = 1
		briefing = "We found multiple correct API server TXT records!"
		message = briefing + "<br/>"
		message += "But really, you should have just one.<br/>"
		message += "These are the records we found: <br/><br/>"

	else:

		status = 0
		briefing = "API server TXT record found: "
		briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0]['record']
		message = "Congratulations! You have set up your API server "
		message += "TXT record correctly.<br/><br/>"

	for record in classified_records.get('CORRECT', []):

		message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>"
				% (record['protocol'],
				   record['domain'],
				   record['port'],
				   record['path'],
				   record['record']))

	r = classified_records['CORRECT'][0]

	return (status, briefing, message, {
			'protocol' : r['protocol'],
			'domain' : r['domain'],
			'port' : r['port'],
			'path' : r['path']
		})
def testFunction(domain_url):

    view = {"domain_url": domain_url}

    if (domainNameLookup(domain_url)[0] != 0):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    (status, b, m, answers) = xmppServerServiceRecordLookup(domain_url)
    if (status != 0):
        wiew["warning"] = "XMPP Server of domain %s not found!" % (domain_url)
        return warning(view)

    xmpp = sleekxmpp.ClientXMPP("*****@*****.**", "ei3tseq")

    situation = {}

    for answer in answers:

        conn_address = answer["domain"], answer["port"]
        view["xmpp_server"] = conn_address[0]

        if (not xmpp.connect(
                conn_address, reattempt=False, use_ssl=False, use_tls=False)):
            situation[conn_address] = make_output_builder(
                view, xmpp_connection_problem)
            continue

        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                                  ito=domain_url,
                                  ifrom=xmpp.boundjid)

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=5)
            except Exception as e:
                if (str(e) != ""):
                    view["error"] = str(e)
                situation[conn_address] = make_output_builder(
                    view, xmpp_disco_query_send_error)
                continue

            if (len(response.xml.findall("iq[@type='error']")) != 0):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                situation[conn_address] = make_output_builder(
                    view, xmpp_server_error)
                continue

            its = response.xml.findall("{%s}query/{%s}item" %
                                       ((DISCO_ITEMS_NS, ) * 2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                                      ito=item_jid,
                                      ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    response = iq.send(block=True, timeout=5)
                except Exception as e:
                    if (str(e) != ""):
                        view["error"] = str(e)
                    situation[conn_address] = make_output_builder(
                        view, xmpp_disco_query_send_error)
                    continue

                if (len(response.xml.findall("iq[@type='error']")) != 0):
                    view["error"] = response.xml.findall(
                        "iq[@type='error']")[0]
                    situation[conn_address] = make_output_builder(
                        view, xmpp_server_error)
                    continue

                ids = response.xml.findall("{%s}query/{%s}identity" %
                                           ((DISCO_INFO_NS, ) * 2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    view["discovery"] = True
                    view["channel_server"] = item_jid
                    if (identity_category == 'pubsub'
                            and identity_type == 'channels'):

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            resolver.nameservers = [nameserver]
                            resolver.lifetime = 5
                            PTR_name = "_buddycloud-server._tcp." + domain_url
                            answer = resolver.query(PTR_name,
                                                    dns.rdatatype.PTR)
                        except Exception:
                            pass
                        else:
                            #TODO check if PTR record and DISCO are pointing
                            # to the same place -- they must!
                            view["ptr_record"] = True
                        return is_buddycloud_enabled(view)

            if not conn_address in situation:
                situation[conn_address] = make_output_builder(
                    view, not_buddycloud_enabled)

        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        resolver.nameservers = [nameserver]
        resolver.lifetime = 5
        PTR_name = "_buddycloud-server._tcp." + domain_url
        answer = resolver.query(PTR_name, dns.rdatatype.PTR)
    except (NXDOMAIN, NoAnswer, Timeout):
        pass
    except Exception:
        pass
    else:
        view["ptr_record"] = True
        #view["channel_server"] = answer
        return is_buddycloud_enabled(view)

    if (len(situation) == 1):
        return situation[situation.keys()[0]]()

    view["xmpp_servers"] = []

    status = 2
    for xmpp_server in situation:
        output = situation[xmpp_server]()
        if (output[0] == 1):
            status = 1
        view["xmpp_servers"].append({
            "name":
            "%s through port %s" % (xmpp_server),
            "error":
            output[2]
        })

    view["status"] = status

    return multiple_problems(view)