예제 #1
0
    def _api_config(self, stream, request, query):
        response = Message()

        indent, mimetype, sort_keys = None, "application/json", False
        dictionary = cgi.parse_qs(query)
        if "debug" in dictionary and utils.intify(dictionary["debug"][0]):
            indent, mimetype, sort_keys = 4, "text/plain", True

        if request.method == "POST":
            s = request.body.read()
            updates = qs_to_dictionary(s)
            privacy.check(updates)

            # Very low barrier to prevent damage from kiddies
            if "agent.interval" in updates:
                interval = int(updates["agent.interval"])
                if interval < 1380 and interval != 0:
                    raise ConfigError("Bad agent.interval")

            CONFIG.merge_api(updates, DATABASE.connection())
            STATE.update("config", updates)
            # Empty JSON b/c '204 No Content' is treated as an error
            s = "{}"
        else:
            s = json.dumps(CONFIG.conf, sort_keys=sort_keys, indent=indent)

        stringio = StringIO.StringIO(s)
        response.compose(code="200", reason="Ok", body=stringio,
                         mimetype=mimetype)
        stream.send_response(request, response)
예제 #2
0
def config_api(stream, request, query):

    ''' Implements /api/config API '''

    # Adapted from neubot/api/server.py

    #
    # Fetch and process common options from the query
    # string, for now the only implemented option is
    # debug, which modifies the semantic to return text
    # for humans instead of JSON.
    #

    mimetype = 'application/json'
    indent = None

    options = cgi.parse_qs(query)

    if utils.intify(options.get('debug', ['0'])[0]):
        mimetype = 'text/plain'
        indent = 4

    #
    # Now that we know the response format, decide what is
    # the content of the response.  If the labels option is
    # available we return the documentation coupled with a
    # setting.  When the method is not POST, return instead
    # the name and value of each setting.
    #

    if utils.intify(options.get('labels', ['0'])[0]):
        obj = CONFIG.descriptions
    elif request.method != 'POST':
        obj = CONFIG.conf
    else:

        #
        # When the method is POST we need to read the
        # new settings from the request body.  Settings
        # are a x-www-form-urlencoded dictionary to
        # ease AJAX programming.
        #

        body = request.body.read()
        updates = marshal.qs_to_dictionary(body)

        #
        # PRE-update checks.  We need to make sure that
        # the following things are True:
        #
        # 1. that the incoming dictionary does not contain
        #    invalid privacy settings;
        #
        # 2. that the interval between automatic tests is
        #    either reasonable or set to zero, which means
        #    that it needs to be extracted randomly.
        #

        count = privacy.count_valid(updates, 'privacy.')
        if count < 0:
            raise ConfigError('Passed invalid privacy settings')

        agent_interval = int(updates.get('agent.interval', 0))
        if agent_interval != 0 and agent_interval < 1380:
            raise ConfigError('Passed invalid agent.interval')

        # Merge settings
        CONFIG.merge_api(updates, DATABASE.connection())

        #
        # Update the state, such that, if the AJAX code is
        # tracking the state it gets a notification that
        # some configurations variable have been modified.
        # Given that we communicate the update via that
        # channel, the response body is an empty dict to
        # keep happy the AJAX code.
        #

        STATE.update('config', updates)
        obj = '{}'

    #
    # Now that we know the body, prepare and send
    # the response for the client.
    #

    response = Message()

    body = json.dumps(obj, sort_keys=True, indent=indent)
    response.compose(code="200", reason="Ok", body=body, mimetype=mimetype)
    stream.send_response(request, response)