Back to index

php5  5.3.10
php_xml.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
00016   |          Shane Caraveo <shane@caraveo.com>                           |
00017   |          Dmitry Stogov <dmitry@zend.com>                             |
00018   +----------------------------------------------------------------------+
00019 */
00020 /* $Id: php_xml.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "php_soap.h"
00023 #include "libxml/parser.h"
00024 #include "libxml/parserInternals.h"
00025 
00026 /* Channel libxml file io layer through the PHP streams subsystem.
00027  * This allows use of ftps:// and https:// urls */
00028 
00029 static int is_blank(const xmlChar* str)
00030 {
00031        while (*str != '\0') {
00032               if (*str != ' '  && *str != 0x9 && *str != 0xa && *str != 0xd) {
00033                      return 0;
00034               }
00035               str++;
00036        }
00037        return 1;
00038 }
00039 
00040 /* removes all empty text, comments and other insignoficant nodes */
00041 static void cleanup_xml_node(xmlNodePtr node)
00042 {
00043        xmlNodePtr trav;
00044        xmlNodePtr del = NULL;
00045 
00046        trav = node->children;
00047        while (trav != NULL) {
00048               if (del != NULL) {
00049                      xmlUnlinkNode(del);
00050                      xmlFreeNode(del);
00051                      del = NULL;
00052               }
00053               if (trav->type == XML_TEXT_NODE) {
00054                      if (is_blank(trav->content)) {
00055                             del = trav;
00056                      }
00057               } else if ((trav->type != XML_ELEMENT_NODE) &&
00058                          (trav->type != XML_CDATA_SECTION_NODE)) {
00059                      del = trav;
00060               } else if (trav->children != NULL) {
00061                      cleanup_xml_node(trav);
00062               }
00063               trav = trav->next;
00064        }
00065        if (del != NULL) {
00066               xmlUnlinkNode(del);
00067               xmlFreeNode(del);
00068        }
00069 }
00070 
00071 static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
00072 {
00073 }
00074 
00075 static void soap_Comment(void *ctx, const xmlChar *value)
00076 {
00077 }
00078 
00079 xmlDocPtr soap_xmlParseFile(const char *filename TSRMLS_DC)
00080 {
00081        xmlParserCtxtPtr ctxt = NULL;
00082        xmlDocPtr ret;
00083        zend_bool old_allow_url_fopen;
00084 
00085 /*
00086        xmlInitParser();
00087 */
00088 
00089        old_allow_url_fopen = PG(allow_url_fopen);
00090        PG(allow_url_fopen) = 1;
00091        ctxt = xmlCreateFileParserCtxt(filename);
00092        PG(allow_url_fopen) = old_allow_url_fopen;
00093        if (ctxt) {
00094               ctxt->keepBlanks = 0;
00095               ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
00096               ctxt->sax->comment = soap_Comment;
00097               ctxt->sax->warning = NULL;
00098               ctxt->sax->error = NULL;
00099               /*ctxt->sax->fatalError = NULL;*/
00100               xmlParseDocument(ctxt);
00101               if (ctxt->wellFormed) {
00102                      ret = ctxt->myDoc;
00103                      if (ret->URL == NULL && ctxt->directory != NULL) {
00104                             ret->URL = xmlCharStrdup(ctxt->directory);
00105                      }
00106               } else {
00107                      ret = NULL;
00108                      xmlFreeDoc(ctxt->myDoc);
00109                      ctxt->myDoc = NULL;
00110               }
00111               xmlFreeParserCtxt(ctxt);
00112        } else {
00113               ret = NULL;
00114        }
00115 
00116 /*
00117        xmlCleanupParser();
00118 */
00119 
00120        if (ret) {
00121               cleanup_xml_node((xmlNodePtr)ret);
00122        }
00123        return ret;
00124 }
00125 
00126 xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
00127 {
00128        xmlParserCtxtPtr ctxt = NULL;
00129        xmlDocPtr ret;
00130 
00131 /*
00132        xmlInitParser();
00133 */
00134        ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
00135        if (ctxt) {
00136               ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
00137               ctxt->sax->comment = soap_Comment;
00138               ctxt->sax->warning = NULL;
00139               ctxt->sax->error = NULL;
00140               /*ctxt->sax->fatalError = NULL;*/
00141 #if LIBXML_VERSION >= 20703
00142               ctxt->options |= XML_PARSE_HUGE;
00143 #endif
00144               xmlParseDocument(ctxt);
00145               if (ctxt->wellFormed) {
00146                      ret = ctxt->myDoc;
00147                      if (ret->URL == NULL && ctxt->directory != NULL) {
00148                             ret->URL = xmlCharStrdup(ctxt->directory);
00149                      }
00150               } else {
00151                      ret = NULL;
00152                      xmlFreeDoc(ctxt->myDoc);
00153                      ctxt->myDoc = NULL;
00154               }
00155               xmlFreeParserCtxt(ctxt);
00156        } else {
00157               ret = NULL;
00158        }
00159 
00160 /*
00161        xmlCleanupParser();
00162 */
00163 
00164 /*
00165        if (ret) {
00166               cleanup_xml_node((xmlNodePtr)ret);
00167        }
00168 */
00169        return ret;
00170 }
00171 
00172 #ifndef ZEND_ENGINE_2
00173 int php_stream_xmlIO_match_wrapper(const char *filename)
00174 {
00175        TSRMLS_FETCH();
00176        return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
00177 }
00178 
00179 void *php_stream_xmlIO_open_wrapper(const char *filename)
00180 {
00181        TSRMLS_FETCH();
00182        return php_stream_open_wrapper((char*)filename, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
00183 }
00184 
00185 int php_stream_xmlIO_read(void *context, char *buffer, int len)
00186 {
00187        TSRMLS_FETCH();
00188        return php_stream_read((php_stream*)context, buffer, len);
00189 }
00190 
00191 int php_stream_xmlIO_close(void *context)
00192 {
00193        TSRMLS_FETCH();
00194        return php_stream_close((php_stream*)context);
00195 }
00196 #endif
00197 
00198 xmlNsPtr attr_find_ns(xmlAttrPtr node)
00199 {
00200        if (node->ns) {
00201               return node->ns;
00202        } else if (node->parent->ns) {
00203               return node->parent->ns;
00204        } else {
00205               return xmlSearchNs(node->doc, node->parent, NULL);
00206        }
00207 }
00208 
00209 xmlNsPtr node_find_ns(xmlNodePtr node)
00210 {
00211        if (node->ns) {
00212               return node->ns;
00213        } else {
00214               return xmlSearchNs(node->doc, node, NULL);
00215        }
00216 }
00217 
00218 int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
00219 {
00220        if (name == NULL || strcmp((char*)node->name, name) == 0) {
00221               if (ns) {
00222                      xmlNsPtr nsPtr = attr_find_ns(node);
00223                      if (nsPtr) {
00224                             return (strcmp((char*)nsPtr->href, ns) == 0);
00225                      } else {
00226                             return FALSE;
00227                      }
00228               }
00229               return TRUE;
00230        }
00231        return FALSE;
00232 }
00233 
00234 int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
00235 {
00236        if (name == NULL || strcmp((char*)node->name, name) == 0) {
00237               if (ns) {
00238                      xmlNsPtr nsPtr = node_find_ns(node);
00239                      if (nsPtr) {
00240                             return (strcmp((char*)nsPtr->href, ns) == 0);
00241                      } else {
00242                             return FALSE;
00243                      }
00244               }
00245               return TRUE;
00246        }
00247        return FALSE;
00248 }
00249 
00250 
00251 xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
00252 {
00253        while (node!=NULL) {
00254               if (attr_is_equal_ex(node, name, ns)) {
00255                      return node;
00256               }
00257               node = node->next;
00258        }
00259        return NULL;
00260 }
00261 
00262 xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
00263 {
00264        while (node!=NULL) {
00265               if (node_is_equal_ex(node, name, ns)) {
00266                      return node;
00267               }
00268               node = node->next;
00269        }
00270        return NULL;
00271 }
00272 
00273 xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
00274 {
00275        while (node != NULL) {
00276               if (node_is_equal_ex(node, name, ns)) {
00277                      return node;
00278               } else if (node->children != NULL) {
00279                      xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
00280                      if (tmp) {
00281                             return tmp;
00282                      }
00283               }
00284               node = node->next;
00285        }
00286        return NULL;
00287 }
00288 
00289 xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
00290 {
00291        xmlAttrPtr attr;
00292 
00293        while (node != NULL) {
00294               if (name != NULL) {
00295                      node = get_node_ex(node, name, name_ns);
00296                      if (node==NULL) {
00297                             return NULL;
00298                      }
00299               }
00300 
00301               attr = get_attribute_ex(node->properties, attribute, attr_ns);
00302               if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
00303                      return node;
00304               }
00305               node = node->next;
00306        }
00307        return NULL;
00308 }
00309 
00310 xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
00311 {
00312        while (node != NULL) {
00313               if (node_is_equal_ex(node, name, name_ns)) {
00314                      xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
00315                      if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
00316                             return node;
00317                      }
00318               }
00319               if (node->children != NULL) {
00320                      xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
00321                      if (tmp) {
00322                             return tmp;
00323                      }
00324               }
00325               node = node->next;
00326        }
00327        return NULL;
00328 }
00329 
00330 int parse_namespace(const xmlChar *inval, char **value, char **namespace)
00331 {
00332        char *found = strrchr((char*)inval, ':');
00333 
00334        if (found != NULL && found != (char*)inval) {
00335               (*namespace) = estrndup((char*)inval, found - (char*)inval);
00336               (*value) = estrdup(++found);
00337        } else {
00338               (*value) = estrdup((char*)inval);
00339               (*namespace) = NULL;
00340        }
00341 
00342        return FALSE;
00343 }