Annotation of embedaddon/php/ext/soap/php_packet_soap.c, revision 1.1.1.2

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: */
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      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) {
1.1.1.2 ! misho     194:                                zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1       misho     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) {
1.1.1.2 ! misho     201:                                zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1       misho     202:                                faultactor = Z_STRVAL_P(zv);
                    203:                                FREE_ZVAL(zv);
                    204:                        }
                    205: 
                    206:                        tmp = get_node(fault->children, "detail");
                    207:                        if (tmp != NULL) {
1.1.1.2 ! misho     208:                                details = master_to_zval(NULL, tmp TSRMLS_CC);
1.1       misho     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) {
1.1.1.2 ! misho     224:                                        zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1       misho     225:                                        faultstring = Z_STRVAL_P(zv);
                    226:                                        FREE_ZVAL(zv);
                    227:                                }
                    228:                        }
                    229: 
                    230:                        tmp = get_node(fault->children,"Detail");
                    231:                        if (tmp != NULL) {
1.1.1.2 ! misho     232:                                details = master_to_zval(NULL, tmp TSRMLS_CC);
1.1       misho     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) {
1.1.1.2 ! misho     328:                                                        tmp = master_to_zval(param->encode, val TSRMLS_CC);
1.1       misho     329:                                                } else {
1.1.1.2 ! misho     330:                                                        tmp = master_to_zval(NULL, val TSRMLS_CC);
1.1       misho     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: 
1.1.1.2 ! misho     353:                                                tmp = master_to_zval(NULL, val TSRMLS_CC);
1.1       misho     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:                                }
1.1.1.2 ! misho     417:                                val = master_to_zval(enc, trav TSRMLS_CC);
1.1       misho     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>