File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / soap / php_packet_soap.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:55 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:   +----------------------------------------------------------------------+
    3:   | PHP Version 5                                                        |
    4:   +----------------------------------------------------------------------+
    5:   | Copyright (c) 1997-2014 The PHP Group                                |
    6:   +----------------------------------------------------------------------+
    7:   | This source file is subject to version 3.01 of the PHP license,      |
    8:   | that is bundled with this package in the file LICENSE, and is        |
    9:   | available through the world-wide-web at the following url:           |
   10:   | http://www.php.net/license/3_01.txt                                  |
   11:   | If you did not receive a copy of the PHP license and are unable to   |
   12:   | obtain it through the world-wide-web, please send a note to          |
   13:   | license@php.net so we can mail you a copy immediately.               |
   14:   +----------------------------------------------------------------------+
   15:   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
   16:   |          Shane Caraveo <shane@caraveo.com>                           |
   17:   |          Dmitry Stogov <dmitry@zend.com>                             |
   18:   +----------------------------------------------------------------------+
   19: */
   20: /* $Id: php_packet_soap.c,v 1.1.1.4 2014/06/15 20:03:55 misho Exp $ */
   21: 
   22: #include "php_soap.h"
   23: 
   24: /* SOAP client calls this function to parse response from SOAP server */
   25: int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval *return_value, zval *soap_headers TSRMLS_DC)
   26: {
   27: 	char* envelope_ns = NULL;
   28: 	xmlDocPtr response;
   29: 	xmlNodePtr trav, env, head, body, resp, cur, fault;
   30: 	xmlAttrPtr attr;
   31: 	int param_count = 0;
   32: 	int soap_version = SOAP_1_1;
   33: 	HashTable *hdrs = NULL;
   34: 
   35: 	ZVAL_NULL(return_value);
   36: 
   37: 	/* Response for one-way opearation */
   38: 	if (buffer_size == 0) {
   39: 		return TRUE;
   40: 	}
   41: 
   42: 	/* Parse XML packet */
   43: 	response = soap_xmlParseMemory(buffer, buffer_size);
   44: 
   45: 	if (!response) {
   46: 		add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL TSRMLS_CC);
   47: 		return FALSE;
   48: 	}
   49: 	if (xmlGetIntSubset(response) != NULL) {
   50: 		add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL TSRMLS_CC);
   51: 		xmlFreeDoc(response);
   52: 		return FALSE;
   53: 	}
   54: 
   55: 	/* Get <Envelope> element */
   56: 	env = NULL;
   57: 	trav = response->children;
   58: 	while (trav != NULL) {
   59: 		if (trav->type == XML_ELEMENT_NODE) {
   60: 			if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
   61: 				env = trav;
   62: 				envelope_ns = SOAP_1_1_ENV_NAMESPACE;
   63: 				soap_version = SOAP_1_1;
   64: 			} else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
   65: 				env = trav;
   66: 				envelope_ns = SOAP_1_2_ENV_NAMESPACE;
   67: 				soap_version = SOAP_1_2;
   68: 			} else {
   69: 				add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL TSRMLS_CC);
   70: 				xmlFreeDoc(response);
   71: 				return FALSE;
   72: 			}
   73: 		}
   74: 		trav = trav->next;
   75: 	}
   76: 	if (env == NULL) {
   77: 		add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL TSRMLS_CC);
   78: 		xmlFreeDoc(response);
   79: 		return FALSE;
   80: 	}
   81: 
   82: 	attr = env->properties;
   83: 	while (attr != NULL) {
   84: 		if (attr->ns == NULL) {
   85: 			add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
   86: 			xmlFreeDoc(response);
   87: 			return FALSE;
   88: 		} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
   89: 			if (soap_version == SOAP_1_2) {
   90: 				add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL TSRMLS_CC);
   91: 				xmlFreeDoc(response);
   92: 				return FALSE;
   93: 			} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
   94: 				add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
   95: 				xmlFreeDoc(response);
   96: 				return FALSE;
   97: 			}
   98: 		}
   99: 		attr = attr->next;
  100: 	}
  101: 
  102: 	/* Get <Header> element */
  103: 	head = NULL;
  104: 	trav = env->children;
  105: 	while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
  106: 		trav = trav->next;
  107: 	}
  108: 	if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
  109: 		head = trav;
  110: 		trav = trav->next;
  111: 	}
  112: 
  113: 	/* Get <Body> element */
  114: 	body = NULL;
  115: 	while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
  116: 		trav = trav->next;
  117: 	}
  118: 	if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
  119: 		body = trav;
  120: 		trav = trav->next;
  121: 	}
  122: 	while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
  123: 		trav = trav->next;
  124: 	}
  125: 	if (body == NULL) {
  126: 		add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL TSRMLS_CC);
  127: 		xmlFreeDoc(response);
  128: 		return FALSE;
  129: 	}
  130: 	attr = body->properties;
  131: 	while (attr != NULL) {
  132: 		if (attr->ns == NULL) {
  133: 			if (soap_version == SOAP_1_2) {
  134: 				add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
  135: 				xmlFreeDoc(response);
  136: 				return FALSE;
  137: 			}
  138: 		} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
  139: 			if (soap_version == SOAP_1_2) {
  140: 				add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL TSRMLS_CC);
  141: 				xmlFreeDoc(response);
  142: 				return FALSE;
  143: 			} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
  144: 				add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
  145: 				xmlFreeDoc(response);
  146: 				return FALSE;
  147: 			}
  148: 		}
  149: 		attr = attr->next;
  150: 	}
  151: 	if (trav != NULL && soap_version == SOAP_1_2) {
  152: 		add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL TSRMLS_CC);
  153: 		xmlFreeDoc(response);
  154: 		return FALSE;
  155: 	}
  156: 
  157: 	if (head != NULL) {
  158: 		attr = head->properties;
  159: 		while (attr != NULL) {
  160: 			if (attr->ns == NULL) {
  161: 				add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
  162: 				xmlFreeDoc(response);
  163: 				return FALSE;
  164: 			} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
  165: 				if (soap_version == SOAP_1_2) {
  166: 					add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL TSRMLS_CC);
  167: 					xmlFreeDoc(response);
  168: 					return FALSE;
  169: 				} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
  170: 					add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
  171: 					xmlFreeDoc(response);
  172: 					return FALSE;
  173: 				}
  174: 			}
  175: 			attr = attr->next;
  176: 		}
  177: 	}
  178: 
  179: 	/* Check if <Body> contains <Fault> element */
  180: 	fault = get_node_ex(body->children,"Fault",envelope_ns);
  181: 	if (fault != NULL) {
  182: 		char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
  183: 		zval *details = NULL;
  184: 		xmlNodePtr tmp;
  185: 
  186: 		if (soap_version == SOAP_1_1) {
  187: 			tmp = get_node(fault->children, "faultcode");
  188: 			if (tmp != NULL && tmp->children != NULL) {
  189: 				faultcode = (char*)tmp->children->content;
  190: 			}
  191: 
  192: 			tmp = get_node(fault->children, "faultstring");
  193: 			if (tmp != NULL && tmp->children != NULL) {
  194: 				zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
  195: 				faultstring = Z_STRVAL_P(zv);
  196: 				FREE_ZVAL(zv);
  197: 			}
  198: 
  199: 			tmp = get_node(fault->children, "faultactor");
  200: 			if (tmp != NULL && tmp->children != NULL) {
  201: 				zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
  202: 				faultactor = Z_STRVAL_P(zv);
  203: 				FREE_ZVAL(zv);
  204: 			}
  205: 
  206: 			tmp = get_node(fault->children, "detail");
  207: 			if (tmp != NULL) {
  208: 				details = master_to_zval(NULL, tmp TSRMLS_CC);
  209: 			}
  210: 		} else {
  211: 			tmp = get_node(fault->children, "Code");
  212: 			if (tmp != NULL && tmp->children != NULL) {
  213: 				tmp = get_node(tmp->children, "Value");
  214: 				if (tmp != NULL && tmp->children != NULL) {
  215: 					faultcode = (char*)tmp->children->content;
  216: 				}
  217: 			}
  218: 
  219: 			tmp = get_node(fault->children,"Reason");
  220: 			if (tmp != NULL && tmp->children != NULL) {
  221: 				/* TODO: lang attribute */
  222: 				tmp = get_node(tmp->children,"Text");
  223: 				if (tmp != NULL && tmp->children != NULL) {
  224: 					zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
  225: 					faultstring = Z_STRVAL_P(zv);
  226: 					FREE_ZVAL(zv);
  227: 				}
  228: 			}
  229: 
  230: 			tmp = get_node(fault->children,"Detail");
  231: 			if (tmp != NULL) {
  232: 				details = master_to_zval(NULL, tmp TSRMLS_CC);
  233: 			}
  234: 		}
  235: 		add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
  236: 		if (faultstring) {
  237: 			efree(faultstring);
  238: 		}
  239: 		if (faultactor) {
  240: 			efree(faultactor);
  241: 		}
  242: 		if (details) {
  243: 			Z_DELREF_P(details);
  244: 		}
  245: 		xmlFreeDoc(response);
  246: 		return FALSE;
  247: 	}
  248: 
  249: 	/* Parse content of <Body> element */
  250: 	array_init(return_value);
  251: 	resp = body->children;
  252: 	while (resp != NULL && resp->type != XML_ELEMENT_NODE) {
  253: 		resp = resp->next;
  254: 	}
  255: 	if (resp != NULL) {
  256: 		if (fn != NULL && fn->binding && fn->binding->bindingType == BINDING_SOAP) {
  257: 		  /* Function has WSDL description */
  258: 			sdlParamPtr *h_param, param = NULL;
  259: 			xmlNodePtr val = NULL;
  260: 			char *name, *ns = NULL;
  261: 			zval* tmp;
  262: 			sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
  263: 			int res_count;
  264: 
  265: 			hdrs = fnb->output.headers;
  266: 
  267: 			if (fn->responseParameters) {
  268: 			  res_count = zend_hash_num_elements(fn->responseParameters);
  269: 				zend_hash_internal_pointer_reset(fn->responseParameters);
  270: 				while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
  271: 					param = (*h_param);
  272: 					if (fnb->style == SOAP_DOCUMENT) {
  273: 						if (param->element) {
  274: 							name = param->element->name;
  275: 							ns = param->element->namens;
  276: /*
  277: 							name = param->encode->details.type_str;
  278: 							ns = param->encode->details.ns;
  279: */
  280: 						} else {
  281: 							name = param->paramName;
  282: 						}
  283: 					} else {
  284: 						name = fn->responseName;
  285: 						/* ns = ? */
  286: 					}
  287: 
  288: 					/* Get value of parameter */
  289: 					cur = get_node_ex(resp, name, ns);
  290: 					if (!cur) {
  291: 						cur = get_node(resp, name);
  292: 						/* TODO: produce warning invalid ns */
  293: 					}
  294: 					if (!cur && fnb->style == SOAP_RPC) {
  295: 					  cur = resp;
  296: 					}
  297: 					if (cur) {
  298: 						if (fnb->style == SOAP_DOCUMENT) {
  299: 							val = cur;
  300: 						} else {
  301: 							val = get_node(cur->children, param->paramName);
  302: 							if (res_count == 1) {
  303: 								if (val == NULL) {
  304: 									val = get_node(cur->children, "return");
  305: 								}
  306: 								if (val == NULL) {
  307: 									val = get_node(cur->children, "result");
  308: 								}
  309: 								if (val == NULL && cur->children && cur->children->next == NULL) {
  310: 									val = cur->children;								  
  311: 								}
  312: 							}
  313: 						}
  314: 					}
  315: 
  316: 					if (!val) {
  317: 						/* TODO: may be "nil" is not OK? */
  318: 						MAKE_STD_ZVAL(tmp);
  319: 						ZVAL_NULL(tmp);
  320: /*
  321: 						add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
  322: 						xmlFreeDoc(response);
  323: 						return FALSE;
  324: */
  325: 					} else {
  326: 						/* Decoding value of parameter */
  327: 						if (param != NULL) {
  328: 							tmp = master_to_zval(param->encode, val TSRMLS_CC);
  329: 						} else {
  330: 							tmp = master_to_zval(NULL, val TSRMLS_CC);
  331: 						}
  332: 					}
  333: 					add_assoc_zval(return_value, param->paramName, tmp);
  334: 
  335: 					param_count++;
  336: 
  337: 					zend_hash_move_forward(fn->responseParameters);
  338: 				}
  339: 			}
  340: 		} else {
  341: 		  /* Function has no WSDL description */
  342: 			xmlNodePtr val;
  343: 			val = resp->children;
  344: 			while (val != NULL) {
  345: 				while (val && val->type != XML_ELEMENT_NODE) {
  346: 					val = val->next;
  347: 				}
  348: 				if (val != NULL) {
  349: 					if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) {
  350: 						zval *tmp;
  351: 						zval **arr;
  352: 
  353: 						tmp = master_to_zval(NULL, val TSRMLS_CC);
  354: 						if (val->name) {
  355: 							if (zend_hash_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name)+1, (void**)&arr) == SUCCESS) {
  356: 								add_next_index_zval(*arr, tmp);
  357: 							} else if (val->next && get_node(val->next, (char*)val->name)) {
  358: 								zval *arr;
  359: 
  360: 								MAKE_STD_ZVAL(arr);
  361: 								array_init(arr);
  362: 								add_next_index_zval(arr, tmp);
  363: 								add_assoc_zval(return_value, (char*)val->name, arr);
  364: 							} else {
  365: 								add_assoc_zval(return_value, (char*)val->name, tmp);
  366: 							}
  367: 						} else {
  368: 							add_next_index_zval(return_value, tmp);
  369: 						}
  370: 						++param_count;
  371: 					}
  372: 					val = val->next;
  373: 				}
  374: 			}
  375: 		}
  376: 	}
  377: 
  378: 	if (Z_TYPE_P(return_value) == IS_ARRAY) {
  379: 		if (param_count == 0) {
  380: 			zval_dtor(return_value);
  381: 			ZVAL_NULL(return_value);
  382: 		} else if (param_count == 1) {
  383: 			zval *tmp;
  384: 
  385: 			zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
  386: 			zend_hash_get_current_data(Z_ARRVAL_P(return_value), (void**)&tmp);
  387: 			tmp = *(zval**)tmp;
  388: 			Z_ADDREF_P(tmp);
  389: 			zval_dtor(return_value);
  390: 			*return_value = *tmp;
  391: 			FREE_ZVAL(tmp);
  392: 		}
  393: 	}
  394: 
  395: 	if (soap_headers && head) {
  396: 		trav = head->children;
  397: 		while (trav != NULL) {
  398: 			if (trav->type == XML_ELEMENT_NODE) {
  399: 				encodePtr enc = NULL;
  400: 				zval* val;
  401: 
  402: 				if (hdrs) {
  403: 					smart_str key = {0};
  404: 					sdlSoapBindingFunctionHeaderPtr *hdr;
  405: 
  406: 					if (trav->ns) {
  407: 						smart_str_appends(&key, (char*)trav->ns->href);
  408: 						smart_str_appendc(&key,':');
  409: 					}
  410: 					smart_str_appends(&key, (char*)trav->name);
  411: 					smart_str_0(&key);
  412: 					if (zend_hash_find(hdrs, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
  413: 						enc = (*hdr)->encode;
  414: 					}
  415: 					smart_str_free(&key);
  416: 				}
  417: 				val = master_to_zval(enc, trav TSRMLS_CC);
  418: 				add_assoc_zval(soap_headers, (char*)trav->name, val);
  419: 			}
  420: 			trav = trav->next;
  421: 		}
  422: 	}
  423: 
  424: 	xmlFreeDoc(response);
  425: 	return TRUE;
  426: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>