php_xml.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 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$ */
  21. #include "php_soap.h"
  22. #include "ext/libxml/php_libxml.h"
  23. #include "libxml/parser.h"
  24. #include "libxml/parserInternals.h"
  25. /* Channel libxml file io layer through the PHP streams subsystem.
  26. * This allows use of ftps:// and https:// urls */
  27. static int is_blank(const xmlChar* str)
  28. {
  29. while (*str != '\0') {
  30. if (*str != ' ' && *str != 0x9 && *str != 0xa && *str != 0xd) {
  31. return 0;
  32. }
  33. str++;
  34. }
  35. return 1;
  36. }
  37. /* removes all empty text, comments and other insignoficant nodes */
  38. static void cleanup_xml_node(xmlNodePtr node)
  39. {
  40. xmlNodePtr trav;
  41. xmlNodePtr del = NULL;
  42. trav = node->children;
  43. while (trav != NULL) {
  44. if (del != NULL) {
  45. xmlUnlinkNode(del);
  46. xmlFreeNode(del);
  47. del = NULL;
  48. }
  49. if (trav->type == XML_TEXT_NODE) {
  50. if (is_blank(trav->content)) {
  51. del = trav;
  52. }
  53. } else if ((trav->type != XML_ELEMENT_NODE) &&
  54. (trav->type != XML_CDATA_SECTION_NODE)) {
  55. del = trav;
  56. } else if (trav->children != NULL) {
  57. cleanup_xml_node(trav);
  58. }
  59. trav = trav->next;
  60. }
  61. if (del != NULL) {
  62. xmlUnlinkNode(del);
  63. xmlFreeNode(del);
  64. }
  65. }
  66. static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
  67. {
  68. }
  69. static void soap_Comment(void *ctx, const xmlChar *value)
  70. {
  71. }
  72. xmlDocPtr soap_xmlParseFile(const char *filename TSRMLS_DC)
  73. {
  74. xmlParserCtxtPtr ctxt = NULL;
  75. xmlDocPtr ret;
  76. zend_bool old_allow_url_fopen;
  77. /*
  78. xmlInitParser();
  79. */
  80. old_allow_url_fopen = PG(allow_url_fopen);
  81. PG(allow_url_fopen) = 1;
  82. ctxt = xmlCreateFileParserCtxt(filename);
  83. PG(allow_url_fopen) = old_allow_url_fopen;
  84. if (ctxt) {
  85. zend_bool old;
  86. ctxt->keepBlanks = 0;
  87. ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
  88. ctxt->sax->comment = soap_Comment;
  89. ctxt->sax->warning = NULL;
  90. ctxt->sax->error = NULL;
  91. /*ctxt->sax->fatalError = NULL;*/
  92. #if LIBXML_VERSION >= 20703
  93. ctxt->options |= XML_PARSE_HUGE;
  94. #endif
  95. old = php_libxml_disable_entity_loader(1 TSRMLS_CC);
  96. xmlParseDocument(ctxt);
  97. php_libxml_disable_entity_loader(old TSRMLS_CC);
  98. if (ctxt->wellFormed) {
  99. ret = ctxt->myDoc;
  100. if (ret->URL == NULL && ctxt->directory != NULL) {
  101. ret->URL = xmlCharStrdup(ctxt->directory);
  102. }
  103. } else {
  104. ret = NULL;
  105. xmlFreeDoc(ctxt->myDoc);
  106. ctxt->myDoc = NULL;
  107. }
  108. xmlFreeParserCtxt(ctxt);
  109. } else {
  110. ret = NULL;
  111. }
  112. /*
  113. xmlCleanupParser();
  114. */
  115. if (ret) {
  116. cleanup_xml_node((xmlNodePtr)ret);
  117. }
  118. return ret;
  119. }
  120. xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
  121. {
  122. xmlParserCtxtPtr ctxt = NULL;
  123. xmlDocPtr ret;
  124. TSRMLS_FETCH();
  125. /*
  126. xmlInitParser();
  127. */
  128. ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
  129. if (ctxt) {
  130. zend_bool old;
  131. ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
  132. ctxt->sax->comment = soap_Comment;
  133. ctxt->sax->warning = NULL;
  134. ctxt->sax->error = NULL;
  135. /*ctxt->sax->fatalError = NULL;*/
  136. #if LIBXML_VERSION >= 20703
  137. ctxt->options |= XML_PARSE_HUGE;
  138. #endif
  139. old = php_libxml_disable_entity_loader(1 TSRMLS_CC);
  140. xmlParseDocument(ctxt);
  141. php_libxml_disable_entity_loader(old TSRMLS_CC);
  142. if (ctxt->wellFormed) {
  143. ret = ctxt->myDoc;
  144. if (ret->URL == NULL && ctxt->directory != NULL) {
  145. ret->URL = xmlCharStrdup(ctxt->directory);
  146. }
  147. } else {
  148. ret = NULL;
  149. xmlFreeDoc(ctxt->myDoc);
  150. ctxt->myDoc = NULL;
  151. }
  152. xmlFreeParserCtxt(ctxt);
  153. } else {
  154. ret = NULL;
  155. }
  156. /*
  157. xmlCleanupParser();
  158. */
  159. /*
  160. if (ret) {
  161. cleanup_xml_node((xmlNodePtr)ret);
  162. }
  163. */
  164. return ret;
  165. }
  166. xmlNsPtr attr_find_ns(xmlAttrPtr node)
  167. {
  168. if (node->ns) {
  169. return node->ns;
  170. } else if (node->parent->ns) {
  171. return node->parent->ns;
  172. } else {
  173. return xmlSearchNs(node->doc, node->parent, NULL);
  174. }
  175. }
  176. xmlNsPtr node_find_ns(xmlNodePtr node)
  177. {
  178. if (node->ns) {
  179. return node->ns;
  180. } else {
  181. return xmlSearchNs(node->doc, node, NULL);
  182. }
  183. }
  184. int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
  185. {
  186. if (name == NULL || strcmp((char*)node->name, name) == 0) {
  187. if (ns) {
  188. xmlNsPtr nsPtr = attr_find_ns(node);
  189. if (nsPtr) {
  190. return (strcmp((char*)nsPtr->href, ns) == 0);
  191. } else {
  192. return FALSE;
  193. }
  194. }
  195. return TRUE;
  196. }
  197. return FALSE;
  198. }
  199. int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
  200. {
  201. if (name == NULL || strcmp((char*)node->name, name) == 0) {
  202. if (ns) {
  203. xmlNsPtr nsPtr = node_find_ns(node);
  204. if (nsPtr) {
  205. return (strcmp((char*)nsPtr->href, ns) == 0);
  206. } else {
  207. return FALSE;
  208. }
  209. }
  210. return TRUE;
  211. }
  212. return FALSE;
  213. }
  214. xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
  215. {
  216. while (node!=NULL) {
  217. if (attr_is_equal_ex(node, name, ns)) {
  218. return node;
  219. }
  220. node = node->next;
  221. }
  222. return NULL;
  223. }
  224. xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
  225. {
  226. while (node!=NULL) {
  227. if (node_is_equal_ex(node, name, ns)) {
  228. return node;
  229. }
  230. node = node->next;
  231. }
  232. return NULL;
  233. }
  234. xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
  235. {
  236. while (node != NULL) {
  237. if (node_is_equal_ex(node, name, ns)) {
  238. return node;
  239. } else if (node->children != NULL) {
  240. xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
  241. if (tmp) {
  242. return tmp;
  243. }
  244. }
  245. node = node->next;
  246. }
  247. return NULL;
  248. }
  249. xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
  250. {
  251. xmlAttrPtr attr;
  252. while (node != NULL) {
  253. if (name != NULL) {
  254. node = get_node_ex(node, name, name_ns);
  255. if (node==NULL) {
  256. return NULL;
  257. }
  258. }
  259. attr = get_attribute_ex(node->properties, attribute, attr_ns);
  260. if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
  261. return node;
  262. }
  263. node = node->next;
  264. }
  265. return NULL;
  266. }
  267. xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
  268. {
  269. while (node != NULL) {
  270. if (node_is_equal_ex(node, name, name_ns)) {
  271. xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
  272. if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
  273. return node;
  274. }
  275. }
  276. if (node->children != NULL) {
  277. xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
  278. if (tmp) {
  279. return tmp;
  280. }
  281. }
  282. node = node->next;
  283. }
  284. return NULL;
  285. }
  286. int parse_namespace(const xmlChar *inval, char **value, char **namespace)
  287. {
  288. char *found = strrchr((char*)inval, ':');
  289. if (found != NULL && found != (char*)inval) {
  290. (*namespace) = estrndup((char*)inval, found - (char*)inval);
  291. (*value) = estrdup(++found);
  292. } else {
  293. (*value) = estrdup((char*)inval);
  294. (*namespace) = NULL;
  295. }
  296. return FALSE;
  297. }