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>