PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/soap - php_packet_soap.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 162 249 65.1 %
Date: 2014-07-21 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:17 +0000 (3 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.