//----------------------------------------------------------------------------
//
//  Copyright (C) Intel Corporation, 2007.
//            (C) Red Hat, Inc, 2015.
//
//  File:       OpenWsmanClient.cpp
//
//  Contents:   An implementation of the WsmanClient interface using openwsman
//
//----------------------------------------------------------------------------

#include "OpenWsmanClient.h"


extern "C" {
#include "u/libu.h"
#include "wsman-api.h"
}

#include "wsman-client-transport.h"

#define WSMAN_ENCODING		"UTF-8"

using namespace WsmanClientNamespace;

static bool CheckWsmanResponse(WsManClient* cl, WsXmlDocH& doc);
static bool ResourceNotFound(WsManClient* cl, WsXmlDocH& enumerationRes);
static string XmlDocToString(WsXmlDocH& doc);
static client_opt_t *SetOptions(WsManClient* cl);
static string GetSubscribeContext(WsXmlDocH& doc);
static string ExtractPayload(WsXmlDocH& doc);
static string ExtractItems(WsXmlDocH& doc);

// Construct from params.

OpenWsmanClient::OpenWsmanClient(
	const string &host,
	const int port,
	const string &path,
	const string &scheme,
	const string &auth_method,
	const string &username,
	const string &password,
	 // proxy address include proxy port
	const string &proxy,
	//proxy user name
	const string &proxy_username,
	//proxy password
	const string &proxy_password
#ifdef _WIN32
	// determines which cert store to search
	,const bool local,
	// search for a client cert with this name
	const string &cert,
	// search for a cient cert with this oid
	const string &oid
#endif
)
{
	cl = wsmc_create(
		host.c_str(),
		port,
		path.c_str(),
		scheme.c_str(),
		username.c_str(),
		password.c_str());
	SetAuth(auth_method);
#ifdef _WIN32
	SetClientCert(oid, cert, local);
#endif
	SetProxy(proxy.c_str(), proxy_username, proxy_password);
	wsmc_transport_init(cl, (void*)NULL);
}

// Destructor.
OpenWsmanClient::~OpenWsmanClient()
{
	wsmc_transport_fini(cl);
	wsmc_release(cl);
}

string OpenWsmanClient::Identify() const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());

	WsXmlDocH identifyResponse = wsmc_action_identify(cl, options);
	CheckWsmanResponse(cl, identifyResponse);
	string xml = ExtractPayload(identifyResponse);
	ws_xml_destroy_doc(identifyResponse);
	return xml;
}

string OpenWsmanClient::Create(const string &resourceUri, const string &data) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());

	WsXmlDocH createResponse = wsmc_action_create_fromtext(cl,
			resourceUri.c_str(),
			options,
			data.c_str(), data.length(), WSMAN_ENCODING);
	CheckWsmanResponse(cl, createResponse);
	string xml = ExtractPayload(createResponse);
	ws_xml_destroy_doc(createResponse);
	return xml;
}

void OpenWsmanClient::Delete(const string &resourceUri, const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	WsXmlDocH deleteResponse = wsmc_action_delete(cl,
			resourceUri.c_str(),
			options);
	CheckWsmanResponse(cl, deleteResponse);
	ws_xml_destroy_doc(deleteResponse);
}

void OpenWsmanClient::Enumerate(
	const string &resourceUri,
	vector<string> &enumRes,
	const WsmanOptions &options,
	const WsmanFilter &filter) const
{
	WsXmlDocH doc;
	char *enumContext;
	WsXmlDocH enum_response = wsmc_action_enumerate(cl, (char *)resourceUri.c_str(),  options, filter);

	if(ResourceNotFound(cl, enum_response))
		throw WsmanResourceNotFound(resourceUri.c_str());

	enumContext = wsmc_get_enum_context(enum_response);
	ws_xml_destroy_doc(enum_response);

	while (enumContext != NULL && enumContext[0] != 0 ) {
		doc = wsmc_action_pull(cl, resourceUri.c_str(), options, NULL, enumContext);
		CheckWsmanResponse(cl, doc);
		string payload = ExtractItems(doc);

		if (payload.length() > 0)
			enumRes.push_back(payload);

		wsmc_free_enum_context(enumContext);
		enumContext = wsmc_get_enum_context(doc);
		ws_xml_destroy_doc(doc);
	}

	wsmc_free_enum_context(enumContext);
}

void OpenWsmanClient::Enumerate(
	const string &resourceUri,
	vector<string> &enumRes,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	Enumerate(resourceUri, enumRes, options, WsmanFilter());
}

void OpenWsmanClient::Enumerate(
	const string &resourceUri,
	WsmanFilter &filter,
	vector<string> &enumRes) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());

	Enumerate(resourceUri, enumRes, options, filter);
}

string OpenWsmanClient::Get(
	const string &resourceUri,
	const WsmanOptions &options) const
{
	WsXmlDocH doc = wsmc_action_get(cl, (char *)resourceUri.c_str(), options);
	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

string OpenWsmanClient::Get(
	const string &resourceUri,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	return Get(resourceUri, options);
}

string OpenWsmanClient::Put(
	const string &resourceUri,
	const string &content,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	WsXmlDocH doc = wsmc_action_put_fromtext(
		cl,
		resourceUri.c_str(),
		options,
		content.c_str(),
		content.length(),
		WSMAN_ENCODING);

	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

string OpenWsmanClient::Invoke(
	const string &resourceUri,
	const string &methodName,
	const WsmanOptions &options) const
{
	WsXmlDocH doc = wsmc_action_invoke(
		cl,
		resourceUri.c_str(),
		options,
		methodName.c_str(),
		NULL);

	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

string OpenWsmanClient::Invoke(
	const string &resourceUri,
	const string &methodName,
	const string &content,
	const WsmanOptions &options) const
{
	WsXmlDocH doc = wsmc_action_invoke_fromtext(
		cl,
		resourceUri.c_str(),
		options,
		const_cast<char*>(methodName.c_str()),
		content.c_str(),
		content.length(),
		WSMAN_ENCODING);

	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

string OpenWsmanClient::Invoke(
	const string &resourceUri,
	const string &methodName,
	const string &content,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	return Invoke(resourceUri, methodName, content, options);
}

string OpenWsmanClient::Subscribe(
	const string &resourceUri,
	const SubscribeInfo &info,
	string &subsContext) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.setDeliveryMode(static_cast<WsmanDeliveryMode>(info.delivery_mode));
	options.setDeliveryURI(info.delivery_uri);

	if (!info.refenceParam.empty())
		options.setReference(info.refenceParam);

	// Add selectors.
	options.addSelectors(info.selectorset);

	options.setExpires(info.expires);
	options.setHeartbeatInterval(info.heartbeat_interval);

	WsXmlDocH doc = wsmc_action_subscribe(cl, (char *)resourceUri.c_str(), options, NULL);
	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	subsContext = GetSubscribeContext(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

string OpenWsmanClient::Renew(
	const string &resourceUri,
	const string &subsContext,
	float expire,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.setExpires(expire);
	options.addSelectors(s);

	WsXmlDocH doc = wsmc_action_renew(
		cl,
		resourceUri.c_str(),
		options,
		subsContext.c_str());

	CheckWsmanResponse(cl, doc);
	string xml = ExtractPayload(doc);
	ws_xml_destroy_doc(doc);
	return xml;
}

void OpenWsmanClient::Unsubscribe(
	const string &resourceUri,
	const string &subsContext,
	const NameValuePairs *s) const
{
	WsmanOptions options;
	options.setNamespace(GetNamespace());
	options.addSelectors(s);

	WsXmlDocH doc = wsmc_action_unsubscribe(
		cl,
		resourceUri.c_str(),
		options,
		subsContext.c_str());

	CheckWsmanResponse(cl, doc);
	ws_xml_destroy_doc(doc);
	return;
}


string GetSubscribeContext(WsXmlDocH& doc)
{
	string str;
	char *buf = NULL;
	WsXmlNodeH bodyNode = ws_xml_get_soap_body(doc);
	WsXmlNodeH tmp = NULL;
	if(bodyNode == NULL) return str;
	bodyNode = ws_xml_get_child(bodyNode, 0, XML_NS_EVENTING, WSEVENT_SUBSCRIBE_RESP);
	if(bodyNode == NULL) return str;
	bodyNode = ws_xml_get_child(bodyNode, 0, XML_NS_EVENTING, WSEVENT_SUBSCRIPTION_MANAGER);
	if(bodyNode == NULL) return str;
	tmp = ws_xml_get_child(bodyNode, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS);
	if(tmp == NULL) {
		tmp = ws_xml_get_child(bodyNode, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PROPERTIES);
		if(tmp == NULL) return str;
	}
	wsmc_node_to_buf(tmp, &buf);
	str = string(buf);
	u_free(buf);
	return str;
}

string ExtractPayload(WsXmlDocH& doc)
{
	WsXmlNodeH bodyNode = ws_xml_get_soap_body(doc);
	WsXmlNodeH payloadNode = ws_xml_get_child(bodyNode, 0, NULL, NULL);
	char *buf = NULL;
	wsmc_node_to_buf( payloadNode, &buf);
	string payload = string(buf);
	u_free(buf);
	return payload;
}

string ExtractItems(WsXmlDocH& doc)
{
	string payload;
	WsXmlNodeH bodyNode = ws_xml_get_soap_body(doc);
	WsXmlNodeH pullResponse = ws_xml_get_child(bodyNode, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP);
	WsXmlNodeH itemsNode = ws_xml_get_child(pullResponse, 0, XML_NS_ENUMERATION, WSENUM_ITEMS);
	WsXmlNodeH n = ws_xml_get_child(itemsNode, 0 , NULL, NULL );
	if (n) {
		char *buf = NULL;
		wsmc_node_to_buf( n, &buf);
		payload = string(buf);
		u_free(buf);
	}
	return payload;
}

string XmlDocToString(WsXmlDocH& doc) {
	char *buf;
	int  len;
	ws_xml_dump_memory_enc(doc, &buf, &len, WSMAN_ENCODING);
	string str = string(buf);	// This constructor copies the data.
	if (buf)
#ifdef _WIN32
		ws_xml_free_memory(buf);
#else
	u_free(buf);
#endif
	return str;
}

bool CheckWsmanResponse(WsManClient* cl, WsXmlDocH& doc)
{
	long lastError = wsmc_get_last_error(cl);
	string error;

	if(lastError) {
		char tmp[10];
		error = "Failed to establish a connection with the server.\n";
		sprintf(tmp, "%ld", lastError);
		error.append("Openwsman last error = ").append(tmp);
		ws_xml_destroy_doc(doc);
		throw WsmanClientException(error.c_str(), WSMAN_CONNECT_ERROR);
	}

	long responseCode = wsmc_get_response_code(cl);
	if (responseCode != 200 &&
			responseCode != 400 &&
			responseCode != 500)
	{
		char tmp[10];
		error = "An HTTP error occurred.\n";
		sprintf(tmp, "%ld", responseCode);
		error.append("HTTP Error = ").append(tmp);
		ws_xml_destroy_doc(doc);
		throw WsmanClientException(error.c_str(), WSMAN_HTTP_ERROR);
	}

	if(!doc)
		throw WsmanClientException("The Wsman response was NULL.");

	if (wsmc_check_for_fault(doc)) {
		char tmp[10];
		WsManFault *fault = wsmc_fault_new();
		wsmc_get_fault_data(doc, fault);
		string subcode_s = fault->subcode ? string(fault->subcode) : "";
		string code_s = fault->code ? string(fault->code) : "";
		string reason_s = fault->reason ? string(fault->reason) : "";
		string detail_s = fault->fault_detail ? string(fault->fault_detail) : "";
		ws_xml_destroy_doc(doc);
		wsmc_fault_destroy(fault);
		error = "A Soap Fault was received:";
		error.append("\nFaultCode: " + code_s);
		error.append("\nFaultSubCode: " + subcode_s);
		error.append("\nFaultReason: " + reason_s);
		error.append("\nFaultDetail: " + detail_s);
		sprintf(tmp, "%ld", responseCode);
		error.append("\nHttpCode:  = ").append(tmp);
		throw WsmanSoapFault(error.c_str(), code_s, subcode_s, reason_s, detail_s);
	}

	return true;
}

bool ResourceNotFound(WsManClient* cl, WsXmlDocH& enumerationRes)
{
	long responseCode = wsmc_get_response_code(cl);
	if(wsmc_get_last_error(cl) ||
			(responseCode != 200 && responseCode != 400 && responseCode != 500) ||
			!enumerationRes)
	{
		CheckWsmanResponse(cl, enumerationRes);
	}

	if (!wsmc_check_for_fault(enumerationRes))
		return false;

	WsManFault *fault = wsmc_fault_new();
	bool ret = false;
	wsmc_get_fault_data(enumerationRes, fault);
	string subcode_s = fault->subcode ? string(fault->subcode) : "";
	if(subcode_s.find("DestinationUnreachable") != string::npos) {
		wsmc_fault_destroy(fault);
		return true;
	}

	wsmc_fault_destroy(fault);
	if(!ret)
		CheckWsmanResponse(cl, enumerationRes);

	return ret;
}

void OpenWsmanClient::SetAuth(const string &auth_method)
{
	if (auth_method.empty())
		return;

	wsman_transport_set_auth_method(cl, auth_method.c_str());
	if (wsmc_transport_get_auth_value(cl) == WS_MAX_AUTH ) {
		// Authentication method not supported, reverting to digest
		wsman_transport_set_auth_method(cl, "digest");
	}
}
void OpenWsmanClient::SetTimeout(unsigned long mtime)
{
	wsman_transport_set_timeout(cl,mtime);
}

void OpenWsmanClient::SetUserName(const string &user_name)
{
	if (user_name.empty())
		return;

	wsman_transport_set_userName(cl, user_name.c_str());
}

void OpenWsmanClient::SetPassword(const string &password)
{
	if (password.empty())
		return;

	wsman_transport_set_password(cl, password.c_str());
}

void OpenWsmanClient::SetEncoding(const string &encoding)
{
	if (encoding.empty())
		return;

	wsmc_set_encoding(cl, encoding.c_str());
}

void OpenWsmanClient::SetNamespace(const string &ns)
{
	if (ns.empty())
		return;

	wsmc_set_namespace(cl, ns.c_str());
}

void OpenWsmanClient::SetProxy(
	const string &proxy,
	const string &proxy_username,
	const string &proxy_password)
{
        if (!proxy.empty())
                wsman_transport_set_proxy(cl, proxy.c_str());

        if (!proxy_username.empty())
                wsman_transport_set_proxy_username(cl, proxy_username.c_str());

        if (!proxy_password.empty())
                wsman_transport_set_proxy_password(cl, proxy_password.c_str());
}

#ifdef _WIN32
void OpenWsmanClient::SetClientCert(
	const string &caOid,
	const string &caName,
	const bool localCert)
{
	if (!caOid.empty())
		wsman_transport_set_caoid(cl, caOid.c_str());

	if (!caName.empty())
		wsman_transport_set_cainfo(cl, caName.c_str());

	wsman_transport_set_calocal(cl, localCert);
}


#else
// Set server certificate params
// params: cainfo - string naming a file holding one or more certificates to verify the peer with.
//         capath - string naming a dierctory holding multiple CA certificates to verify the peer with.
// Give empty strings if you want curl to search for certificates inthe default path
void OpenWsmanClient::SetServerCert(
	const string &cainfo,
	const string &capath)
{
	// This means curl verifies the server certificate
	wsman_transport_set_verify_peer(cl, 1);

	// This means the certificate must indicate that the server is the server to which you meant to connect.
	wsman_transport_set_verify_host(cl, 2);

	if (!cainfo.empty())
		wsman_transport_set_cainfo(cl, cainfo.c_str());

	if (!capath.empty())
		wsman_transport_set_capath(cl, capath.c_str());
}

// Set client certificates params
// params: cert - file name of your certificate.
//         key  - file name of your private key.
void OpenWsmanClient::SetClientCert(
	const string &cert,
	const string &key)
{
	if (!cert.empty())
		wsman_transport_set_cert(cl, cert.c_str());

	if (!key.empty())
		wsman_transport_set_key(cl, key.c_str());
}
#endif

string OpenWsmanClient::GetNamespace() const
{
	char *ns = wsmc_get_namespace(cl);
	return ns ? string(ns) : string();
}
