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)
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)