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 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 xpidf_generate_body_content(void *body, void *data)
{
	pjxpidf_pres *pres = body;
	struct ast_sip_exten_state_data *state_data = data;
	static pj_str_t STR_ADDR_PARAM = { ";user=ip", 8 };
	char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
	pj_xml_attr *attr;
	enum ast_sip_pidf_state local_state;
	pj_str_t uri;
	char sanitized[PJSIP_MAX_URL_SIZE];
	pj_xml_node *atom;
	pj_xml_node *address;
	pj_xml_node *status;
	pj_xml_node *msnsubstatus;

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

	ast_sip_presence_xml_find_node_attr(state_data->pool, pres, "atom", "id",
			&atom, &attr);
	pj_strdup2(state_data->pool, &attr->value, state_data->exten);

	ast_sip_presence_xml_find_node_attr(state_data->pool, atom, "address",
			"uri", &address, &attr);

	ast_sip_sanitize_xml(state_data->remote, sanitized, sizeof(sanitized));

	uri.ptr = (char*) pj_pool_alloc(state_data->pool,
			strlen(sanitized) + STR_ADDR_PARAM.slen);
	pj_strcpy2( &uri, sanitized);
	pj_strcat( &uri, &STR_ADDR_PARAM);
	pj_strdup(state_data->pool, &attr->value, &uri);

	ast_sip_presence_xml_create_attr(state_data->pool, address, "priority", "0.80000");

	ast_sip_presence_xml_find_node_attr(state_data->pool, address,
			"status", "status", &status, &attr);
	pj_strdup2(state_data->pool, &attr->value,
		   (local_state ==  NOTIFY_OPEN) ? "open" :
		   (local_state == NOTIFY_INUSE) ? "inuse" : "closed");

	ast_sip_presence_xml_find_node_attr(state_data->pool, address,
			"msnsubstatus", "substatus", &msnsubstatus, &attr);
	pj_strdup2(state_data->pool, &attr->value,
		   (local_state == NOTIFY_OPEN) ? "online" :
		   (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");

	return 0;
}