コード例 #1
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
static void qualify_and_schedule_all(void)
{
	struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", "");
	struct ao2_container *aors;
	struct ao2_container *contacts;

	if (!var) {
		return;
	}
	aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"aor", AST_RETRIEVE_FLAG_MULTIPLE, var);

	ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, unschedule_all_cb, NULL);

	if (aors) {
		ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL);
		ao2_ref(aors, -1);
	}

	contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"contact", AST_RETRIEVE_FLAG_MULTIPLE, var);
	if (contacts) {
		ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_without_aor, NULL);
		ao2_ref(contacts, -1);
	}

	ast_variables_destroy(var);

}
コード例 #2
0
static int json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
{
    struct ast_variable *current = NULL;
    struct ast_json_iter *it_json_var;

    for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
            it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
        struct ast_variable *new_var;

        new_var = ast_variable_new(ast_json_object_iter_key(it_json_var),
                                   ast_json_string_get(ast_json_object_iter_value(it_json_var)),
                                   "");
        if (!new_var) {
            ast_variables_destroy(*variables);
            *variables = NULL;
            return 1;
        }

        if (!current) {
            *variables = new_var;
            current = *variables;
        } else {
            current->next = new_var;
            current = new_var;
        }
    }

    return 0;
}
コード例 #3
0
ファイル: json.c プロジェクト: huangjingpei/asterisk
int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
{
	struct ast_json_iter *it_json_var;

	*variables = NULL;

	for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
		 it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
		struct ast_variable *new_var;
		const char *key = ast_json_object_iter_key(it_json_var);

		if (ast_strlen_zero(key)) {
			continue;
		}

		new_var = ast_variable_new(key,
		                           ast_json_string_get(ast_json_object_iter_value(it_json_var)),
		                           "");
		if (!new_var) {
			ast_variables_destroy(*variables);
			*variables = NULL;
			return -1;
		}

		ast_variable_list_append(variables, new_var);
	}

	return 0;
}
コード例 #4
0
ファイル: location.c プロジェクト: edvinanet/asterisk
static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
{
	struct ast_variable *objset;
	struct ast_variable *i;

	objset = ast_sorcery_objectset_create2(ast_sip_get_sorcery(), aor,
		AST_HANDLER_ONLY_STRING);
	if (!objset) {
		return -1;
	}

	ast_str_append(buf, 0, "ObjectType: %s\r\n",
		       ast_sorcery_object_get_type(aor));
	ast_str_append(buf, 0, "ObjectName: %s\r\n",
		       ast_sorcery_object_get_id(aor));

	for (i = objset; i; i = i->next) {
		char *camel = ast_to_camel_case(i->name);

		if (strcmp(camel, "Contact") == 0) {
			ast_free(camel);
			camel = NULL;
		}
		ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
		ast_free(camel);
	}

	ast_variables_destroy(objset);
	return 0;
}
コード例 #5
0
ファイル: resource_asterisk.c プロジェクト: GGGO/asterisk
static void return_sorcery_object(struct ast_sorcery *sorcery, void *sorcery_obj,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_json *, return_set, NULL, ast_json_unref);
	struct ast_variable *change_set;
	struct ast_variable *it_change_set;

	return_set = ast_json_array_create();
	if (!return_set) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	/* Note that we can't use the sorcery JSON change set directly,
	 * as it will hand us back an Object (with fields), and we need
	 * a more generic representation of whatever the API call asked
	 * for, i.e., a list of tuples.
	 */
	change_set = ast_sorcery_objectset_create(sorcery, sorcery_obj);
	if (!change_set) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	for (it_change_set = change_set; it_change_set; it_change_set = it_change_set->next) {
		struct ast_json *tuple;

		tuple = ast_json_pack("{s: s, s: s}",
			"attribute", it_change_set->name,
			"value", it_change_set->value);
		if (!tuple) {
			ast_variables_destroy(change_set);
			ast_ari_response_alloc_failed(response);
			return;
		}

		if (ast_json_array_append(return_set, tuple)) {
			ast_json_unref(tuple);
			ast_variables_destroy(change_set);
			ast_ari_response_alloc_failed(response);
			return;
		}
	}
	ast_variables_destroy(change_set);

	ast_ari_response_ok(response, ast_json_ref(return_set));
}
コード例 #6
0
/*!
 * \internal
 * \brief Destroy the notify AMI data releasing any resources.
 */
static void notify_ami_data_destroy(void *obj)
{
	struct notify_data *data = obj;
	struct ast_variable *info = data->info;

	ao2_cleanup(data->endpoint);
	ast_variables_destroy(info);
}
コード例 #7
0
/*!
 * \internal
 * \brief Destroy the notify AMI URI data releasing any resources.
 */
static void notify_ami_uri_data_destroy(void *obj)
{
	struct notify_uri_data *data = obj;
	struct ast_variable *info = data->info;

	ast_free(data->uri);
	ast_variables_destroy(info);
}
コード例 #8
0
ファイル: json.c プロジェクト: MattheusNiels/BackupCerberus
enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
{
	struct ast_json_iter *it_json_var;

	*variables = NULL;

	for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
		it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
		struct ast_variable *new_var;
		const char *key = ast_json_object_iter_key(it_json_var);
		const char *value;
		struct ast_json *json_value;

		if (ast_strlen_zero(key)) {
			continue;
		}

		json_value = ast_json_object_iter_value(it_json_var);
		if (ast_json_typeof(json_value) != AST_JSON_STRING) {
			/* Error: Only strings allowed */
			ast_variables_destroy(*variables);
			*variables = NULL;
			return AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE;
		}
		value = ast_json_string_get(json_value);
		/* Should never be NULL.  Otherwise, how could it be a string type? */
		ast_assert(value != NULL);
		if (!value) {
			/* To be safe. */
			continue;
		}
		new_var = ast_variable_new(key, value, "");
		if (!new_var) {
			/* Error: OOM */
			ast_variables_destroy(*variables);
			*variables = NULL;
			return AST_JSON_TO_AST_VARS_CODE_OOM;
		}

		ast_variable_list_append(variables, new_var);
	}

	return AST_JSON_TO_AST_VARS_CODE_SUCCESS;
}
コード例 #9
0
ファイル: agent.c プロジェクト: n02018222/asterisk
static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
										int exact, size_t *var_len, WriteMethod **write_method)
{
	const struct ast_channel_tech *tech = NULL;
	struct ast_variable *channel_types, *next;
	static unsigned long long_ret;
	struct ast_channel *chan;
	u_long i;

	if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
		return NULL;

	channel_types = ast_channeltype_list();
	for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
		;
	if (next != NULL)
		tech = ast_get_channel_tech(next->name);
	ast_variables_destroy(channel_types);
	if (next == NULL || tech == NULL)
		return NULL;
	
	switch (vp->magic) {
	case ASTCHANTYPEINDEX:
		long_ret = name[*length - 1];
		return (u_char *)&long_ret;
	case ASTCHANTYPENAME:
		*var_len = strlen(tech->type);
		return (u_char *)tech->type;
	case ASTCHANTYPEDESC:
		*var_len = strlen(tech->description);
		return (u_char *)tech->description;
	case ASTCHANTYPEDEVSTATE:
		long_ret = tech->devicestate ? 1 : 2;
		return (u_char *)&long_ret;
	case ASTCHANTYPEINDICATIONS:
		long_ret = tech->indicate ? 1 : 2;
		return (u_char *)&long_ret;
	case ASTCHANTYPETRANSFER:
		long_ret = tech->transfer ? 1 : 2;
		return (u_char *)&long_ret;
	case ASTCHANTYPECHANNELS:
		long_ret = 0;
		for (chan = ast_channel_walk_locked(NULL); chan; chan = ast_channel_walk_locked(chan)) {
			if (chan->tech == tech)
				long_ret++;
			ast_channel_unlock(chan);
		}
		return (u_char *)&long_ret;
	default:
		break;
	}
	return NULL;
}
コード例 #10
0
/*! \brief Internal helper function which returns a filtered objectset. 
 *
 * The following are filtered out of the objectset:
 * \li The id field. This is returned to the caller in an out parameter.
 * \li Fields that are not registered with sorcery.
 *
 * \param objectset Objectset to filter.
 * \param[out] id The ID of the sorcery object, as found in the objectset.
 * \param sorcery The sorcery instance that is requesting an objectset.
 * \param type The object type
 *
 * \return The filtered objectset
 */
static struct ast_variable *sorcery_realtime_filter_objectset(struct ast_variable *objectset, struct ast_variable **id,
		const struct ast_sorcery *sorcery, const char *type)
{
	struct ast_variable *previous = NULL, *field = objectset;
	struct ast_sorcery_object_type *object_type;

	object_type = ast_sorcery_get_object_type(sorcery, type);
	if (!object_type) {
		ast_log(LOG_WARNING, "Unknown sorcery object type %s. Expect errors\n", type);
		/* Continue since we still want to filter out the id */
	}

	while (field) {
		int remove_field = 0;
		int delete_field = 0;

		if (!strcmp(field->name, UUID_FIELD)) {
			*id = field;
			remove_field = 1;
		} else if (object_type &&
				!ast_sorcery_is_object_field_registered(object_type, field->name)) {
			ast_debug(1, "Filtering out realtime field '%s' from retrieval\n", field->name);
			remove_field = 1;
			delete_field = 1;
		}

		if (remove_field) {
			struct ast_variable *removed;

			if (previous) {
				previous->next = field->next;
			} else {
				objectset = field->next;
			}

			removed = field;
			field = field->next;
			removed->next = NULL;
			if (delete_field) {
				ast_variables_destroy(removed);
			}
		} else {
			previous = field;
			field = field->next;
		}
	}

	ao2_cleanup(object_type);

	return objectset;
}
コード例 #11
0
ファイル: pjsip_cli.c プロジェクト: adaptiman/asterisk
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
{
	struct ast_sip_cli_context *context = arg;
	struct ast_variable *i;
	int max_name_width = 13;
	int max_value_width = 14;
	int width;
	char *separator;
	struct ast_variable *objset;

	if (!context->output_buffer) {
		return -1;
	}

	objset = ast_sorcery_objectset_create(ast_sip_get_sorcery(),obj);
	if (!objset) {
		return -1;
	}

	for (i = objset; i; i = i->next) {
		if (i->name) {
			width = strlen(i->name);
			max_name_width = width > max_name_width ? width : max_name_width;
		}
		if (i->value) {
			width = strlen(i->value);
			max_value_width = width > max_value_width ? width : max_value_width;
		}
	}

	separator = ast_alloca(max_name_width + max_value_width + 8);

	memset(separator, '=', max_name_width + max_value_width + 3);
	separator[max_name_width + max_value_width + 3] = 0;

	ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, "ParameterName", "ParameterValue");
	ast_str_append(&context->output_buffer, 0, " %s\n", separator);

	objset = ast_variable_list_sort(objset);

	for (i = objset; i; i = i->next) {
		ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, i->name, i->value);
	}

	ast_variables_destroy(objset);

	return 0;
}
コード例 #12
0
static int sorcery_realtime_create(const struct ast_sorcery *sorcery, void *data, void *object)
{
	const char *family = data;
	RAII_VAR(struct ast_variable *, fields, ast_sorcery_objectset_create(sorcery, object), ast_variables_destroy);
	struct ast_variable *id = ast_variable_new(UUID_FIELD, ast_sorcery_object_get_id(object), "");

	if (!fields || !id) {
		ast_variables_destroy(id);
		return -1;
	}

	/* Place the identifier at the front for sanity sake */
	id->next = fields;
	fields = id;

	return (ast_store_realtime_fields(family, fields) <= 0) ? -1 : 0;
}
コード例 #13
0
ファイル: agent.c プロジェクト: xhook/asterisk-v11
static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
								   int exact, size_t *var_len, WriteMethod **write_method)
{
	static unsigned long long_ret;
	struct ast_variable *channel_types, *next;

	if (header_generic(vp, name, length, exact, var_len, write_method))
		return NULL;

	if (vp->magic != ASTCHANTYPECOUNT)
		return NULL;

	for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
		long_ret++;
	ast_variables_destroy(channel_types);

	return (u_char *)&long_ret;
}
コード例 #14
0
/*! \brief Helper function which converts a json object to a sorcery object set */
static struct ast_variable *sorcery_json_to_objectset(struct ast_json *json)
{
	struct ast_json_iter *field;
	struct ast_variable *objset = NULL;

	for (field = ast_json_object_iter(json); field; field = ast_json_object_iter_next(json, field)) {
		struct ast_json *value = ast_json_object_iter_value(field);
		struct ast_variable *variable = ast_variable_new(ast_json_object_iter_key(field), ast_json_string_get(value), "");

		if (!variable) {
			ast_variables_destroy(objset);
			return NULL;
		}

		variable->next = objset;
		objset = variable;
	}

	return objset;
}
コード例 #15
0
ファイル: res_sorcery_astdb.c プロジェクト: asterisk/asterisk
/*! \brief Internal helper function which returns a filtered objectset.
 *
 * The following are filtered out of the objectset:
 * \li Fields that are not registered with sorcery.
 *
 * \param objectset Objectset to filter.
 * \param sorcery The sorcery instance that is requesting an objectset.
 * \param type The object type
 *
 * \return The filtered objectset
 */
static struct ast_variable *sorcery_astdb_filter_objectset(struct ast_variable *objectset, const struct ast_sorcery *sorcery,
	const char *type)
{
	struct ast_variable *previous = NULL, *field = objectset;
	struct ast_sorcery_object_type *object_type;

	object_type = ast_sorcery_get_object_type(sorcery, type);
	if (!object_type) {
		ast_log(LOG_WARNING, "Unknown sorcery object type %s. Expect errors\n", type);
		return objectset;
	}

	while (field) {
		struct ast_variable *removed;

		if (ast_sorcery_is_object_field_registered(object_type, field->name)) {
			previous = field;
			field = field->next;
			continue;
		}

		ast_debug(1, "Filtering out astdb field '%s' from retrieval\n", field->name);

		if (previous) {
			previous->next = field->next;
		} else {
			objectset = field->next;
		}

		removed = field;
		field = field->next;
		removed->next = NULL;

		ast_variables_destroy(removed);
	}

	ao2_cleanup(object_type);

	return objectset;
}
コード例 #16
0
static void sorcery_realtime_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
{
	const char *family = data;
	RAII_VAR(struct ast_config *, rows, NULL, ast_config_destroy);
	RAII_VAR(struct ast_variable *, all, NULL, ast_variables_destroy);
	struct ast_category *row = NULL;

	if (!fields) {
		char field[strlen(UUID_FIELD) + 6], value[2];

		/* If no fields have been specified we want all rows, so trick realtime into doing it */
		snprintf(field, sizeof(field), "%s LIKE", UUID_FIELD);
		snprintf(value, sizeof(value), "%%");

		if (!(all = ast_variable_new(field, value, ""))) {
			return;
		}

		fields = all;
	}

	if (!(rows = ast_load_realtime_multientry_fields(family, fields))) {
		return;
	}

	while ((row = ast_category_browse_filtered(rows, NULL, row, NULL))) {
		struct ast_variable *objectset = ast_category_detach_variables(row);
		RAII_VAR(struct ast_variable *, id, NULL, ast_variables_destroy);
		RAII_VAR(void *, object, NULL, ao2_cleanup);

		objectset = sorcery_realtime_filter_objectset(objectset, &id, sorcery, type);

		if (id && (object = ast_sorcery_alloc(sorcery, type, id->value)) && !ast_sorcery_objectset_apply(sorcery, object, objectset)) {
			ao2_link(objects, object);
		}

		ast_variables_destroy(objectset);
	}
}
コード例 #17
0
static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
                                     int exact, size_t *var_len, WriteMethod **write_method)
{
    static unsigned long long_ret;
    struct ast_variable *channel_types, *next;

    if (header_generic(vp, name, length, exact, var_len, write_method))
        return NULL;

    switch (vp->magic) {
    case ASTCHANTYPECOUNT:
        long_ret = 0;
        for (channel_types = next = ast_channeltype_list(); next; next = next->next) {
            long_ret++;
        }
        ast_variables_destroy(channel_types);
        return (u_char *)&long_ret;
    default:
        break;
    }
    return NULL;
}
コード例 #18
0
/*!
 * \internal
 * \brief Completes SIPNotify AMI command in URI mode.
 */
static void manager_notify_uri(struct mansession *s,
	const struct message *m, const char *uri)
{
	struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);

	switch (push_notify_uri(uri, vars, notify_ami_uri_data_create)) {
	case INVALID_ENDPOINT:
		/* Shouldn't be possible. */
		ast_assert(0);
		break;
	case ALLOC_ERROR:
		ast_variables_destroy(vars);
		astman_send_error(s, m, "Unable to allocate NOTIFY task data");
		break;
	case TASK_PUSH_ERROR:
		/* Don't need to destroy vars since it is handled by cleanup in push_notify_uri */
		astman_send_error(s, m, "Unable to push Notify task");
		break;
	case SUCCESS:
		astman_send_ack(s, m, "NOTIFY sent");
		break;
	}
}
コード例 #19
0
ファイル: res_realtime.c プロジェクト: n02018222/asterisk
static char *cli_realtime_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 
{
#define CRL_HEADER_FORMAT "%30s  %-30s\n"
	struct ast_variable *var = NULL, *orig_var = NULL;

	switch (cmd) {
	case CLI_INIT:
		e->command = "realtime load";
		e->usage =
			"Usage: realtime load <family> <colmatch> <value>\n"
			"       Prints out a list of variables using the RealTime driver.\n"
			"       You must supply a family name, a column to match on, and a value to match to.\n";
		return NULL;
	case CLI_GENERATE:
		return NULL;
	}


	if (a->argc < 5) 
		return CLI_SHOWUSAGE;

	var = ast_load_realtime_all(a->argv[2], a->argv[3], a->argv[4], SENTINEL);

	if (var) {
		ast_cli(a->fd, CRL_HEADER_FORMAT, "Column Name", "Column Value");
		ast_cli(a->fd, CRL_HEADER_FORMAT, "--------------------", "--------------------");
		orig_var = var;
		while (var) {
			ast_cli(a->fd, CRL_HEADER_FORMAT, var->name, var->value);
			var = var->next;
		}
	} else {
		ast_cli(a->fd, "No rows found matching search criteria.\n");
	}
	ast_variables_destroy(orig_var);
	return CLI_SUCCESS;
}
コード例 #20
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
/*!
 * \internal
 * \brief Find an endpoint associated with the given contact.
 */
static struct ast_sip_endpoint *find_an_endpoint(struct ast_sip_contact *contact)
{
	struct ao2_container *endpoints;
	struct ast_sip_endpoint *endpoint;
	struct ast_variable *var;
	char *aor = ast_alloca(strlen(contact->aor) + 3);

	sprintf(aor, "%%%s%%", contact->aor);
	var = ast_variable_new("aors LIKE", aor, "");
	endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"endpoint", AST_RETRIEVE_FLAG_MULTIPLE, var);

	ast_variables_destroy(var);

	/*
	 * Because aors are a string list, we have to use a pattern match but since a simple
	 * pattern match could return an endpoint that has an aor of "aaabccc" when searching
	 * for "abc", we still have to iterate over them to find an exact aor match.
	 */
	endpoint = ao2_callback(endpoints, 0, on_endpoint, (char *)contact->aor);
	ao2_ref(endpoints, -1);

	return endpoint;
}
コード例 #21
0
ファイル: http.c プロジェクト: BackupTheBerlios/solid-pbx-svn
static void *ast_httpd_helper_thread(void *data)
{
	char buf[4096];
	char cookie[4096];
	char timebuf[256];
	struct ast_http_server_instance *ser = data;
	struct ast_variable *var, *prev=NULL, *vars=NULL;
	char *uri, *c, *title=NULL;
	char *vname, *vval;
	int status = 200, contentlength = 0;
	time_t t;

	if (fgets(buf, sizeof(buf), ser->f)) {
		/* Skip method */
		uri = buf;
		while(*uri && (*uri > 32))
			uri++;
		if (*uri) {
			*uri = '\0';
			uri++;
		}

		/* Skip white space */
		while (*uri && (*uri < 33))
			uri++;

		if (*uri) {
			c = uri;
			while (*c && (*c > 32))
				 c++;
			if (*c) {
				*c = '\0';
			}
		}

		while (fgets(cookie, sizeof(cookie), ser->f)) {
			/* Trim trailing characters */
			while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
				cookie[strlen(cookie) - 1] = '\0';
			}
			if (ast_strlen_zero(cookie))
				break;
			if (!strncasecmp(cookie, "Cookie: ", 8)) {
				vname = cookie + 8;
				vval = strchr(vname, '=');
				if (vval) {
					/* Ditch the = and the quotes */
					*vval = '\0';
					vval++;
					if (*vval)
						vval++;
					if (strlen(vval))
						vval[strlen(vval) - 1] = '\0';
					var = ast_variable_new(vname, vval);
					if (var) {
						if (prev)
							prev->next = var;
						else
							vars = var;
						prev = var;
					}
				}
			}
		}

		if (*uri) {
			if (!strcasecmp(buf, "get")) 
				c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
			else 
				c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
		} else 
			c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");

		/* If they aren't mopped up already, clean up the cookies */
		if (vars)
			ast_variables_destroy(vars);

		if (!c)
			c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
		if (c) {
			time(&t);
			strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
			ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
			ast_cli(ser->fd, "Server: Asterisk\r\n");
			ast_cli(ser->fd, "Date: %s\r\n", timebuf);
			ast_cli(ser->fd, "Connection: close\r\n");
			if (contentlength) {
				char *tmp;
				tmp = strstr(c, "\r\n\r\n");
				if (tmp) {
					ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
					write(ser->fd, c, (tmp + 4 - c));
					write(ser->fd, tmp + 4, contentlength);
				}
			} else
				ast_cli(ser->fd, "%s", c);
			free(c);
		}
		if (title)
			free(title);
	}
	fclose(ser->f);
	free(ser);
	return NULL;
}
コード例 #22
0
ファイル: res_http_post.c プロジェクト: cfhb/vlink-cti
static int http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
{
	struct ast_variable *var, *cookies;
	unsigned long ident = 0;
	FILE *f;
	int content_len = 0;
	struct ast_str *post_dir;
	GMimeMessage *message;
	int message_count = 0;
	char * boundary_marker = NULL;

	if (method != AST_HTTP_POST) {
		ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
		return -1;
	}

	if (!astman_is_authed(ast_http_manid_from_vars(headers))) {
		ast_http_error(ser, 403, "Access Denied", "Sorry, I cannot let you do that, Dave.");
		return -1;
	}

	if (!urih) {
		ast_http_error(ser, 400, "Missing URI handle", "There was an error parsing the request");
	        return -1;
	}

	cookies = ast_http_get_cookies(headers);
	for (var = cookies; var; var = var->next) {
		if (!strcasecmp(var->name, "mansession_id")) {
			sscanf(var->value, "%30lx", &ident);
			break;
		}
	}
	if (cookies) {
		ast_variables_destroy(cookies);
	}

	if (ident == 0) {
		ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request.");
		return -1;
	}
	if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
		ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request.");
		return -1;
	}

	if (!(f = tmpfile())) {
		ast_log(LOG_ERROR, "Could not create temp file.\n");
		ast_http_error(ser, 500, "Internal server error", "Could not create temp file.");
		return -1;
	}

	for (var = headers; var; var = var->next) {
		fprintf(f, "%s: %s\r\n", var->name, var->value);

		if (!strcasecmp(var->name, "Content-Length")) {
			if ((sscanf(var->value, "%30u", &content_len)) != 1) {
				ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n");
				fclose(f);
				ast_http_error(ser, 500, "Internal server error", "Invalid Content-Length in POST request!");
				return -1;
			}
			ast_debug(1, "Got a Content-Length of %d\n", content_len);
		} else if (!strcasecmp(var->name, "Content-Type")) {
			boundary_marker = strstr(var->value, "boundary=");
			if (boundary_marker) {
				boundary_marker += strlen("boundary=");
			}
		}
	}

	fprintf(f, "\r\n");

	if (0 > readmimefile(ser->f, f, boundary_marker, content_len)) {
		if (option_debug) {
			ast_log(LOG_DEBUG, "Cannot find boundary marker in POST request.\n");
		}
		fclose(f);

		return -1;
	}

	if (fseek(f, SEEK_SET, 0)) {
		ast_log(LOG_ERROR, "Failed to seek temp file back to beginning.\n");
		fclose(f);
		ast_http_error(ser, 500, "Internal server error", "Failed to seek temp file back to beginning.");
		return -1;
	}

	post_dir = urih->data;

	message = parse_message(f); /* Takes ownership and will close f */

	if (!message) {
		ast_log(LOG_ERROR, "Error parsing MIME data\n");

		ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request.");
		return -1;
	}

	if (!(message_count = process_message(message, ast_str_buffer(post_dir)))) {
		ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n");
		g_object_unref(message);
		ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request.");
		return -1;
	}
	g_object_unref(message);

	ast_http_error(ser, 200, "OK", "File successfully uploaded.");
	return 0;
}
コード例 #23
0
ファイル: resource_asterisk.c プロジェクト: GGGO/asterisk
void ast_ari_asterisk_update_object(struct ast_variable *headers, struct ast_ari_asterisk_update_object_args *args, struct ast_ari_response *response)
{
	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
	RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
	RAII_VAR(void *, sorcery_obj, NULL, ao2_cleanup);
	struct ast_json *fields;
	struct ast_variable *update_set = NULL;
	int created = 0;

	sorcery = ast_sorcery_retrieve_by_module_name(args->config_class);
	if (!sorcery) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"configClass '%s' not found",
			args->config_class);
		return;
	}

	object_type = ast_sorcery_get_object_type(sorcery, args->object_type);
	if (!object_type) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"objectType '%s' not found",
			args->object_type);
		return;
	}

	sorcery_obj = ast_sorcery_retrieve_by_id(sorcery, args->object_type, args->id);
	if (!sorcery_obj) {
		ast_debug(5, "Sorcery object '%s' does not exist; creating it\n", args->id);
		sorcery_obj = ast_sorcery_alloc(sorcery, args->object_type, args->id);
		if (!sorcery_obj) {
			ast_ari_response_alloc_failed(response);
			return;
		}

		created = 1;
	} else {
		void *copy;

		copy = ast_sorcery_copy(sorcery, sorcery_obj);
		if (!copy) {
			ast_ari_response_alloc_failed(response);
			return;
		}

		ao2_ref(sorcery_obj, -1);
		sorcery_obj = copy;
	}

	fields = ast_json_object_get(args->fields, "fields");
	if (!fields && !created) {
		/* Whoops. We need data. */
		ast_ari_response_error(
			response, 400, "Bad request",
			"Fields must be provided to update object '%s'",
			args->id);
		return;
	} else if (fields) {
		size_t i;

		for (i = 0; i < ast_json_array_size(fields); i++) {
			struct ast_variable *new_var;
			struct ast_json *json_value = ast_json_array_get(fields, i);

			if (!json_value) {
				continue;
			}

			new_var = ast_variable_new(
				ast_json_string_get(ast_json_object_get(json_value, "attribute")),
				ast_json_string_get(ast_json_object_get(json_value, "value")),
				"");
			if (!new_var) {
				ast_variables_destroy(update_set);
				ast_ari_response_alloc_failed(response);
				return;
			}
			ast_variable_list_append(&update_set, new_var);
		}
	}

	/* APPLY! Note that a NULL update_set is fine (and necessary), as it
	 * will force validation on a newly created object.
	 */
	if (ast_sorcery_objectset_apply(sorcery, sorcery_obj, update_set)) {
		ast_variables_destroy(update_set);
		ast_ari_response_error(
			response, 400, "Bad request",
			"%s of object '%s' failed field value validation",
			created ? "Creation" : "Update",
			args->id);
		return;
	}

	ast_variables_destroy(update_set);

	if (created) {
		if (ast_sorcery_create(sorcery, sorcery_obj)) {
			ast_ari_response_error(
				response, 403, "Forbidden",
				"Cannot create sorcery objects of type '%s'",
				args->object_type);
			return;
		}
	} else {
		if (ast_sorcery_update(sorcery, sorcery_obj)) {
			ast_ari_response_error(
				response, 403, "Forbidden",
				"Cannot update sorcery objects of type '%s'",
				args->object_type);
			return;
		}
	}

	return_sorcery_object(sorcery, sorcery_obj, response);
}
コード例 #24
0
static void *ast_httpd_helper_thread(void *data)
{
	char buf[4096];
	char cookie[4096];
	char timebuf[256];
	struct ast_http_server_instance *ser = data;
	struct ast_variable *vars = NULL;
	char *uri, *c, *title=NULL;
	int status = 200, contentlength = 0;
	time_t t;
	unsigned int static_content = 0;

	if (fgets(buf, sizeof(buf), ser->f)) {
		/* Skip method */
		uri = buf;
		while(*uri && (*uri > 32))
			uri++;
		if (*uri) {
			*uri = '\0';
			uri++;
		}

		/* Skip white space */
		while (*uri && (*uri < 33))
			uri++;

		if (*uri) {
			c = uri;
			while (*c && (*c > 32))
				 c++;
			if (*c) {
				*c = '\0';
			}
		}

		while (fgets(cookie, sizeof(cookie), ser->f)) {
			/* Trim trailing characters */
			while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
				cookie[strlen(cookie) - 1] = '\0';
			}
			if (ast_strlen_zero(cookie))
				break;
			if (!strncasecmp(cookie, "Cookie: ", 8)) {
				vars = parse_cookies(cookie);
			}
		}

		if (*uri) {
			if (!strcasecmp(buf, "get")) 
				c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
			else 
				c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
		} else 
			c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");

		/* If they aren't mopped up already, clean up the cookies */
		if (vars)
			ast_variables_destroy(vars);

		if (!c)
			c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
		if (c) {
			time(&t);
			strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
			ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
			ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION);
			ast_cli(ser->fd, "Date: %s\r\n", timebuf);
			ast_cli(ser->fd, "Connection: close\r\n");
			if (!static_content)
				ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n");
				/* We set the no-cache headers only for dynamic content.
				* If you want to make sure the static file you requested is not from cache,
				* append a random variable to your GET request.  Ex: 'something.html?r=109987734'
				*/

			if (contentlength) {
				char *tmp;
				tmp = strstr(c, "\r\n\r\n");
				if (tmp) {
					ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
					if (write(ser->fd, c, (tmp + 4 - c)) < 0) {
						ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
					}
					if (write(ser->fd, tmp + 4, contentlength) < 0) {
						ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
					}
				}
			} else
				ast_cli(ser->fd, "%s", c);
			free(c);
		}
		if (title)
			free(title);
	}
	fclose(ser->f);
	free(ser);
	ast_atomic_fetchadd_int(&session_count, -1);
	return NULL;
}
コード例 #25
0
static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, 
	char **title, int *contentlength, struct ast_variable **cookies, 
	unsigned int *static_content)
{
	char *c;
	char *turi;
	char *params;
	char *var;
	char *val;
	struct ast_http_uri *urih=NULL;
	int len;
	struct ast_variable *vars=NULL, *v, *prev = NULL;
	
	
	params = strchr(uri, '?');
	if (params) {
		*params = '\0';
		params++;
		while ((var = strsep(&params, "&"))) {
			val = strchr(var, '=');
			if (val) {
				*val = '\0';
				val++;
				ast_uri_decode(val);
			} else 
				val = "";
			ast_uri_decode(var);
			if ((v = ast_variable_new(var, val))) {
				if (vars)
					prev->next = v;
				else
					vars = v;
				prev = v;
			}
		}
	}
	if (prev)
		prev->next = *cookies;
	else
		vars = *cookies;
	*cookies = NULL;
	ast_uri_decode(uri);
	if (!strncasecmp(uri, prefix, prefix_len)) {
		uri += prefix_len;
		if (!*uri || (*uri == '/')) {
			if (*uri == '/')
				uri++;
			ast_rwlock_rdlock(&uris_lock);
			urih = uris;
			while(urih) {
				len = strlen(urih->uri);
				if (!strncasecmp(urih->uri, uri, len)) {
					if (!uri[len] || uri[len] == '/') {
						turi = uri + len;
						if (*turi == '/')
							turi++;
						if (!*turi || urih->has_subtree) {
							uri = turi;
							break;
						}
					}
				}
				urih = urih->next;
			}
			if (!urih)
				ast_rwlock_unlock(&uris_lock);
		}
	}
	if (urih) {
		if (urih->static_content)
			*static_content = 1;
		c = urih->callback(sin, uri, vars, status, title, contentlength);
		ast_rwlock_unlock(&uris_lock);
	} else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
		/* Special case: If no prefix, and no URI, send to /static/index.html */
		c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "Redirecting to /static/index.html.");
		*status = 302;
		*title = strdup("Moved Temporarily");
	} else {
		c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
		*status = 404;
		*title = strdup("Not Found");
	}
	ast_variables_destroy(vars);
	return c;
}