def xmpp_disco_query_send_error_template():

    briefing_template = "Could not send "+code("{{disco_type}}")+" query to "
    briefing_template += "{{^xmpp_server}}" + bold("{{domain_url}}")
    briefing_template += "{{/xmpp_server}}"
    briefing_template += "{{#xmpp_server}}" + bold("{{xmpp_server}}")
    briefing_template += "{{/xmpp_server}}."
    message_template = briefing_template
    message_template += "{{#error}}" + breakline()
    message_template += "Error response: " + code("{{&error}}") +"{{/error}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
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)
def buddycloud_enabled_conflict_template():

    briefing_template = bold("{{domain_url}}") + " is "
    briefing_template += italic("buddycloud enabled") + ","
    briefing_template += " but we detected a conflict problem."
    message_template = briefing_template + breakline()
    message_template += "Using " + code("Service Discovery")
    message_template += ", we found your channel server at "
    message_template += bold("{{channel_server}}") + "!" + breakline()
    message_template += "But we also found a channel server through "
    message_template += code("TXT record lookup") + ", which is different: "
    message_template += bold("{{channel_server2}}") + "!" + breakline()
    message_template += "The channel server addresses found through "
    message_template += code("Service Discovery") + " and " + code("TXT record lookup") + " must match!"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def warning_template():

    briefing_template = bold("Precondition problem:") + " "
    briefing_template += code("{{warning}}")
    message_template = "This test did not even run. " + briefing_template
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def warning_template():

    briefing_template = bold("Precondition problem:") + " "
    briefing_template += code("{{warning}}")
    message_template = "This test did not even run. " + briefing_template
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def is_buddycloud_enabled_template():

    briefing_template = bold("{{domain_url}}") + " is "
    briefing_template += italic("buddycloud enabled") + "."
    message_template = "Congratulations! " + briefing_template + breakline()
    message_template += "{{#discovery}}Using " + code("Service Discovery")
    message_template += ", we found your channel server at "
    message_template += bold("{{channel_server}}") + "!" + breakline()
    message_template += "{{#ptr_record}}We also found your channel server "
    message_template += code("PTR record") + ".{{/ptr_record}}{{/discovery}}"
    message_template += "{{#ptr_record}}Using " + code("PTR record") + ", we"
    message_template += " found your channel server at "
    message_template += bold("{{channel_server}}") + "!" + breakline() + "Bu"
    message_template += "t we could not find it through "
    message_template += code("Service Discovery") + ".{{/ptr_record}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def is_buddycloud_enabled_template():

    briefing_template = bold("{{domain_url}}") + " is "
    briefing_template += italic("buddycloud enabled") + "."
    message_template = "Congratulations! " + briefing_template + breakline()
    message_template += "{{#discovery}}Using " + code("Service Discovery")
    message_template += ", we found your channel server at "
    message_template += bold("{{channel_server}}") + "!" + breakline()
    message_template += "{{#ptr_record}}We also found your channel server "
    message_template += code("PTR record") + ".{{/ptr_record}}{{/discovery}}"
    message_template += "{{#ptr_record}}Using " + code("PTR record") + ", we"
    message_template += " found your channel server at "
    message_template += bold("{{channel_server}}") + "!" + breakline() + "Bu"
    message_template += "t we could not find it through "
    message_template += code("Service Discovery") + ".{{/ptr_record}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def xmpp_server_error_template():

    briefing_template = "The {{disco_type}} query got an error response from"
    briefing_template += " " + bold("{{xmpp_server}}") + "."
    message_template = briefing_template + breakline() + "The XMPP server at"
    message_template += " " + bold("{{xmpp_server}}") + " returned the follo"
    message_template += "wing error: " + code("{{&error}}")
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def record_correct_template():

    briefing_template = "We could find the API server " + code("TXT record")
    briefing_template += " for " + bold("{{domain_url}}") + "!"
    message_template = "Congratulations! " + briefing_template + breakline()
    message_template += breakline() + "This is your record:" + breakline()
    message_template += code_block("{{&record}}")
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def xmpp_server_error_template():

    briefing_template = "The {{disco_type}} query got an error response from"
    briefing_template += " " + bold("{{xmpp_server}}") + "."
    message_template = briefing_template + breakline() + "The XMPP server at"
    message_template += " " + bold("{{xmpp_server}}") + " returned the follo"
    message_template += "wing error: " + code("{{&error}}")
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def no_record_template():

    briefing_template = "Could not find the API server " + code("TXT record")
    briefing_template += " for " + bold("{{domain_url}}") + "!"
    message_template = briefing_template + breakline()
    message_template += "Please add one in your DNS settings." + breakline()
    message_template += "Refer to the " + link("install instructions",
        "http://buddycloud.com/install#buddycloud_dns_") + " for more info."
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def xmpp_disco_query_send_error_template():

    briefing_template = "Could not send " + code("{{disco_type}}") + " query"
    briefing_template += " to " + bold("{{xmpp_server}}") + "."
    message_template = briefing_template + breakline() + "Beware it may not "
    message_template += "be a problem with domain " + bold("{{domain_url}}")
    message_template += " or the XMPP server at " + bold("{{xmpp_server}}")
    message_template += "." + breakline() + "{{#error}}Problem: {{error}}{{/"
    message_template += "error}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def xmpp_disco_query_send_error_template():

    briefing_template = "Could not send " + code("{{disco_type}}") + " query"
    briefing_template += " to " + bold("{{xmpp_server}}") + "."
    message_template = briefing_template + breakline() + "Beware it may not "
    message_template += "be a problem with domain " + bold("{{domain_url}}")
    message_template += " or the XMPP server at " + bold("{{xmpp_server}}")
    message_template += "." + breakline() + "{{#error}}Problem: {{error}}{{/"
    message_template += "error}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def xmpp_server_error_template():

    briefing_template = "The {{disco_type}} query got an error response from"
    briefing_template += "{{^xmpp_server}}" + bold("{{domain_url}}")
    briefing_template += "{{/xmpp_server}}"
    briefing_template += "{{#xmpp_server}}" + bold("{{xmpp_server}}")
    briefing_template += "{{/xmpp_server}}."
    message_template = briefing_template
    message_template += "{{#error}}" + breakline()
    message_template += "Error response: " + code("{{&error}}") +"{{/error}}"
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def record_error_template():

    briefing_template = "We could find the API server " + code("TXT record")
    briefing_template += " for " + bold("{{domain_url}}")
    briefing_template += " but it is problematic!"
    message_template = briefing_template + breakline()
    message_template += breakline() + "This is your record:" + breakline()
    message_template += code_block("{{&record}}")
    message_template += "{{&error}}" + breakline()
    message_template += "Please fix this in your DNS settings." + breakline()
    message_template += "Refer to the " + link("install instructions",
        "http://buddycloud.com/install#buddycloud_dns_") + " for more info."
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
def record_error_template():

    briefing_template = "We could find the Buddycloud server " + code("TXT record")
    briefing_template += " for " + bold("{{domain_url}}")
    briefing_template += " but it is problematic!"
    message_template = briefing_template + breakline()
    message_template += breakline() + "This is your record:" + breakline()
    message_template += code_block("{{&record}}")
    message_template += breakline() + "{{&error}}" + breakline()
    message_template += "Please fix this in your DNS settings." + breakline()
    message_template += "Refer to this " + link("document",
        "http://buddycloud.github.io/buddycloud-xep/#DNS-discovery") + " for more info."
    briefing_template = parse(briefing_template)
    message_template = parse(message_template)
    return briefing_template, message_template
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)