/** * Do deserialization over complex schema types and move to the next element * @param $current_child is the relevent xml node to parse, and * move the current_child to the next child * @param $sig_param_node the sig model for the param * * @param $classmap the classmap passed by the user * @return the result complex type value. */ function wsf_deserialize_complex_types(&$current_child, DomNode $sig_param_node, $classmap, $cid2cont_type, $cid2attachments) { $ret_val = NULL; $target_namespace = NULL; $min_occurs = 1; $max_occurs = 1; $sig_param_attris = $sig_param_node->attributes; $param_type = NULL; $param_name = NULL; $is_attribute = FALSE; $nillable = FALSE; if ($sig_param_attris->getNamedItem(WSF_NAME)) { $param_name = $sig_param_attris->getNamedItem(WSF_NAME)->value; } if ($sig_param_attris->getNamedItem(WSF_TARGETNAMESPACE)) { $target_namespace = $sig_param_attris->getNamedItem(WSF_TARGETNAMESPACE)->value; } if ($sig_param_attris->getNamedItem(WSF_MIN_OCCURS)) { $min_occurs = $sig_param_attris->getNamedItem(WSF_MIN_OCCURS)->value; } if ($sig_param_attris->getNamedItem(WSF_MAX_OCCURS)) { $max_occurs = $sig_param_attris->getNamedItem(WSF_MAX_OCCURS)->value; } if ($sig_param_attris->getNamedItem(WSF_TYPE)) { $param_type = $sig_param_attris->getNamedItem(WSF_TYPE)->value; } if ($sig_param_attris->getNamedItem(WSF_XSD_NILLABLE) && ($sig_param_attris->getNamedItem(WSF_XSD_NILLABLE)->value = "true")) { $nillable = TRUE; } if ($sig_param_attris->getNamedItem(WSF_ATTRIBUTE) && $sig_param_attris->getNamedItem(WSF_ATTRIBUTE)->value == "yes") { $is_attribute = TRUE; } if ($max_occurs > 1 || $max_occurs == "unbounded") { $i = 0; $tmp_array = array(); while ($current_child !== NULL && $current_child->localName == $param_name) { if ($sig_param_node->hasChildNodes()) { if ($classmap) { $converted_value = wsf_parse_payload_for_class_map($current_child, $sig_param_node, $param_type, $classmap, $cid2cont_type, $cid2attachments); } else { $converted_value = wsf_parse_payload_for_array($current_child, $sig_param_node, $cid2cont_type, $cid2attachments); } } else { if ($classmap) { $converted_value = wsf_parse_payload_for_unknown_class_map($current_child, $param_type, $classmap); } else { $converted_value = wsf_parse_payload_for_unknown_array($current_child); } } if (!$current_child->firstChild && !$current_child->hasAttributes()) { // handling nil element $converted_value = wsf_wsdl_deserialize_string_value($param_type, "", $sig_param_node, $current_child); } $tmp_array[$i++] = $converted_value; $current_child = $current_child->nextSibling; while ($current_child != NULL && $current_child->nodeType != XML_ELEMENT_NODE) { $current_child = $current_child->nextSibling; } } $ret_val = $tmp_array; } else { if ($sig_param_node->hasChildNodes()) { if ($classmap) { $converted_value = wsf_parse_payload_for_class_map($current_child, $sig_param_node, $param_type, $classmap, $cid2cont_type, $cid2attachments); } else { $converted_value = wsf_parse_payload_for_array($current_child, $sig_param_node, $cid2cont_type, $cid2attachments); } } else { if ($classmap) { $converted_value = wsf_parse_payload_for_unknown_class_map($current_child, $param_type, $classmap); } else { $converted_value = wsf_parse_payload_for_unknown_array($current_child); } } if (!$current_child->firstChild && !$current_child->hasAttributes()) { // handling nil element $converted_value = wsf_wsdl_deserialize_string_value($param_type, "", $sig_param_node, $current_child); } $ret_val = $converted_value; $current_child = $current_child->nextSibling; while ($current_child != NULL && $current_child->nodeType != XML_ELEMENT_NODE) { $current_child = $current_child->nextSibling; } } return $ret_val; }
/** * service invoke function */ function wsf_serivce_invoke_function($operation_node, $function_name, $class_name, $class_args, $soap_body_node, $header_node, $classmap, $mtom_on, $cid2cont_type, $cid2attachments) { require_once 'wsf_wsdl_consts.php'; require_once 'wsf_wsdl_util.php'; require_once 'wsf_wsdl_deserialization.php'; $sig_node = NULL; $binding_details_node = NULL; if ($operation_node) { foreach ($operation_node->childNodes as $operation_child) { if ($operation_child->tagName == WSF_SIGNATURE) { $sig_node = $operation_child; } if ($operation_child->tagName == WSF_BINDINDG_DETAILS) { $binding_details_node = $operation_child; } } } $is_doc = TRUE; //currently we only support doc-lit style parsing.. $is_wrapper = FALSE; $params_node = NULL; $is_direct_list = FALSE; if ($sig_node) { $params_node = $sig_node->firstChild; if ($params_node && $params_node->localName == WSF_PARAMS) { if ($params_node->hasAttributes()) { /* Wrapper element of the request operation */ $sig_attrs = $params_node->attributes; if ($sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT)) { $ele_name = $sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT)->value; } if ($sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT_NS)) { $ele_ns = $sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT_NS)->value; } $is_wrapper = TRUE; } else { /* No wrapper element in the request */ $ele_ns = NULL; $ele_name = NULL; /* check for the only param target-namespace */ $only_param = $params_node->firstChild; $sig_attrs = $only_param->attributes; if ($sig_attrs->getNamedItem(WSF_TARGETNAMESPACE)) { $ele_ns = $sig_attrs->getNamedItem(WSF_TARGETNAMESPACE)->value; } if ($sig_attrs->getNamedItem(WSF_NAME)) { $ele_name = $sig_attrs->getNamedItem(WSF_NAME)->value; } if ($sig_attrs->getNamedItem(WSF_LIST)) { $is_direct_list = $sig_attrs->getNamedItem(WSF_LIST)->value; } } } } if (!$soap_body_node) { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "soap_body not found"); } // parsing input headers $header_params = array(); $output_headers = array(); if ($header_node) { $header_first_child = $header_node->firstChild; $output_index = 0; if ($binding_details_node) { $binding_details_childs = $binding_details_node->childNodes; foreach ($binding_details_childs as $binding_details_child) { if ($binding_details_child->nodeType == XML_ELEMENT_NODE && $binding_details_child->nodeName == WSF_SOAPHEADER && $binding_details_child->attributes->getNamedItem(WSF_HEADER_FOR_ATTRIBUTE)) { if ($binding_details_child->attributes->getNamedItem(WSF_HEADER_FOR_ATTRIBUTE)->value == WSF_WSDL_INPUT) { //so this is the next input element.. $sig_attrs = $binding_details_child->attributes; if ($sig_attrs->getNamedItem(WSF_TYPE)) { $ele_name = $sig_attrs->getNamedItem(WSF_TYPE)->value; } if ($sig_attrs->getNamedItem(WSF_TYPE_NAMESPACE)) { $ele_ns = $sig_attrs->getNamedItem(WSF_TYPE_NAMESPACE)->value; } // for the starting sig we have to go for the header node name we want //go to the next header if ($header_first_child) { $header_child = $header_first_child; while ($header_child && ($header_child->nodeType == XML_TEXT_NODE || !($header_child->localName == $ele_name && $header_child->namespaceURI == $ele_ns))) { $header_child = $header_child->nextSibling; } } if ($header_child) { $header_sig = $binding_details_child->firstChild; if ($classmap != NULL && !empty($classmap)) { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse header {$ele_name} as a classmap"); $new_param = wsf_parse_payload_for_class_map($header_child, $header_sig, $ele_name, $classmap, $cid2cont_type, $cid2attachments); ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "parsed_pram " . print_r($new_param, TRUE) . " as a classmap"); } else { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse header {$ele_name} as an array"); $new_param = wsf_parse_payload_for_array($header_child, $header_sig, $cid2cont_type, $cid2attachments); } $header_params[] = $new_param; } else { //if header child doesn't exist better check whether it is an requeired header if ($sig_attrs && $sig_attrs->getNamedItem(WSF_REQUIRED) && $sig_attrs->getNamedItem(WSF_REQUIRED)->value == "true") { //throwing faults saying it is required throw new WSFault("Sender", "Requried header {$ele_name}|{$ele_ns} missing"); } } } else { if ($binding_details_child->attributes->getNamedItem(WSF_HEADER_FOR_ATTRIBUTE)->value == WSF_WSDL_OUTPUT) { $output_headers[$output_index] = array(); //to retrive later $header_params[] =& $output_headers[$output_index]; //to feed to the user operation $output_index++; } } } } } } //parsing the pyalod $op_param_values = array(); if ($classmap != NULL && !empty($classmap)) { if ($soap_body_node) { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse payload as a classmap"); $op_param_values = wsf_parse_payload_for_class_map($soap_body_node, $params_node, $ele_name, $classmap, $cid2cont_type, $cid2attachments); } $arg_array = array_merge(array($op_param_values), $header_params); } else { if ($soap_body_node) { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse payload as an array"); $op_param_values = wsf_parse_payload_for_array($soap_body_node, $params_node, $cid2cont_type, $cid2attachments); if (!is_array($op_param_values) || $is_direct_list) { // this can happens when returning simple types $op_param_values = array($op_param_values); } } $arg_array = array_merge($op_param_values, $header_params); } ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, print_r($arg_array, TRUE)); if ($class_name != NULL) { // First call the constructor $class = new ReflectionClass($class_name); if ($class) { if ($class_args && is_array($class_args)) { $class_inst = $class->newInstanceArgs($class_args); } else { $class_inst = $class->newInstanceArgs(array()); } // Then the user method $method = $class->getMethod($function_name); if ($classmap != NULL && !empty($classmap) || $is_direct_list) { // for direct lists we follow same api as classmap $response_value = $method->invokeArgs($class_inst, $arg_array); } else { $response_value = $method->invokeArgs($class_inst, $arg_array); } } else { ws_log_write(__FILE__, __LINE__, WSF_LOG_ERROR, "class : {$class_name} doesn't exists"); } } else { if ($classmap != NULL && !empty($classmap) || $is_direct_list) { // for direct lists we follow same api as classmap $response_value = call_user_func_array($function_name, $arg_array); } else { $response_value = call_user_func_array($function_name, $arg_array); } } $attachment_map = array(); $response_payload_string = wsf_wsdl_create_response_payload($response_value, $sig_node, $mtom_on, $attachment_map, $classmap); $output_header_string = wsf_wsdl_create_response_headers($binding_details_node, $output_headers, $mtom_on, $attachment_map, $classmap); return array(WSF_RESPONSE_PAYLOAD => $response_payload_string, WSF_OUTPUT_HEADERS => $output_header_string, WSF_ATTACHMENT_MAP => $attachment_map); }
/** * Processes and validate response message and assign values to class map. * @param DomDocument $payload_dom response payload * @param DomDocument $header_dom response header, can be NULL * @param DomDocument $operation_sig_dom operation sig model * @param array $response_parameters array of response parameters * @return mixed an object, an array or a simple type in line with the * expected format of the response */ function wsf_client_response_and_validate(DomDocument $payload_dom, $header_dom, DomDocument $operation_sig_dom, $response_parameters, $mtom_on = FALSE) { require_once 'wsf_wsdl_consts.php'; require_once 'wsf_wsdl_util.php'; require_once 'wsf_wsdl_deserialization.php'; $payload_node = $payload_dom->documentElement; $operation_sig_node = $operation_sig_dom->documentElement; $binding_details_node = NULL; $sig_method = NULL; //extracting out the sig_method from the operation sig node if ($operation_sig_node) { foreach ($operation_sig_node->childNodes as $operation_sig_child) { if ($operation_sig_child->tagName == WSF_SIGNATURE) { $sig_method = $operation_sig_child; } if ($operation_sig_child->tagName == WSF_BINDINDG_DETAILS) { $binding_details_node = $operation_sig_child; } } } $ele_ns = NULL; $is_wrapper = FALSE; if ($sig_method) { $returns_node = $sig_method->firstChild; while ($returns_node && $returns_node->localName != WSF_RETURNS) { $returns_node = $returns_node->nextSibling; } if ($returns_node) { if ($returns_node->hasAttributes()) { /* Wrapper element of the request operation */ $sig_attrs = $returns_node->attributes; $ele_name = NULL; $ele_ns = NULL; if ($sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT)) { $ele_name = $sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT)->value; } if ($sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT_NS)) { $ele_ns = $sig_attrs->getNamedItem(WSF_WRAPPER_ELEMENT_NS)->value; } $is_wrapper = TRUE; } else { /* No wrapper element in the request */ $ele_ns = NULL; $ele_name = NULL; /* check for the only param target-namespace */ $only_param = $returns_node->firstChild; $sig_attrs = $only_param->attributes; if ($sig_attrs->getNamedItem(WSF_TARGETNAMESPACE)) { $ele_ns = $sig_attrs->getNamedItem(WSF_TARGETNAMESPACE)->value; } if ($sig_attrs->getNamedItem(WSF_NAME)) { $ele_name = $sig_attrs->getNamedItem(WSF_NAME)->value; } } } } /** get SOAP body DOM tree to compare with Sig model */ if (!$payload_node) { error_log("soap_body not found", 0); } $classmap = NULL; $cid2cont_type = array(); $cid2attachments = array(); if (array_key_exists(WSF_CLASSMAP, $response_parameters)) { $classmap = $response_parameters[WSF_CLASSMAP]; } if (array_key_exists("attachments", $response_parameters)) { $cid2attachments = $response_parameters["attachments"]; } if (array_key_exists("cid2contentType", $response_parameters)) { $cid2cont_type = $response_parameters["cid2contentType"]; } $op_param_values = array(); if ($classmap !== NULL) { $op_param_values = wsf_parse_payload_for_class_map($payload_node, $returns_node, $ele_name, $classmap, $cid2cont_type, $cid2attachments); } else { $op_param_values = wsf_parse_payload_for_array($payload_node, $returns_node, $cid2cont_type, $cid2attachments); } $header_node = NULL; if ($header_dom) { $header_node = $header_dom->documentElement; } $header_params = array(); if ($header_node) { $header_first_child = $header_node->firstChild; $output_index = 0; if ($binding_details_node) { $binding_details_childs = $binding_details_node->childNodes; foreach ($binding_details_childs as $binding_details_child) { if ($binding_details_child->nodeType == XML_ELEMENT_NODE && $binding_details_child->nodeName == WSF_SOAPHEADER && $binding_details_child->attributes->getNamedItem(WSF_HEADER_FOR_ATTRIBUTE)) { if ($binding_details_child->attributes->getNamedItem(WSF_HEADER_FOR_ATTRIBUTE)->value == WSF_WSDL_OUTPUT) { //so this is the next input element.. $sig_attrs = $binding_details_child->attributes; if ($sig_attrs->getNamedItem(WSF_TYPE)) { $ele_name = $sig_attrs->getNamedItem(WSF_TYPE)->value; } if ($sig_attrs->getNamedItem(WSF_TYPE_NAMESPACE)) { $ele_ns = $sig_attrs->getNamedItem(WSF_TYPE_NAMESPACE)->value; } //go to the next header if ($header_first_child) { $header_child = $header_first_child; while ($header_child && ($header_child->nodeType == XML_TEXT_NODE || !($header_child->localName == $ele_name && $header_child->namespaceURI == $ele_ns))) { $header_child = $header_child->nextSibling; } } if ($header_child) { $header_sig = $binding_details_child->firstChild; if ($classmap != NULL && !empty($classmap)) { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse header {$ele_name} as a classmap"); $new_param = wsf_parse_payload_for_class_map($header_child, $header_sig, $ele_name, $classmap, $cid2cont_type, $cid2attachments); } else { ws_log_write(__FILE__, __LINE__, WSF_LOG_DEBUG, "starting to parse header {$ele_name} as an array"); $new_param = wsf_parse_payload_for_array($header_child, $header_sig, $cid2cont_type, $cid2attachments); } $header_params[] = $new_param; } } } } } } return array(WSF_RESPONSE_PAYLOAD_PARAM => $op_param_values, WSF_RESPONSE_HEADER_PARAM => $header_params); }