/*******************************************************************************
 * Copyright (C) 2004-2006 Intel Corp. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  - Neither the name of Intel Corp. nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

/**
 * @author Anas Nashif
 * @author Liang Hou
 * Contributions from:
 * @author Sumeet Kukreja, Dell Inc.
 */

#ifdef HAVE_CONFIG_H
#include "wsman_config.h"
#endif

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"

#include "u/libu.h"


#include "wsman-xml-api.h"
#include "wsman-soap.h"
#include "wsman-xml.h"
#include "wsman-client-api.h"
#include "wsman-xml-serializer.h"

#include "wsman-soap-envelope.h"
#include "wsman-soap-message.h"
#include "sfcc-interface.h"
#include "cim_data.h"


static void
CimResource_destroy(CimClientInfo *cimclient)
{
	if (!cimclient)
		return;
	if (cimclient->resource_uri)
		u_free(cimclient->resource_uri);
	if (cimclient->method)
		u_free(cimclient->method);
	if (cimclient->requested_class)
		u_free(cimclient->requested_class);
	if (cimclient->method_args) {
		/* NOTE: clean up is performed with call to wsman_free_method_hnode() and hash_free() */
		hash_free(cimclient->method_args);
	}
	if (cimclient->selectors) {
		hash_free(cimclient->selectors);
		debug("selectors destroyed");
	}
	if (cimclient->username)
		u_free(cimclient->username);
	if (cimclient->password)
		u_free(cimclient->password);
	cim_release_client(cimclient);
	u_free(cimclient);
	debug("cimclient destroyed");
	return;
}




static CimClientInfo*
CimResource_Init(WsContextH cntx, char *username, char *password)
{
	char *_tmp = NULL;
	char *resource_uri = NULL;
	char *show_extensions;
	char *exclude_nil_properties;
	CimClientInfo *cimclient= (CimClientInfo *)u_zalloc(sizeof(CimClientInfo));
	if(!cimclient){
		return NULL;
	}
	WsmanStatus status;

	wsman_status_init(&status);
	resource_uri = wsman_get_resource_uri(cntx, NULL);
	debug ("username: %s, password: %s", username, (password)?"XXXXX":"Not Set" );

	debug("Connecting using sfcc %s frontend", get_cim_client_frontend());

	cimclient->cc = (void *)cim_connect_to_cimom(get_cim_host(),
			get_cim_port(), username, password , get_cim_client_frontend(), &status);

	if (!cimclient->cc) {
		CimResource_destroy(cimclient);
		u_free(status.fault_msg);
		return NULL;
	}

	cimclient->cntx = cntx;
	cimclient->namespaces = get_vendor_namespaces();
	cimclient->selectors = wsman_get_selector_list(cntx, NULL);

	cimclient->requested_class = wsman_get_class_name(cntx);

	cimclient->method = wsman_get_method_name(cntx);
	if(username) {
		cimclient->username = u_strdup(username);
	}
	if(password) {
		cimclient->password = u_strdup(password);
	}

	if (cimclient->selectors) {
		_tmp = cim_get_namespace_selector(cimclient->selectors);
	}
	if (_tmp) {
		cimclient->cim_namespace = _tmp;
	} else {
		cimclient->cim_namespace = get_cim_namespace();
	}
	if(resource_uri) {
		cimclient->resource_uri = u_strdup(resource_uri);
		cimclient->method_args = wsman_get_method_args(cntx, resource_uri );
	}
	show_extensions = wsman_get_option_set(cntx, NULL, WSMB_SHOW_EXTENSION );

	if (show_extensions && strcmp(show_extensions, "true") == 0) {
		cimclient->flags |= FLAG_CIM_EXTENSIONS;
	}
	
	exclude_nil_properties = wsman_get_option_set(cntx, NULL, WSMB_EXCLUDE_NIL_PROPS);
	if (exclude_nil_properties && strcmp(exclude_nil_properties, "true") == 0) {
		cimclient->flags |= FLAG_CIM_SCHEMA_OPT;
	}
	if (get_omit_schema_optional() == 1) {
		cimclient->flags |= FLAG_CIM_SCHEMA_OPT;
	}

	u_free(show_extensions);
	u_free(status.fault_msg);
	return cimclient;
}

static int
verify_class_namespace(CimClientInfo *client)
{
	hscan_t hs;
	hnode_t *hn;
	int rv = 0;
	if (!client) {
		return 0;
	}
        if (!client->resource_uri) {
          return 0;
        }
	if (strcmp( client->resource_uri, CIM_ALL_AVAILABLE_CLASSES ) == 0 ) {
		return 1;
	}
        if (strstr( client->resource_uri, XML_NS_CIM_INTRINSIC ) != NULL ) {
	        return 1;
	}
  
        /* Ok if class schema is CIM, uri starts with XML_NS_CIM_CLASS
         * and method is not 'Create' (CIM_ is abstract, cannot be created)
         */
	if (client->requested_class && client->method
            && (strncmp(client->requested_class, "CIM_", 4) == 0 )
	    && (strstr(client->resource_uri , XML_NS_CIM_CLASS) == client->resource_uri )
	    && (strcmp(client->method, TRANSFER_CREATE) != 0)) {
		return 1;
	}

	if (client->requested_class && client->namespaces) {
		hash_scan_begin(&hs, client->namespaces);
		while ((hn = hash_scan_next(&hs))) {
			if ( ( strstr(client->requested_class,
							(char*) hnode_getkey(hn)) != NULL) &&
					(strstr(client->resource_uri ,
						(char*) hnode_get(hn) ) != NULL) ) {
				rv = 1;
				break;
			}
		}
	}
	return rv;
}




int
CimResource_Delete_EP( SoapOpH op,
		void* appData,
		void *opaqueData )
{
	WsmanStatus status;
	CimClientInfo *cimclient = NULL;
	SoapH soap = soap_get_op_soap(op);
	WsmanMessage *msg = wsman_get_msg_from_op(op);
	WsXmlDocH in_doc = NULL;
	WsXmlDocH doc = NULL;
	WsContextH cntx;
	debug( "Delete Endpoint Called");
	wsman_status_init(&status);

	in_doc = soap_get_op_doc(op, 1);
	cntx = ws_create_ep_context(soap, in_doc);

	if (!msg) {
		status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status.fault_detail_code=0;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			msg->auth_data.username,
			msg->auth_data.password );
	if (!cimclient) {
		status.fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status.fault_detail_code = 0;
		goto cleanup;
	}

	if (!verify_class_namespace(cimclient) ) {
		status.fault_code = WSA_DESTINATION_UNREACHABLE;
		status.fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
	} else if ( (doc = wsman_create_response_envelope( in_doc, NULL)) ) {
		if (strstr(cimclient->resource_uri , XML_NS_CIM_CLASS ) != NULL) {
			cim_delete_instance_from_enum(cimclient, &status);
		} else {
			debug("no base class, getting instance directly with getInstance");
			cim_delete_instance(cimclient, &status);
		}
	}
cleanup:
	if (wsman_check_status(&status) != 0) {
		ws_xml_destroy_doc(doc);
		doc = wsman_generate_fault( soap_get_op_doc(op, 1),
				status.fault_code, status.fault_detail_code, status.fault_msg);
	}
	if (doc) {
		soap_set_op_doc(op, doc, 0);
	} else {
		error("Invalid doc");
	}

	CimResource_destroy(cimclient);
	ws_destroy_context(cntx);
	u_free(status.fault_msg);
	return 0;
}

int
CimResource_Get_EP( SoapOpH op,
		void* appData,
		void *opaqueData )
{
	WsXmlDocH doc = NULL;
	WsmanStatus status;
	CimClientInfo *cimclient = NULL;
	char *fragstr = NULL;
	WsmanMessage *msg = wsman_get_msg_from_op(op);
	SoapH soap = soap_get_op_soap(op);

	WsXmlDocH in_doc = soap_get_op_doc(op, 1);
	WsContextH cntx = ws_create_ep_context(soap, in_doc);

	wsman_status_init(&status);
	if (!msg) {
		status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status.fault_detail_code=0;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			msg->auth_data.username,
			msg->auth_data.password );
	if (!cimclient) {
		status.fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status.fault_detail_code = 0;
		goto cleanup;
	}
	if (!verify_class_namespace(cimclient) ) {
		status.fault_code = WSA_DESTINATION_UNREACHABLE;
		status.fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
	} else {
		if ( (doc = wsman_create_response_envelope( in_doc, NULL)) ) {
			WsXmlNodeH body = ws_xml_get_soap_body(doc);
			fragstr = wsman_get_fragment_string(cntx, in_doc);
			if(fragstr)
				body = ws_xml_add_child(body, XML_NS_WS_MAN, WSM_XML_FRAGMENT,
				NULL);
			if (strstr(cimclient->resource_uri , XML_NS_CIM_CLASS ) != NULL) {
				cim_get_instance_from_enum(cimclient, cntx, body, fragstr, &status);
			} else {
				debug("no base class, getting instance directly with getInstance");
				cim_get_instance(cimclient, cntx, body, fragstr, &status);
			}
		}
	}
cleanup:
	if (wsman_check_status(&status) != 0) {
		ws_xml_destroy_doc(doc);
		doc = wsman_generate_fault( soap_get_op_doc(op, 1),
				status.fault_code, status.fault_detail_code, status.fault_msg);
	}
	if ( doc ) {
		soap_set_op_doc(op, doc, 0);
	} else {
		debug( "Invalid doc" );
	}

	CimResource_destroy(cimclient);
	ws_destroy_context(cntx);
	u_free(status.fault_msg);
	return 0;
}

int
CimResource_Custom_EP( SoapOpH op,
		void* appData,
		void *opaqueData )
{
	debug( "Custom Method Endpoint Called");
	WsXmlDocH doc = NULL, in_doc = NULL;
	CimClientInfo *cimclient = NULL;
	WsmanStatus status;
	WsmanMessage *msg = NULL;
	char *action;
	WsContextH cntx;

	wsman_status_init(&status);
	in_doc = soap_get_op_doc(op, 1);
	cntx = ws_create_ep_context(soap_get_op_soap(op), in_doc);

	msg = wsman_get_msg_from_op(op);
	action = wsman_get_action(cntx, in_doc );
	if (!msg) {
		status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status.fault_detail_code=0;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx, msg->auth_data.username,
			msg->auth_data.password);
	if (!cimclient) {
		status.fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status.fault_detail_code = 0;
		goto cleanup;
	}
	if (action && cimclient->resource_uri &&
			!strstr(action, cimclient->resource_uri)) {
		status.fault_code = WSA_ACTION_NOT_SUPPORTED;
		status.fault_detail_code = OWSMAN_NO_DETAILS;
		debug("action not supported");
		goto cleanup;
	}
	if (!verify_class_namespace(cimclient) ) {
		status.fault_code = WSA_DESTINATION_UNREACHABLE;
		status.fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
	} else {

		if ((doc = wsman_create_response_envelope( in_doc, NULL))) {
			WsXmlNodeH body = ws_xml_get_soap_body(doc);
			cim_invoke_method(cimclient, cntx, body, &status);
		}
	}

cleanup:
	if (wsman_check_status(&status) != 0) {
		ws_xml_destroy_doc(doc);
		doc = wsman_generate_fault( in_doc,
				status.fault_code, status.fault_detail_code, status.fault_msg);
	}
	if (doc) {
		soap_set_op_doc(op, doc, 0);
	} else {
		error("Invalid doc");
	}

	ws_destroy_context(cntx);
	CimResource_destroy(cimclient);
	u_free(status.fault_msg);
	return 0;
}




int
CimResource_Enumerate_EP( WsContextH cntx,
		WsEnumerateInfo* enumInfo,
		WsmanStatus *status,
		void *opaqueData)
{
	debug("CIM Enumeration");
	WsXmlDocH doc;
	int retval = 0;

	CimClientInfo *cimclient = NULL;

	if (!enumInfo) {
		status->fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status->fault_detail_code = 0;
		retval = 1;
		goto cleanup;
	}

	cimclient = CimResource_Init(cntx,
			enumInfo->auth_data.username,
			enumInfo->auth_data.password );
	if (!cimclient) {
		status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status->fault_detail_code = 0;
		retval = 1;
		goto cleanup;
	}

	if (!verify_class_namespace(cimclient)) {
		error("resource uri namespace mismatch");
		status->fault_code = WSA_DESTINATION_UNREACHABLE;
		status->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
		retval = 1;
		goto cleanup;
	}

	if (!wsman_parse_enum_request(cntx, enumInfo, status)) {
          retval = 1;
          goto cleanup;
        }
	cim_enum_instances(cimclient, enumInfo, status);

	if (status && status->fault_code != 0) {
		retval = 1;
		goto cleanup;
	}
	if (enumInfo->flags & WSMAN_ENUMINFO_OPT) {
		doc = wsman_create_response_envelope( cntx->indoc , NULL);
		WsXmlNodeH node = ws_xml_add_child(ws_xml_get_soap_body(doc),
				XML_NS_ENUMERATION, WSENUM_ENUMERATE_RESP , NULL);
		cim_get_enum_items(cimclient, cntx, node,
				enumInfo, XML_NS_WS_MAN, enumInfo->maxItems,
				enumInfo->maxsize);
		int index2 = enumInfo->index + 1;
		if (enumInfo->totalItems == 0 ||index2 == enumInfo->totalItems)  {
			cim_release_enum_context(enumInfo);
			CimResource_destroy(cimclient);
			return retval;
		}
	}
cleanup:
	/* the cimclient is stored inside the enumInfo and kept in-memory
	 * during the Pull_EP requests until the final Release_EP call.
	 * 
	 * Only destroy it here in case of error
	 * 
	 */
	if (retval && cimclient) {
		CimResource_destroy(cimclient);
	}
	else if(cimclient && cimclient->selectors) {
		hash_free(cimclient->selectors);
		cimclient->selectors = NULL;
		debug("selectors destroyed");
	}
	return retval;
}


int
CimResource_Release_EP( WsContextH cntx,
		WsEnumerateInfo* enumInfo,
		WsmanStatus *status,
		void *opaqueData)
{
	debug( "Release Endpoint Called");
	if(enumInfo->flags & WSMAN_ENUMINFO_CIM_CONTEXT_CLEANUP)
		return 0;
	CimClientInfo * cimclient = cim_getclient_from_enum_context(enumInfo);
	cim_release_enum_context(enumInfo);
	if (cimclient) {
		CimResource_destroy(cimclient);
	}
	return 0;
}


int
CimResource_Pull_EP( WsContextH cntx,
		WsEnumerateInfo* enumInfo,
		WsmanStatus *status,
		void *opaqueData)
{

	WsXmlDocH doc = NULL;
	CimClientInfo *cimclient = NULL;
	WsXmlNodeH body, pullnode;
	int maxelements;
	unsigned long maxsize;
	debug( "Pull Endpoint Called");

	if (!enumInfo) {
		status->fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status->fault_detail_code=0;
		doc = wsman_generate_fault( cntx->indoc, status->fault_code,
			status->fault_detail_code, NULL);
		goto cleanup;
	}

	cimclient = cim_getclient_from_enum_context(enumInfo);
	if (!cimclient) {
		status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status->fault_detail_code = 0;
		doc = wsman_generate_fault( cntx->indoc, status->fault_code,
			status->fault_detail_code, NULL);
		goto cleanup;
	}
	cimclient->cntx = cntx;

	if (!verify_class_namespace(cimclient) ) {
		status->fault_code = WSA_DESTINATION_UNREACHABLE;
		status->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
		doc = wsman_generate_fault( cntx->indoc, status->fault_code,
				status->fault_detail_code, NULL);
		goto cleanup;
	}

	doc = wsman_create_response_envelope( cntx->indoc, NULL);
	body = ws_xml_get_soap_body(doc);
	pullnode = ws_xml_add_child(body, XML_NS_ENUMERATION,
			WSENUM_PULL_RESP, NULL);

	maxelements= wsman_get_max_elements(cntx, NULL);
	maxsize = wsman_get_max_envelope_size(cntx, NULL);
	if(maxsize == 0) {
		body = ws_xml_get_soap_body(cntx->indoc);
		body = ws_xml_get_child(body, 0, XML_NS_ENUMERATION, WSENUM_PULL);
		maxsize = ws_deserialize_uint32(NULL, body,
					     0, XML_NS_ENUMERATION,
					     WSENUM_MAX_CHARACTERS);
	}
	cim_get_enum_items(cimclient, cntx, pullnode,
			enumInfo, XML_NS_ENUMERATION,  maxelements, maxsize);

cleanup:
	if ( enumInfo->totalItems == 0 ||
		( enumInfo->index + 1 ) == enumInfo->totalItems) {
		cim_release_enum_context(enumInfo);
		if (cimclient) {
			CimResource_destroy(cimclient);
		}
		enumInfo->flags |= WSMAN_ENUMINFO_CIM_CONTEXT_CLEANUP;
	}

	ws_destroy_context(cntx);
	return 0;
}

int
CimResource_Create_EP( SoapOpH op,
		void* appData,
		void *opaqueData )
{

	WsXmlDocH doc = NULL;
	CimClientInfo *cimclient = NULL;
	WsmanStatus status;
	char *fragstr = NULL;

	SoapH soap = soap_get_op_soap(op);
	WsContextH cntx = ws_create_ep_context(soap, soap_get_op_doc(op, 1));
	WsmanMessage *msg = wsman_get_msg_from_op(op);
	debug( "Create Endpoint Called");
	wsman_status_init(&status);

	if (!msg) {
		status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status.fault_detail_code=0;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			msg->auth_data.username, msg->auth_data.password );
	if (!cimclient) {
		status.fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status.fault_detail_code = 0;
		goto cleanup;
	}
	if (!verify_class_namespace(cimclient) ) {
		status.fault_code = WSA_DESTINATION_UNREACHABLE;
		status.fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
		goto cleanup;
	}

	if ((doc = wsman_create_response_envelope( soap_get_op_doc(op, 1), NULL))) {
		WsXmlNodeH body = ws_xml_get_soap_body(doc);
		WsXmlNodeH in_body = ws_xml_get_soap_body(soap_get_op_doc(op, 1));
		if (!ws_xml_get_child(in_body, 0, NULL, NULL)) {
			status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
			status.fault_detail_code = 0;
		} else {
			char *xsd = u_strdup_printf("%s.xsd", cimclient->resource_uri);
			fragstr = wsman_get_fragment_string(cntx, cntx->indoc);
			if(fragstr) {
				if(ws_xml_get_child(in_body, 0, XML_NS_WS_MAN, WSM_XML_FRAGMENT))
					cim_create_instance(cimclient, cntx, in_body, body, fragstr, &status);
			}
			else {
				if (ws_xml_get_child(in_body, 0, cimclient->resource_uri, cimclient->requested_class)) {
					cim_create_instance(cimclient, cntx , in_body, body, NULL, &status);
				} else if (ws_xml_get_child(in_body, 0, xsd, cimclient->requested_class)) {
					cim_create_instance(cimclient, cntx , in_body, body, NULL, &status);
				} else {
					status.fault_code = WXF_INVALID_REPRESENTATION;
					status.fault_detail_code = WSMAN_DETAIL_INVALID_NAMESPACE;
				}
			}
			u_free(xsd);
		}
	}

cleanup:
	if (wsman_check_status(&status) != 0) {
		ws_xml_destroy_doc(doc);
		doc = wsman_generate_fault( soap_get_op_doc(op, 1),
				status.fault_code, status.fault_detail_code, status.fault_msg);
	}

	if ( doc ) {
		soap_set_op_doc(op, doc, 0);
	} else {
		debug( "Invalid doc" );
	}

	CimResource_destroy(cimclient);
	ws_destroy_context(cntx);
	u_free(status.fault_msg);
	return 0;
}



int
CimResource_Put_EP( SoapOpH op,
		void* appData,
		void *opaqueData )
{
	debug( "Put Endpoint Called");
	WsXmlDocH doc = NULL;
	CimClientInfo *cimclient = NULL;
	WsmanStatus status;
	WsmanMessage *msg;
	char *fragstr;

	SoapH soap = soap_get_op_soap(op);
	WsContextH cntx = ws_create_ep_context(soap, soap_get_op_doc(op, 1));
	WsXmlDocH indoc = soap_get_op_doc(op, 1);

	wsman_status_init(&status);
	msg = wsman_get_msg_from_op(op);

	if (!msg) {
		status.fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status.fault_detail_code=0;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			msg->auth_data.username, msg->auth_data.password );
	if (!cimclient) {
		status.fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status.fault_detail_code = 0;
		goto cleanup;
	}

	if (!verify_class_namespace(cimclient) ) {
		status.fault_code = WSA_DESTINATION_UNREACHABLE;
		status.fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
	}

	if ((doc = wsman_create_response_envelope( indoc, NULL))) {
		WsXmlNodeH body = ws_xml_get_soap_body(doc);
		WsXmlNodeH in_body = ws_xml_get_soap_body(indoc);
		fragstr = wsman_get_fragment_string(cntx, indoc);
		if(fragstr)
			body = ws_xml_add_child(body, XML_NS_WS_MAN, WSM_XML_FRAGMENT,
			NULL);
		if (ws_xml_get_child(in_body, 0, NULL, NULL)) {
			cim_put_instance(cimclient, cntx , in_body, body, fragstr, &status);
		} else {
			status.fault_code = WXF_INVALID_REPRESENTATION;
			status.fault_detail_code = WSMAN_DETAIL_MISSING_VALUES;
		}
	}

cleanup:
	if (wsman_check_status(&status) != 0) {
		ws_xml_destroy_doc(doc);
		doc = wsman_generate_fault( indoc,
				status.fault_code, status.fault_detail_code, status.fault_msg);
	}

	if ( doc ) {
		soap_set_op_doc(op, doc, 0);
	} else {
		debug( "Invalid doc" );
	}

	CimResource_destroy(cimclient);
	ws_destroy_context(cntx);
	u_free(status.fault_msg);
	return 0;
}
#ifdef ENABLE_EVENTING_SUPPORT
int
CimResource_EventPoll_EP(WsEventThreadContextH cntx)
{
	int retval = 0;
	return retval;
}

int
CimResource_Subscribe_EP(WsContextH cntx,
		WsSubscribeInfo* subsInfo,
		WsmanStatus *status,
		void *opaqueData)
{
	debug("CIM Subscription");
	int retval = 0;
	CimClientInfo *cimclient = NULL;
	CMPIInstance *instance = NULL;
	CMPIObjectPath *indicationfilter = NULL;
	CMPIObjectPath *indicationhandler = NULL;
	CMPIObjectPath *indicationsubscription = NULL;
	if (!subsInfo) {
		status->fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status->fault_detail_code=0;
		retval = 1;
		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			subsInfo->auth_data.username,
			subsInfo->auth_data.password );
	if (!cimclient) {
		status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status->fault_detail_code = 0;
		retval = 1;
		goto cleanup;
	}

	if (!verify_class_namespace(cimclient)) {
		error("resource uri namespace mismatch");
		status->fault_code = WSA_DESTINATION_UNREACHABLE;
		status->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
		retval = 1;
		goto cleanup;
	}
// to do here: create indication filter here and something else necessary
	subsInfo->eventpoll= CimResource_EventPoll_EP;
	subsInfo->cancel = CimResource_SubscriptionCancel_EP;
	subsInfo->vendor_namespaces = cimclient->namespaces;
	subsInfo->cim_namespace = u_strdup(cimclient->cim_namespace);
	if(subsInfo->flags & WSMAN_SUBSCRIPTION_SELECTORSET) { //Subscribe to an Indication filter instance
		indicationfilter = cim_get_indicationfilter_objectpath_from_selectors(cimclient, cntx, status);
		if(indicationfilter)
			subsInfo->existingfilterOP = CMClone(indicationfilter, NULL);
		else {
			status->fault_code = WSA_DESTINATION_UNREACHABLE;
			status->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
		}

		debug("subscribe to an existing filter");
	}
	else {
		indicationfilter = cim_create_indication_filter(cimclient, subsInfo, status);
	}
	if(status->fault_code ) {
		retval = 1;
		goto cleanup;
	}

	indicationhandler = cim_create_indication_handler(cimclient, subsInfo, status);
	if(status->fault_code) {
		retval = 1;
		goto cleanup;
	}
	cim_create_indication_subscription(cimclient, subsInfo,
		indicationfilter, indicationhandler, status);
	if(status->fault_code)
		retval = 1;
cleanup:
	if(instance)
		CMRelease(instance);
	if(indicationfilter)
		CMRelease(indicationfilter);
	if(indicationhandler)
		CMRelease(indicationhandler);
	if(indicationsubscription)
		CMRelease(indicationsubscription);
	CimResource_destroy(cimclient);
	return retval;
}

int CimResource_Renew_EP(WsContextH cntx,
		WsSubscribeInfo* subsInfo,
		WsmanStatus *status,
		void *opaqueData)
{
	debug("CIM Renew");
	int retval = 0;
	CimClientInfo *cimclient = NULL;
	if (!subsInfo) {
		status->fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status->fault_detail_code=0;
		retval = 1;
 		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			subsInfo->auth_data.username,
			subsInfo->auth_data.password );
	if (!cimclient) {
		status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status->fault_detail_code = 0;
		retval = 1;
		goto cleanup;
	}
	cim_update_indication_subscription(cimclient, subsInfo, status);
	if(status->fault_code)
		retval = 1;
	CimResource_destroy(cimclient);
cleanup:
	return retval;
}

int CimResource_UnSubscribe_EP(WsContextH cntx,
		WsSubscribeInfo* subsInfo,
		WsmanStatus *status,
		void *opaqueData)
{
	debug("CIM UnSubscribe");
	int retval = 0;
	CimClientInfo *cimclient = NULL;
	if (!subsInfo) {
		status->fault_code = WSMAN_SCHEMA_VALIDATION_ERROR;
		status->fault_detail_code=0;
		retval = 1;
 		goto cleanup;
	}
	cimclient = CimResource_Init(cntx,
			subsInfo->auth_data.username,
			subsInfo->auth_data.password );
	if (!cimclient) {
		status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
		status->fault_detail_code = 0;
		retval = 1;
 		goto cleanup;
	}
	cim_delete_indication_subscription(cimclient, subsInfo, status);
	if(status->fault_code)
		retval = 1;
	CimResource_destroy(cimclient);
cleanup:
	return retval;
}

int CimResource_SubscriptionCancel_EP(WsEventThreadContextH cntx)
{
	WsmanStatus status;
	return CimResource_UnSubscribe_EP(cntx->soap->cntx, cntx->subsInfo, &status, NULL);
}
#endif
