text: /*
    +----------------------------------------------------------------------+
    | PHP Version 5                                                        |
    +----------------------------------------------------------------------+
    | Copyright (c) 1997-2011 The PHP Group                                |
    +----------------------------------------------------------------------+
    | This source file is subject to version 3.01 of the PHP license,      |
    | that is bundled with this package in the file LICENSE, and is        |
    | available through the world-wide-web at the following url:           |
    | http://www.php.net/license/3_01.txt                                  |
    | If you did not receive a copy of the PHP license and are unable to   |
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
    | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
    |          Shane Caraveo <shane@caraveo.com>                           |
    |          Dmitry Stogov <dmitry@zend.com>                             |
    +----------------------------------------------------------------------+
  */
  /* $Id: php_xml.c 306939 2011-01-01 02:19:59Z felipe $ */
  
  #include "php_soap.h"
  #include "libxml/parser.h"
  #include "libxml/parserInternals.h"
  
  /* Channel libxml file io layer through the PHP streams subsystem.
   * This allows use of ftps:// and https:// urls */
  
  static int is_blank(const xmlChar* 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);
  	}
  }
  
  static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
  {
  }
  
  static void soap_Comment(void *ctx, const xmlChar *value)
  {
  }
  
  xmlDocPtr soap_xmlParseFile(const char *filename TSRMLS_DC)
  {
  	xmlParserCtxtPtr ctxt = NULL;
  	xmlDocPtr ret;
  	zend_bool old_allow_url_fopen;
  
  /*
  	xmlInitParser();
  */
  
  	old_allow_url_fopen = PG(allow_url_fopen);
  	PG(allow_url_fopen) = 1;
  	ctxt = xmlCreateFileParserCtxt(filename);
  	PG(allow_url_fopen) = old_allow_url_fopen;
  	if (ctxt) {
  		ctxt->keepBlanks = 0;
  		ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
  		ctxt->sax->comment = soap_Comment;
  		ctxt->sax->warning = NULL;
  		ctxt->sax->error = NULL;
  		/*ctxt->sax->fatalError = NULL;*/
  		xmlParseDocument(ctxt);
  		if (ctxt->wellFormed) {
  			ret = ctxt->myDoc;
  			if (ret->URL == NULL && ctxt->directory != NULL) {
  				ret->URL = xmlCharStrdup(ctxt->directory);
  			}
  		} else {
  			ret = NULL;
  			xmlFreeDoc(ctxt->myDoc);
  			ctxt->myDoc = NULL;
  		}
  		xmlFreeParserCtxt(ctxt);
  	} else {
  		ret = NULL;
  	}
  
  /*
  	xmlCleanupParser();
  */
  
  	if (ret) {
  		cleanup_xml_node((xmlNodePtr)ret);
  	}
  	return ret;
  }
  
  xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
  {
  	xmlParserCtxtPtr ctxt = NULL;
  	xmlDocPtr ret;
  
  /*
  	xmlInitParser();
  */
  	ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
  	if (ctxt) {
  		ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
  		ctxt->sax->comment = soap_Comment;
  		ctxt->sax->warning = NULL;
  		ctxt->sax->error = NULL;
  		/*ctxt->sax->fatalError = NULL;*/
  #if LIBXML_VERSION >= 20703
  		ctxt->options |= XML_PARSE_HUGE;
  #endif
  		xmlParseDocument(ctxt);
  		if (ctxt->wellFormed) {
  			ret = ctxt->myDoc;
  			if (ret->URL == NULL && ctxt->directory != NULL) {
  				ret->URL = xmlCharStrdup(ctxt->directory);
  			}
  		} else {
  			ret = NULL;
  			xmlFreeDoc(ctxt->myDoc);
  			ctxt->myDoc = NULL;
  		}
  		xmlFreeParserCtxt(ctxt);
  	} else {
  		ret = NULL;
  	}
  
  /*
  	xmlCleanupParser();
  */
  
  /*
  	if (ret) {
  		cleanup_xml_node((xmlNodePtr)ret);
  	}
  */
  	return ret;
  }
  
  #ifndef ZEND_ENGINE_2
  int php_stream_xmlIO_match_wrapper(const char *filename)
  {
  	TSRMLS_FETCH();
  	return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
  }
  
  void *php_stream_xmlIO_open_wrapper(const char *filename)
  {
  	TSRMLS_FETCH();
  	return php_stream_open_wrapper((char*)filename, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
  }
  
  int php_stream_xmlIO_read(void *context, char *buffer, int len)
  {
  	TSRMLS_FETCH();
  	return php_stream_read((php_stream*)context, buffer, len);
  }
  
  int php_stream_xmlIO_close(void *context)
  {
  	TSRMLS_FETCH();
  	return php_stream_close((php_stream*)context);
  }
  #endif
  
  xmlNsPtr attr_find_ns(xmlAttrPtr node)
  {
  	if (node->ns) {
  		return node->ns;
  	} else if (node->parent->ns) {
  		return node->parent->ns;
  	} else {
  		return xmlSearchNs(node->doc, node->parent, NULL);
  	}
  }
  
  xmlNsPtr node_find_ns(xmlNodePtr node)
  {
  	if (node->ns) {
  		return node->ns;
  	} else {
  		return xmlSearchNs(node->doc, node, NULL);
  	}
  }
  
  int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
  {
  	if (name == NULL || strcmp((char*)node->name, name) == 0) {
  		if (ns) {
  			xmlNsPtr nsPtr = attr_find_ns(node);
  			if (nsPtr) {
  				return (strcmp((char*)nsPtr->href, ns) == 0);
  			} else {
  				return FALSE;
  			}
  		}
  		return TRUE;
  	}
  	return FALSE;
  }
  
  int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
  {
  	if (name == NULL || strcmp((char*)node->name, name) == 0) {
  		if (ns) {
  			xmlNsPtr nsPtr = node_find_ns(node);
  			if (nsPtr) {
  				return (strcmp((char*)nsPtr->href, ns) == 0);
  			} else {
  				return FALSE;
  			}
  		}
  		return TRUE;
  	}
  	return FALSE;
  }
  
  
  xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
  {
  	while (node!=NULL) {
  		if (attr_is_equal_ex(node, name, ns)) {
  			return node;
  		}
  		node = node->next;
  	}
  	return NULL;
  }
  
  xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
  {
  	while (node!=NULL) {
  		if (node_is_equal_ex(node, name, ns)) {
  			return node;
  		}
  		node = node->next;
  	}
  	return NULL;
  }
  
  xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
  {
  	while (node != NULL) {
  		if (node_is_equal_ex(node, name, ns)) {
  			return node;
  		} else if (node->children != NULL) {
  			xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
  			if (tmp) {
  				return tmp;
  			}
  		}
  		node = node->next;
  	}
  	return NULL;
  }
  
  xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
  {
  	xmlAttrPtr attr;
  
  	while (node != NULL) {
  		if (name != NULL) {
  			node = get_node_ex(node, name, name_ns);
  			if (node==NULL) {
  				return NULL;
  			}
  		}
  
  		attr = get_attribute_ex(node->properties, attribute, attr_ns);
  		if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
  			return node;
  		}
  		node = node->next;
  	}
  	return NULL;
  }
  
  xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
  {
  	while (node != NULL) {
  		if (node_is_equal_ex(node, name, name_ns)) {
  			xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
  			if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
  				return node;
  			}
  		}
  		if (node->children != NULL) {
  			xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
  			if (tmp) {
  				return tmp;
  			}
  		}
  		node = node->next;
  	}
  	return NULL;
  }
  
  int parse_namespace(const xmlChar *inval, char **value, char **namespace)
  {
  	char *found = strrchr((char*)inval, ':');
  
  	if (found != NULL && found != (char*)inval) {
  		(*namespace) = estrndup((char*)inval, found - (char*)inval);
  		(*value) = estrdup(++found);
  	} else {
  		(*value) = estrdup((char*)inval);
  		(*namespace) = NULL;
  	}
  
  	return FALSE;
  }
  