Annotation of embedaddon/php/ext/soap/php_packet_soap.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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 321634 2012-01-01 13:15:04Z felipe $ */
! 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);
! 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);
! 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);
! 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);
! 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);
! 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: #ifdef ZEND_ENGINE_2
! 243: if (details) {
! 244: Z_DELREF_P(details);
! 245: }
! 246: #endif
! 247: xmlFreeDoc(response);
! 248: return FALSE;
! 249: }
! 250:
! 251: /* Parse content of <Body> element */
! 252: array_init(return_value);
! 253: resp = body->children;
! 254: while (resp != NULL && resp->type != XML_ELEMENT_NODE) {
! 255: resp = resp->next;
! 256: }
! 257: if (resp != NULL) {
! 258: if (fn != NULL && fn->binding && fn->binding->bindingType == BINDING_SOAP) {
! 259: /* Function has WSDL description */
! 260: sdlParamPtr *h_param, param = NULL;
! 261: xmlNodePtr val = NULL;
! 262: char *name, *ns = NULL;
! 263: zval* tmp;
! 264: sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
! 265: int res_count;
! 266:
! 267: hdrs = fnb->output.headers;
! 268:
! 269: if (fn->responseParameters) {
! 270: res_count = zend_hash_num_elements(fn->responseParameters);
! 271: zend_hash_internal_pointer_reset(fn->responseParameters);
! 272: while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
! 273: param = (*h_param);
! 274: if (fnb->style == SOAP_DOCUMENT) {
! 275: if (param->element) {
! 276: name = param->element->name;
! 277: ns = param->element->namens;
! 278: /*
! 279: name = param->encode->details.type_str;
! 280: ns = param->encode->details.ns;
! 281: */
! 282: } else {
! 283: name = param->paramName;
! 284: }
! 285: } else {
! 286: name = fn->responseName;
! 287: /* ns = ? */
! 288: }
! 289:
! 290: /* Get value of parameter */
! 291: cur = get_node_ex(resp, name, ns);
! 292: if (!cur) {
! 293: cur = get_node(resp, name);
! 294: /* TODO: produce warning invalid ns */
! 295: }
! 296: if (!cur && fnb->style == SOAP_RPC) {
! 297: cur = resp;
! 298: }
! 299: if (cur) {
! 300: if (fnb->style == SOAP_DOCUMENT) {
! 301: val = cur;
! 302: } else {
! 303: val = get_node(cur->children, param->paramName);
! 304: if (res_count == 1) {
! 305: if (val == NULL) {
! 306: val = get_node(cur->children, "return");
! 307: }
! 308: if (val == NULL) {
! 309: val = get_node(cur->children, "result");
! 310: }
! 311: if (val == NULL && cur->children && cur->children->next == NULL) {
! 312: val = cur->children;
! 313: }
! 314: }
! 315: }
! 316: }
! 317:
! 318: if (!val) {
! 319: /* TODO: may be "nil" is not OK? */
! 320: MAKE_STD_ZVAL(tmp);
! 321: ZVAL_NULL(tmp);
! 322: /*
! 323: add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
! 324: xmlFreeDoc(response);
! 325: return FALSE;
! 326: */
! 327: } else {
! 328: /* Decoding value of parameter */
! 329: if (param != NULL) {
! 330: tmp = master_to_zval(param->encode, val);
! 331: } else {
! 332: tmp = master_to_zval(NULL, val);
! 333: }
! 334: }
! 335: add_assoc_zval(return_value, param->paramName, tmp);
! 336:
! 337: param_count++;
! 338:
! 339: zend_hash_move_forward(fn->responseParameters);
! 340: }
! 341: }
! 342: } else {
! 343: /* Function has no WSDL description */
! 344: xmlNodePtr val;
! 345: val = resp->children;
! 346: while (val != NULL) {
! 347: while (val && val->type != XML_ELEMENT_NODE) {
! 348: val = val->next;
! 349: }
! 350: if (val != NULL) {
! 351: if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) {
! 352: zval *tmp;
! 353: zval **arr;
! 354:
! 355: tmp = master_to_zval(NULL, val);
! 356: if (val->name) {
! 357: if (zend_hash_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name)+1, (void**)&arr) == SUCCESS) {
! 358: add_next_index_zval(*arr, tmp);
! 359: } else if (val->next && get_node(val->next, (char*)val->name)) {
! 360: zval *arr;
! 361:
! 362: MAKE_STD_ZVAL(arr);
! 363: array_init(arr);
! 364: add_next_index_zval(arr, tmp);
! 365: add_assoc_zval(return_value, (char*)val->name, arr);
! 366: } else {
! 367: add_assoc_zval(return_value, (char*)val->name, tmp);
! 368: }
! 369: } else {
! 370: add_next_index_zval(return_value, tmp);
! 371: }
! 372: ++param_count;
! 373: }
! 374: val = val->next;
! 375: }
! 376: }
! 377: }
! 378: }
! 379:
! 380: if (Z_TYPE_P(return_value) == IS_ARRAY) {
! 381: if (param_count == 0) {
! 382: zval_dtor(return_value);
! 383: ZVAL_NULL(return_value);
! 384: } else if (param_count == 1) {
! 385: zval *tmp;
! 386:
! 387: zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
! 388: zend_hash_get_current_data(Z_ARRVAL_P(return_value), (void**)&tmp);
! 389: tmp = *(zval**)tmp;
! 390: Z_ADDREF_P(tmp);
! 391: zval_dtor(return_value);
! 392: *return_value = *tmp;
! 393: FREE_ZVAL(tmp);
! 394: }
! 395: }
! 396:
! 397: if (soap_headers && head) {
! 398: trav = head->children;
! 399: while (trav != NULL) {
! 400: if (trav->type == XML_ELEMENT_NODE) {
! 401: encodePtr enc = NULL;
! 402: zval* val;
! 403:
! 404: if (hdrs) {
! 405: smart_str key = {0};
! 406: sdlSoapBindingFunctionHeaderPtr *hdr;
! 407:
! 408: if (trav->ns) {
! 409: smart_str_appends(&key, (char*)trav->ns->href);
! 410: smart_str_appendc(&key,':');
! 411: }
! 412: smart_str_appends(&key, (char*)trav->name);
! 413: smart_str_0(&key);
! 414: if (zend_hash_find(hdrs, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
! 415: enc = (*hdr)->encode;
! 416: }
! 417: smart_str_free(&key);
! 418: }
! 419: val = master_to_zval(enc, trav);
! 420: add_assoc_zval(soap_headers, (char*)trav->name, val);
! 421: }
! 422: trav = trav->next;
! 423: }
! 424: }
! 425:
! 426: xmlFreeDoc(response);
! 427: return TRUE;
! 428: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>