php_xml.c 7.4 KB

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