lasso/lasso/id-wsf-2.0/data_service.c

1064 lines
32 KiB
C

/* $Id: idwsf2_data_service.c 3101 2007-05-30 11:40:10Z dlaniel $
*
* Lasso - A free implementation of the Liberty Alliance specifications.
*
* Copyright (C) 2004-2007 Entr'ouvert
* http://lasso.entrouvert.org
*
* Authors: See AUTHORS file in top-level directory.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* SECTION:idwsf2_data_service
* @short_description: ID-WSF 2.0 Data Service profile
*
* DataService allows Attribute Consumers (WSC) to request an Attribute Provider (WSP) to get
* or modify data about users with their consent.
*/
#include "../xml/private.h"
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include "./data_service.h"
#include "../xml/id-wsf-2.0/idwsf2_strings.h"
#include "../xml/id-wsf-2.0/disco_service_type.h"
#include "../xml/id-wsf-2.0/dstref_query.h"
#include "../xml/id-wsf-2.0/dstref_query_response.h"
#include "../xml/id-wsf-2.0/dstref_data.h"
#include "../xml/id-wsf-2.0/util_status.h"
#include "../xml/id-wsf-2.0/util_response.h"
#include "../xml/id-wsf-2.0/sb2_redirect_request.h"
#include "../xml/id-wsf-2.0/dstref_modify.h"
#include "../xml/id-wsf-2.0/dstref_modify_item.h"
#include "../xml/id-wsf-2.0/dstref_modify_response.h"
#include "../xml/id-wsf-2.0/dstref_create.h"
#include "../xml/id-wsf-2.0/dstref_delete.h"
#include "../xml/soap-1.1/soap_envelope.h"
#include "../xml/soap-1.1/soap_fault.h"
#include "../xml/private.h"
#include "../utils.h"
#include "./private.h"
#include "./idwsf2_helper.h"
#include "./soap_binding.h"
struct _LassoIdWsf2DataServicePrivate
{
gboolean dispose_has_run;
GList *query_items; /* of LassoIdWsf2DstRefQueryItem */
GList *query_datas; /* of LassoIdWsf2DstRefData */
GList *modify_items; /* of LassoIdWsf2DstRefModifyItem */
gchar *service_type;
gchar *service_type_prefix;
GHashTable *namespaces;
};
extern GHashTable *idwsf2_dst_services_by_prefix; /* cf xml/xml.c */
#define lasso_idwsf2_data_service_set_dst_service_type(dst_node, service_type, prefix) \
lasso_assign_string(dst_node->hrefServiceType, service_type); \
lasso_assign_string(dst_node->prefixServiceType, prefix); \
static void
lasso_idwsf2_data_service_clean_private_data(LassoIdWsf2DataService *service)
{
LassoIdWsf2DataServicePrivate *pdata = service->private_data;
lasso_release_string(pdata->service_type);
lasso_release_string(pdata->service_type_prefix);
lasso_release_list_of_gobjects(pdata->query_items);
lasso_release_list_of_gobjects(pdata->modify_items);
lasso_release_ghashtable(pdata->namespaces);
}
/**
* lasso_idwsf2_data_service_set_service_type:
* @service: a #LassoIdWsf2DataService object
* @prefix: a prefix to use in producing XML documents
* @service_type: the service type URI
*
* Fix a service type for this @service.
*/
gint
lasso_idwsf2_data_service_set_service_type(LassoIdWsf2DataService *service, const char *prefix,
const char *service_type)
{
if (!LASSO_IS_IDWSF2_DATA_SERVICE(service) || lasso_strisempty(prefix)
|| lasso_strisempty(service_type))
return LASSO_PARAM_ERROR_INVALID_VALUE;
lasso_assign_string(service->private_data->service_type_prefix, prefix);
lasso_assign_string(service->private_data->service_type, service_type);
return 0;
}
/**
* lasso_idwsf2_data_service_get_service_type:
* @service: a #LassoIdWsf2DataService object
*
* Return the service type of the received request
*
* Return value:(allow-none)(transfer none): the URI of the service type or NULL.
*/
const char*
lasso_idwsf2_data_service_get_service_type(LassoIdWsf2DataService *service)
{
if (! LASSO_IS_IDWSF2_DATA_SERVICE(service))
return NULL;
return service->private_data->service_type;
}
/**
* lasso_idwsf2_data_service_get_service_type_prefix:
* @service: a #LassoIdWsf2DataService object
*
* Return the service type prefix of the received request
*
* Return value:(allow-none)(transfer none): the URI of the service type prefix or NULL.
*/
const char*
lasso_idwsf2_data_service_get_service_type_prefix(LassoIdWsf2DataService *service)
{
if (! LASSO_IS_IDWSF2_DATA_SERVICE(service))
return NULL;
return service->private_data->service_type_prefix;
}
static gint
lasso_idwsf2_data_service_init_request(LassoIdWsf2DataService *service,
LassoNode *(*constructor)())
{
int rc = 0;
LassoNode *request;
LassoSoapEnvelope *envelope;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_release_list_of_gobjects(service->private_data->query_items);
lasso_release_list_of_gobjects(service->private_data->modify_items);
lasso_check_good_rc(lasso_idwsf2_profile_init_request(&service->parent));
request = (LassoNode*)constructor();
envelope = lasso_idwsf2_profile_get_soap_envelope_request(&service->parent);
lasso_assign_new_gobject(service->parent.parent.request, request);
lasso_soap_envelope_add_to_body(envelope, request);
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_init_query:
* @service: a #LassoIdWsf2DataService
*
* Initialise an ID-WSF 2.0 DataService query request.
*
* Return value: 0 on success; or a negative value otherwise.
**/
gint
lasso_idwsf2_data_service_init_query(LassoIdWsf2DataService *service)
{
return lasso_idwsf2_data_service_init_request(service,
(LassoNode *(*)())lasso_idwsf2_dstref_query_new);
}
/**
* lasso_idwsf2_data_service_init_modify:
* @service: a #LassoIdWsf2DataService
*
* Initialise an ID-WSF 2.0 DataService modify request.
*
* Return value: 0 on success; or a negative value otherwise.
**/
gint
lasso_idwsf2_data_service_init_modify(LassoIdWsf2DataService *service)
{
return lasso_idwsf2_data_service_init_request(service,
(LassoNode *(*)())lasso_idwsf2_dstref_modify_new);
}
gint
lasso_idwsf2_data_service_init_create(LassoIdWsf2DataService *service)
{
return lasso_idwsf2_data_service_init_request(service,
(LassoNode *(*)())lasso_idwsf2_dstref_create_new);
}
gint
lasso_idwsf2_data_service_init_delete(LassoIdWsf2DataService *service)
{
return lasso_idwsf2_data_service_init_request(service,
(LassoNode *(*)())lasso_idwsf2_dstref_delete_new);
}
/**
* lasso_idwsf2_data_service_get_request_type:
* @service: a #LassoIdWsf2DataService object
*
* Return the type of the currently handled request.
*/
LassoIdWsf2DataServiceRequestType
lasso_idwsf2_data_service_get_request_type(LassoIdWsf2DataService *service)
{
GType request_type = 0;
#define check_request_type(a, b) \
if (request_type == a) { \
return b ;\
}
if (! LASSO_IS_IDWSF2_DATA_SERVICE(service))
return LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_UNKNOWN;
request_type = G_TYPE_FROM_INSTANCE(service->parent.parent.request);
check_request_type(LASSO_TYPE_IDWSF2_DSTREF_QUERY,
LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY);
check_request_type(LASSO_TYPE_IDWSF2_DSTREF_MODIFY,
LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY);
#undef check_request_type
return LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_UNKNOWN;
}
/**
* lasso_idwsf2_data_service_add_query_item:
* @service: a #LassoIdWsf2DataService
* @item_query: a query string
* @item_id:(allow-none): identifier of the queried item, which will allow to retrieve it in the
* response
*
* Add an item in the query request.
*
* Return value: 0 on success; or a negative value otherwise.
**/
gint
lasso_idwsf2_data_service_add_query_item(LassoIdWsf2DataService *service, const gchar *item_query,
const gchar *item_id)
{
LassoIdWsf2DstRefQueryItem *item;
GList *i;
int rc = 0;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_check_non_empty_string(item_query);
if (item_id == NULL) {
item_id = lasso_build_unique_id(32);
}
/* Check duplicates */
lasso_foreach(i, service->private_data->query_items) {
LassoIdWsf2DstRefQueryItem *old_item = (LassoIdWsf2DstRefQueryItem *)i->data;
if (lasso_strisequal(old_item->parent.parent.itemID,item_id)) {
return LASSO_IDWSF2_DST_ERROR_DUPLICATE_ITEM;
}
}
item = lasso_idwsf2_dstref_query_item_new_full(item_query, item_id);
lasso_list_add_gobject(service->private_data->query_items, item);
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_add_modify_item:
* @service: a #LassoIdWsf2DataService
* @item_query: XPATH of the item to modify
* @new_data:(allow-none):new value for the selected item
* @overrideAllowed:(allow-none)(default FALSE): FALSE means only allowing to create a new item, but
* not modify existing one, TRUE means allowing to modify existing item
* @item_id:(allow-none): identifier of the item to modify
*
* Add an item in the modification request.
*
* Return value: 0 on success; or a negative value otherwise.
**/
gint
lasso_idwsf2_data_service_add_modify_item(LassoIdWsf2DataService *service, const gchar *item_query,
xmlNode *new_data, gboolean overrideAllowed, const gchar *item_id)
{
LassoIdWsf2DstRefModifyItem *item;
int rc = 0;
GList *i;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_check_non_empty_string(item_query);
if (item_id == NULL) {
item_id = lasso_build_unique_id(10);
}
lasso_foreach(i, service->private_data->modify_items) {
LassoIdWsf2DstRefModifyItem *old_item = (LassoIdWsf2DstRefModifyItem *)i->data;
if (lasso_strisequal(old_item->id,item_id)) {
return LASSO_IDWSF2_DST_ERROR_DUPLICATE_ITEM;
}
}
item = lasso_idwsf2_dstref_modify_item_new_full(
item_query, item_id, new_data, overrideAllowed);
lasso_list_add_gobject(service->private_data->modify_items, item);
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_get_item_ids:
* @service: a #LassoIdWsf2DataService object
*
* Return the list of items ids for the currently handled request.
*
* Return value:(element-type utf8)(transfer full): a list of string ids, or NULL if none is found.
* The caller must free the return value.
*/
GList*
lasso_idwsf2_data_service_get_item_ids(LassoIdWsf2DataService *service)
{
GList *i, *result = NULL;
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
lasso_foreach(i, service->private_data->query_items) {
LassoIdWsf2DstRefQueryItem *old_item = (LassoIdWsf2DstRefQueryItem *)i->data;
lasso_list_add_string(result, old_item->parent.parent.itemID);
}
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
lasso_foreach(i, service->private_data->modify_items) {
LassoIdWsf2DstRefModifyItem *old_item = (LassoIdWsf2DstRefModifyItem *)i->data;
lasso_list_add_string(result, old_item->id);
}
break;
default:
break;
}
return result;
}
/**
* lasso_idwsf2_data_service_get_items:
* @service: a #LassoIdWsf2DataService object
*
* Return value:(element-type LassoNode)(transfer none): a list of Query or Modify items, or NULL if
* none is found.
*/
GList*
lasso_idwsf2_data_service_get_items(LassoIdWsf2DataService *service)
{
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
return service->private_data->query_items;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
return service->private_data->modify_items;
default:
break;
}
return NULL;
}
/**
* lasso_idwsf2_data_service_get_item:
* @service: a #LassoIdWsf2DataService object
* @item_id: the itemID of the item to return, if NULL try to get the only one item (if there is
* more than one, it returns NULL).
*
* Retrieve a specific item from a request.
*
* Return value:(transfer none)(allow-none): a #LassoIdWsf2DstRefQueryItem or a #LassoIdWsf2DstRefModifyItem object, or NULL if
* no item for the given item_id exists.
*/
LassoNode*
lasso_idwsf2_data_service_get_item(LassoIdWsf2DataService *service,
const char *item_id)
{
GList *i;
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
if (item_id == NULL) {
if (g_list_length(service->private_data->query_items) == 1)
return (LassoNode*)service->private_data->query_items->data;
else
return NULL;
}
lasso_foreach(i, service->private_data->query_items) {
LassoIdWsf2DstRefQueryItem *old_item = (LassoIdWsf2DstRefQueryItem *)i->data;
if (lasso_strisequal(old_item->parent.parent.itemID,item_id)) {
return (LassoNode*)old_item;
}
}
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
if (item_id == NULL) {
if (g_list_length(service->private_data->modify_items) == 1)
return (LassoNode*)service->private_data->modify_items->data;
else
return NULL;
}
lasso_foreach(i, service->private_data->modify_items) {
LassoIdWsf2DstRefModifyItem *old_item = (LassoIdWsf2DstRefModifyItem *)i->data;
if (lasso_strisequal(old_item->id,item_id)) {
return (LassoNode*)old_item;
}
}
break;
default:
break;
}
return NULL;
}
/**
* lasso_idwsf2_data_service_add_namespace:
* @service: a #LassoIdWsf2DataService object
*
* Add a new namespace to use for example in XPath elements or in Data or NewData objects.
*
* Return value: 0 if successful, an error code otherwise.
*/
gint
lasso_idwsf2_data_service_add_namespace(LassoIdWsf2DataService *service, const char *prefix,
const char *href)
{
if (xmlValidateNCName(BAD_CAST prefix, 0) && ! lasso_strisempty(href))
return LASSO_PARAM_ERROR_INVALID_VALUE;
if (g_hash_table_lookup(service->private_data->namespaces, prefix) != NULL ||
lasso_strisequal(service->private_data->service_type_prefix,prefix) ||
lasso_strisequal(prefix,LASSO_IDWSF2_DSTREF_PREFIX)) {
return LASSO_PARAM_ERROR_INVALID_VALUE;
}
g_hash_table_insert(service->private_data->namespaces, g_strdup(prefix), g_strdup(href));
return 0;
}
static void
add_custom_namespace(const char *prefix, const char *href, LassoNode *node)
{
lasso_node_add_custom_namespace(node, prefix, href);
}
/**
* lasso_idwsf2_data_service_build_request_msg:
* @service: a #LassoIdWsf2DataService object
* @security_mech_id:(allow-none): the security mechanism to employ, default is Bearer mechanism.
*
* Build the request message.
*
* Return value: 0 if successful, an error code otherwise.
*/
gint
lasso_idwsf2_data_service_build_request_msg(LassoIdWsf2DataService *service,
const char *security_mech_id)
{
int rc = 0;
LassoSoapEnvelope *envelope;
LassoIdWsf2DstRefQuery *query = (LassoIdWsf2DstRefQuery*)service->parent.parent.request;
LassoIdWsf2DstRefModify *modify = (LassoIdWsf2DstRefModify*)service->parent.parent.request;
const char *service_type = NULL;
const char *prefix = NULL;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
envelope = lasso_idwsf2_profile_get_soap_envelope_request(&service->parent);
service_type = lasso_wsa_endpoint_reference_get_idwsf2_service_type(
lasso_idwsf2_profile_get_epr(&service->parent));
if (service_type) {
const char *prefix = lasso_get_prefix_for_idwsf2_dst_service_href(service_type);
if (! prefix)
prefix = "dstref";
} else {
service_type = service->private_data->service_type;
prefix = service->private_data->service_type_prefix;
}
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
if (service_type) {
lasso_idwsf2_data_service_set_dst_service_type(query, service_type, prefix);
}
lasso_assign_list_of_gobjects(query->QueryItem, service->private_data->query_items);
g_hash_table_foreach(service->private_data->namespaces,
(GHFunc)add_custom_namespace,
query);
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
if (service_type) {
lasso_idwsf2_data_service_set_dst_service_type(modify, service_type, prefix);
}
lasso_assign_list_of_gobjects(modify->ModifyItem, service->private_data->modify_items);
break;
default:
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_REQUEST);
break;
}
rc = lasso_idwsf2_profile_build_request_msg(&service->parent, security_mech_id);
cleanup:
return rc;
}
static gint
lasso_idwsf2_data_service_process_query(LassoIdWsf2DataService *service)
{
LassoIdWsf2DstRefQuery *query;
GList *i;
int rc = 0;
query = (LassoIdWsf2DstRefQuery*)service->parent.parent.request;
lasso_check_good_rc(lasso_idwsf2_data_service_set_service_type(
service,
query->prefixServiceType,
query->hrefServiceType));
/* Parse QueryItems to get a list of Query strings */
/* FIXME: extract TestItems */
lasso_foreach(i, query->QueryItem)
{
LassoIdWsf2DstRefQueryItem *item = (LassoIdWsf2DstRefQueryItem *)i->data;
/* FIXME: check more query items invariants. */
if (! LASSO_IS_IDWSF2_DSTREF_QUERY_ITEM(item)) {
lasso_release_list_of_gobjects(service->private_data->query_items);
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_REQUEST);
}
lasso_list_add_gobject(service->private_data->query_items,
item);
}
cleanup:
return rc;
}
static gint
lasso_idwsf2_data_service_process_modify(LassoIdWsf2DataService *service)
{
LassoIdWsf2DstRefModify *modify;
GList *i;
int rc = 0;
modify = (LassoIdWsf2DstRefModify*)service->parent.parent.request;
lasso_foreach(i, modify->ModifyItem)
{
LassoIdWsf2DstRefModifyItem *item = (LassoIdWsf2DstRefModifyItem*)i->data;
/* FIXME: check more Modify Item invariants */
if (! LASSO_IS_IDWSF2_DSTREF_MODIFY_ITEM(item)) {
lasso_release_list_of_gobjects(service->private_data->modify_items);
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_REQUEST);
}
lasso_list_add_gobject(service->private_data->modify_items, item);
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_process_request_msg:
* @service: a #LassoIdWsf2DataService object
* @msg: the message string
*
* Process a newly received requests.
*/
gint
lasso_idwsf2_data_service_process_request_msg(LassoIdWsf2DataService *service, const char *msg)
{
int rc = 0;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_check_good_rc(lasso_idwsf2_profile_process_request_msg(&service->parent, msg));
lasso_idwsf2_data_service_clean_private_data(service);
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
rc = lasso_idwsf2_data_service_process_query(service);
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
rc = lasso_idwsf2_data_service_process_modify(service);
break;
default:
rc = LASSO_PROFILE_ERROR_INVALID_REQUEST;
break;
}
if (rc == LASSO_PROFILE_ERROR_INVALID_REQUEST) {
lasso_idwsf2_data_service_set_status_code(service,
LASSO_DST2_STATUS_CODE1_FAILED,
"InvalidRequest");
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_validate_request:
* @service: a #LassoIdWsf2DataService object
*
* Initialize a new response object corresponding to the current request. If not request if found or
* the request is invalid, a failure response is created.
*
* Return value: 0 if successful, or LASSO_PROFILE_ERROR_INVALID_REQUEST.
*/
gint
lasso_idwsf2_data_service_validate_request(LassoIdWsf2DataService *service)
{
LassoIdWsf2DstRefQueryResponse *query_response;
LassoIdWsf2DstRefModifyResponse *modify_response;
LassoNode *response = NULL;
int rc = 0;
const char *service_type = NULL;
const char *prefix = NULL;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_check_good_rc(lasso_idwsf2_profile_init_response(&service->parent));
if (service_type) {
const char *prefix = lasso_get_prefix_for_idwsf2_dst_service_href(service_type);
if (! prefix)
prefix = "dstref";
} else {
service_type = service->private_data->service_type;
prefix = service->private_data->service_type_prefix;
}
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
query_response = lasso_idwsf2_dstref_query_response_new();
if (service_type) {
lasso_idwsf2_data_service_set_dst_service_type(query_response,
service_type, prefix);
}
response = (LassoNode*)query_response;
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
modify_response = lasso_idwsf2_dstref_modify_response_new();
if (service_type) {
lasso_idwsf2_data_service_set_dst_service_type(modify_response,
service_type, prefix);
}
response = (LassoNode*)modify_response;
break;
default:
lasso_idwsf2_data_service_set_status_code(service,
LASSO_DST2_STATUS_CODE1_FAILED, "InvalidRequest");
return LASSO_PROFILE_ERROR_INVALID_REQUEST;
}
if (response) {
LassoSoapEnvelope *envelope =
lasso_idwsf2_profile_get_soap_envelope_response(&service->parent);
lasso_assign_new_gobject(service->parent.parent.response, response);
lasso_soap_envelope_add_to_body(envelope, response);
lasso_idwsf2_data_service_set_status_code(service, LASSO_DST2_STATUS_CODE1_OK, NULL);
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_set_status_code:
* @service: a #LassoIdWsf2DataService
* @status_code: a first level status code
* @status_code2: a second level status code
*
* Set the status code for the current response, if no response exists, it starts one using
* lasso_idwsf2_data_service_validate_request(), if it fails, report a SOAP Fault.
*/
gint
lasso_idwsf2_data_service_set_status_code(LassoIdWsf2DataService *service,
const char *status_code, const char *status_code2)
{
LassoNode *response;
LassoIdWsf2UtilStatus **status = NULL;
LassoIdWsf2UtilStatus *new_status = NULL;
int rc = 0;
response = service->parent.parent.response;
if (LASSO_IS_IDWSF2_UTIL_RESPONSE(response)) {
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
status = &LASSO_IDWSF2_UTIL_RESPONSE(response)->Status;
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
status = &LASSO_IDWSF2_UTIL_RESPONSE(response)->Status;
break;
default:
break;
}
}
new_status = lasso_idwsf2_util_status_new_with_code(status_code, status_code2);
if (! LASSO_IS_IDWSF2_UTIL_RESPONSE(response) || ! status) {
GList details = { .data = new_status, .next = NULL, .prev = NULL };
lasso_check_good_rc(lasso_idwsf2_profile_init_soap_fault_response(&service->parent,
LASSO_SOAP_FAULT_CODE_CLIENT, "Unknown Request Type",
&details));
} else {
lasso_assign_gobject(*status, new_status);
}
cleanup:
lasso_release_gobject(new_status);
return rc;
}
/**
* lasso_idwsf2_data_service_set_query_item_result:
* @service: a #LassoIdWsf2DataService object
* @item_id:(allow-none): target a certain QueryItem if NULL, means there is only one query item
* @xml_data:(allow-none): the data to add
* @add:(allow-none)(default FALSE): add data to existing datas
*
* Set result data for a certain query-item.
*/
gint
lasso_idwsf2_data_service_set_query_item_result(LassoIdWsf2DataService *service,
const char *item_id, xmlNode *xml_data, gboolean add)
{
LassoIdWsf2DstRefQueryItem *item;
LassoIdWsf2DstRefData *data;
int rc = 0;
if (lasso_idwsf2_data_service_get_request_type(service)
!= LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY) {
goto_cleanup_with_rc(LASSO_IDWSF2_DST_ERROR_ITEM_NOT_FOUND);
}
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
item = (LassoIdWsf2DstRefQueryItem*)lasso_idwsf2_data_service_get_item(service, item_id);
if (! LASSO_IS_IDWSF2_DSTREF_QUERY_ITEM(item)) {
goto_cleanup_with_rc(LASSO_IDWSF2_DST_ERROR_ITEM_NOT_FOUND);
}
data = lasso_idwsf2_data_service_get_query_item_result(service, item_id);
if (data == NULL) {
data = lasso_idwsf2_dstref_data_new();
}
if (xml_data) {
if (! add) {
lasso_release_list_of_xml_node(data->parent.parent.any);
}
lasso_list_add_xml_node(data->parent.parent.any, xml_data);
}
if (item_id) {
lasso_assign_string(data->parent.itemIDRef, item_id);
}
if (g_list_find(service->private_data->query_datas, data) == NULL) {
lasso_list_add_gobject(service->private_data->query_datas, data);
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_build_response_msg:
* @service: a #LassoIdWsf2DataService object
*
* Build the response message corresponding to the current request.
*
* Return value: 0 if successfull, an error code otherwise.
*/
gint
lasso_idwsf2_data_service_build_response_msg(LassoIdWsf2DataService *service)
{
LassoIdWsf2DstRefQueryResponse *query_response;
GList *datas;
int rc = 0;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
if (! LASSO_IS_SOAP_FAULT(service->parent.parent.response)) {
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
goto_cleanup_if_fail_with_rc(
LASSO_IS_IDWSF2_DSTREF_QUERY_RESPONSE(
service->parent.parent.response),
LASSO_PROFILE_ERROR_INVALID_RESPONSE);
query_response = (LassoIdWsf2DstRefQueryResponse*)service->parent.parent.response;
datas = lasso_idwsf2_data_service_get_query_item_results(service);
lasso_assign_list_of_gobjects(query_response->Data, datas);
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
goto_cleanup_with_rc(LASSO_ERROR_UNIMPLEMENTED);
break;
default:
break;
}
}
rc = lasso_idwsf2_profile_build_response_msg(&service->parent);
cleanup:
return rc;
}
static gint
_lasso_idwsf2_data_service_process_query_response(LassoIdWsf2DataService * service,
LassoIdWsf2DstRefQueryResponse *response)
{
int rc = 0;
goto_cleanup_if_fail_with_rc(LASSO_IS_IDWSF2_DSTREF_QUERY_RESPONSE(response),
LASSO_PROFILE_ERROR_INVALID_RESPONSE);
if (service->private_data) {
lasso_assign_list_of_gobjects(service->private_data->query_datas, response->Data);
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_process_response_msg:
* @service: a #LassoIdWsf2DataService object
* @msg: (allow-none): the message content
*
* Process a received SOAP message response.
*
* Return value: 0 if successful, an error code otherwise.
*/
gint
lasso_idwsf2_data_service_process_response_msg(
LassoIdWsf2DataService *service, const char *msg)
{
LassoIdWsf2DstRefQueryResponse *query_response;
LassoIdWsf2UtilStatus *status;
int rc = 0;
lasso_bad_param(IDWSF2_DATA_SERVICE, service);
lasso_check_good_rc(lasso_idwsf2_profile_process_response_msg(&service->parent, msg));
status = lasso_idwsf2_data_service_get_response_status(service);
if (! status || ! status->code) {
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_STATUS_CODE);
}
if (lasso_strisequal(status->code,LASSO_DST2_STATUS_CODE1_FAILED)) {
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_STATUS_NOT_SUCCESS);
}
if (lasso_strisequal(status->code,LASSO_DST2_STATUS_CODE1_PARTIAL)) {
rc = LASSO_IDWSF2_DST_ERROR_PARTIAL_FAILURE;
}
if (lasso_strisnotequal(status->code,LASSO_DST2_STATUS_CODE1_OK)) {
rc = LASSO_IDWSF2_DST_ERROR_UNKNOWN_STATUS_CODE;
}
switch (lasso_idwsf2_data_service_get_request_type(service)) {
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY:
query_response = (LassoIdWsf2DstRefQueryResponse*)service->parent.parent.response;
lasso_check_good_rc(_lasso_idwsf2_data_service_process_query_response(service, query_response));
break;
case LASSO_IDWSF2_DATA_SERVICE_REQUEST_TYPE_MODIFY:
rc = LASSO_ERROR_UNIMPLEMENTED;
break;
default:
rc = LASSO_ERROR_UNDEFINED;
break;
}
cleanup:
return rc;
}
/**
* lasso_idwsf2_data_service_get_response_status:
* @service: a #LassoIdWsf2UtilStatus object
*
* Return the status from the current response.
*
* Return value:(transfer none)(allow-none): a #LassoIdWsf2UtilStatus object, or NULL.
*/
LassoIdWsf2UtilStatus*
lasso_idwsf2_data_service_get_response_status(LassoIdWsf2DataService *service)
{
LassoIdWsf2UtilResponse *response;
LassoSoapFault *fault;
response = (void*)(fault = (void*)service->parent.parent.response);
if (LASSO_IS_IDWSF2_UTIL_RESPONSE(response)) {
return response->Status;
}
if (LASSO_IS_SOAP_FAULT(fault)) {
if (LASSO_IS_SOAP_DETAIL(fault->Detail) && fault->Detail->any
&& LASSO_IS_IDWSF2_UTIL_STATUS(fault->Detail->any->data)) {
return (LassoIdWsf2UtilStatus*)fault->Detail->any->data;
}
}
return NULL;
}
/**
* lasso_idwsf2_data_service_get_query_item_result:
* @service: a #LassoIdWsf2DataService object
* @item_id:(allow-none): an item_id or NULL if only one data is present
*
* Return value:(allow-none)(transfer none): a #LassoIdWsf2DstRefData or NULL if none is found.
*/
LassoIdWsf2DstRefData*
lasso_idwsf2_data_service_get_query_item_result(LassoIdWsf2DataService *service,
const char *item_id)
{
GList *i;
if (! LASSO_IS_IDWSF2_DATA_SERVICE(service))
return NULL;
if (! item_id) {
if (g_list_length(service->private_data->query_datas) == 1) {
return (LassoIdWsf2DstRefData*)service->private_data->query_datas->data;
}
return NULL;
}
lasso_foreach(i, service->private_data->query_datas) {
LassoIdWsf2DstRefData *data = (LassoIdWsf2DstRefData*)i->data;
if (lasso_strisequal(data->parent.itemIDRef,item_id)) {
return data;
}
}
return NULL;
}
/**
* lasso_idwsf2_data_service_get_query_item_result_content:
* @service: a #LassoIdWsf2DataService object
* @item_id:(allow-none): the identifier of the result asked, if NULL and there is only one respone,
* returns it.
*
* Returns the text content of the query item result identified by @item_id or the only query item
* result if @item_id is NULL.
* <para>If @item_id is NULL and there is multiple results, returns NULL.</para>
*
* Return value:(transfer full): the text content of the query item result.
*/
char*
lasso_idwsf2_data_service_get_query_item_result_content(LassoIdWsf2DataService *service,
const char *item_id)
{
LassoIdWsf2DstRefData *data = NULL;
LassoIdWsf2DstRefAppData *app_data = NULL;
GList *i = NULL;
GString *gstr = NULL;
char *result = NULL;
data = lasso_idwsf2_data_service_get_query_item_result(service, item_id);
if (! data)
return NULL;
app_data = (LassoIdWsf2DstRefAppData*)data;
gstr = g_string_sized_new(128);
lasso_foreach(i, app_data->any) {
xmlNode *node = (xmlNode*)i->data;
xmlChar *content;
content = xmlNodeGetContent(node);
g_string_append(gstr, (char*)content);
xmlFree(content);
}
result = gstr->str;
lasso_release_gstring(gstr, FALSE);
return result;
}
/**
* lasso_idwsf2_data_service_get_query_item_results:
* @service: a #LassoIdWsf2DataService object
*
* Return value:(allow-none)(transfer none)(element-type LassoIdWsf2DstRefData): the list of
* #LassoIdWsf2DstRefData or NULL if none is found.
*/
GList*
lasso_idwsf2_data_service_get_query_item_results(LassoIdWsf2DataService *service)
{
if (LASSO_IS_IDWSF2_DATA_SERVICE(service) && service->private_data) {
return service->private_data->query_datas;
}
return NULL;
}
static LassoNodeClass *parent_class = NULL;
static void
dispose(GObject *object)
{
LassoIdWsf2DataService *service = LASSO_IDWSF2_DATA_SERVICE(object);
LassoIdWsf2DataServicePrivate *pdata = service->private_data;
if (!pdata || pdata->dispose_has_run == TRUE)
return;
pdata->dispose_has_run = TRUE;
lasso_idwsf2_data_service_clean_private_data(service);
G_OBJECT_CLASS(parent_class)->dispose(object);
}
static void
finalize(GObject *object)
{
LassoIdWsf2DataService *service = LASSO_IDWSF2_DATA_SERVICE(object);
lasso_release(service->private_data);
service->private_data = NULL;
G_OBJECT_CLASS(parent_class)->finalize(object);
}
static void
instance_init(LassoIdWsf2DataService *service)
{
service->private_data = g_new0(LassoIdWsf2DataServicePrivate, 1);
service->private_data->namespaces = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free);
}
static void
class_init(LassoIdWsf2DataServiceClass *klass)
{
parent_class = g_type_class_peek_parent(klass);
lasso_node_class_set_nodename(LASSO_NODE_CLASS(klass), "IdWsf2DataService");
lasso_node_class_set_ns(LASSO_NODE_CLASS(klass), LASSO_LASSO_HREF, LASSO_LASSO_PREFIX);
G_OBJECT_CLASS(klass)->dispose = dispose;
G_OBJECT_CLASS(klass)->finalize = finalize;
}
GType
lasso_idwsf2_data_service_get_type()
{
static GType this_type = 0;
if (!this_type) {
static const GTypeInfo this_info = {
sizeof(LassoIdWsf2DataServiceClass),
NULL,
NULL,
(GClassInitFunc) class_init,
NULL,
NULL,
sizeof(LassoIdWsf2DataService),
0,
(GInstanceInitFunc) instance_init,
NULL
};
this_type = g_type_register_static(LASSO_TYPE_IDWSF2_PROFILE,
"LassoIdWsf2DataService", &this_info, 0);
}
return this_type;
}
/**
* lasso_idwsf2_data_service_new:
* @server:(allow-none): a #LassoServer object, for resolving ProviderIDs
*
* Create a new #LassoIdWsf2DataService.
*
* Return value: a newly created #LassoIdWsf2DataService object
**/
LassoIdWsf2DataService*
lasso_idwsf2_data_service_new(LassoServer *server)
{
LassoIdWsf2DataService *service;
service = g_object_new(LASSO_TYPE_IDWSF2_DATA_SERVICE, NULL);
service->parent.parent.server = lasso_ref(server);
return service;
}