node.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 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: Christian Stocker <chregu@php.net> |
  16. | Rob Richards <rrichards@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #if HAVE_LIBXML && HAVE_DOM
  24. #include "php_dom.h"
  25. /* {{{ arginfo */
  26. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_insert_before, 0, 0, 1)
  27. ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
  28. ZEND_ARG_OBJ_INFO(0, refChild, DOMNode, 1)
  29. ZEND_END_ARG_INFO();
  30. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_replace_child, 0, 0, 2)
  31. ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
  32. ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
  33. ZEND_END_ARG_INFO();
  34. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_remove_child, 0, 0, 1)
  35. ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
  36. ZEND_END_ARG_INFO();
  37. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_append_child, 0, 0, 1)
  38. ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
  39. ZEND_END_ARG_INFO();
  40. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_child_nodes, 0, 0, 0)
  41. ZEND_END_ARG_INFO();
  42. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_clone_node, 0, 0, 0)
  43. ZEND_ARG_INFO(0, deep)
  44. ZEND_END_ARG_INFO();
  45. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_normalize, 0, 0, 0)
  46. ZEND_END_ARG_INFO();
  47. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_supported, 0, 0, 2)
  48. ZEND_ARG_INFO(0, feature)
  49. ZEND_ARG_INFO(0, version)
  50. ZEND_END_ARG_INFO();
  51. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_attributes, 0, 0, 0)
  52. ZEND_END_ARG_INFO();
  53. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_compare_document_position, 0, 0, 1)
  54. ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
  55. ZEND_END_ARG_INFO();
  56. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_same_node, 0, 0, 1)
  57. ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
  58. ZEND_END_ARG_INFO();
  59. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_prefix, 0, 0, 1)
  60. ZEND_ARG_INFO(0, namespaceURI)
  61. ZEND_END_ARG_INFO();
  62. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_default_namespace, 0, 0, 1)
  63. ZEND_ARG_INFO(0, namespaceURI)
  64. ZEND_END_ARG_INFO();
  65. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_namespace_uri, 0, 0, 1)
  66. ZEND_ARG_INFO(0, prefix)
  67. ZEND_END_ARG_INFO();
  68. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_equal_node, 0, 0, 1)
  69. ZEND_ARG_OBJ_INFO(0, arg, DOMNode, 0)
  70. ZEND_END_ARG_INFO();
  71. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_feature, 0, 0, 2)
  72. ZEND_ARG_INFO(0, feature)
  73. ZEND_ARG_INFO(0, version)
  74. ZEND_END_ARG_INFO();
  75. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_set_user_data, 0, 0, 3)
  76. ZEND_ARG_INFO(0, key)
  77. ZEND_ARG_INFO(0, data)
  78. ZEND_ARG_INFO(0, handler)
  79. ZEND_END_ARG_INFO();
  80. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_user_data, 0, 0, 1)
  81. ZEND_ARG_INFO(0, key)
  82. ZEND_END_ARG_INFO();
  83. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getNodePath, 0, 0, 0)
  84. ZEND_END_ARG_INFO();
  85. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getLineNo, 0, 0, 0)
  86. ZEND_END_ARG_INFO();
  87. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14N, 0, 0, 0)
  88. ZEND_ARG_INFO(0, exclusive)
  89. ZEND_ARG_INFO(0, with_comments)
  90. ZEND_ARG_ARRAY_INFO(0, xpath, 1)
  91. ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
  92. ZEND_END_ARG_INFO();
  93. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14NFile, 0, 0, 1)
  94. ZEND_ARG_INFO(0, uri)
  95. ZEND_ARG_INFO(0, exclusive)
  96. ZEND_ARG_INFO(0, with_comments)
  97. ZEND_ARG_ARRAY_INFO(0, xpath, 1)
  98. ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
  99. ZEND_END_ARG_INFO();
  100. /* }}} */
  101. /*
  102. * class DOMNode
  103. *
  104. * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1950641247
  105. * Since:
  106. */
  107. const zend_function_entry php_dom_node_class_functions[] = { /* {{{ */
  108. PHP_FALIAS(insertBefore, dom_node_insert_before, arginfo_dom_node_insert_before)
  109. PHP_FALIAS(replaceChild, dom_node_replace_child, arginfo_dom_node_replace_child)
  110. PHP_FALIAS(removeChild, dom_node_remove_child, arginfo_dom_node_remove_child)
  111. PHP_FALIAS(appendChild, dom_node_append_child, arginfo_dom_node_append_child)
  112. PHP_FALIAS(hasChildNodes, dom_node_has_child_nodes, arginfo_dom_node_has_child_nodes)
  113. PHP_FALIAS(cloneNode, dom_node_clone_node, arginfo_dom_node_clone_node)
  114. PHP_FALIAS(normalize, dom_node_normalize, arginfo_dom_node_normalize)
  115. PHP_FALIAS(isSupported, dom_node_is_supported, arginfo_dom_node_is_supported)
  116. PHP_FALIAS(hasAttributes, dom_node_has_attributes, arginfo_dom_node_has_attributes)
  117. PHP_FALIAS(compareDocumentPosition, dom_node_compare_document_position, arginfo_dom_node_compare_document_position)
  118. PHP_FALIAS(isSameNode, dom_node_is_same_node, arginfo_dom_node_is_same_node)
  119. PHP_FALIAS(lookupPrefix, dom_node_lookup_prefix, arginfo_dom_node_lookup_prefix)
  120. PHP_FALIAS(isDefaultNamespace, dom_node_is_default_namespace, arginfo_dom_node_is_default_namespace)
  121. PHP_FALIAS(lookupNamespaceUri, dom_node_lookup_namespace_uri, arginfo_dom_node_lookup_namespace_uri)
  122. PHP_FALIAS(isEqualNode, dom_node_is_equal_node, arginfo_dom_node_is_equal_node)
  123. PHP_FALIAS(getFeature, dom_node_get_feature, arginfo_dom_node_get_feature)
  124. PHP_FALIAS(setUserData, dom_node_set_user_data, arginfo_dom_node_set_user_data)
  125. PHP_FALIAS(getUserData, dom_node_get_user_data, arginfo_dom_node_get_user_data)
  126. PHP_ME(domnode, getNodePath, arginfo_dom_node_getNodePath, ZEND_ACC_PUBLIC)
  127. PHP_ME(domnode, getLineNo, arginfo_dom_node_getLineNo, ZEND_ACC_PUBLIC)
  128. PHP_ME(domnode, C14N, arginfo_dom_node_C14N, ZEND_ACC_PUBLIC)
  129. PHP_ME(domnode, C14NFile, arginfo_dom_node_C14NFile, ZEND_ACC_PUBLIC)
  130. PHP_FE_END
  131. };
  132. /* }}} */
  133. static void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
  134. {
  135. xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
  136. if (nodep->type == XML_ELEMENT_NODE) {
  137. /* Following if block primarily used for inserting nodes created via createElementNS */
  138. if (nodep->nsDef != NULL) {
  139. curns = nodep->nsDef;
  140. while (curns) {
  141. nsdftptr = curns->next;
  142. if (curns->href != NULL) {
  143. if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
  144. (curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
  145. curns->next = NULL;
  146. if (prevns == NULL) {
  147. nodep->nsDef = nsdftptr;
  148. } else {
  149. prevns->next = nsdftptr;
  150. }
  151. dom_set_old_ns(doc, curns);
  152. curns = prevns;
  153. }
  154. }
  155. prevns = curns;
  156. curns = nsdftptr;
  157. }
  158. }
  159. xmlReconciliateNs(doc, nodep);
  160. }
  161. }
  162. /* }}} */
  163. /* {{{ nodeName string
  164. readonly=yes
  165. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D095
  166. Since:
  167. */
  168. int dom_node_node_name_read(dom_object *obj, zval *retval)
  169. {
  170. xmlNode *nodep;
  171. xmlNsPtr ns;
  172. char *str = NULL;
  173. xmlChar *qname = NULL;
  174. nodep = dom_object_get_node(obj);
  175. if (nodep == NULL) {
  176. php_dom_throw_error(INVALID_STATE_ERR, 0);
  177. return FAILURE;
  178. }
  179. switch (nodep->type) {
  180. case XML_ATTRIBUTE_NODE:
  181. case XML_ELEMENT_NODE:
  182. ns = nodep->ns;
  183. if (ns != NULL && ns->prefix) {
  184. qname = xmlStrdup(ns->prefix);
  185. qname = xmlStrcat(qname, (xmlChar *) ":");
  186. qname = xmlStrcat(qname, nodep->name);
  187. str = (char *) qname;
  188. } else {
  189. str = (char *) nodep->name;
  190. }
  191. break;
  192. case XML_NAMESPACE_DECL:
  193. ns = nodep->ns;
  194. if (ns != NULL && ns->prefix) {
  195. qname = xmlStrdup((xmlChar *) "xmlns");
  196. qname = xmlStrcat(qname, (xmlChar *) ":");
  197. qname = xmlStrcat(qname, nodep->name);
  198. str = (char *) qname;
  199. } else {
  200. str = (char *) nodep->name;
  201. }
  202. break;
  203. case XML_DOCUMENT_TYPE_NODE:
  204. case XML_DTD_NODE:
  205. case XML_PI_NODE:
  206. case XML_ENTITY_DECL:
  207. case XML_ENTITY_REF_NODE:
  208. case XML_NOTATION_NODE:
  209. str = (char *) nodep->name;
  210. break;
  211. case XML_CDATA_SECTION_NODE:
  212. str = "#cdata-section";
  213. break;
  214. case XML_COMMENT_NODE:
  215. str = "#comment";
  216. break;
  217. case XML_HTML_DOCUMENT_NODE:
  218. case XML_DOCUMENT_NODE:
  219. str = "#document";
  220. break;
  221. case XML_DOCUMENT_FRAG_NODE:
  222. str = "#document-fragment";
  223. break;
  224. case XML_TEXT_NODE:
  225. str = "#text";
  226. break;
  227. default:
  228. php_error_docref(NULL, E_WARNING, "Invalid Node Type");
  229. }
  230. if (str != NULL) {
  231. ZVAL_STRING(retval, str);
  232. } else {
  233. ZVAL_EMPTY_STRING(retval);
  234. }
  235. if (qname != NULL) {
  236. xmlFree(qname);
  237. }
  238. return SUCCESS;
  239. }
  240. /* }}} */
  241. /* {{{ nodeValue string
  242. readonly=no
  243. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D080
  244. Since:
  245. */
  246. int dom_node_node_value_read(dom_object *obj, zval *retval)
  247. {
  248. xmlNode *nodep = dom_object_get_node(obj);
  249. char *str = NULL;
  250. if (nodep == NULL) {
  251. php_dom_throw_error(INVALID_STATE_ERR, 0);
  252. return FAILURE;
  253. }
  254. /* Access to Element node is implemented as a convience method */
  255. switch (nodep->type) {
  256. case XML_ATTRIBUTE_NODE:
  257. case XML_TEXT_NODE:
  258. case XML_ELEMENT_NODE:
  259. case XML_COMMENT_NODE:
  260. case XML_CDATA_SECTION_NODE:
  261. case XML_PI_NODE:
  262. str = (char *) xmlNodeGetContent(nodep);
  263. break;
  264. case XML_NAMESPACE_DECL:
  265. str = (char *) xmlNodeGetContent(nodep->children);
  266. break;
  267. default:
  268. str = NULL;
  269. break;
  270. }
  271. if(str != NULL) {
  272. ZVAL_STRING(retval, str);
  273. xmlFree(str);
  274. } else {
  275. ZVAL_NULL(retval);
  276. }
  277. return SUCCESS;
  278. }
  279. int dom_node_node_value_write(dom_object *obj, zval *newval)
  280. {
  281. xmlNode *nodep = dom_object_get_node(obj);
  282. if (nodep == NULL) {
  283. php_dom_throw_error(INVALID_STATE_ERR, 0);
  284. return FAILURE;
  285. }
  286. /* Access to Element node is implemented as a convience method */
  287. switch (nodep->type) {
  288. case XML_ELEMENT_NODE:
  289. case XML_ATTRIBUTE_NODE:
  290. if (nodep->children) {
  291. node_list_unlink(nodep->children);
  292. php_libxml_node_free_list((xmlNodePtr) nodep->children);
  293. nodep->children = NULL;
  294. }
  295. case XML_TEXT_NODE:
  296. case XML_COMMENT_NODE:
  297. case XML_CDATA_SECTION_NODE:
  298. case XML_PI_NODE:
  299. {
  300. zend_string *str = zval_get_string(newval);
  301. xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
  302. zend_string_release_ex(str, 0);
  303. break;
  304. }
  305. default:
  306. break;
  307. }
  308. return SUCCESS;
  309. }
  310. /* }}} */
  311. /* {{{ nodeType int
  312. readonly=yes
  313. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-111237558
  314. Since:
  315. */
  316. int dom_node_node_type_read(dom_object *obj, zval *retval)
  317. {
  318. xmlNode *nodep;
  319. nodep = dom_object_get_node(obj);
  320. if (nodep == NULL) {
  321. php_dom_throw_error(INVALID_STATE_ERR, 0);
  322. return FAILURE;
  323. }
  324. /* Specs dictate that they are both type XML_DOCUMENT_TYPE_NODE */
  325. if (nodep->type == XML_DTD_NODE) {
  326. ZVAL_LONG(retval, XML_DOCUMENT_TYPE_NODE);
  327. } else {
  328. ZVAL_LONG(retval, nodep->type);
  329. }
  330. return SUCCESS;
  331. }
  332. /* }}} */
  333. /* {{{ parentNode DomNode
  334. readonly=yes
  335. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317
  336. Since:
  337. */
  338. int dom_node_parent_node_read(dom_object *obj, zval *retval)
  339. {
  340. xmlNode *nodep, *nodeparent;
  341. nodep = dom_object_get_node(obj);
  342. if (nodep == NULL) {
  343. php_dom_throw_error(INVALID_STATE_ERR, 0);
  344. return FAILURE;
  345. }
  346. nodeparent = nodep->parent;
  347. if (!nodeparent) {
  348. ZVAL_NULL(retval);
  349. return SUCCESS;
  350. }
  351. php_dom_create_object(nodeparent, retval, obj);
  352. return SUCCESS;
  353. }
  354. /* }}} */
  355. /* {{{ childNodes DomNodeList
  356. readonly=yes
  357. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1451460987
  358. Since:
  359. */
  360. int dom_node_child_nodes_read(dom_object *obj, zval *retval)
  361. {
  362. xmlNode *nodep = dom_object_get_node(obj);
  363. dom_object *intern;
  364. if (nodep == NULL) {
  365. php_dom_throw_error(INVALID_STATE_ERR, 0);
  366. return FAILURE;
  367. }
  368. php_dom_create_interator(retval, DOM_NODELIST);
  369. intern = Z_DOMOBJ_P(retval);
  370. dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL);
  371. return SUCCESS;
  372. }
  373. /* }}} */
  374. /* {{{ firstChild DomNode
  375. readonly=yes
  376. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-169727388
  377. Since:
  378. */
  379. int dom_node_first_child_read(dom_object *obj, zval *retval)
  380. {
  381. xmlNode *nodep, *first = NULL;
  382. nodep = dom_object_get_node(obj);
  383. if (nodep == NULL) {
  384. php_dom_throw_error(INVALID_STATE_ERR, 0);
  385. return FAILURE;
  386. }
  387. if (dom_node_children_valid(nodep) == SUCCESS) {
  388. first = nodep->children;
  389. }
  390. if (!first) {
  391. ZVAL_NULL(retval);
  392. return SUCCESS;
  393. }
  394. php_dom_create_object(first, retval, obj);
  395. return SUCCESS;
  396. }
  397. /* }}} */
  398. /* {{{ lastChild DomNode
  399. readonly=yes
  400. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-61AD09FB
  401. Since:
  402. */
  403. int dom_node_last_child_read(dom_object *obj, zval *retval)
  404. {
  405. xmlNode *nodep, *last = NULL;
  406. nodep = dom_object_get_node(obj);
  407. if (nodep == NULL) {
  408. php_dom_throw_error(INVALID_STATE_ERR, 0);
  409. return FAILURE;
  410. }
  411. if (dom_node_children_valid(nodep) == SUCCESS) {
  412. last = nodep->last;
  413. }
  414. if (!last) {
  415. ZVAL_NULL(retval);
  416. return SUCCESS;
  417. }
  418. php_dom_create_object(last, retval, obj);
  419. return SUCCESS;
  420. }
  421. /* }}} */
  422. /* {{{ previousSibling DomNode
  423. readonly=yes
  424. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-640FB3C8
  425. Since:
  426. */
  427. int dom_node_previous_sibling_read(dom_object *obj, zval *retval)
  428. {
  429. xmlNode *nodep, *prevsib;
  430. nodep = dom_object_get_node(obj);
  431. if (nodep == NULL) {
  432. php_dom_throw_error(INVALID_STATE_ERR, 0);
  433. return FAILURE;
  434. }
  435. prevsib = nodep->prev;
  436. if (!prevsib) {
  437. ZVAL_NULL(retval);
  438. return SUCCESS;
  439. }
  440. php_dom_create_object(prevsib, retval, obj);
  441. return SUCCESS;
  442. }
  443. /* }}} */
  444. /* {{{ nextSibling DomNode
  445. readonly=yes
  446. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6AC54C2F
  447. Since:
  448. */
  449. int dom_node_next_sibling_read(dom_object *obj, zval *retval)
  450. {
  451. xmlNode *nodep, *nextsib;
  452. nodep = dom_object_get_node(obj);
  453. if (nodep == NULL) {
  454. php_dom_throw_error(INVALID_STATE_ERR, 0);
  455. return FAILURE;
  456. }
  457. nextsib = nodep->next;
  458. if (!nextsib) {
  459. ZVAL_NULL(retval);
  460. return SUCCESS;
  461. }
  462. php_dom_create_object(nextsib, retval, obj);
  463. return SUCCESS;
  464. }
  465. /* }}} */
  466. /* {{{ attributes DomNamedNodeMap
  467. readonly=yes
  468. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-84CF096
  469. Since:
  470. */
  471. int dom_node_attributes_read(dom_object *obj, zval *retval)
  472. {
  473. xmlNode *nodep = dom_object_get_node(obj);
  474. dom_object *intern;
  475. if (nodep == NULL) {
  476. php_dom_throw_error(INVALID_STATE_ERR, 0);
  477. return FAILURE;
  478. }
  479. if (nodep->type == XML_ELEMENT_NODE) {
  480. php_dom_create_interator(retval, DOM_NAMEDNODEMAP);
  481. intern = Z_DOMOBJ_P(retval);
  482. dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL);
  483. } else {
  484. ZVAL_NULL(retval);
  485. }
  486. return SUCCESS;
  487. }
  488. /* }}} */
  489. /* {{{ ownerDocument DomDocument
  490. readonly=yes
  491. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-node-ownerDoc
  492. Since:
  493. */
  494. int dom_node_owner_document_read(dom_object *obj, zval *retval)
  495. {
  496. xmlNode *nodep = dom_object_get_node(obj);
  497. xmlDocPtr docp;
  498. if (nodep == NULL) {
  499. php_dom_throw_error(INVALID_STATE_ERR, 0);
  500. return FAILURE;
  501. }
  502. if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
  503. ZVAL_NULL(retval);
  504. return SUCCESS;
  505. }
  506. docp = nodep->doc;
  507. if (!docp) {
  508. return FAILURE;
  509. }
  510. php_dom_create_object((xmlNodePtr) docp, retval, obj);
  511. return SUCCESS;
  512. }
  513. /* }}} */
  514. /* {{{ namespaceUri string
  515. readonly=yes
  516. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSname
  517. Since: DOM Level 2
  518. */
  519. int dom_node_namespace_uri_read(dom_object *obj, zval *retval)
  520. {
  521. xmlNode *nodep = dom_object_get_node(obj);
  522. char *str = NULL;
  523. if (nodep == NULL) {
  524. php_dom_throw_error(INVALID_STATE_ERR, 0);
  525. return FAILURE;
  526. }
  527. switch (nodep->type) {
  528. case XML_ELEMENT_NODE:
  529. case XML_ATTRIBUTE_NODE:
  530. case XML_NAMESPACE_DECL:
  531. if (nodep->ns != NULL) {
  532. str = (char *) nodep->ns->href;
  533. }
  534. break;
  535. default:
  536. str = NULL;
  537. break;
  538. }
  539. if (str != NULL) {
  540. ZVAL_STRING(retval, str);
  541. } else {
  542. ZVAL_NULL(retval);
  543. }
  544. return SUCCESS;
  545. }
  546. /* }}} */
  547. /* {{{ prefix string
  548. readonly=no
  549. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSPrefix
  550. Since: DOM Level 2
  551. */
  552. int dom_node_prefix_read(dom_object *obj, zval *retval)
  553. {
  554. xmlNode *nodep = dom_object_get_node(obj);
  555. xmlNsPtr ns;
  556. char *str = NULL;
  557. if (nodep == NULL) {
  558. php_dom_throw_error(INVALID_STATE_ERR, 0);
  559. return FAILURE;
  560. }
  561. switch (nodep->type) {
  562. case XML_ELEMENT_NODE:
  563. case XML_ATTRIBUTE_NODE:
  564. case XML_NAMESPACE_DECL:
  565. ns = nodep->ns;
  566. if (ns != NULL && ns->prefix) {
  567. str = (char *) ns->prefix;
  568. }
  569. break;
  570. default:
  571. str = NULL;
  572. break;
  573. }
  574. if (str == NULL) {
  575. ZVAL_EMPTY_STRING(retval);
  576. } else {
  577. ZVAL_STRING(retval, str);
  578. }
  579. return SUCCESS;
  580. }
  581. int dom_node_prefix_write(dom_object *obj, zval *newval)
  582. {
  583. zend_string *str;
  584. xmlNode *nodep, *nsnode = NULL;
  585. xmlNsPtr ns = NULL, curns;
  586. char *strURI;
  587. char *prefix;
  588. nodep = dom_object_get_node(obj);
  589. if (nodep == NULL) {
  590. php_dom_throw_error(INVALID_STATE_ERR, 0);
  591. return FAILURE;
  592. }
  593. switch (nodep->type) {
  594. case XML_ELEMENT_NODE:
  595. nsnode = nodep;
  596. case XML_ATTRIBUTE_NODE:
  597. if (nsnode == NULL) {
  598. nsnode = nodep->parent;
  599. if (nsnode == NULL) {
  600. nsnode = xmlDocGetRootElement(nodep->doc);
  601. }
  602. }
  603. str = zval_get_string(newval);
  604. prefix = ZSTR_VAL(str);
  605. if (nsnode && nodep->ns != NULL && !xmlStrEqual(nodep->ns->prefix, (xmlChar *)prefix)) {
  606. strURI = (char *) nodep->ns->href;
  607. if (strURI == NULL ||
  608. (!strcmp(prefix, "xml") && strcmp(strURI, (char *) XML_XML_NAMESPACE)) ||
  609. (nodep->type == XML_ATTRIBUTE_NODE && !strcmp(prefix, "xmlns") &&
  610. strcmp(strURI, (char *) DOM_XMLNS_NAMESPACE)) ||
  611. (nodep->type == XML_ATTRIBUTE_NODE && !strcmp((char *) nodep->name, "xmlns"))) {
  612. ns = NULL;
  613. } else {
  614. curns = nsnode->nsDef;
  615. while (curns != NULL) {
  616. if (xmlStrEqual((xmlChar *)prefix, curns->prefix) && xmlStrEqual(nodep->ns->href, curns->href)) {
  617. ns = curns;
  618. break;
  619. }
  620. curns = curns->next;
  621. }
  622. if (ns == NULL) {
  623. ns = xmlNewNs(nsnode, nodep->ns->href, (xmlChar *)prefix);
  624. }
  625. }
  626. if (ns == NULL) {
  627. zend_string_release_ex(str, 0);
  628. php_dom_throw_error(NAMESPACE_ERR, dom_get_strict_error(obj->document));
  629. return FAILURE;
  630. }
  631. xmlSetNs(nodep, ns);
  632. }
  633. zend_string_release_ex(str, 0);
  634. break;
  635. default:
  636. break;
  637. }
  638. return SUCCESS;
  639. }
  640. /* }}} */
  641. /* {{{ localName string
  642. readonly=yes
  643. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSLocalN
  644. Since: DOM Level 2
  645. */
  646. int dom_node_local_name_read(dom_object *obj, zval *retval)
  647. {
  648. xmlNode *nodep = dom_object_get_node(obj);
  649. if (nodep == NULL) {
  650. php_dom_throw_error(INVALID_STATE_ERR, 0);
  651. return FAILURE;
  652. }
  653. if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE || nodep->type == XML_NAMESPACE_DECL) {
  654. ZVAL_STRING(retval, (char *) (nodep->name));
  655. } else {
  656. ZVAL_NULL(retval);
  657. }
  658. return SUCCESS;
  659. }
  660. /* }}} */
  661. /* {{{ baseURI string
  662. readonly=yes
  663. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-baseURI
  664. Since: DOM Level 3
  665. */
  666. int dom_node_base_uri_read(dom_object *obj, zval *retval)
  667. {
  668. xmlNode *nodep = dom_object_get_node(obj);
  669. xmlChar *baseuri;
  670. if (nodep == NULL) {
  671. php_dom_throw_error(INVALID_STATE_ERR, 0);
  672. return FAILURE;
  673. }
  674. baseuri = xmlNodeGetBase(nodep->doc, nodep);
  675. if (baseuri) {
  676. ZVAL_STRING(retval, (char *) (baseuri));
  677. xmlFree(baseuri);
  678. } else {
  679. ZVAL_NULL(retval);
  680. }
  681. return SUCCESS;
  682. }
  683. /* }}} */
  684. /* {{{ textContent string
  685. readonly=no
  686. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-textContent
  687. Since: DOM Level 3
  688. */
  689. int dom_node_text_content_read(dom_object *obj, zval *retval)
  690. {
  691. xmlNode *nodep = dom_object_get_node(obj);
  692. char *str = NULL;
  693. if (nodep == NULL) {
  694. php_dom_throw_error(INVALID_STATE_ERR, 0);
  695. return FAILURE;
  696. }
  697. str = (char *) xmlNodeGetContent(nodep);
  698. if (str != NULL) {
  699. ZVAL_STRING(retval, str);
  700. xmlFree(str);
  701. } else {
  702. ZVAL_EMPTY_STRING(retval);
  703. }
  704. return SUCCESS;
  705. }
  706. int dom_node_text_content_write(dom_object *obj, zval *newval)
  707. {
  708. xmlNode *nodep = dom_object_get_node(obj);
  709. zend_string *str;
  710. if (nodep == NULL) {
  711. php_dom_throw_error(INVALID_STATE_ERR, 0);
  712. return FAILURE;
  713. }
  714. if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
  715. if (nodep->children) {
  716. node_list_unlink(nodep->children);
  717. php_libxml_node_free_list((xmlNodePtr) nodep->children);
  718. nodep->children = NULL;
  719. }
  720. }
  721. str = zval_get_string(newval);
  722. /* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
  723. xmlNodeSetContent(nodep, (xmlChar *) "");
  724. xmlNodeAddContent(nodep, (xmlChar *) ZSTR_VAL(str));
  725. zend_string_release_ex(str, 0);
  726. return SUCCESS;
  727. }
  728. /* }}} */
  729. static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, xmlNodePtr nextsib, xmlNodePtr fragment, dom_object *intern, dom_object *childobj) /* {{{ */
  730. {
  731. xmlNodePtr newchild, node;
  732. newchild = fragment->children;
  733. if (newchild) {
  734. if (prevsib == NULL) {
  735. nodep->children = newchild;
  736. } else {
  737. prevsib->next = newchild;
  738. }
  739. newchild->prev = prevsib;
  740. if (nextsib == NULL) {
  741. nodep->last = fragment->last;
  742. } else {
  743. fragment->last->next = nextsib;
  744. nextsib->prev = fragment->last;
  745. }
  746. node = newchild;
  747. while (node != NULL) {
  748. node->parent = nodep;
  749. if (node->doc != nodep->doc) {
  750. xmlSetTreeDoc(node, nodep->doc);
  751. if (node->_private != NULL) {
  752. childobj = node->_private;
  753. childobj->document = intern->document;
  754. php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
  755. }
  756. }
  757. if (node == fragment->last) {
  758. break;
  759. }
  760. node = node->next;
  761. }
  762. fragment->children = NULL;
  763. fragment->last = NULL;
  764. }
  765. return newchild;
  766. }
  767. /* }}} */
  768. /* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild);
  769. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727
  770. Since:
  771. */
  772. PHP_FUNCTION(dom_node_insert_before)
  773. {
  774. zval *id, *node, *ref = NULL;
  775. xmlNodePtr child, new_child, parentp, refp;
  776. dom_object *intern, *childobj, *refpobj;
  777. int ret, stricterror;
  778. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|O!", &id, dom_node_class_entry, &node, dom_node_class_entry, &ref, dom_node_class_entry) == FAILURE) {
  779. return;
  780. }
  781. DOM_GET_OBJ(parentp, id, xmlNodePtr, intern);
  782. if (dom_node_children_valid(parentp) == FAILURE) {
  783. RETURN_FALSE;
  784. }
  785. DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
  786. new_child = NULL;
  787. stricterror = dom_get_strict_error(intern->document);
  788. if (dom_node_is_read_only(parentp) == SUCCESS ||
  789. (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
  790. php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
  791. RETURN_FALSE;
  792. }
  793. if (dom_hierarchy(parentp, child) == FAILURE) {
  794. php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
  795. RETURN_FALSE;
  796. }
  797. if (child->doc != parentp->doc && child->doc != NULL) {
  798. php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
  799. RETURN_FALSE;
  800. }
  801. if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
  802. php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
  803. RETURN_FALSE;
  804. }
  805. if (child->doc == NULL && parentp->doc != NULL) {
  806. childobj->document = intern->document;
  807. php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
  808. }
  809. if (ref != NULL) {
  810. DOM_GET_OBJ(refp, ref, xmlNodePtr, refpobj);
  811. if (refp->parent != parentp) {
  812. php_dom_throw_error(NOT_FOUND_ERR, stricterror);
  813. RETURN_FALSE;
  814. }
  815. if (child->parent != NULL) {
  816. xmlUnlinkNode(child);
  817. }
  818. if (child->type == XML_TEXT_NODE && (refp->type == XML_TEXT_NODE ||
  819. (refp->prev != NULL && refp->prev->type == XML_TEXT_NODE))) {
  820. if (child->doc == NULL) {
  821. xmlSetTreeDoc(child, parentp->doc);
  822. }
  823. new_child = child;
  824. new_child->parent = refp->parent;
  825. new_child->next = refp;
  826. new_child->prev = refp->prev;
  827. refp->prev = new_child;
  828. if (new_child->prev != NULL) {
  829. new_child->prev->next = new_child;
  830. }
  831. if (new_child->parent != NULL) {
  832. if (new_child->parent->children == refp) {
  833. new_child->parent->children = new_child;
  834. }
  835. }
  836. } else if (child->type == XML_ATTRIBUTE_NODE) {
  837. xmlAttrPtr lastattr;
  838. if (child->ns == NULL)
  839. lastattr = xmlHasProp(refp->parent, child->name);
  840. else
  841. lastattr = xmlHasNsProp(refp->parent, child->name, child->ns->href);
  842. if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
  843. if (lastattr != (xmlAttrPtr) child) {
  844. xmlUnlinkNode((xmlNodePtr) lastattr);
  845. php_libxml_node_free_resource((xmlNodePtr) lastattr);
  846. } else {
  847. DOM_RET_OBJ(child, &ret, intern);
  848. return;
  849. }
  850. }
  851. } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
  852. new_child = _php_dom_insert_fragment(parentp, refp->prev, refp, child, intern, childobj);
  853. }
  854. if (new_child == NULL) {
  855. new_child = xmlAddPrevSibling(refp, child);
  856. }
  857. } else {
  858. if (child->parent != NULL){
  859. xmlUnlinkNode(child);
  860. }
  861. if (child->type == XML_TEXT_NODE && parentp->last != NULL && parentp->last->type == XML_TEXT_NODE) {
  862. child->parent = parentp;
  863. if (child->doc == NULL) {
  864. xmlSetTreeDoc(child, parentp->doc);
  865. }
  866. new_child = child;
  867. if (parentp->children == NULL) {
  868. parentp->children = child;
  869. parentp->last = child;
  870. } else {
  871. child = parentp->last;
  872. child->next = new_child;
  873. new_child->prev = child;
  874. parentp->last = new_child;
  875. }
  876. } else if (child->type == XML_ATTRIBUTE_NODE) {
  877. xmlAttrPtr lastattr;
  878. if (child->ns == NULL)
  879. lastattr = xmlHasProp(parentp, child->name);
  880. else
  881. lastattr = xmlHasNsProp(parentp, child->name, child->ns->href);
  882. if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
  883. if (lastattr != (xmlAttrPtr) child) {
  884. xmlUnlinkNode((xmlNodePtr) lastattr);
  885. php_libxml_node_free_resource((xmlNodePtr) lastattr);
  886. } else {
  887. DOM_RET_OBJ(child, &ret, intern);
  888. return;
  889. }
  890. }
  891. } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
  892. new_child = _php_dom_insert_fragment(parentp, parentp->last, NULL, child, intern, childobj);
  893. }
  894. if (new_child == NULL) {
  895. new_child = xmlAddChild(parentp, child);
  896. }
  897. }
  898. if (NULL == new_child) {
  899. php_error_docref(NULL, E_WARNING, "Couldn't add newnode as the previous sibling of refnode");
  900. RETURN_FALSE;
  901. }
  902. dom_reconcile_ns(parentp->doc, new_child);
  903. DOM_RET_OBJ(new_child, &ret, intern);
  904. }
  905. /* }}} end dom_node_insert_before */
  906. /* {{{ proto DomNode dom_node_replace_child(DomNode newChild, DomNode oldChild);
  907. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-785887307
  908. Since:
  909. */
  910. PHP_FUNCTION(dom_node_replace_child)
  911. {
  912. zval *id, *newnode, *oldnode;
  913. xmlNodePtr children, newchild, oldchild, nodep;
  914. dom_object *intern, *newchildobj, *oldchildobj;
  915. int foundoldchild = 0, stricterror;
  916. int ret;
  917. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OOO", &id, dom_node_class_entry, &newnode, dom_node_class_entry, &oldnode, dom_node_class_entry) == FAILURE) {
  918. return;
  919. }
  920. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  921. if (dom_node_children_valid(nodep) == FAILURE) {
  922. RETURN_FALSE;
  923. }
  924. DOM_GET_OBJ(newchild, newnode, xmlNodePtr, newchildobj);
  925. DOM_GET_OBJ(oldchild, oldnode, xmlNodePtr, oldchildobj);
  926. children = nodep->children;
  927. if (!children) {
  928. RETURN_FALSE;
  929. }
  930. stricterror = dom_get_strict_error(intern->document);
  931. if (dom_node_is_read_only(nodep) == SUCCESS ||
  932. (newchild->parent != NULL && dom_node_is_read_only(newchild->parent) == SUCCESS)) {
  933. php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
  934. RETURN_FALSE;
  935. }
  936. if (newchild->doc != nodep->doc && newchild->doc != NULL) {
  937. php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
  938. RETURN_FALSE;
  939. }
  940. if (dom_hierarchy(nodep, newchild) == FAILURE) {
  941. php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
  942. RETURN_FALSE;
  943. }
  944. /* check for the old child and whether the new child is already a child */
  945. while (children) {
  946. if (children == oldchild) {
  947. foundoldchild = 1;
  948. break;
  949. }
  950. children = children->next;
  951. }
  952. if (foundoldchild) {
  953. if (newchild->type == XML_DOCUMENT_FRAG_NODE) {
  954. xmlNodePtr prevsib, nextsib;
  955. prevsib = oldchild->prev;
  956. nextsib = oldchild->next;
  957. xmlUnlinkNode(oldchild);
  958. newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj);
  959. if (newchild) {
  960. dom_reconcile_ns(nodep->doc, newchild);
  961. }
  962. } else if (oldchild != newchild) {
  963. if (newchild->doc == NULL && nodep->doc != NULL) {
  964. xmlSetTreeDoc(newchild, nodep->doc);
  965. newchildobj->document = intern->document;
  966. php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL);
  967. }
  968. xmlReplaceNode(oldchild, newchild);
  969. dom_reconcile_ns(nodep->doc, newchild);
  970. }
  971. DOM_RET_OBJ(oldchild, &ret, intern);
  972. return;
  973. } else {
  974. php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
  975. RETURN_FALSE;
  976. }
  977. }
  978. /* }}} end dom_node_replace_child */
  979. /* {{{ proto DomNode dom_node_remove_child(DomNode oldChild);
  980. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1734834066
  981. Since:
  982. */
  983. PHP_FUNCTION(dom_node_remove_child)
  984. {
  985. zval *id, *node;
  986. xmlNodePtr children, child, nodep;
  987. dom_object *intern, *childobj;
  988. int ret, stricterror;
  989. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
  990. return;
  991. }
  992. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  993. if (dom_node_children_valid(nodep) == FAILURE) {
  994. RETURN_FALSE;
  995. }
  996. DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
  997. stricterror = dom_get_strict_error(intern->document);
  998. if (dom_node_is_read_only(nodep) == SUCCESS ||
  999. (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
  1000. php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
  1001. RETURN_FALSE;
  1002. }
  1003. children = nodep->children;
  1004. if (!children) {
  1005. php_dom_throw_error(NOT_FOUND_ERR, stricterror);
  1006. RETURN_FALSE;
  1007. }
  1008. while (children) {
  1009. if (children == child) {
  1010. xmlUnlinkNode(child);
  1011. DOM_RET_OBJ(child, &ret, intern);
  1012. return;
  1013. }
  1014. children = children->next;
  1015. }
  1016. php_dom_throw_error(NOT_FOUND_ERR, stricterror);
  1017. RETURN_FALSE
  1018. }
  1019. /* }}} end dom_node_remove_child */
  1020. /* {{{ proto DomNode dom_node_append_child(DomNode newChild);
  1021. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-184E7107
  1022. Since:
  1023. */
  1024. PHP_FUNCTION(dom_node_append_child)
  1025. {
  1026. zval *id, *node;
  1027. xmlNodePtr child, nodep, new_child = NULL;
  1028. dom_object *intern, *childobj;
  1029. int ret, stricterror;
  1030. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
  1031. return;
  1032. }
  1033. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1034. if (dom_node_children_valid(nodep) == FAILURE) {
  1035. RETURN_FALSE;
  1036. }
  1037. DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
  1038. stricterror = dom_get_strict_error(intern->document);
  1039. if (dom_node_is_read_only(nodep) == SUCCESS ||
  1040. (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
  1041. php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
  1042. RETURN_FALSE;
  1043. }
  1044. if (dom_hierarchy(nodep, child) == FAILURE) {
  1045. php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
  1046. RETURN_FALSE;
  1047. }
  1048. if (!(child->doc == NULL || child->doc == nodep->doc)) {
  1049. php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
  1050. RETURN_FALSE;
  1051. }
  1052. if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
  1053. php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
  1054. RETURN_FALSE;
  1055. }
  1056. if (child->doc == NULL && nodep->doc != NULL) {
  1057. childobj->document = intern->document;
  1058. php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
  1059. }
  1060. if (child->parent != NULL){
  1061. xmlUnlinkNode(child);
  1062. }
  1063. if (child->type == XML_TEXT_NODE && nodep->last != NULL && nodep->last->type == XML_TEXT_NODE) {
  1064. child->parent = nodep;
  1065. if (child->doc == NULL) {
  1066. xmlSetTreeDoc(child, nodep->doc);
  1067. }
  1068. new_child = child;
  1069. if (nodep->children == NULL) {
  1070. nodep->children = child;
  1071. nodep->last = child;
  1072. } else {
  1073. child = nodep->last;
  1074. child->next = new_child;
  1075. new_child->prev = child;
  1076. nodep->last = new_child;
  1077. }
  1078. } else if (child->type == XML_ATTRIBUTE_NODE) {
  1079. xmlAttrPtr lastattr;
  1080. if (child->ns == NULL)
  1081. lastattr = xmlHasProp(nodep, child->name);
  1082. else
  1083. lastattr = xmlHasNsProp(nodep, child->name, child->ns->href);
  1084. if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
  1085. if (lastattr != (xmlAttrPtr) child) {
  1086. xmlUnlinkNode((xmlNodePtr) lastattr);
  1087. php_libxml_node_free_resource((xmlNodePtr) lastattr);
  1088. }
  1089. }
  1090. } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
  1091. new_child = _php_dom_insert_fragment(nodep, nodep->last, NULL, child, intern, childobj);
  1092. }
  1093. if (new_child == NULL) {
  1094. new_child = xmlAddChild(nodep, child);
  1095. if (new_child == NULL) {
  1096. php_error_docref(NULL, E_WARNING, "Couldn't append node");
  1097. RETURN_FALSE;
  1098. }
  1099. }
  1100. dom_reconcile_ns(nodep->doc, new_child);
  1101. DOM_RET_OBJ(new_child, &ret, intern);
  1102. }
  1103. /* }}} end dom_node_append_child */
  1104. /* {{{ proto bool dom_node_has_child_nodes();
  1105. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-810594187
  1106. Since:
  1107. */
  1108. PHP_FUNCTION(dom_node_has_child_nodes)
  1109. {
  1110. zval *id;
  1111. xmlNode *nodep;
  1112. dom_object *intern;
  1113. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
  1114. return;
  1115. }
  1116. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1117. if (dom_node_children_valid(nodep) == FAILURE) {
  1118. RETURN_FALSE;
  1119. }
  1120. if (nodep->children) {
  1121. RETURN_TRUE;
  1122. } else {
  1123. RETURN_FALSE;
  1124. }
  1125. }
  1126. /* }}} end dom_node_has_child_nodes */
  1127. /* {{{ proto DomNode dom_node_clone_node(bool deep);
  1128. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3A0ED0A4
  1129. Since:
  1130. */
  1131. PHP_FUNCTION(dom_node_clone_node)
  1132. {
  1133. zval *id;
  1134. xmlNode *n, *node;
  1135. int ret;
  1136. dom_object *intern;
  1137. zend_bool recursive = 0;
  1138. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|b", &id, dom_node_class_entry, &recursive) == FAILURE) {
  1139. return;
  1140. }
  1141. DOM_GET_OBJ(n, id, xmlNodePtr, intern);
  1142. node = xmlDocCopyNode(n, n->doc, recursive);
  1143. if (!node) {
  1144. RETURN_FALSE;
  1145. }
  1146. /* When deep is false Element nodes still require the attributes
  1147. Following taken from libxml as xmlDocCopyNode doesn't do this */
  1148. if (n->type == XML_ELEMENT_NODE && recursive == 0) {
  1149. if (n->nsDef != NULL) {
  1150. node->nsDef = xmlCopyNamespaceList(n->nsDef);
  1151. }
  1152. if (n->ns != NULL) {
  1153. xmlNsPtr ns;
  1154. ns = xmlSearchNs(n->doc, node, n->ns->prefix);
  1155. if (ns == NULL) {
  1156. ns = xmlSearchNs(n->doc, n, n->ns->prefix);
  1157. if (ns != NULL) {
  1158. xmlNodePtr root = node;
  1159. while (root->parent != NULL) {
  1160. root = root->parent;
  1161. }
  1162. node->ns = xmlNewNs(root, ns->href, ns->prefix);
  1163. }
  1164. } else {
  1165. node->ns = ns;
  1166. }
  1167. }
  1168. if (n->properties != NULL) {
  1169. node->properties = xmlCopyPropList(node, n->properties);
  1170. }
  1171. }
  1172. /* If document cloned we want a new document proxy */
  1173. if (node->doc != n->doc) {
  1174. intern = NULL;
  1175. }
  1176. DOM_RET_OBJ(node, &ret, intern);
  1177. }
  1178. /* }}} end dom_node_clone_node */
  1179. /* {{{ proto void dom_node_normalize();
  1180. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-normalize
  1181. Since:
  1182. */
  1183. PHP_FUNCTION(dom_node_normalize)
  1184. {
  1185. zval *id;
  1186. xmlNode *nodep;
  1187. dom_object *intern;
  1188. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
  1189. return;
  1190. }
  1191. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1192. dom_normalize(nodep);
  1193. }
  1194. /* }}} end dom_node_normalize */
  1195. /* {{{ proto bool dom_node_is_supported(string feature, string version);
  1196. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Level-2-Core-Node-supports
  1197. Since: DOM Level 2
  1198. */
  1199. PHP_FUNCTION(dom_node_is_supported)
  1200. {
  1201. zval *id;
  1202. size_t feature_len, version_len;
  1203. char *feature, *version;
  1204. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &id, dom_node_class_entry, &feature, &feature_len, &version, &version_len) == FAILURE) {
  1205. return;
  1206. }
  1207. if (dom_has_feature(feature, version)) {
  1208. RETURN_TRUE;
  1209. } else {
  1210. RETURN_FALSE;
  1211. }
  1212. }
  1213. /* }}} end dom_node_is_supported */
  1214. /* {{{ proto bool dom_node_has_attributes();
  1215. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeHasAttrs
  1216. Since: DOM Level 2
  1217. */
  1218. PHP_FUNCTION(dom_node_has_attributes)
  1219. {
  1220. zval *id;
  1221. xmlNode *nodep;
  1222. dom_object *intern;
  1223. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
  1224. return;
  1225. }
  1226. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1227. if (nodep->type != XML_ELEMENT_NODE)
  1228. RETURN_FALSE;
  1229. if (nodep->properties) {
  1230. RETURN_TRUE;
  1231. } else {
  1232. RETURN_FALSE;
  1233. }
  1234. }
  1235. /* }}} end dom_node_has_attributes */
  1236. /* {{{ proto short dom_node_compare_document_position(DomNode other);
  1237. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-compareDocumentPosition
  1238. Since: DOM Level 3
  1239. */
  1240. PHP_FUNCTION(dom_node_compare_document_position)
  1241. {
  1242. DOM_NOT_IMPLEMENTED();
  1243. }
  1244. /* }}} end dom_node_compare_document_position */
  1245. /* {{{ proto bool dom_node_is_same_node(DomNode other);
  1246. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isSameNode
  1247. Since: DOM Level 3
  1248. */
  1249. PHP_FUNCTION(dom_node_is_same_node)
  1250. {
  1251. zval *id, *node;
  1252. xmlNodePtr nodeotherp, nodep;
  1253. dom_object *intern, *nodeotherobj;
  1254. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
  1255. return;
  1256. }
  1257. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1258. DOM_GET_OBJ(nodeotherp, node, xmlNodePtr, nodeotherobj);
  1259. if (nodep == nodeotherp) {
  1260. RETURN_TRUE;
  1261. } else {
  1262. RETURN_FALSE;
  1263. }
  1264. }
  1265. /* }}} end dom_node_is_same_node */
  1266. /* {{{ proto string dom_node_lookup_prefix(string namespaceURI);
  1267. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-lookupNamespacePrefix
  1268. Since: DOM Level 3
  1269. */
  1270. PHP_FUNCTION(dom_node_lookup_prefix)
  1271. {
  1272. zval *id;
  1273. xmlNodePtr nodep, lookupp = NULL;
  1274. dom_object *intern;
  1275. xmlNsPtr nsptr;
  1276. size_t uri_len = 0;
  1277. char *uri;
  1278. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_node_class_entry, &uri, &uri_len) == FAILURE) {
  1279. return;
  1280. }
  1281. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1282. if (uri_len > 0) {
  1283. switch (nodep->type) {
  1284. case XML_ELEMENT_NODE:
  1285. lookupp = nodep;
  1286. break;
  1287. case XML_DOCUMENT_NODE:
  1288. case XML_HTML_DOCUMENT_NODE:
  1289. lookupp = xmlDocGetRootElement((xmlDocPtr) nodep);
  1290. break;
  1291. case XML_ENTITY_NODE :
  1292. case XML_NOTATION_NODE:
  1293. case XML_DOCUMENT_FRAG_NODE:
  1294. case XML_DOCUMENT_TYPE_NODE:
  1295. case XML_DTD_NODE:
  1296. RETURN_NULL();
  1297. break;
  1298. default:
  1299. lookupp = nodep->parent;
  1300. }
  1301. if (lookupp != NULL) {
  1302. nsptr = xmlSearchNsByHref(lookupp->doc, lookupp, (xmlChar *) uri);
  1303. if (nsptr && nsptr->prefix != NULL) {
  1304. RETURN_STRING((char *) nsptr->prefix);
  1305. }
  1306. }
  1307. }
  1308. RETURN_NULL();
  1309. }
  1310. /* }}} end dom_node_lookup_prefix */
  1311. /* {{{ proto bool dom_node_is_default_namespace(string namespaceURI);
  1312. URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace
  1313. Since: DOM Level 3
  1314. */
  1315. PHP_FUNCTION(dom_node_is_default_namespace)
  1316. {
  1317. zval *id;
  1318. xmlNodePtr nodep;
  1319. dom_object *intern;
  1320. xmlNsPtr nsptr;
  1321. size_t uri_len = 0;
  1322. char *uri;
  1323. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_node_class_entry, &uri, &uri_len) == FAILURE) {
  1324. return;
  1325. }
  1326. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1327. if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
  1328. nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
  1329. }
  1330. if (nodep && uri_len > 0) {
  1331. nsptr = xmlSearchNs(nodep->doc, nodep, NULL);
  1332. if (nsptr && xmlStrEqual(nsptr->href, (xmlChar *) uri)) {
  1333. RETURN_TRUE;
  1334. }
  1335. }
  1336. RETURN_FALSE;
  1337. }
  1338. /* }}} end dom_node_is_default_namespace */
  1339. /* {{{ proto string dom_node_lookup_namespace_uri(string prefix);
  1340. URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
  1341. Since: DOM Level 3
  1342. */
  1343. PHP_FUNCTION(dom_node_lookup_namespace_uri)
  1344. {
  1345. zval *id;
  1346. xmlNodePtr nodep;
  1347. dom_object *intern;
  1348. xmlNsPtr nsptr;
  1349. size_t prefix_len;
  1350. char *prefix;
  1351. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!", &id, dom_node_class_entry, &prefix, &prefix_len) == FAILURE) {
  1352. return;
  1353. }
  1354. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1355. if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
  1356. nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
  1357. if (nodep == NULL) {
  1358. RETURN_NULL();
  1359. }
  1360. }
  1361. nsptr = xmlSearchNs(nodep->doc, nodep, (xmlChar *) prefix);
  1362. if (nsptr && nsptr->href != NULL) {
  1363. RETURN_STRING((char *) nsptr->href);
  1364. }
  1365. RETURN_NULL();
  1366. }
  1367. /* }}} end dom_node_lookup_namespace_uri */
  1368. /* {{{ proto bool dom_node_is_equal_node(DomNode arg);
  1369. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isEqualNode
  1370. Since: DOM Level 3
  1371. */
  1372. PHP_FUNCTION(dom_node_is_equal_node)
  1373. {
  1374. DOM_NOT_IMPLEMENTED();
  1375. }
  1376. /* }}} end dom_node_is_equal_node */
  1377. /* {{{ proto DomNode dom_node_get_feature(string feature, string version);
  1378. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getFeature
  1379. Since: DOM Level 3
  1380. */
  1381. PHP_FUNCTION(dom_node_get_feature)
  1382. {
  1383. DOM_NOT_IMPLEMENTED();
  1384. }
  1385. /* }}} end dom_node_get_feature */
  1386. /* {{{ proto mixed dom_node_set_user_data(string key, mixed data, userdatahandler handler);
  1387. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-setUserData
  1388. Since: DOM Level 3
  1389. */
  1390. PHP_FUNCTION(dom_node_set_user_data)
  1391. {
  1392. DOM_NOT_IMPLEMENTED();
  1393. }
  1394. /* }}} end dom_node_set_user_data */
  1395. /* {{{ proto mixed dom_node_get_user_data(string key);
  1396. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getUserData
  1397. Since: DOM Level 3
  1398. */
  1399. PHP_FUNCTION(dom_node_get_user_data)
  1400. {
  1401. DOM_NOT_IMPLEMENTED();
  1402. }
  1403. /* }}} end dom_node_get_user_data */
  1404. static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
  1405. {
  1406. zval *id;
  1407. zval *xpath_array=NULL, *ns_prefixes=NULL;
  1408. xmlNodePtr nodep;
  1409. xmlDocPtr docp;
  1410. xmlNodeSetPtr nodeset = NULL;
  1411. dom_object *intern;
  1412. zend_bool exclusive=0, with_comments=0;
  1413. xmlChar **inclusive_ns_prefixes = NULL;
  1414. char *file = NULL;
  1415. int ret = -1;
  1416. size_t file_len = 0;
  1417. xmlOutputBufferPtr buf;
  1418. xmlXPathContextPtr ctxp=NULL;
  1419. xmlXPathObjectPtr xpathobjp=NULL;
  1420. if (mode == 0) {
  1421. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
  1422. "O|bba!a!", &id, dom_node_class_entry, &exclusive, &with_comments,
  1423. &xpath_array, &ns_prefixes) == FAILURE) {
  1424. return;
  1425. }
  1426. } else {
  1427. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
  1428. "Os|bba!a!", &id, dom_node_class_entry, &file, &file_len, &exclusive,
  1429. &with_comments, &xpath_array, &ns_prefixes) == FAILURE) {
  1430. return;
  1431. }
  1432. }
  1433. DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
  1434. docp = nodep->doc;
  1435. if (! docp) {
  1436. php_error_docref(NULL, E_WARNING, "Node must be associated with a document");
  1437. RETURN_FALSE;
  1438. }
  1439. if (xpath_array == NULL) {
  1440. if (nodep->type != XML_DOCUMENT_NODE) {
  1441. ctxp = xmlXPathNewContext(docp);
  1442. ctxp->node = nodep;
  1443. xpathobjp = xmlXPathEvalExpression((xmlChar *) "(.//. | .//@* | .//namespace::*)", ctxp);
  1444. ctxp->node = NULL;
  1445. if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
  1446. nodeset = xpathobjp->nodesetval;
  1447. } else {
  1448. if (xpathobjp) {
  1449. xmlXPathFreeObject(xpathobjp);
  1450. }
  1451. xmlXPathFreeContext(ctxp);
  1452. php_error_docref(NULL, E_WARNING, "XPath query did not return a nodeset.");
  1453. RETURN_FALSE;
  1454. }
  1455. }
  1456. } else {
  1457. /*xpath query from xpath_array */
  1458. HashTable *ht = Z_ARRVAL_P(xpath_array);
  1459. zval *tmp;
  1460. char *xquery;
  1461. tmp = zend_hash_str_find(ht, "query", sizeof("query")-1);
  1462. if (tmp && Z_TYPE_P(tmp) == IS_STRING) {
  1463. xquery = Z_STRVAL_P(tmp);
  1464. } else {
  1465. php_error_docref(NULL, E_WARNING, "'query' missing from xpath array or is not a string");
  1466. RETURN_FALSE;
  1467. }
  1468. ctxp = xmlXPathNewContext(docp);
  1469. ctxp->node = nodep;
  1470. tmp = zend_hash_str_find(ht, "namespaces", sizeof("namespaces")-1);
  1471. if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) {
  1472. zval *tmpns;
  1473. zend_string *prefix;
  1474. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) {
  1475. if (Z_TYPE_P(tmpns) == IS_STRING) {
  1476. if (prefix) {
  1477. xmlXPathRegisterNs(ctxp, (xmlChar *) ZSTR_VAL(prefix), (xmlChar *) Z_STRVAL_P(tmpns));
  1478. }
  1479. }
  1480. } ZEND_HASH_FOREACH_END();
  1481. }
  1482. xpathobjp = xmlXPathEvalExpression((xmlChar *) xquery, ctxp);
  1483. ctxp->node = NULL;
  1484. if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
  1485. nodeset = xpathobjp->nodesetval;
  1486. } else {
  1487. if (xpathobjp) {
  1488. xmlXPathFreeObject(xpathobjp);
  1489. }
  1490. xmlXPathFreeContext(ctxp);
  1491. php_error_docref(NULL, E_WARNING, "XPath query did not return a nodeset.");
  1492. RETURN_FALSE;
  1493. }
  1494. }
  1495. if (ns_prefixes != NULL) {
  1496. if (exclusive) {
  1497. zval *tmpns;
  1498. int nscount = 0;
  1499. inclusive_ns_prefixes = safe_emalloc(zend_hash_num_elements(Z_ARRVAL_P(ns_prefixes)) + 1,
  1500. sizeof(xmlChar *), 0);
  1501. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(ns_prefixes), tmpns) {
  1502. if (Z_TYPE_P(tmpns) == IS_STRING) {
  1503. inclusive_ns_prefixes[nscount++] = (xmlChar *) Z_STRVAL_P(tmpns);
  1504. }
  1505. } ZEND_HASH_FOREACH_END();
  1506. inclusive_ns_prefixes[nscount] = NULL;
  1507. } else {
  1508. php_error_docref(NULL, E_NOTICE,
  1509. "Inclusive namespace prefixes only allowed in exclusive mode.");
  1510. }
  1511. }
  1512. if (mode == 1) {
  1513. buf = xmlOutputBufferCreateFilename(file, NULL, 0);
  1514. } else {
  1515. buf = xmlAllocOutputBuffer(NULL);
  1516. }
  1517. if (buf != NULL) {
  1518. ret = xmlC14NDocSaveTo(docp, nodeset, exclusive, inclusive_ns_prefixes,
  1519. with_comments, buf);
  1520. }
  1521. if (inclusive_ns_prefixes != NULL) {
  1522. efree(inclusive_ns_prefixes);
  1523. }
  1524. if (xpathobjp != NULL) {
  1525. xmlXPathFreeObject(xpathobjp);
  1526. }
  1527. if (ctxp != NULL) {
  1528. xmlXPathFreeContext(ctxp);
  1529. }
  1530. if (buf == NULL || ret < 0) {
  1531. RETVAL_FALSE;
  1532. } else {
  1533. if (mode == 0) {
  1534. #ifdef LIBXML2_NEW_BUFFER
  1535. ret = xmlOutputBufferGetSize(buf);
  1536. #else
  1537. ret = buf->buffer->use;
  1538. #endif
  1539. if (ret > 0) {
  1540. #ifdef LIBXML2_NEW_BUFFER
  1541. RETVAL_STRINGL((char *) xmlOutputBufferGetContent(buf), ret);
  1542. #else
  1543. RETVAL_STRINGL((char *) buf->buffer->content, ret);
  1544. #endif
  1545. } else {
  1546. RETVAL_EMPTY_STRING();
  1547. }
  1548. }
  1549. }
  1550. if (buf) {
  1551. int bytes;
  1552. bytes = xmlOutputBufferClose(buf);
  1553. if (mode == 1 && (ret >= 0)) {
  1554. RETURN_LONG(bytes);
  1555. }
  1556. }
  1557. }
  1558. /* }}} */
  1559. /* {{{ proto string DOMNode::C14N([bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
  1560. Canonicalize nodes to a string */
  1561. PHP_METHOD(domnode, C14N)
  1562. {
  1563. dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1564. }
  1565. /* }}} */
  1566. /* {{{ proto int DOMNode::C14NFile(string uri [, bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
  1567. Canonicalize nodes to a file */
  1568. PHP_METHOD(domnode, C14NFile)
  1569. {
  1570. dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1571. }
  1572. /* }}} */
  1573. /* {{{ proto int DOMNode::getNodePath()
  1574. Gets an xpath for a node */
  1575. PHP_METHOD(domnode, getNodePath)
  1576. {
  1577. zval *id;
  1578. xmlNode *nodep;
  1579. dom_object *intern;
  1580. char *value;
  1581. DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
  1582. value = (char *) xmlGetNodePath(nodep);
  1583. if (value == NULL) {
  1584. RETURN_NULL();
  1585. } else {
  1586. RETVAL_STRING(value);
  1587. xmlFree(value);
  1588. }
  1589. }
  1590. /* }}} */
  1591. /* {{{ proto int DOMNode::getLineNo()
  1592. Gets line number for a node */
  1593. PHP_METHOD(domnode, getLineNo)
  1594. {
  1595. zval *id;
  1596. xmlNode *nodep;
  1597. dom_object *intern;
  1598. if (zend_parse_parameters_none() == FAILURE) {
  1599. return;
  1600. }
  1601. DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
  1602. RETURN_LONG(xmlGetLineNo(nodep));
  1603. }
  1604. /* }}} */
  1605. #endif
  1606. /*
  1607. * Local variables:
  1608. * tab-width: 4
  1609. * c-basic-offset: 4
  1610. * End:
  1611. * vim600: noet sw=4 ts=4 fdm=marker
  1612. * vim<600: noet sw=4 ts=4
  1613. */