static int dialog_info_generate_body_content(void *body, void *data)
{
	pj_xml_node *dialog_info = body, *dialog, *state;
	struct ast_sip_exten_state_data *state_data = data;
	char *local = ast_strdupa(state_data->local), *stripped, *statestring = NULL;
	char *pidfstate = NULL, *pidfnote = NULL;
	enum ast_sip_pidf_state local_state;
	unsigned int version;
	char version_str[32], sanitized[PJSIP_MAX_URL_SIZE];

	if (!local || !state_data->datastores) {
		return -1;
	}

	if (dialog_info_xml_get_version(state_data->datastores, &version)) {
		ast_log(LOG_WARNING, "dialog-info+xml version could not be retrieved from datastore\n");
		return -1;
	}

	stripped = ast_strip_quoted(local, "<", ">");
	ast_sip_sanitize_xml(stripped, sanitized, sizeof(sanitized));

	ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring,
			&pidfstate, &pidfnote, &local_state);

	ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "xmlns", "urn:ietf:params:xml:ns:dialog-info");

	snprintf(version_str, sizeof(version_str), "%u", version);
	ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "version", version_str);

	ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "state", "full");
	ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "entity", sanitized);

	dialog = ast_sip_presence_xml_create_node(state_data->pool, dialog_info, "dialog");
	ast_sip_presence_xml_create_attr(state_data->pool, dialog, "id", state_data->exten);
	if (state_data->exten_state == AST_EXTENSION_RINGING) {
		ast_sip_presence_xml_create_attr(state_data->pool, dialog, "direction", "recipient");
	}

	state = ast_sip_presence_xml_create_node(state_data->pool, dialog, "state");
	pj_strdup2(state_data->pool, &state->content, statestring);

	if (state_data->exten_state == AST_EXTENSION_ONHOLD) {
		pj_xml_node *local_node, *target, *param;

		local_node = ast_sip_presence_xml_create_node(state_data->pool, dialog, "local");
		target = ast_sip_presence_xml_create_node(state_data->pool, local_node, "target");
		ast_sip_presence_xml_create_attr(state_data->pool, target, "uri", sanitized);
		param = ast_sip_presence_xml_create_node(state_data->pool, target, "param");
		ast_sip_presence_xml_create_attr(state_data->pool, param, "pname", "+sip.rendering");
		ast_sip_presence_xml_create_attr(state_data->pool, param, "pvalue", "no");
	}

	return 0;
}
static int pidf_supplement_body(void *body, void *data)
{
	struct ast_sip_exten_state_data *state_data = data;
	pj_xml_node *node;
	char sanitized[1024];

	if (ast_strlen_zero(state_data->user_agent) ||
	    !strstr(state_data->user_agent, "digium")) {
		/* not a digium phone */
		return 0;
	}

	if (!(node = ast_sip_presence_xml_create_node(
		      state_data->pool, body, "tuple"))) {
		ast_log(LOG_WARNING, "Unable to create PIDF tuple\n");
		return -1;
	}

	ast_sip_presence_xml_create_attr(
		state_data->pool, node, "id", "digium-presence");

	if (!(node = ast_sip_presence_xml_create_node(
		      state_data->pool, node, "status"))) {
		ast_log(LOG_WARNING, "Unable to create PIDF tuple status\n");
		return -1;
	}

	if (!(node = ast_sip_presence_xml_create_node(
		      state_data->pool, node, "digium_presence"))) {
		ast_log(LOG_WARNING, "Unable to create digium presence\n");
		return -1;
	}

	if (!ast_strlen_zero(state_data->presence_message)) {
		ast_sip_sanitize_xml(state_data->presence_message, sanitized, sizeof(sanitized));
		pj_strdup2(state_data->pool, &node->content, sanitized);
	}

	ast_sip_presence_xml_create_attr(
		state_data->pool, node, "type", ast_presence_state2str(
			state_data->presence_state));

	if (!ast_strlen_zero(state_data->presence_subtype)) {
		ast_sip_sanitize_xml(state_data->presence_subtype, sanitized, sizeof(sanitized));
		ast_sip_presence_xml_create_attr(
			state_data->pool, node, "subtype", sanitized);
	}

	return 0;
}
static void *dialog_info_allocate_body(void *data)
{
	struct ast_sip_exten_state_data *state_data = data;

	return ast_sip_presence_xml_create_node(state_data->pool, NULL, "dialog-info");
}