Example #1
0
/* Get OVS DB map value by given map key
 *
 * FROM RFC7047:
 *
 *   <pair>
 *     A 2-element JSON array that represents a pair within a database
 *     map.  The first element is an <atom> that represents the key, and
 *     the second element is an <atom> that represents the value.
 *
 *   <map>
 *     A 2-element JSON array that represents a database map value.  The
 *     first element of the array must be the string "map", and the
 *     second element must be an array of zero or more <pair>s giving the
 *     values in the map.  All of the <pair>s must have the same key and
 *     value types.
 *
 * EXAMPLE:
 *  [
 *    "map", [
 *             [ "key_a", <YAJL value>], [ "key_b", <YAJL value>], ...
 *           ]
 *  ]
 */
yajl_val ovs_utils_get_map_value(yajl_val jval, const char *key) {
  size_t map_len = 0;
  size_t array_len = 0;
  yajl_val *map_values = NULL;
  yajl_val *array_values = NULL;
  const char *str_val = NULL;

  /* check YAJL array */
  if (!YAJL_IS_ARRAY(jval) || (key == NULL))
    return NULL;

  /* check a database map value (2-element, first one should be a string */
  array_len = YAJL_GET_ARRAY(jval)->len;
  array_values = YAJL_GET_ARRAY(jval)->values;
  if ((array_len != 2) || (!YAJL_IS_STRING(array_values[0])) ||
      (!YAJL_IS_ARRAY(array_values[1])))
    return NULL;

  /* check first element of the array */
  str_val = YAJL_GET_STRING(array_values[0]);
  if (str_val == NULL || strcmp("map", str_val) != 0)
    return NULL;

  /* try to find map value by map key */
  if (YAJL_GET_ARRAY(array_values[1]) == NULL)
    return NULL;

  map_len = YAJL_GET_ARRAY(array_values[1])->len;
  map_values = YAJL_GET_ARRAY(array_values[1])->values;
  for (size_t i = 0; i < map_len; i++) {
    /* check YAJL array */
    if (!YAJL_IS_ARRAY(map_values[i]) || YAJL_GET_ARRAY(map_values[i]) == NULL)
      break;

    /* check a database pair value (2-element, first one represents a key
     * and it should be a string in our case */
    array_len = YAJL_GET_ARRAY(map_values[i])->len;
    array_values = YAJL_GET_ARRAY(map_values[i])->values;
    if ((array_len != 2) || (!YAJL_IS_STRING(array_values[0])))
      break;

    /* return map value if given key equals map key */
    str_val = YAJL_GET_STRING(array_values[0]);
    if (str_val != NULL && strcmp(key, str_val) == 0)
      return array_values[1];
  }
  return NULL;
}
Example #2
0
void YAJLVec2i(Vec2i *value, yajl_val node, const char *name)
{
	if (!YAJLTryLoadValue(&node, name) || !YAJL_IS_ARRAY(node))
	{
		return;
	}
	*value = YAJL_GET_VEC2I(node);
}
Example #3
0
/*
 * Add a value to the value on top of the stack or the "root" member in the
 * context if the end of the parsing process is reached.
 */
static int context_add_value (context_t *ctx, yajl_val v)
{
    /* We're checking for NULL values in all the calling functions. */
    assert (ctx != NULL);
    assert (v != NULL);

    /*
     * There are three valid states in which this function may be called:
     *   - There is no value on the stack => This is the only value. This is the
     *     last step done when parsing a document. We assign the value to the
     *     "root" member and return.
     *   - The value on the stack is an object. In this case store the key on the
     *     stack or, if the key has already been read, add key and value to the
     *     object.
     *   - The value on the stack is an array. In this case simply add the value
     *     and return.
     */
    if (ctx->stack == NULL)
    {
        assert (ctx->root == NULL);
        ctx->root = v;
        return (0);
    }
    else if (YAJL_IS_OBJECT (ctx->stack->value))
    {
        if (ctx->stack->key == NULL)
        {
            if (!YAJL_IS_STRING (v))
                RETURN_ERROR (ctx, EINVAL, "context_add_value: "
                              "Object key is not a string (%#04x)",
                              v->type);

            ctx->stack->key = v->u.string;
            v->u.string = NULL;
            free(v);
            return (0);
        }
        else /* if (ctx->key != NULL) */
        {
            char * key;

            key = ctx->stack->key;
            ctx->stack->key = NULL;
            return (object_add_keyval (ctx, ctx->stack->value, key, v));
        }
    }
    else if (YAJL_IS_ARRAY (ctx->stack->value))
    {
        return (array_add_value (ctx, ctx->stack->value, v));
    }
    else
    {
        RETURN_ERROR (ctx, EINVAL, "context_add_value: Cannot add value to "
                      "a value of type %#04x (not a composite type)",
                      ctx->stack->value->type);
    }
}
Example #4
0
void YAJLVec2i(Vec2i *value, yajl_val node, const char *name)
{
	if (!YAJLTryLoadValue(&node, name) || !YAJL_IS_ARRAY(node))
	{
		return;
	}
	value->x = (int)YAJL_GET_INTEGER(YAJL_GET_ARRAY(node)->values[0]);
	value->y = (int)YAJL_GET_INTEGER(YAJL_GET_ARRAY(node)->values[1]);
}
Example #5
0
/* Add YAJL value into YAJL generator handle (JSON object)
 *
 * jgen - YAJL generator handle allocated by yajl_gen_alloc()
 * jval - YAJL value usually returned by yajl_tree_get()
 */
static yajl_gen_status ovs_yajl_gen_val(yajl_gen jgen, yajl_val jval) {
  size_t array_len = 0;
  yajl_val *jvalues = NULL;
  yajl_val jobj_value = NULL;
  const char *obj_key = NULL;
  size_t obj_len = 0;
  yajl_gen_status yajl_gen_ret = yajl_gen_status_ok;

  if (jval == NULL)
    return yajl_gen_generation_complete;

  if (YAJL_IS_STRING(jval))
    OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, YAJL_GET_STRING(jval));
  else if (YAJL_IS_DOUBLE(jval))
    OVS_YAJL_CALL(yajl_gen_double, jgen, YAJL_GET_DOUBLE(jval));
  else if (YAJL_IS_INTEGER(jval))
    OVS_YAJL_CALL(yajl_gen_double, jgen, YAJL_GET_INTEGER(jval));
  else if (YAJL_IS_TRUE(jval))
    OVS_YAJL_CALL(yajl_gen_bool, jgen, 1);
  else if (YAJL_IS_FALSE(jval))
    OVS_YAJL_CALL(yajl_gen_bool, jgen, 0);
  else if (YAJL_IS_NULL(jval))
    OVS_YAJL_CALL(yajl_gen_null, jgen);
  else if (YAJL_IS_ARRAY(jval)) {
    /* create new array and add all elements into the array */
    array_len = YAJL_GET_ARRAY(jval)->len;
    jvalues = YAJL_GET_ARRAY(jval)->values;
    OVS_YAJL_CALL(yajl_gen_array_open, jgen);
    for (size_t i = 0; i < array_len; i++)
      OVS_YAJL_CALL(ovs_yajl_gen_val, jgen, jvalues[i]);
    OVS_YAJL_CALL(yajl_gen_array_close, jgen);
  } else if (YAJL_IS_OBJECT(jval)) {
    /* create new object and add all elements into the object */
    OVS_YAJL_CALL(yajl_gen_map_open, jgen);
    obj_len = YAJL_GET_OBJECT(jval)->len;
    for (size_t i = 0; i < obj_len; i++) {
      obj_key = YAJL_GET_OBJECT(jval)->keys[i];
      jobj_value = YAJL_GET_OBJECT(jval)->values[i];
      OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, obj_key);
      OVS_YAJL_CALL(ovs_yajl_gen_val, jgen, jobj_value);
    }
    OVS_YAJL_CALL(yajl_gen_map_close, jgen);
  } else {
    OVS_ERROR("%s() unsupported value type %d (skip)", __FUNCTION__,
              (int)(jval)->type);
    goto yajl_gen_failure;
  }
  return yajl_gen_status_ok;

yajl_gen_failure:
  OVS_ERROR("%s() error to generate value", __FUNCTION__);
  return yajl_gen_ret;
}
Example #6
0
void bson_from_json_type(bson *b, yajl_val value, const char* key)
{
    if( YAJL_IS_STRING( value ) )
    {
        char* string = YAJL_GET_STRING( value );
        bson_append_string( b, key, string );
    }
    else if( YAJL_IS_NUMBER( value ) )
    {
        char* string = value->u.number.r;
        size_t len = strlen( string );

        // Hack to detect a double, since 'flags' is always set to double.
        if( memchr( string, '.', len ) ||
                memchr( string, 'e', len ) ||
                memchr( string, 'E', len ) )
        {
            double number = YAJL_GET_DOUBLE( value );
            bson_append_double( b, key, number );
        }
        else
        {
            uint64_t number = YAJL_GET_INTEGER( value );

            if( number <= INT_MIN && number <= INT_MAX)
                bson_append_int( b, key, (int)number );
            else
                bson_append_long( b, key, number);
        }
    }
    else if ( YAJL_IS_FALSE( value ) )
    {
        bson_append_bool( b, key, 0 );
    }
    else if ( YAJL_IS_TRUE( value ) )
    {
        bson_append_bool( b, key, 1 );
    }
    else if ( YAJL_IS_ARRAY( value ) )
    {
        bson_append_start_array( b, key );
        bson_from_json_array( b, value );
        bson_append_finish_array( b );
    }
    else if ( YAJL_IS_OBJECT( value ) )
    {
        bson_append_start_object( b, key );
        bson_from_json_object( b, value );
        bson_append_finish_object( b );
    }
}
Example #7
0
SEXP ParseValue(yajl_val node, int bigint){
  if(YAJL_IS_NULL(node)){
    return R_NilValue;
  }
  if(YAJL_IS_STRING(node)){
    SEXP tmp = PROTECT(allocVector(STRSXP, 1));
    SET_STRING_ELT(tmp, 0, mkCharCE(YAJL_GET_STRING(node),  CE_UTF8));
    UNPROTECT(1);
    return tmp;
  }
  if(YAJL_IS_INTEGER(node)){
    long long int val = YAJL_GET_INTEGER(node);
    /* 2^53 is highest int stored as double without loss */
    if(bigint && (val > 9007199254740992 || val < -9007199254740992)){
      char buf[32];
      #ifdef _WIN32
      snprintf(buf, 32, "%I64d", val);
      #else
      snprintf(buf, 32, "%lld", val);
      #endif
      return mkString(buf);
    /* see .Machine$integer.max in R */
    } else if(val > 2147483647 || val < -2147483647){
      return ScalarReal(val);
    } else {
      return ScalarInteger(val);
    }
  }
  if(YAJL_IS_DOUBLE(node)){
    return(ScalarReal(YAJL_GET_DOUBLE(node)));
  }
  if(YAJL_IS_NUMBER(node)){
    /* A number that is not int or double (very rare) */
    /* This seems to correctly round to Inf/0/-Inf */
    return(ScalarReal(YAJL_GET_DOUBLE(node)));
  }
  if(YAJL_IS_TRUE(node)){
    return(ScalarLogical(1));
  }
  if(YAJL_IS_FALSE(node)){
    return(ScalarLogical(0));
  }
  if(YAJL_IS_OBJECT(node)){
    return(ParseObject(node, bigint));
  }
  if(YAJL_IS_ARRAY(node)){
    return(ParseArray(node, bigint));
  }
  error("Invalid YAJL node type.");
}
Example #8
0
static void yajl_array_free (yajl_val v)
{
    size_t i;

    if (!YAJL_IS_ARRAY(v)) return;

    for (i = 0; i < v->u.array.len; i++)
    {
        yajl_tree_free (v->u.array.values[i]);
        v->u.array.values[i] = NULL;
    }

    free(v->u.array.values);
    free(v);
}
Example #9
0
/*
 * Parsing nested objects and arrays is implemented using a stack. When a new
 * object or array starts (a curly or a square opening bracket is read), an
 * appropriate value is pushed on the stack. When the end of the object is
 * reached (an appropriate closing bracket has been read), the value is popped
 * off the stack and added to the enclosing object using "context_add_value".
 */
static int context_push(context_t *ctx, yajl_val v)
{
    stack_elem_t *stack;

    stack = malloc (sizeof (*stack));
    if (stack == NULL)
        RETURN_ERROR (ctx, ENOMEM, "Out of memory");
    memset (stack, 0, sizeof (*stack));

    assert ((ctx->stack == NULL)
            || YAJL_IS_OBJECT (v)
            || YAJL_IS_ARRAY (v));

    stack->value = v;
    stack->next = ctx->stack;
    ctx->stack = stack;

    return (0);
}
Example #10
0
void message_bus_write_json(yajl_gen g, void *context) {
    state *state = context;

    yajl_val output_values = state_get_json(state, STATE_OUTPUT_VALUES);

    assert(YAJL_IS_ARRAY(output_values));

    yajl_gen_map_open(g);

    int len = YAJL_GET_ARRAY(output_values)->len;
    for (int i = 0; i < len; i++) {
        char *k = YAJL_GET_STRING(YAJL_GET_ARRAY(output_values)->values[i]);

        state_value_type type = state_get_value_type(state, k);

        yajl_gen_string(g, (unsigned char *)k, strlen(k));

        float float_value;
        int int_value;
        yajl_val json_value;
        switch (type) {
            case state_value_type_float:
                float_value = state_get_float(state, k);
                yajl_gen_double(g, (double)float_value);
                break;
            case state_value_type_int:
                int_value = state_get_int(state, k);
                yajl_gen_integer(g, int_value);
                break;
            case state_value_type_json:
                json_value = state_get_json(state, k);
                json_write_value(g, json_value);
                break;
            default:
                assert(0);
                break;
        }
    }

    yajl_gen_map_close(g);
}
Example #11
0
static int array_add_value (context_t *ctx,
                            yajl_val array, yajl_val value)
{
    yajl_val *tmp;

    /* We're checking for NULL pointers in "context_add_value" or its
     * callers. */
    assert (ctx != NULL);
    assert (array != NULL);
    assert (value != NULL);

    /* "context_add_value" will only call us with array values. */
    assert(YAJL_IS_ARRAY(array));

    tmp = realloc(array->u.array.values,
                  sizeof(*(array->u.array.values)) * (array->u.array.len + 1));
    if (tmp == NULL)
        RETURN_ERROR(ctx, ENOMEM, "Out of memory");
    array->u.array.values = tmp;
    array->u.array.values[array->u.array.len] = value;
    array->u.array.len++;

    return 0;
}
Example #12
0
struct github *fetch_github_commits(yajl_val *root, const char *repo, int *commit_count) {

	CURL *curl;
	CURLcode code;
	yajl_val val;
	struct github *commits = NULL;
	struct mem_buffer mem = {NULL, 0};
	char API_URL[URLLEN], errbuf[1024];

	// Use per_page field to limit json reply to the amount of commits specified
	snprintf(API_URL, URLLEN, "https://api.github.com/repos/%s/commits?per_page=%d", repo, *commit_count);
	*commit_count = 0;

	curl = curl_easy_init();
	if (!curl)
		goto cleanup;

#ifdef TEST
	curl_easy_setopt(curl, CURLOPT_URL, getenv("IRCBOT_TESTFILE"));
#else
	curl_easy_setopt(curl, CURLOPT_URL, API_URL);
#endif
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
	curl_easy_setopt(curl, CURLOPT_USERAGENT, "irc-bot"); // Github requires a user-agent
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 8L);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_memory);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &mem);

	code = curl_easy_perform(curl);
	if (code != CURLE_OK) {
		fprintf(stderr, "Error: %s\n", curl_easy_strerror(code));
		goto cleanup;
	}
	if (!mem.buffer) {
		fprintf(stderr, "Error: Body was empty");
		goto cleanup;
	}
	*root = yajl_tree_parse(mem.buffer, errbuf, sizeof(errbuf));
	if (!*root) {
		fprintf(stderr, "%s\n", errbuf);
		goto cleanup;
	}
	if (YAJL_IS_ARRAY(*root)) {
		*commit_count = YAJL_GET_ARRAY(*root)->len;
		commits = malloc_w(*commit_count * sizeof(*commits));
	}
	// Find the field we are interested in the json reply, save a reference to it & null terminate
	for (int i = 0; i < *commit_count; i++) {
		val = yajl_tree_get(YAJL_GET_ARRAY(*root)->values[i], CFG("sha"),                      yajl_t_string);
		if (!val) break;
		commits[i].sha  = YAJL_GET_STRING(val);

		val = yajl_tree_get(YAJL_GET_ARRAY(*root)->values[i], CFG("commit", "author", "name"), yajl_t_string);
		if (!val) break;
		commits[i].name = YAJL_GET_STRING(val);

		val = yajl_tree_get(YAJL_GET_ARRAY(*root)->values[i], CFG("commit", "message"),        yajl_t_string);
		if (!val) break;
		commits[i].msg  = YAJL_GET_STRING(val);
		null_terminate(commits[i].msg, '\n'); // Cut commit message at newline character if present

		val = yajl_tree_get(YAJL_GET_ARRAY(*root)->values[i], CFG("html_url"),                 yajl_t_string);
		if (!val) break;
		commits[i].url  = YAJL_GET_STRING(val);
	}
cleanup:
	free(mem.buffer);
	curl_easy_cleanup(curl);
	return commits;
}
Example #13
0
File: v1.c Project: fahlgren/kore
int
v1(struct http_request *http_req)
{
	struct jsonrpc_request	req;
	int			ret;
	
	/* We only allow POST/PUT methods. */
	if (http_req->method != HTTP_METHOD_POST &&
	    http_req->method != HTTP_METHOD_PUT) {
		http_response_header(http_req, "allow", "POST, PUT");
		http_response(http_req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
		return (KORE_RESULT_OK);
	}
	
	/* Read JSON-RPC request. */
	if ((ret = jsonrpc_read_request(http_req, &req)) != 0)
		return jsonrpc_error(&req, ret, NULL);
	
	/* Echo command takes and gives back params. */
	if (strcmp(req.method, "echo") == 0) {
		if (!YAJL_IS_ARRAY(req.params)) {
			jsonrpc_log(&req, LOG_ERR,
			    "Echo only accepts positional params");
			return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
		}
		for (size_t i = 0; i < req.params->u.array.len; i++) {
			yajl_val v = req.params->u.array.values[i];
			if (!YAJL_IS_STRING(v)) {
				jsonrpc_log(&req, -3,
				    "Echo only accepts strings");
				return jsonrpc_error(&req,
				    JSONRPC_INVALID_PARAMS, NULL);
			}
		}
		return jsonrpc_result(&req, write_string_array_params, NULL);
	}
	
	/* Date command displays date and time according to parameters. */
	if (strcmp(req.method, "date") == 0) {
		time_t		time_value;
		struct tm	time_info;
		char		timestamp[33];
		struct tm	*(*gettm)(const time_t *, struct tm *) =
				    localtime_r;
		
		if (YAJL_IS_OBJECT(req.params)) {
			const char	*path[] = {"local", NULL};
			yajl_val	bf;

			bf = yajl_tree_get(req.params, path, yajl_t_false);
			if (bf != NULL)
				gettm = gmtime_r;
		} else if (req.params != NULL) {
			jsonrpc_log(&req, LOG_ERR,
			    "Date only accepts named params");
			return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
		}

		if ((time_value = time(NULL)) == -1)
			return jsonrpc_error(&req, -2,
			    "Failed to get date time");
		
		if (gettm(&time_value, &time_info) == NULL)
			return jsonrpc_error(&req, -3,
			    "Failed to get date time info");
		
		memset(timestamp, 0, sizeof(timestamp));
		if (strftime_l(timestamp, sizeof(timestamp) - 1, "%c",
		    &time_info, LC_GLOBAL_LOCALE) == 0)
			return jsonrpc_error(&req, -4,
			    "Failed to get printable date time");
		
		return jsonrpc_result(&req, write_string, timestamp);
	}
	
	return jsonrpc_error(&req, JSONRPC_METHOD_NOT_FOUND, NULL);
}