]> granicus.if.org Git - php/commitdiff
SOAP 1.2 specification conformity was improved
authorDmitry Stogov <dmitry@php.net>
Fri, 30 Jan 2004 15:07:19 +0000 (15:07 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 30 Jan 2004 15:07:19 +0000 (15:07 +0000)
ext/soap/TODO
ext/soap/php_encoding.c
ext/soap/php_http.c
ext/soap/php_packet_soap.c
ext/soap/php_schema.c
ext/soap/php_sdl.c
ext/soap/php_xml.c
ext/soap/php_xml.h
ext/soap/soap.c

index 3da3773d6b79bf4f2bd33e430fba1237b9197bff..2bda464236d0d855c511594cdbcbb86cf1c36d65 100644 (file)
@@ -9,7 +9,6 @@ General
 
 SOAP
 ----
-- SOAP message MUST NOT contain Processing Instructions <?xml-stylesheet ... ?> (XML_PI_NODE)
 - support for SOAP headers
   - actor attribute
   - mustUnderstend attribute
index a138eae329c4784dfbd4277713370481854536c6..2e9eb23b065b3f68345353efd7118d9fa0f067b8 100644 (file)
@@ -2321,19 +2321,20 @@ static xmlNodePtr check_and_resolve_href(xmlNodePtr data)
                /* SOAP 1.2 enc:id enc:ref */
                href = get_attribute_ex(data->properties, "ref", SOAP_1_2_ENC_NAMESPACE);
                if (href) {
-                       /*  Internal href try and find node */
+                       char* id;
+
                        if (href->children->content[0] == '#') {
-                               xmlNodePtr ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", &href->children->content[1], SOAP_1_2_ENC_NAMESPACE);
-                               if (!ret) {
-                                       php_error(E_ERROR,"SOAP-ERROR: Encoding: Unresolved reference '%s'",href->children->content);
-                               } else if (ret == data) {
-                                       php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of id and ref information items '%s'",href->children->content);
-                               }
-                               return ret;
+                               id = href->children->content+1;
                        } else {
-                               /*  TODO: External href....? */
-                               php_error(E_ERROR,"SOAP-ERROR: Encoding: External reference '%s'",href->children->content);
+                               id = href->children->content;
+                       }
+                       xmlNodePtr ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", id, SOAP_1_2_ENC_NAMESPACE);
+                       if (!ret) {
+                               php_error(E_ERROR,"SOAP-ERROR: Encoding: Unresolved reference '%s'",href->children->content);
+                       } else if (ret == data) {
+                               php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of id and ref information items '%s'",href->children->content);
                        }
+                       return ret;
                }
        }
        return data;
@@ -2513,13 +2514,13 @@ static void get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_
                        } else {
                          cur_stype = NULL;
                        }
-                       
+
                        if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_ns", sizeof("enc_ns"), (void **)&ztype) == SUCCESS) {
                          cur_ns = Z_STRVAL_PP(ztype);
                        } else {
                          cur_ns = NULL;
                        }
-                               
+
                } else if (Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp)) {
                        cur_type = APACHE_MAP;
                  cur_stype = NULL;
index f2f8da2fbd342d5389a0fce17a3ccab369bcbd89..e4a6c9e0e74f4bbe31e4a06fab97e87fd01ffad0 100644 (file)
@@ -90,7 +90,7 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, in
 #endif
        int port;
        int old_error_reporting;
-       
+
        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
            Z_TYPE_PP(proxy_host) == IS_STRING &&
            zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
@@ -134,14 +134,14 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, in
                smart_str_append_const(&soap_headers, "\r\n");
                if (php_stream_write(stream, soap_headers.c, soap_headers.len) != soap_headers.len) {
                        php_stream_close(stream);
-                       stream = NULL;                                          
+                       stream = NULL;
                }
                smart_str_free(&soap_headers);
 
                if (stream) {
                        if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC) || http_headers == NULL) {
                                php_stream_close(stream);
-                               stream = NULL;                                          
+                               stream = NULL;
                        }
                        efree(http_headers);
                }
@@ -222,7 +222,15 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so
                return FALSE;
        }
 
-       use_ssl = strcmp(phpurl->scheme, "https") == 0;
+       use_ssl = 0;
+       if (strcmp(phpurl->scheme, "https") == 0) {
+               use_ssl = 1;
+       } else if (strcmp(phpurl->scheme, "http") != 0) {
+               xmlFree(buf);
+               php_url_free(phpurl);
+               add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL TSRMLS_CC);
+               return FALSE;
+       }
 #ifdef ZEND_ENGINE_2
        if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) == NULL) {
                xmlFree(buf);
@@ -257,7 +265,7 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so
                        add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL TSRMLS_CC);
                        return FALSE;
                }
-       } 
+       }
 
        if (stream) {
                zval **cookies, **login, **password;
index 54c38ad27f6b1d1703652a43cc05202dbb3b7e70..03315c586d11f971b7bec03f0835af86b90b31e9 100644 (file)
@@ -27,6 +27,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
        char* envelope_ns = NULL;
        xmlDocPtr response;
        xmlNodePtr trav, env, head, body, resp, cur, fault;
+       xmlAttrPtr attr;
        int param_count = 0;
        int old_error_reporting;
        int soap_version;
@@ -48,6 +49,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
        }
        if (xmlGetIntSubset(response) != NULL) {
                add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL TSRMLS_CC);
+               xmlFreeDoc(response);
                return FALSE;
        }
 
@@ -65,7 +67,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
                                envelope_ns = SOAP_1_2_ENV_NAMESPACE;
                                soap_version = SOAP_1_2;
                        } else {
-                               add_soap_fault(this_ptr, "Client", "looks like we got bad SOAP response\n", NULL, NULL TSRMLS_CC);
+                               add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL TSRMLS_CC);
                                xmlFreeDoc(response);
                                return FALSE;
                        }
@@ -73,11 +75,25 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
                trav = trav->next;
        }
        if (env == NULL) {
-               add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element\n", NULL, NULL TSRMLS_CC);
+               add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL TSRMLS_CC);
                xmlFreeDoc(response);
                return FALSE;
        }
 
+       attr = env->properties;
+       while (attr != NULL) {
+               if (attr->ns == NULL) {
+                       add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
+                       xmlFreeDoc(response);
+                       return FALSE;
+               } else if (soap_version == SOAP_1_2 && attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
+                       add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL TSRMLS_CC);
+                       xmlFreeDoc(response);
+                       return FALSE;
+               }
+               attr = attr->next;
+       }
+
        /* Get <Header> element */
        head = NULL;
        trav = env->children;
@@ -91,20 +107,29 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
 
        /* Get <Body> element */
        body = NULL;
-       while (trav != NULL) {
-               if (trav->type == XML_ELEMENT_NODE) {
-                       if (body == NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
-                               body = trav;
-                       } else {
-                               add_soap_fault(this_ptr, "Client", "looks like we got bad SOAP response\n", NULL, NULL TSRMLS_CC);
-                               xmlFreeDoc(response);
-                               return FALSE;
-                       }
-               }
+       while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
+               trav = trav->next;
+       }
+       if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
+               body = trav;
+               trav = trav->next;
+       }
+       while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
        }
        if (body == NULL) {
-               add_soap_fault(this_ptr, "Client", "looks like we got \"Envelope\" without \"Body\" element\n", NULL, NULL TSRMLS_CC);
+               add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL TSRMLS_CC);
+               xmlFreeDoc(response);
+               return FALSE;
+       }
+       attr = get_attribute_ex(body->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
+       if (attr && soap_version == SOAP_1_2) {
+               add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL TSRMLS_CC);
+               xmlFreeDoc(response);
+               return FALSE;
+       }
+       if (trav != NULL && soap_version == SOAP_1_2) {
+               add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL TSRMLS_CC);
                xmlFreeDoc(response);
                return FALSE;
        }
index cd114ca33b72ca25b913a9332da81f75183ca50c..69372c39ce5754d0d1aa005c8e89ce4695778d2e 100644 (file)
@@ -115,48 +115,6 @@ static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char
        return enc;
 }
 
-static int is_blank(const char* str)
-{
-       while (*str != '\0') {
-               if (*str != ' '  && *str != 0x9 && *str != 0xa && *str != 0xd) {
-                       return 0;
-               }
-               str++;
-       }
-       return 1;
-}
-
-/* removes all empty text, comments and other insignoficant nodes */
-static void schema_cleanup(xmlNodePtr schema)
-{
-       xmlNodePtr trav;
-       xmlNodePtr del = NULL;
-
-       trav = schema->children;
-       while (trav != NULL) {
-               if (del != NULL) {
-                       xmlUnlinkNode(del);
-                       xmlFreeNode(del);
-                       del = NULL;
-               }
-               if (trav->type == XML_TEXT_NODE) {
-                       if (is_blank(trav->content)) {
-                               del = trav;
-                       }
-               } else if ((trav->type != XML_ELEMENT_NODE) &&
-                          (trav->type != XML_CDATA_SECTION_NODE)) {
-                       del = trav;
-               } else if (trav->children != NULL) {
-                       schema_cleanup(trav);
-               }
-               trav = trav->next;
-       }
-       if (del != NULL) {
-               xmlUnlinkNode(del);
-               xmlFreeNode(del);
-       }
-}
-
 static void schema_load_file(sdlPtr sdl, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import) {
        if (location != NULL &&
            !zend_hash_exists(&sdl->docs, location, strlen(location)+1)) {
@@ -169,6 +127,7 @@ static void schema_load_file(sdlPtr sdl, xmlAttrPtr ns, xmlChar *location, xmlAt
                if (doc == NULL) {
                        php_error(E_ERROR, "SOAP-ERROR: Parsing Schema: can't import schema from '%s'",location);
                }
+               cleanup_xml(doc);
                schema = get_node(doc->children, "schema");
                if (schema == NULL) {
                        xmlFreeDoc(doc);
@@ -226,7 +185,6 @@ int load_schema(sdlPtr sdl,xmlNodePtr schema)
        xmlNodePtr trav;
        xmlAttrPtr tns;
 
-       schema_cleanup(schema);
        if (!sdl->types) {
                sdl->types = malloc(sizeof(HashTable));
                zend_hash_init(sdl->types, 0, NULL, delete_type, 1);
index 28edfd08c26a0e5285ea0b0fe35508dfd0e70895..54b82fcd1478dfacc58aab90bb0b66ac34792756 100644 (file)
@@ -178,6 +178,7 @@ static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include)
        if (!wsdl) {
                php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Couldn't load from '%s'", struri);
        }
+       cleanup_xml(wsdl);
 
        zend_hash_add(&tmpsdl->docs, struri, strlen(struri)+1, (void**)&wsdl, sizeof(xmlDocPtr), NULL);
 
index f2a50b50f9d59b0a49bec4aa2e04f2e2254135a6..65e058c2bfd2893f7bedaf808e6de571f7785f6c 100644 (file)
@@ -194,3 +194,50 @@ int parse_namespace(const char *inval, char **value, char **namespace)
 
        return FALSE;
 }
+
+static int is_blank(const char* str)
+{
+       while (*str != '\0') {
+               if (*str != ' '  && *str != 0x9 && *str != 0xa && *str != 0xd) {
+                       return 0;
+               }
+               str++;
+       }
+       return 1;
+}
+
+/* removes all empty text, comments and other insignoficant nodes */
+static void cleanup_xml_node(xmlNodePtr node)
+{
+       xmlNodePtr trav;
+       xmlNodePtr del = NULL;
+
+       trav = node->children;
+       while (trav != NULL) {
+               if (del != NULL) {
+                       xmlUnlinkNode(del);
+                       xmlFreeNode(del);
+                       del = NULL;
+               }
+               if (trav->type == XML_TEXT_NODE) {
+                       if (is_blank(trav->content)) {
+                               del = trav;
+                       }
+               } else if ((trav->type != XML_ELEMENT_NODE) &&
+                          (trav->type != XML_CDATA_SECTION_NODE)) {
+                       del = trav;
+               } else if (trav->children != NULL) {
+                       cleanup_xml_node(trav);
+               }
+               trav = trav->next;
+       }
+       if (del != NULL) {
+               xmlUnlinkNode(del);
+               xmlFreeNode(del);
+       }
+}
+
+void cleanup_xml(xmlDocPtr doc)
+{
+       cleanup_xml_node((xmlNodePtr)doc);
+}
index f223aac6d30bbbb0183b9519bed0ac9f5808cb26..eb34d2db11fbc1f9c95143bcda1eedf6a310b16b 100644 (file)
@@ -41,6 +41,8 @@ xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns
 xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns);
 int parse_namespace(const char *inval,char **value,char **namespace);
 
+void cleanup_xml(xmlDocPtr doc);
+
 int php_stream_xmlIO_match_wrapper(const char *filename);
 void *php_stream_xmlIO_open_wrapper(const char *filename);
 int php_stream_xmlIO_read(void *context, char *buffer, int len);
index 4e1f3e923cebb6e7098cc76d42c700fc77d9b5ba..cfae730052c88071c06b3b85c5605050b33840f9 100644 (file)
@@ -1205,23 +1205,52 @@ PHP_METHOD(soapserver, handle)
        SOAP_SERVER_END_CODE();
 }
 
-static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
+static void soap_server_fault(char* code, char* string, char *actor, zval* details)
 {
-       char buffer[1024];
-       int buffer_len;
        int soap_version;
+       xmlChar *buf, cont_len[30];
+       int size;
+       zval ret;
+       xmlDocPtr doc_return;
+       TSRMLS_FETCH();
+
+       soap_version = SOAP_GLOBAL(soap_version);
+
+       INIT_ZVAL(ret);
+
+       set_soap_fault(&ret, code, string, actor, details TSRMLS_CC);
+
+       doc_return = seralize_response_call(NULL, NULL, NULL, &ret, soap_version TSRMLS_CC);
+
+       xmlDocDumpMemory(doc_return, &buf, &size);
+
+       /*
+          Want to return HTTP 500 but apache wants to over write
+          our fault code with their own handling... Figure this out later
+       */
+       sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error"), 1);
+       sprintf(cont_len,"Content-Length: %d", size);
+       sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
+       if (soap_version == SOAP_1_2) {
+               sapi_add_header("Content-Type: application/soap+xml; charset=\"utf-8\"", sizeof("Content-Type: application/soap+xml; charset=\"utf-8\""), 1);
+       } else {
+               sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
+       }
+       php_write(buf, size TSRMLS_CC);
+
+       xmlFreeDoc(doc_return);
+       xmlFree(buf);
+       zend_bailout();
+}
+
+static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
+{
        TSRMLS_FETCH();
 
        if (!SOAP_GLOBAL(use_soap_error_handler)) {
                old_error_handler(error_num, error_filename, error_lineno, format, args);
                return;
        }
-       soap_version = SOAP_GLOBAL(soap_version);
-       buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
-       buffer[sizeof(buffer)-1]=0;
-       if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
-               buffer_len = sizeof(buffer) - 1;
-       }
 
        /*
          Trap all errors
@@ -1230,14 +1259,19 @@ static void soap_error_handler(int error_num, const char *error_filename, const
         */
        if (error_num == E_USER_ERROR || error_num == E_COMPILE_ERROR || error_num == E_CORE_ERROR ||
                error_num == E_ERROR || error_num == E_PARSE) {
-               zval outbuf, outbuflen, ret;
-               xmlChar *buf, cont_len[30];
-               int size;
-               xmlDocPtr doc_return;
+
+               char buffer[1024];
+               int buffer_len;
+               zval outbuf, outbuflen;
 
                INIT_ZVAL(outbuf);
                INIT_ZVAL(outbuflen);
-               INIT_ZVAL(ret);
+
+               buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
+               buffer[sizeof(buffer)-1]=0;
+               if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
+                       buffer_len = sizeof(buffer) - 1;
+               }
 
                /* Get output buffer and send as fault detials */
                if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
@@ -1245,37 +1279,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const
                }
                php_end_ob_buffer(0, 0 TSRMLS_CC);
 
-               set_soap_fault(&ret, "Server", buffer, NULL, &outbuf TSRMLS_CC);
-               doc_return = seralize_response_call(NULL, NULL, NULL, &ret, soap_version TSRMLS_CC);
-
-               /*
-                 xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8);
-               */
-               xmlDocDumpMemory(doc_return, &buf, &size);
-
-               /*
-                  Want to return HTTP 500 but apache wants to over write
-                  our fault code with their own handling... Figure this out later
-               */
-               sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error"), 1);
-               sprintf(cont_len,"Content-Length: %d", size);
-               sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
-               if (soap_version == SOAP_1_2) {
-                       sapi_add_header("Content-Type: application/soap+xml; charset=\"utf-8\"", sizeof("Content-Type: application/soap+xml; charset=\"utf-8\""), 1);
-               } else {
-                       sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
-               }
-               php_write(buf, size TSRMLS_CC);
-
-               xmlFreeDoc(doc_return);
-               xmlFree(buf);
-
-               zval_dtor(&outbuf);
-               zval_dtor(&outbuflen);
-/* ???
-               zval_dtor(&ret);
-*/
-               zend_bailout();
+               soap_server_fault("Server", buffer, NULL, &outbuf TSRMLS_CC);
        }
 }
 
@@ -1727,6 +1731,9 @@ static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char
                        } else if (strcmp(fault_code,"Server") == 0) {
                                smart_str_appendl(&code, SOAP_1_1_ENV_NS_PREFIX, sizeof(SOAP_1_1_ENV_NS_PREFIX)-1);
                                smart_str_appendc(&code, ':');
+                       } else if (strcmp(fault_code,"VersionMismatch") == 0) {
+                               smart_str_appendl(&code, SOAP_1_1_ENV_NS_PREFIX, sizeof(SOAP_1_1_ENV_NS_PREFIX)-1);
+                               smart_str_appendc(&code, ':');
                        }
                        smart_str_appends(&code,fault_code);
                } else if (soap_version == SOAP_1_2) {
@@ -1738,6 +1745,9 @@ static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char
                                smart_str_appendl(&code, SOAP_1_2_ENV_NS_PREFIX, sizeof(SOAP_1_2_ENV_NS_PREFIX)-1);
                                smart_str_appendc(&code, ':');
                                smart_str_appendl(&code,"Receiver",sizeof("Receiver")-1);
+                       } else if (strcmp(fault_code,"VersionMismatch") == 0) {
+                               smart_str_appendl(&code, SOAP_1_2_ENV_NS_PREFIX, sizeof(SOAP_1_2_ENV_NS_PREFIX)-1);
+                               smart_str_appendc(&code, ':');
                        } else {
                                smart_str_appends(&code,fault_code);
                        }
@@ -1758,6 +1768,7 @@ static void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *functi
 {
        char* envelope_ns = NULL;
        xmlNodePtr trav,env,head,body,func;
+       xmlAttrPtr attr;
        int cur_param = 0,num_of_params = 0;
        zval tmp_function_name, **tmp_parameters = NULL;
        sdlFunctionPtr function;
@@ -1780,13 +1791,23 @@ static void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *functi
                                envelope_ns = SOAP_1_2_ENV_NAMESPACE;
                                SOAP_GLOBAL(soap_version) = SOAP_1_2;
                        } else {
-                               php_error(E_ERROR,"looks like we got bad SOAP request\n");
+                               soap_server_fault("VersionMismatch","Wrong Version", NULL, NULL);
                        }
                }
                trav = trav->next;
        }
        if (env == NULL) {
-               php_error(E_ERROR,"looks like we got XML without \"Envelope\" element\n");
+               php_error(E_ERROR,"looks like we got XML without \"Envelope\" element");
+       }
+
+       attr = env->properties;
+       while (attr != NULL) {
+               if (attr->ns == NULL) {
+                       php_error(E_ERROR,"A SOAP Envelope element cannot have non Namespace qualified attributes");
+               } else if (*version == SOAP_1_2 && attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
+                       php_error(E_ERROR,"encodingStyle cannot be specified on the Envelope");
+               }
+               attr = attr->next;
        }
 
        /* Get <Header> element */
@@ -1802,18 +1823,26 @@ static void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *functi
 
        /* Get <Body> element */
        body = NULL;
-       while (trav != NULL) {
-               if (trav->type == XML_ELEMENT_NODE) {
-                       if (body == NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
-                               body = trav;
-                       } else {
-                               php_error(E_ERROR,"looks like we got bad SOAP request\n");
-                       }
-               }
+       while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
+               trav = trav->next;
+       }
+       if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
+               body = trav;
+               trav = trav->next;
+       }
+       while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
        }
        if (body == NULL) {
-               php_error(E_ERROR,"looks like we got \"Envelope\" without \"Body\" element\n");
+               php_error(E_ERROR,"Body must be present in a SOAP envelope");
+       }
+       attr = get_attribute_ex(body->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
+       if (attr && *version == SOAP_1_2) {
+               php_error(E_ERROR,"encodingStyle cannot be specified on the Body");
+       }
+
+       if (trav != NULL && *version == SOAP_1_2) {
+               php_error(E_ERROR,"A SOAP 1.2 envelope can contain only Header and Body");
        }
 
        func = NULL;
@@ -1821,19 +1850,23 @@ static void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *functi
        while (trav != NULL) {
                if (trav->type == XML_ELEMENT_NODE) {
                        if (func != NULL) {
-                               php_error(E_ERROR,"looks like we got \"Body\" with several functions call\n");
+                               php_error(E_ERROR,"looks like we got \"Body\" with several functions call");
                        }
                        func = trav;
                }
                trav = trav->next;
        }
        if (func == NULL) {
-               php_error(E_ERROR,"looks like we got \"Body\" without function call\n");
+               php_error(E_ERROR,"looks like we got \"Body\" without function call");
        }
 
        function = get_function(sdl, func->name);
        if (sdl != NULL && function == NULL) {
-               php_error(E_ERROR, "Error function \"%s\" doesn't exists for this service", func->name);
+               if (*version == SOAP_1_2) {
+                       soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL);
+               } else {
+                       php_error(E_ERROR, "Procedure '%s' not present", func->name);
+               }
        }
 
        INIT_ZVAL(tmp_function_name);
@@ -2047,10 +2080,13 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_
                        parameter = get_param(function, NULL, 0, TRUE);
 
                        if (style == SOAP_RPC) {
-                               param = seralize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
+                         xmlNode *rpc_result;
                                if (version == SOAP_1_2) {
                                        xmlNs *rpc_ns = xmlNewNs(body, RPC_SOAP12_NAMESPACE, RPC_SOAP12_NS_PREFIX);
-                                       xmlNode *rpc_result = xmlNewChild(method, rpc_ns, "result", NULL);
+                                       rpc_result = xmlNewChild(method, rpc_ns, "result", NULL);
+                               }
+                               param = seralize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
+                               if (version == SOAP_1_2) {
                                        xmlNodeSetContent(rpc_result,param->name);
                                }
                        } else {