document.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113
  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: Christian Stocker <chregu@php.net> |
  14. | Rob Richards <rrichards@php.net> |
  15. +----------------------------------------------------------------------+
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "php.h"
  21. #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
  22. #include "php_dom.h"
  23. #include <libxml/SAX.h>
  24. #ifdef LIBXML_SCHEMAS_ENABLED
  25. #include <libxml/relaxng.h>
  26. #include <libxml/xmlschemas.h>
  27. #endif
  28. typedef struct _idsIterator idsIterator;
  29. struct _idsIterator {
  30. xmlChar *elementId;
  31. xmlNode *element;
  32. };
  33. #define DOM_LOAD_STRING 0
  34. #define DOM_LOAD_FILE 1
  35. /*
  36. * class DOMDocument extends DOMNode
  37. *
  38. * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-i-Document
  39. * Since:
  40. */
  41. /* {{{ docType DOMDocumentType
  42. readonly=yes
  43. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-B63ED1A31
  44. Since:
  45. */
  46. int dom_document_doctype_read(dom_object *obj, zval *retval)
  47. {
  48. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  49. xmlDtdPtr dtdptr;
  50. if (docp == NULL) {
  51. php_dom_throw_error(INVALID_STATE_ERR, 1);
  52. return FAILURE;
  53. }
  54. dtdptr = xmlGetIntSubset(docp);
  55. if (!dtdptr) {
  56. ZVAL_NULL(retval);
  57. return SUCCESS;
  58. }
  59. php_dom_create_object((xmlNodePtr) dtdptr, retval, obj);
  60. return SUCCESS;
  61. }
  62. /* }}} */
  63. /* {{{ implementation DOMImplementation
  64. readonly=yes
  65. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1B793EBA
  66. Since:
  67. */
  68. int dom_document_implementation_read(dom_object *obj, zval *retval)
  69. {
  70. php_dom_create_implementation(retval);
  71. return SUCCESS;
  72. }
  73. /* }}} */
  74. /* {{{ documentElement DOMElement
  75. readonly=yes
  76. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-87CD092
  77. Since:
  78. */
  79. int dom_document_document_element_read(dom_object *obj, zval *retval)
  80. {
  81. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  82. xmlNode *root;
  83. if (docp == NULL) {
  84. php_dom_throw_error(INVALID_STATE_ERR, 1);
  85. return FAILURE;
  86. }
  87. root = xmlDocGetRootElement(docp);
  88. if (!root) {
  89. ZVAL_NULL(retval);
  90. return SUCCESS;
  91. }
  92. php_dom_create_object(root, retval, obj);
  93. return SUCCESS;
  94. }
  95. /* }}} */
  96. /* {{{ encoding string
  97. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-encoding
  98. Since: DOM Level 3
  99. */
  100. int dom_document_encoding_read(dom_object *obj, zval *retval)
  101. {
  102. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  103. char *encoding;
  104. if (docp == NULL) {
  105. php_dom_throw_error(INVALID_STATE_ERR, 1);
  106. return FAILURE;
  107. }
  108. encoding = (char *) docp->encoding;
  109. if (encoding != NULL) {
  110. ZVAL_STRING(retval, encoding);
  111. } else {
  112. ZVAL_NULL(retval);
  113. }
  114. return SUCCESS;
  115. }
  116. zend_result dom_document_encoding_write(dom_object *obj, zval *newval)
  117. {
  118. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  119. zend_string *str;
  120. xmlCharEncodingHandlerPtr handler;
  121. if (docp == NULL) {
  122. php_dom_throw_error(INVALID_STATE_ERR, 1);
  123. return FAILURE;
  124. }
  125. str = zval_try_get_string(newval);
  126. if (UNEXPECTED(!str)) {
  127. return FAILURE;
  128. }
  129. handler = xmlFindCharEncodingHandler(ZSTR_VAL(str));
  130. if (handler != NULL) {
  131. xmlCharEncCloseFunc(handler);
  132. if (docp->encoding != NULL) {
  133. xmlFree((xmlChar *)docp->encoding);
  134. }
  135. docp->encoding = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
  136. } else {
  137. zend_value_error("Invalid document encoding");
  138. return FAILURE;
  139. }
  140. zend_string_release_ex(str, 0);
  141. return SUCCESS;
  142. }
  143. /* }}} */
  144. /* {{{ standalone boolean
  145. readonly=no
  146. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-standalone
  147. Since: DOM Level 3
  148. */
  149. int dom_document_standalone_read(dom_object *obj, zval *retval)
  150. {
  151. xmlDoc *docp;
  152. docp = (xmlDocPtr) dom_object_get_node(obj);
  153. if (docp == NULL) {
  154. php_dom_throw_error(INVALID_STATE_ERR, 1);
  155. return FAILURE;
  156. }
  157. ZVAL_BOOL(retval, docp->standalone);
  158. return SUCCESS;
  159. }
  160. int dom_document_standalone_write(dom_object *obj, zval *newval)
  161. {
  162. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  163. zend_long standalone;
  164. if (docp == NULL) {
  165. php_dom_throw_error(INVALID_STATE_ERR, 1);
  166. return FAILURE;
  167. }
  168. standalone = zval_get_long(newval);
  169. docp->standalone = ZEND_NORMALIZE_BOOL(standalone);
  170. return SUCCESS;
  171. }
  172. /* }}} */
  173. /* {{{ version string
  174. readonly=no
  175. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-version
  176. Since: DOM Level 3
  177. */
  178. int dom_document_version_read(dom_object *obj, zval *retval)
  179. {
  180. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  181. char *version;
  182. if (docp == NULL) {
  183. php_dom_throw_error(INVALID_STATE_ERR, 1);
  184. return FAILURE;
  185. }
  186. version = (char *) docp->version;
  187. if (version != NULL) {
  188. ZVAL_STRING(retval, version);
  189. } else {
  190. ZVAL_NULL(retval);
  191. }
  192. return SUCCESS;
  193. }
  194. int dom_document_version_write(dom_object *obj, zval *newval)
  195. {
  196. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  197. zend_string *str;
  198. if (docp == NULL) {
  199. php_dom_throw_error(INVALID_STATE_ERR, 1);
  200. return FAILURE;
  201. }
  202. str = zval_try_get_string(newval);
  203. if (UNEXPECTED(!str)) {
  204. return FAILURE;
  205. }
  206. if (docp->version != NULL) {
  207. xmlFree((xmlChar *) docp->version );
  208. }
  209. docp->version = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
  210. zend_string_release_ex(str, 0);
  211. return SUCCESS;
  212. }
  213. /* }}} */
  214. /* {{{ strictErrorChecking boolean
  215. readonly=no
  216. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-strictErrorChecking
  217. Since: DOM Level 3
  218. */
  219. int dom_document_strict_error_checking_read(dom_object *obj, zval *retval)
  220. {
  221. if (obj->document) {
  222. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  223. ZVAL_BOOL(retval, doc_prop->stricterror);
  224. } else {
  225. ZVAL_FALSE(retval);
  226. }
  227. return SUCCESS;
  228. }
  229. int dom_document_strict_error_checking_write(dom_object *obj, zval *newval)
  230. {
  231. if (obj->document) {
  232. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  233. doc_prop->stricterror = zend_is_true(newval);
  234. }
  235. return SUCCESS;
  236. }
  237. /* }}} */
  238. /* {{{ formatOutput boolean
  239. readonly=no
  240. */
  241. int dom_document_format_output_read(dom_object *obj, zval *retval)
  242. {
  243. if (obj->document) {
  244. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  245. ZVAL_BOOL(retval, doc_prop->formatoutput);
  246. } else {
  247. ZVAL_FALSE(retval);
  248. }
  249. return SUCCESS;
  250. }
  251. int dom_document_format_output_write(dom_object *obj, zval *newval)
  252. {
  253. if (obj->document) {
  254. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  255. doc_prop->formatoutput = zend_is_true(newval);
  256. }
  257. return SUCCESS;
  258. }
  259. /* }}} */
  260. /* {{{ validateOnParse boolean
  261. readonly=no
  262. */
  263. int dom_document_validate_on_parse_read(dom_object *obj, zval *retval)
  264. {
  265. if (obj->document) {
  266. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  267. ZVAL_BOOL(retval, doc_prop->validateonparse);
  268. } else {
  269. ZVAL_FALSE(retval);
  270. }
  271. return SUCCESS;
  272. }
  273. int dom_document_validate_on_parse_write(dom_object *obj, zval *newval)
  274. {
  275. if (obj->document) {
  276. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  277. doc_prop->validateonparse = zend_is_true(newval);
  278. }
  279. return SUCCESS;
  280. }
  281. /* }}} */
  282. /* {{{ resolveExternals boolean
  283. readonly=no
  284. */
  285. int dom_document_resolve_externals_read(dom_object *obj, zval *retval)
  286. {
  287. if (obj->document) {
  288. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  289. ZVAL_BOOL(retval, doc_prop->resolveexternals);
  290. } else {
  291. ZVAL_FALSE(retval);
  292. }
  293. return SUCCESS;
  294. }
  295. int dom_document_resolve_externals_write(dom_object *obj, zval *newval)
  296. {
  297. if (obj->document) {
  298. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  299. doc_prop->resolveexternals = zend_is_true(newval);
  300. }
  301. return SUCCESS;
  302. }
  303. /* }}} */
  304. /* {{{ preserveWhiteSpace boolean
  305. readonly=no
  306. */
  307. int dom_document_preserve_whitespace_read(dom_object *obj, zval *retval)
  308. {
  309. if (obj->document) {
  310. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  311. ZVAL_BOOL(retval, doc_prop->preservewhitespace);
  312. } else {
  313. ZVAL_FALSE(retval);
  314. }
  315. return SUCCESS;
  316. }
  317. int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval)
  318. {
  319. if (obj->document) {
  320. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  321. doc_prop->preservewhitespace = zend_is_true(newval);
  322. }
  323. return SUCCESS;
  324. }
  325. /* }}} */
  326. /* {{{ recover boolean
  327. readonly=no
  328. */
  329. int dom_document_recover_read(dom_object *obj, zval *retval)
  330. {
  331. if (obj->document) {
  332. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  333. ZVAL_BOOL(retval, doc_prop->recover);
  334. } else {
  335. ZVAL_FALSE(retval);
  336. }
  337. return SUCCESS;
  338. }
  339. int dom_document_recover_write(dom_object *obj, zval *newval)
  340. {
  341. if (obj->document) {
  342. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  343. doc_prop->recover = zend_is_true(newval);
  344. }
  345. return SUCCESS;
  346. }
  347. /* }}} */
  348. /* {{{ substituteEntities boolean
  349. readonly=no
  350. */
  351. int dom_document_substitue_entities_read(dom_object *obj, zval *retval)
  352. {
  353. if (obj->document) {
  354. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  355. ZVAL_BOOL(retval, doc_prop->substituteentities);
  356. } else {
  357. ZVAL_FALSE(retval);
  358. }
  359. return SUCCESS;
  360. }
  361. int dom_document_substitue_entities_write(dom_object *obj, zval *newval)
  362. {
  363. if (obj->document) {
  364. dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
  365. doc_prop->substituteentities = zend_is_true(newval);
  366. }
  367. return SUCCESS;
  368. }
  369. /* }}} */
  370. /* {{{ documentURI string
  371. readonly=no
  372. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-documentURI
  373. Since: DOM Level 3
  374. */
  375. int dom_document_document_uri_read(dom_object *obj, zval *retval)
  376. {
  377. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  378. char *url;
  379. if (docp == NULL) {
  380. php_dom_throw_error(INVALID_STATE_ERR, 1);
  381. return FAILURE;
  382. }
  383. url = (char *) docp->URL;
  384. if (url != NULL) {
  385. ZVAL_STRING(retval, url);
  386. } else {
  387. ZVAL_NULL(retval);
  388. }
  389. return SUCCESS;
  390. }
  391. int dom_document_document_uri_write(dom_object *obj, zval *newval)
  392. {
  393. xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
  394. zend_string *str;
  395. if (docp == NULL) {
  396. php_dom_throw_error(INVALID_STATE_ERR, 1);
  397. return FAILURE;
  398. }
  399. str = zval_try_get_string(newval);
  400. if (UNEXPECTED(!str)) {
  401. return FAILURE;
  402. }
  403. if (docp->URL != NULL) {
  404. xmlFree((xmlChar *) docp->URL);
  405. }
  406. docp->URL = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
  407. zend_string_release_ex(str, 0);
  408. return SUCCESS;
  409. }
  410. /* }}} */
  411. /* {{{ config DOMConfiguration
  412. readonly=yes
  413. URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-config
  414. Since: DOM Level 3
  415. */
  416. int dom_document_config_read(dom_object *obj, zval *retval)
  417. {
  418. ZVAL_NULL(retval);
  419. return SUCCESS;
  420. }
  421. /* }}} */
  422. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-2141741547
  423. Since:
  424. */
  425. PHP_METHOD(DOMDocument, createElement)
  426. {
  427. zval *id;
  428. xmlNode *node;
  429. xmlDocPtr docp;
  430. dom_object *intern;
  431. int ret;
  432. size_t name_len, value_len;
  433. char *name, *value = NULL;
  434. id = ZEND_THIS;
  435. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &name, &name_len, &value, &value_len) == FAILURE) {
  436. RETURN_THROWS();
  437. }
  438. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  439. if (xmlValidateName((xmlChar *) name, 0) != 0) {
  440. php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
  441. RETURN_FALSE;
  442. }
  443. node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value);
  444. if (!node) {
  445. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  446. RETURN_THROWS();
  447. }
  448. DOM_RET_OBJ(node, &ret, intern);
  449. }
  450. /* }}} end dom_document_create_element */
  451. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-35CB04B5
  452. Since:
  453. */
  454. PHP_METHOD(DOMDocument, createDocumentFragment)
  455. {
  456. zval *id;
  457. xmlNode *node;
  458. xmlDocPtr docp;
  459. dom_object *intern;
  460. int ret;
  461. id = ZEND_THIS;
  462. if (zend_parse_parameters_none() == FAILURE) {
  463. RETURN_THROWS();
  464. }
  465. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  466. node = xmlNewDocFragment(docp);
  467. if (!node) {
  468. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  469. RETURN_THROWS();
  470. }
  471. DOM_RET_OBJ(node, &ret, intern);
  472. }
  473. /* }}} end dom_document_create_document_fragment */
  474. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1975348127
  475. Since:
  476. */
  477. PHP_METHOD(DOMDocument, createTextNode)
  478. {
  479. zval *id;
  480. xmlNode *node;
  481. xmlDocPtr docp;
  482. int ret;
  483. size_t value_len;
  484. dom_object *intern;
  485. char *value;
  486. id = ZEND_THIS;
  487. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) == FAILURE) {
  488. RETURN_THROWS();
  489. }
  490. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  491. node = xmlNewDocText(docp, (xmlChar *) value);
  492. if (!node) {
  493. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  494. RETURN_THROWS();
  495. }
  496. DOM_RET_OBJ(node, &ret, intern);
  497. }
  498. /* }}} end dom_document_create_text_node */
  499. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1334481328
  500. Since:
  501. */
  502. PHP_METHOD(DOMDocument, createComment)
  503. {
  504. zval *id;
  505. xmlNode *node;
  506. xmlDocPtr docp;
  507. int ret;
  508. size_t value_len;
  509. dom_object *intern;
  510. char *value;
  511. id = ZEND_THIS;
  512. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) == FAILURE) {
  513. RETURN_THROWS();
  514. }
  515. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  516. node = xmlNewDocComment(docp, (xmlChar *) value);
  517. if (!node) {
  518. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  519. RETURN_THROWS();
  520. }
  521. DOM_RET_OBJ(node, &ret, intern);
  522. }
  523. /* }}} end dom_document_create_comment */
  524. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D26C0AF8
  525. Since:
  526. */
  527. PHP_METHOD(DOMDocument, createCDATASection)
  528. {
  529. zval *id;
  530. xmlNode *node;
  531. xmlDocPtr docp;
  532. int ret;
  533. size_t value_len;
  534. dom_object *intern;
  535. char *value;
  536. id = ZEND_THIS;
  537. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) == FAILURE) {
  538. RETURN_THROWS();
  539. }
  540. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  541. node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len);
  542. if (!node) {
  543. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  544. RETURN_THROWS();
  545. }
  546. DOM_RET_OBJ(node, &ret, intern);
  547. }
  548. /* }}} end dom_document_create_cdatasection */
  549. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-135944439
  550. Since:
  551. */
  552. PHP_METHOD(DOMDocument, createProcessingInstruction)
  553. {
  554. zval *id;
  555. xmlNode *node;
  556. xmlDocPtr docp;
  557. int ret;
  558. size_t value_len, name_len = 0;
  559. dom_object *intern;
  560. char *name, *value = NULL;
  561. id = ZEND_THIS;
  562. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &name, &name_len, &value, &value_len) == FAILURE) {
  563. RETURN_THROWS();
  564. }
  565. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  566. if (xmlValidateName((xmlChar *) name, 0) != 0) {
  567. php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
  568. RETURN_FALSE;
  569. }
  570. node = xmlNewPI((xmlChar *) name, (xmlChar *) value);
  571. if (!node) {
  572. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  573. RETURN_THROWS();
  574. }
  575. node->doc = docp;
  576. DOM_RET_OBJ(node, &ret, intern);
  577. }
  578. /* }}} end dom_document_create_processing_instruction */
  579. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1084891198
  580. Since:
  581. */
  582. PHP_METHOD(DOMDocument, createAttribute)
  583. {
  584. zval *id;
  585. xmlAttrPtr node;
  586. xmlDocPtr docp;
  587. int ret;
  588. size_t name_len;
  589. dom_object *intern;
  590. char *name;
  591. id = ZEND_THIS;
  592. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  593. RETURN_THROWS();
  594. }
  595. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  596. if (xmlValidateName((xmlChar *) name, 0) != 0) {
  597. php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
  598. RETURN_FALSE;
  599. }
  600. node = xmlNewDocProp(docp, (xmlChar *) name, NULL);
  601. if (!node) {
  602. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  603. RETURN_THROWS();
  604. }
  605. DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
  606. }
  607. /* }}} end dom_document_create_attribute */
  608. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-392B75AE
  609. Since:
  610. */
  611. PHP_METHOD(DOMDocument, createEntityReference)
  612. {
  613. zval *id;
  614. xmlNode *node;
  615. xmlDocPtr docp = NULL;
  616. dom_object *intern;
  617. int ret;
  618. size_t name_len;
  619. char *name;
  620. id = ZEND_THIS;
  621. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  622. RETURN_THROWS();
  623. }
  624. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  625. if (xmlValidateName((xmlChar *) name, 0) != 0) {
  626. php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
  627. RETURN_FALSE;
  628. }
  629. node = xmlNewReference(docp, (xmlChar *) name);
  630. if (!node) {
  631. php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
  632. RETURN_THROWS();
  633. }
  634. DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
  635. }
  636. /* }}} end dom_document_create_entity_reference */
  637. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C9094
  638. Since:
  639. */
  640. PHP_METHOD(DOMDocument, getElementsByTagName)
  641. {
  642. zval *id;
  643. xmlDocPtr docp;
  644. size_t name_len;
  645. dom_object *intern, *namednode;
  646. char *name;
  647. xmlChar *local;
  648. id = ZEND_THIS;
  649. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  650. RETURN_THROWS();
  651. }
  652. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  653. php_dom_create_iterator(return_value, DOM_NODELIST);
  654. namednode = Z_DOMOBJ_P(return_value);
  655. local = xmlCharStrndup(name, name_len);
  656. dom_namednode_iter(intern, 0, namednode, NULL, local, NULL);
  657. }
  658. /* }}} end dom_document_get_elements_by_tag_name */
  659. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Core-Document-importNode
  660. Since: DOM Level 2
  661. */
  662. PHP_METHOD(DOMDocument, importNode)
  663. {
  664. zval *id, *node;
  665. xmlDocPtr docp;
  666. xmlNodePtr nodep, retnodep;
  667. dom_object *intern, *nodeobj;
  668. int ret;
  669. bool recursive = 0;
  670. /* See http://www.xmlsoft.org/html/libxml-tree.html#xmlDocCopyNode for meaning of values */
  671. int extended_recursive;
  672. id = ZEND_THIS;
  673. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &node, dom_node_class_entry, &recursive) == FAILURE) {
  674. RETURN_THROWS();
  675. }
  676. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  677. DOM_GET_OBJ(nodep, node, xmlNodePtr, nodeobj);
  678. if (nodep->type == XML_HTML_DOCUMENT_NODE || nodep->type == XML_DOCUMENT_NODE
  679. || nodep->type == XML_DOCUMENT_TYPE_NODE) {
  680. php_error_docref(NULL, E_WARNING, "Cannot import: Node Type Not Supported");
  681. RETURN_FALSE;
  682. }
  683. if (nodep->doc == docp) {
  684. retnodep = nodep;
  685. } else {
  686. extended_recursive = recursive;
  687. if ((recursive == 0) && (nodep->type == XML_ELEMENT_NODE)) {
  688. extended_recursive = 2;
  689. }
  690. retnodep = xmlDocCopyNode(nodep, docp, extended_recursive);
  691. if (!retnodep) {
  692. RETURN_FALSE;
  693. }
  694. if ((retnodep->type == XML_ATTRIBUTE_NODE) && (nodep->ns != NULL)) {
  695. xmlNsPtr nsptr = NULL;
  696. xmlNodePtr root = xmlDocGetRootElement(docp);
  697. nsptr = xmlSearchNsByHref (nodep->doc, root, nodep->ns->href);
  698. if (nsptr == NULL) {
  699. int errorcode;
  700. nsptr = dom_get_ns(root, (char *) nodep->ns->href, &errorcode, (char *) nodep->ns->prefix);
  701. }
  702. xmlSetNs(retnodep, nsptr);
  703. }
  704. }
  705. DOM_RET_OBJ((xmlNodePtr) retnodep, &ret, intern);
  706. }
  707. /* }}} end dom_document_import_node */
  708. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrElNS
  709. Since: DOM Level 2
  710. */
  711. PHP_METHOD(DOMDocument, createElementNS)
  712. {
  713. zval *id;
  714. xmlDocPtr docp;
  715. xmlNodePtr nodep = NULL;
  716. xmlNsPtr nsptr = NULL;
  717. int ret;
  718. size_t uri_len = 0, name_len = 0, value_len = 0;
  719. char *uri, *name, *value = NULL;
  720. char *localname = NULL, *prefix = NULL;
  721. int errorcode;
  722. dom_object *intern;
  723. id = ZEND_THIS;
  724. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s|s", &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) {
  725. RETURN_THROWS();
  726. }
  727. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  728. errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
  729. if (errorcode == 0) {
  730. if (xmlValidateName((xmlChar *) localname, 0) == 0) {
  731. nodep = xmlNewDocNode(docp, NULL, (xmlChar *) localname, (xmlChar *) value);
  732. if (nodep != NULL && uri != NULL) {
  733. nsptr = xmlSearchNsByHref(nodep->doc, nodep, (xmlChar *) uri);
  734. if (nsptr == NULL) {
  735. nsptr = dom_get_ns(nodep, uri, &errorcode, prefix);
  736. }
  737. xmlSetNs(nodep, nsptr);
  738. }
  739. } else {
  740. errorcode = INVALID_CHARACTER_ERR;
  741. }
  742. }
  743. xmlFree(localname);
  744. if (prefix != NULL) {
  745. xmlFree(prefix);
  746. }
  747. if (errorcode != 0) {
  748. if (nodep != NULL) {
  749. xmlFreeNode(nodep);
  750. }
  751. php_dom_throw_error(errorcode, dom_get_strict_error(intern->document));
  752. RETURN_FALSE;
  753. }
  754. if (nodep == NULL) {
  755. RETURN_FALSE;
  756. }
  757. nodep->ns = nsptr;
  758. DOM_RET_OBJ(nodep, &ret, intern);
  759. }
  760. /* }}} end dom_document_create_element_ns */
  761. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrAttrNS
  762. Since: DOM Level 2
  763. */
  764. PHP_METHOD(DOMDocument, createAttributeNS)
  765. {
  766. zval *id;
  767. xmlDocPtr docp;
  768. xmlNodePtr nodep = NULL, root;
  769. xmlNsPtr nsptr;
  770. int ret;
  771. size_t uri_len = 0, name_len = 0;
  772. char *uri, *name;
  773. char *localname = NULL, *prefix = NULL;
  774. dom_object *intern;
  775. int errorcode;
  776. id = ZEND_THIS;
  777. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
  778. RETURN_THROWS();
  779. }
  780. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  781. root = xmlDocGetRootElement(docp);
  782. if (root != NULL) {
  783. errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
  784. if (errorcode == 0) {
  785. if (xmlValidateName((xmlChar *) localname, 0) == 0) {
  786. nodep = (xmlNodePtr) xmlNewDocProp(docp, (xmlChar *) localname, NULL);
  787. if (nodep != NULL && uri_len > 0) {
  788. nsptr = xmlSearchNsByHref(nodep->doc, root, (xmlChar *) uri);
  789. if (nsptr == NULL) {
  790. nsptr = dom_get_ns(root, uri, &errorcode, prefix);
  791. }
  792. xmlSetNs(nodep, nsptr);
  793. }
  794. } else {
  795. errorcode = INVALID_CHARACTER_ERR;
  796. }
  797. }
  798. } else {
  799. php_error_docref(NULL, E_WARNING, "Document Missing Root Element");
  800. RETURN_FALSE;
  801. }
  802. xmlFree(localname);
  803. if (prefix != NULL) {
  804. xmlFree(prefix);
  805. }
  806. if (errorcode != 0) {
  807. if (nodep != NULL) {
  808. xmlFreeProp((xmlAttrPtr) nodep);
  809. }
  810. php_dom_throw_error(errorcode, dom_get_strict_error(intern->document));
  811. RETURN_FALSE;
  812. }
  813. if (nodep == NULL) {
  814. RETURN_FALSE;
  815. }
  816. DOM_RET_OBJ(nodep, &ret, intern);
  817. }
  818. /* }}} end dom_document_create_attribute_ns */
  819. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBTNNS
  820. Since: DOM Level 2
  821. */
  822. PHP_METHOD(DOMDocument, getElementsByTagNameNS)
  823. {
  824. zval *id;
  825. xmlDocPtr docp;
  826. size_t uri_len, name_len;
  827. dom_object *intern, *namednode;
  828. char *uri, *name;
  829. xmlChar *local, *nsuri;
  830. id = ZEND_THIS;
  831. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
  832. RETURN_THROWS();
  833. }
  834. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  835. php_dom_create_iterator(return_value, DOM_NODELIST);
  836. namednode = Z_DOMOBJ_P(return_value);
  837. local = xmlCharStrndup(name, name_len);
  838. nsuri = xmlCharStrndup(uri ? uri : "", uri_len);
  839. dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri);
  840. }
  841. /* }}} end dom_document_get_elements_by_tag_name_ns */
  842. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBId
  843. Since: DOM Level 2
  844. */
  845. PHP_METHOD(DOMDocument, getElementById)
  846. {
  847. zval *id;
  848. xmlDocPtr docp;
  849. xmlAttrPtr attrp;
  850. int ret;
  851. size_t idname_len;
  852. dom_object *intern;
  853. char *idname;
  854. id = ZEND_THIS;
  855. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &idname, &idname_len) == FAILURE) {
  856. RETURN_THROWS();
  857. }
  858. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  859. attrp = xmlGetID(docp, (xmlChar *) idname);
  860. if (attrp && attrp->parent) {
  861. DOM_RET_OBJ((xmlNodePtr) attrp->parent, &ret, intern);
  862. } else {
  863. RETVAL_NULL();
  864. }
  865. }
  866. /* }}} end dom_document_get_element_by_id */
  867. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-adoptNode
  868. Since: DOM Level 3
  869. */
  870. PHP_METHOD(DOMDocument, adoptNode)
  871. {
  872. zval *nodep = NULL;
  873. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &nodep, dom_node_class_entry) == FAILURE) {
  874. RETURN_THROWS();
  875. }
  876. DOM_NOT_IMPLEMENTED();
  877. }
  878. /* }}} end dom_document_adopt_node */
  879. /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-normalizeDocument
  880. Since: DOM Level 3
  881. */
  882. PHP_METHOD(DOMDocument, normalizeDocument)
  883. {
  884. zval *id;
  885. xmlDocPtr docp;
  886. dom_object *intern;
  887. id = ZEND_THIS;
  888. if (zend_parse_parameters_none() == FAILURE) {
  889. RETURN_THROWS();
  890. }
  891. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  892. dom_normalize((xmlNodePtr) docp);
  893. }
  894. /* }}} end dom_document_normalize_document */
  895. /* {{{ */
  896. PHP_METHOD(DOMDocument, __construct)
  897. {
  898. xmlDoc *docp = NULL, *olddoc;
  899. dom_object *intern;
  900. char *encoding, *version = NULL;
  901. size_t encoding_len = 0, version_len = 0;
  902. int refcount;
  903. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ss", &version, &version_len, &encoding, &encoding_len) == FAILURE) {
  904. RETURN_THROWS();
  905. }
  906. docp = xmlNewDoc((xmlChar *) version);
  907. if (!docp) {
  908. php_dom_throw_error(INVALID_STATE_ERR, 1);
  909. return;
  910. }
  911. if (encoding_len > 0) {
  912. docp->encoding = (const xmlChar *) xmlStrdup((xmlChar *) encoding);
  913. }
  914. intern = Z_DOMOBJ_P(ZEND_THIS);
  915. if (intern != NULL) {
  916. olddoc = (xmlDocPtr) dom_object_get_node(intern);
  917. if (olddoc != NULL) {
  918. php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
  919. refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
  920. if (refcount != 0) {
  921. olddoc->_private = NULL;
  922. }
  923. }
  924. intern->document = NULL;
  925. if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, docp) == -1) {
  926. /* docp is always non-null so php_libxml_increment_doc_ref() never returns -1 */
  927. ZEND_UNREACHABLE();
  928. }
  929. php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)docp, (void *)intern);
  930. }
  931. }
  932. /* }}} end DOMDocument::__construct */
  933. char *_dom_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len ) /* {{{ */
  934. {
  935. xmlURI *uri;
  936. xmlChar *escsource;
  937. char *file_dest;
  938. int isFileUri = 0;
  939. uri = xmlCreateURI();
  940. escsource = xmlURIEscapeStr((xmlChar *) source, (xmlChar *) ":");
  941. xmlParseURIReference(uri, (char *) escsource);
  942. xmlFree(escsource);
  943. if (uri->scheme != NULL) {
  944. /* absolute file uris - libxml only supports localhost or empty host */
  945. #ifdef PHP_WIN32
  946. if (strncasecmp(source, "file://",7) == 0 && ':' == source[8]) {
  947. isFileUri = 1;
  948. source += 7;
  949. } else
  950. #endif
  951. if (strncasecmp(source, "file:///",8) == 0) {
  952. isFileUri = 1;
  953. #ifdef PHP_WIN32
  954. source += 8;
  955. #else
  956. source += 7;
  957. #endif
  958. } else if (strncasecmp(source, "file://localhost/",17) == 0) {
  959. isFileUri = 1;
  960. #ifdef PHP_WIN32
  961. source += 17;
  962. #else
  963. source += 16;
  964. #endif
  965. }
  966. }
  967. file_dest = source;
  968. if ((uri->scheme == NULL || isFileUri)) {
  969. /* XXX possible buffer overflow if VCWD_REALPATH does not know size of resolved_path */
  970. if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path)) {
  971. xmlFreeURI(uri);
  972. return NULL;
  973. }
  974. file_dest = resolved_path;
  975. }
  976. xmlFreeURI(uri);
  977. return file_dest;
  978. }
  979. /* }}} */
  980. static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t source_len, size_t options) /* {{{ */
  981. {
  982. xmlDocPtr ret;
  983. xmlParserCtxtPtr ctxt = NULL;
  984. dom_doc_propsptr doc_props;
  985. dom_object *intern;
  986. php_libxml_ref_obj *document = NULL;
  987. int validate, recover, resolve_externals, keep_blanks, substitute_ent;
  988. int resolved_path_len;
  989. int old_error_reporting = 0;
  990. char *directory=NULL, resolved_path[MAXPATHLEN];
  991. if (id != NULL) {
  992. intern = Z_DOMOBJ_P(id);
  993. document = intern->document;
  994. }
  995. doc_props = dom_get_doc_props(document);
  996. validate = doc_props->validateonparse;
  997. resolve_externals = doc_props->resolveexternals;
  998. keep_blanks = doc_props->preservewhitespace;
  999. substitute_ent = doc_props->substituteentities;
  1000. recover = doc_props->recover;
  1001. if (document == NULL) {
  1002. efree(doc_props);
  1003. }
  1004. xmlInitParser();
  1005. if (mode == DOM_LOAD_FILE) {
  1006. char *file_dest;
  1007. if (CHECK_NULL_PATH(source, source_len)) {
  1008. zend_value_error("Path to document must not contain any null bytes");
  1009. return NULL;
  1010. }
  1011. file_dest = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
  1012. if (file_dest) {
  1013. ctxt = xmlCreateFileParserCtxt(file_dest);
  1014. }
  1015. } else {
  1016. ctxt = xmlCreateMemoryParserCtxt(source, source_len);
  1017. }
  1018. if (ctxt == NULL) {
  1019. return(NULL);
  1020. }
  1021. /* If loading from memory, we need to set the base directory for the document */
  1022. if (mode != DOM_LOAD_FILE) {
  1023. #ifdef HAVE_GETCWD
  1024. directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
  1025. #elif defined(HAVE_GETWD)
  1026. directory = VCWD_GETWD(resolved_path);
  1027. #endif
  1028. if (directory) {
  1029. if(ctxt->directory != NULL) {
  1030. xmlFree((char *) ctxt->directory);
  1031. }
  1032. resolved_path_len = strlen(resolved_path);
  1033. if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
  1034. resolved_path[resolved_path_len] = DEFAULT_SLASH;
  1035. resolved_path[++resolved_path_len] = '\0';
  1036. }
  1037. ctxt->directory = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
  1038. }
  1039. }
  1040. ctxt->vctxt.error = php_libxml_ctx_error;
  1041. ctxt->vctxt.warning = php_libxml_ctx_warning;
  1042. if (ctxt->sax != NULL) {
  1043. ctxt->sax->error = php_libxml_ctx_error;
  1044. ctxt->sax->warning = php_libxml_ctx_warning;
  1045. }
  1046. if (validate && ! (options & XML_PARSE_DTDVALID)) {
  1047. options |= XML_PARSE_DTDVALID;
  1048. }
  1049. if (resolve_externals && ! (options & XML_PARSE_DTDATTR)) {
  1050. options |= XML_PARSE_DTDATTR;
  1051. }
  1052. if (substitute_ent && ! (options & XML_PARSE_NOENT)) {
  1053. options |= XML_PARSE_NOENT;
  1054. }
  1055. if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
  1056. options |= XML_PARSE_NOBLANKS;
  1057. }
  1058. xmlCtxtUseOptions(ctxt, options);
  1059. ctxt->recovery = recover;
  1060. if (recover) {
  1061. old_error_reporting = EG(error_reporting);
  1062. EG(error_reporting) = old_error_reporting | E_WARNING;
  1063. }
  1064. xmlParseDocument(ctxt);
  1065. if (ctxt->wellFormed || recover) {
  1066. ret = ctxt->myDoc;
  1067. if (ctxt->recovery) {
  1068. EG(error_reporting) = old_error_reporting;
  1069. }
  1070. /* If loading from memory, set the base reference uri for the document */
  1071. if (ret && ret->URL == NULL && ctxt->directory != NULL) {
  1072. ret->URL = xmlStrdup((xmlChar *) ctxt->directory);
  1073. }
  1074. } else {
  1075. ret = NULL;
  1076. xmlFreeDoc(ctxt->myDoc);
  1077. ctxt->myDoc = NULL;
  1078. }
  1079. xmlFreeParserCtxt(ctxt);
  1080. return(ret);
  1081. }
  1082. /* }}} */
  1083. /* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
  1084. static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
  1085. zval *id;
  1086. xmlDoc *docp = NULL, *newdoc;
  1087. dom_doc_propsptr doc_prop;
  1088. dom_object *intern;
  1089. char *source;
  1090. size_t source_len;
  1091. int refcount, ret;
  1092. zend_long options = 0;
  1093. id = getThis();
  1094. if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
  1095. id = NULL;
  1096. }
  1097. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
  1098. RETURN_THROWS();
  1099. }
  1100. if (!source_len) {
  1101. zend_argument_value_error(1, "must not be empty");
  1102. RETURN_THROWS();
  1103. }
  1104. if (ZEND_SIZE_T_INT_OVFL(source_len)) {
  1105. php_error_docref(NULL, E_WARNING, "Input string is too long");
  1106. RETURN_FALSE;
  1107. }
  1108. if (ZEND_LONG_EXCEEDS_INT(options)) {
  1109. php_error_docref(NULL, E_WARNING, "Invalid options");
  1110. RETURN_FALSE;
  1111. }
  1112. newdoc = dom_document_parser(id, mode, source, source_len, options);
  1113. if (!newdoc)
  1114. RETURN_FALSE;
  1115. if (id != NULL) {
  1116. intern = Z_DOMOBJ_P(id);
  1117. if (intern != NULL) {
  1118. docp = (xmlDocPtr) dom_object_get_node(intern);
  1119. doc_prop = NULL;
  1120. if (docp != NULL) {
  1121. php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
  1122. doc_prop = intern->document->doc_props;
  1123. intern->document->doc_props = NULL;
  1124. refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
  1125. if (refcount != 0) {
  1126. docp->_private = NULL;
  1127. }
  1128. }
  1129. intern->document = NULL;
  1130. if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
  1131. RETURN_FALSE;
  1132. }
  1133. intern->document->doc_props = doc_prop;
  1134. }
  1135. php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
  1136. RETURN_TRUE;
  1137. } else {
  1138. DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
  1139. }
  1140. }
  1141. /* }}} end dom_parser_document */
  1142. /* {{{ URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load
  1143. Since: DOM Level 3
  1144. */
  1145. PHP_METHOD(DOMDocument, load)
  1146. {
  1147. dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
  1148. }
  1149. /* }}} end dom_document_load */
  1150. /* {{{ URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML
  1151. Since: DOM Level 3
  1152. */
  1153. PHP_METHOD(DOMDocument, loadXML)
  1154. {
  1155. dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
  1156. }
  1157. /* }}} end dom_document_loadxml */
  1158. /* {{{ Convenience method to save to file */
  1159. PHP_METHOD(DOMDocument, save)
  1160. {
  1161. zval *id;
  1162. xmlDoc *docp;
  1163. size_t file_len = 0;
  1164. int bytes, format, saveempty = 0;
  1165. dom_object *intern;
  1166. dom_doc_propsptr doc_props;
  1167. char *file;
  1168. zend_long options = 0;
  1169. id = ZEND_THIS;
  1170. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &file, &file_len, &options) == FAILURE) {
  1171. RETURN_THROWS();
  1172. }
  1173. if (file_len == 0) {
  1174. zend_argument_value_error(1, "must not be empty");
  1175. RETURN_THROWS();
  1176. }
  1177. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1178. /* encoding handled by property on doc */
  1179. doc_props = dom_get_doc_props(intern->document);
  1180. format = doc_props->formatoutput;
  1181. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1182. saveempty = xmlSaveNoEmptyTags;
  1183. xmlSaveNoEmptyTags = 1;
  1184. }
  1185. bytes = xmlSaveFormatFileEnc(file, docp, NULL, format);
  1186. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1187. xmlSaveNoEmptyTags = saveempty;
  1188. }
  1189. if (bytes == -1) {
  1190. RETURN_FALSE;
  1191. }
  1192. RETURN_LONG(bytes);
  1193. }
  1194. /* }}} end dom_document_save */
  1195. /* {{{ URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-saveXML
  1196. Since: DOM Level 3
  1197. */
  1198. PHP_METHOD(DOMDocument, saveXML)
  1199. {
  1200. zval *id, *nodep = NULL;
  1201. xmlDoc *docp;
  1202. xmlNode *node;
  1203. xmlBufferPtr buf;
  1204. xmlChar *mem;
  1205. dom_object *intern, *nodeobj;
  1206. dom_doc_propsptr doc_props;
  1207. int size, format, saveempty = 0;
  1208. zend_long options = 0;
  1209. id = ZEND_THIS;
  1210. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!l", &nodep, dom_node_class_entry, &options) == FAILURE) {
  1211. RETURN_THROWS();
  1212. }
  1213. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1214. doc_props = dom_get_doc_props(intern->document);
  1215. format = doc_props->formatoutput;
  1216. if (nodep != NULL) {
  1217. /* Dump contents of Node */
  1218. DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
  1219. if (node->doc != docp) {
  1220. php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
  1221. RETURN_FALSE;
  1222. }
  1223. buf = xmlBufferCreate();
  1224. if (!buf) {
  1225. php_error_docref(NULL, E_WARNING, "Could not fetch buffer");
  1226. RETURN_FALSE;
  1227. }
  1228. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1229. saveempty = xmlSaveNoEmptyTags;
  1230. xmlSaveNoEmptyTags = 1;
  1231. }
  1232. xmlNodeDump(buf, docp, node, 0, format);
  1233. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1234. xmlSaveNoEmptyTags = saveempty;
  1235. }
  1236. mem = (xmlChar*) xmlBufferContent(buf);
  1237. if (!mem) {
  1238. xmlBufferFree(buf);
  1239. RETURN_FALSE;
  1240. }
  1241. RETVAL_STRING((char *) mem);
  1242. xmlBufferFree(buf);
  1243. } else {
  1244. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1245. saveempty = xmlSaveNoEmptyTags;
  1246. xmlSaveNoEmptyTags = 1;
  1247. }
  1248. /* Encoding is handled from the encoding property set on the document */
  1249. xmlDocDumpFormatMemory(docp, &mem, &size, format);
  1250. if (options & LIBXML_SAVE_NOEMPTYTAG) {
  1251. xmlSaveNoEmptyTags = saveempty;
  1252. }
  1253. if (!size || !mem) {
  1254. RETURN_FALSE;
  1255. }
  1256. RETVAL_STRINGL((char *) mem, size);
  1257. xmlFree(mem);
  1258. }
  1259. }
  1260. /* }}} end dom_document_savexml */
  1261. static xmlNodePtr php_dom_free_xinclude_node(xmlNodePtr cur) /* {{{ */
  1262. {
  1263. xmlNodePtr xincnode;
  1264. xincnode = cur;
  1265. cur = cur->next;
  1266. xmlUnlinkNode(xincnode);
  1267. php_libxml_node_free_resource(xincnode);
  1268. return cur;
  1269. }
  1270. /* }}} */
  1271. static void php_dom_remove_xinclude_nodes(xmlNodePtr cur) /* {{{ */
  1272. {
  1273. while(cur) {
  1274. if (cur->type == XML_XINCLUDE_START) {
  1275. cur = php_dom_free_xinclude_node(cur);
  1276. /* XML_XINCLUDE_END node will be a sibling of XML_XINCLUDE_START */
  1277. while(cur && cur->type != XML_XINCLUDE_END) {
  1278. /* remove xinclude processing nodes from recursive xincludes */
  1279. if (cur->type == XML_ELEMENT_NODE) {
  1280. php_dom_remove_xinclude_nodes(cur->children);
  1281. }
  1282. cur = cur->next;
  1283. }
  1284. if (cur && cur->type == XML_XINCLUDE_END) {
  1285. cur = php_dom_free_xinclude_node(cur);
  1286. }
  1287. } else {
  1288. if (cur->type == XML_ELEMENT_NODE) {
  1289. php_dom_remove_xinclude_nodes(cur->children);
  1290. }
  1291. cur = cur->next;
  1292. }
  1293. }
  1294. }
  1295. /* }}} */
  1296. /* {{{ Substitutues xincludes in a DomDocument */
  1297. PHP_METHOD(DOMDocument, xinclude)
  1298. {
  1299. zval *id;
  1300. xmlDoc *docp;
  1301. xmlNodePtr root;
  1302. zend_long flags = 0;
  1303. int err;
  1304. dom_object *intern;
  1305. id = ZEND_THIS;
  1306. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flags) == FAILURE) {
  1307. RETURN_THROWS();
  1308. }
  1309. if (ZEND_LONG_EXCEEDS_INT(flags)) {
  1310. php_error_docref(NULL, E_WARNING, "Invalid flags");
  1311. RETURN_FALSE;
  1312. }
  1313. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1314. err = xmlXIncludeProcessFlags(docp, (int)flags);
  1315. /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
  1316. are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
  1317. but are not wanted in resulting document - must be done even if err as it could fail after
  1318. having processed some xincludes */
  1319. root = (xmlNodePtr) docp->children;
  1320. while(root && root->type != XML_ELEMENT_NODE && root->type != XML_XINCLUDE_START) {
  1321. root = root->next;
  1322. }
  1323. if (root) {
  1324. php_dom_remove_xinclude_nodes(root);
  1325. }
  1326. if (err) {
  1327. RETVAL_LONG(err);
  1328. } else {
  1329. RETVAL_FALSE;
  1330. }
  1331. }
  1332. /* }}} */
  1333. /* {{{ Since: DOM extended */
  1334. PHP_METHOD(DOMDocument, validate)
  1335. {
  1336. zval *id;
  1337. xmlDoc *docp;
  1338. dom_object *intern;
  1339. xmlValidCtxt *cvp;
  1340. id = ZEND_THIS;
  1341. if (zend_parse_parameters_none() == FAILURE) {
  1342. RETURN_THROWS();
  1343. }
  1344. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1345. cvp = xmlNewValidCtxt();
  1346. cvp->userData = NULL;
  1347. cvp->error = (xmlValidityErrorFunc) php_libxml_error_handler;
  1348. cvp->warning = (xmlValidityErrorFunc) php_libxml_error_handler;
  1349. if (xmlValidateDocument(cvp, docp)) {
  1350. RETVAL_TRUE;
  1351. } else {
  1352. RETVAL_FALSE;
  1353. }
  1354. xmlFreeValidCtxt(cvp);
  1355. }
  1356. /* }}} */
  1357. #ifdef LIBXML_SCHEMAS_ENABLED
  1358. static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  1359. {
  1360. zval *id;
  1361. xmlDoc *docp;
  1362. dom_object *intern;
  1363. char *source = NULL, *valid_file = NULL;
  1364. size_t source_len = 0;
  1365. int valid_opts = 0;
  1366. zend_long flags = 0;
  1367. xmlSchemaParserCtxtPtr parser;
  1368. xmlSchemaPtr sptr;
  1369. xmlSchemaValidCtxtPtr vptr;
  1370. int is_valid;
  1371. char resolved_path[MAXPATHLEN + 1];
  1372. id = ZEND_THIS;
  1373. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &flags) == FAILURE) {
  1374. RETURN_THROWS();
  1375. }
  1376. if (!source_len) {
  1377. zend_argument_value_error(1, "must not be empty");
  1378. RETURN_THROWS();
  1379. }
  1380. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1381. switch (type) {
  1382. case DOM_LOAD_FILE:
  1383. if (CHECK_NULL_PATH(source, source_len)) {
  1384. zend_argument_value_error(1, "must not contain any null bytes");
  1385. RETURN_THROWS();
  1386. }
  1387. valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
  1388. if (!valid_file) {
  1389. php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
  1390. RETURN_FALSE;
  1391. }
  1392. parser = xmlSchemaNewParserCtxt(valid_file);
  1393. break;
  1394. case DOM_LOAD_STRING:
  1395. parser = xmlSchemaNewMemParserCtxt(source, source_len);
  1396. /* If loading from memory, we need to set the base directory for the document
  1397. but it is not apparent how to do that for schema's */
  1398. break;
  1399. default:
  1400. return;
  1401. }
  1402. xmlSchemaSetParserErrors(parser,
  1403. (xmlSchemaValidityErrorFunc) php_libxml_error_handler,
  1404. (xmlSchemaValidityWarningFunc) php_libxml_error_handler,
  1405. parser);
  1406. sptr = xmlSchemaParse(parser);
  1407. xmlSchemaFreeParserCtxt(parser);
  1408. if (!sptr) {
  1409. if (!EG(exception)) {
  1410. php_error_docref(NULL, E_WARNING, "Invalid Schema");
  1411. }
  1412. RETURN_FALSE;
  1413. }
  1414. docp = (xmlDocPtr) dom_object_get_node(intern);
  1415. vptr = xmlSchemaNewValidCtxt(sptr);
  1416. if (!vptr) {
  1417. xmlSchemaFree(sptr);
  1418. zend_throw_error(NULL, "Invalid Schema Validation Context");
  1419. RETURN_THROWS();
  1420. }
  1421. if (flags & XML_SCHEMA_VAL_VC_I_CREATE) {
  1422. valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE;
  1423. }
  1424. xmlSchemaSetValidOptions(vptr, valid_opts);
  1425. xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
  1426. is_valid = xmlSchemaValidateDoc(vptr, docp);
  1427. xmlSchemaFree(sptr);
  1428. xmlSchemaFreeValidCtxt(vptr);
  1429. if (is_valid == 0) {
  1430. RETURN_TRUE;
  1431. } else {
  1432. RETURN_FALSE;
  1433. }
  1434. }
  1435. /* }}} */
  1436. /* {{{ */
  1437. PHP_METHOD(DOMDocument, schemaValidate)
  1438. {
  1439. _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
  1440. }
  1441. /* }}} end dom_document_schema_validate_file */
  1442. /* {{{ */
  1443. PHP_METHOD(DOMDocument, schemaValidateSource)
  1444. {
  1445. _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
  1446. }
  1447. /* }}} end dom_document_schema_validate */
  1448. static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  1449. {
  1450. zval *id;
  1451. xmlDoc *docp;
  1452. dom_object *intern;
  1453. char *source = NULL, *valid_file = NULL;
  1454. size_t source_len = 0;
  1455. xmlRelaxNGParserCtxtPtr parser;
  1456. xmlRelaxNGPtr sptr;
  1457. xmlRelaxNGValidCtxtPtr vptr;
  1458. int is_valid;
  1459. char resolved_path[MAXPATHLEN + 1];
  1460. id = ZEND_THIS;
  1461. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &source, &source_len) == FAILURE) {
  1462. RETURN_THROWS();
  1463. }
  1464. if (!source_len) {
  1465. zend_argument_value_error(1, "must not be empty");
  1466. RETURN_THROWS();
  1467. }
  1468. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1469. switch (type) {
  1470. case DOM_LOAD_FILE:
  1471. if (CHECK_NULL_PATH(source, source_len)) {
  1472. zend_argument_value_error(1, "must not contain any null bytes");
  1473. RETURN_THROWS();
  1474. }
  1475. valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
  1476. if (!valid_file) {
  1477. php_error_docref(NULL, E_WARNING, "Invalid RelaxNG file source");
  1478. RETURN_FALSE;
  1479. }
  1480. parser = xmlRelaxNGNewParserCtxt(valid_file);
  1481. break;
  1482. case DOM_LOAD_STRING:
  1483. parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
  1484. /* If loading from memory, we need to set the base directory for the document
  1485. but it is not apparent how to do that for schema's */
  1486. break;
  1487. default:
  1488. return;
  1489. }
  1490. xmlRelaxNGSetParserErrors(parser,
  1491. (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
  1492. (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
  1493. parser);
  1494. sptr = xmlRelaxNGParse(parser);
  1495. xmlRelaxNGFreeParserCtxt(parser);
  1496. if (!sptr) {
  1497. php_error_docref(NULL, E_WARNING, "Invalid RelaxNG");
  1498. RETURN_FALSE;
  1499. }
  1500. docp = (xmlDocPtr) dom_object_get_node(intern);
  1501. vptr = xmlRelaxNGNewValidCtxt(sptr);
  1502. if (!vptr) {
  1503. xmlRelaxNGFree(sptr);
  1504. zend_throw_error(NULL, "Invalid RelaxNG Validation Context");
  1505. RETURN_THROWS();
  1506. }
  1507. xmlRelaxNGSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
  1508. is_valid = xmlRelaxNGValidateDoc(vptr, docp);
  1509. xmlRelaxNGFree(sptr);
  1510. xmlRelaxNGFreeValidCtxt(vptr);
  1511. if (is_valid == 0) {
  1512. RETURN_TRUE;
  1513. } else {
  1514. RETURN_FALSE;
  1515. }
  1516. }
  1517. /* }}} */
  1518. /* {{{ */
  1519. PHP_METHOD(DOMDocument, relaxNGValidate)
  1520. {
  1521. _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
  1522. }
  1523. /* }}} end dom_document_relaxNG_validate_file */
  1524. /* {{{ */
  1525. PHP_METHOD(DOMDocument, relaxNGValidateSource)
  1526. {
  1527. _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
  1528. }
  1529. /* }}} end dom_document_relaxNG_validate_xml */
  1530. #endif
  1531. #ifdef LIBXML_HTML_ENABLED
  1532. static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
  1533. {
  1534. zval *id;
  1535. xmlDoc *docp = NULL, *newdoc;
  1536. dom_object *intern;
  1537. dom_doc_propsptr doc_prop;
  1538. char *source;
  1539. size_t source_len;
  1540. int refcount, ret;
  1541. zend_long options = 0;
  1542. htmlParserCtxtPtr ctxt;
  1543. id = getThis();
  1544. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
  1545. RETURN_THROWS();
  1546. }
  1547. if (!source_len) {
  1548. zend_argument_value_error(1, "must not be empty");
  1549. RETURN_THROWS();
  1550. }
  1551. if (ZEND_LONG_EXCEEDS_INT(options)) {
  1552. php_error_docref(NULL, E_WARNING, "Invalid options");
  1553. RETURN_FALSE;
  1554. }
  1555. if (mode == DOM_LOAD_FILE) {
  1556. if (CHECK_NULL_PATH(source, source_len)) {
  1557. zend_argument_value_error(1, "must not contain any null bytes");
  1558. RETURN_THROWS();
  1559. }
  1560. ctxt = htmlCreateFileParserCtxt(source, NULL);
  1561. } else {
  1562. if (ZEND_SIZE_T_INT_OVFL(source_len)) {
  1563. php_error_docref(NULL, E_WARNING, "Input string is too long");
  1564. RETURN_FALSE;
  1565. }
  1566. ctxt = htmlCreateMemoryParserCtxt(source, (int)source_len);
  1567. }
  1568. if (!ctxt) {
  1569. RETURN_FALSE;
  1570. }
  1571. ctxt->vctxt.error = php_libxml_ctx_error;
  1572. ctxt->vctxt.warning = php_libxml_ctx_warning;
  1573. if (ctxt->sax != NULL) {
  1574. ctxt->sax->error = php_libxml_ctx_error;
  1575. ctxt->sax->warning = php_libxml_ctx_warning;
  1576. }
  1577. if (options) {
  1578. htmlCtxtUseOptions(ctxt, (int)options);
  1579. }
  1580. htmlParseDocument(ctxt);
  1581. newdoc = ctxt->myDoc;
  1582. htmlFreeParserCtxt(ctxt);
  1583. if (!newdoc)
  1584. RETURN_FALSE;
  1585. if (id != NULL && instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
  1586. intern = Z_DOMOBJ_P(id);
  1587. if (intern != NULL) {
  1588. docp = (xmlDocPtr) dom_object_get_node(intern);
  1589. doc_prop = NULL;
  1590. if (docp != NULL) {
  1591. php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
  1592. doc_prop = intern->document->doc_props;
  1593. intern->document->doc_props = NULL;
  1594. refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
  1595. if (refcount != 0) {
  1596. docp->_private = NULL;
  1597. }
  1598. }
  1599. intern->document = NULL;
  1600. if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
  1601. RETURN_FALSE;
  1602. }
  1603. intern->document->doc_props = doc_prop;
  1604. }
  1605. php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
  1606. RETURN_TRUE;
  1607. } else {
  1608. DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
  1609. }
  1610. }
  1611. /* }}} */
  1612. /* {{{ Since: DOM extended */
  1613. PHP_METHOD(DOMDocument, loadHTMLFile)
  1614. {
  1615. dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
  1616. }
  1617. /* }}} end dom_document_load_html_file */
  1618. /* {{{ Since: DOM extended */
  1619. PHP_METHOD(DOMDocument, loadHTML)
  1620. {
  1621. dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
  1622. }
  1623. /* }}} end dom_document_load_html */
  1624. /* {{{ Convenience method to save to file as html */
  1625. PHP_METHOD(DOMDocument, saveHTMLFile)
  1626. {
  1627. zval *id;
  1628. xmlDoc *docp;
  1629. size_t file_len;
  1630. int bytes, format;
  1631. dom_object *intern;
  1632. dom_doc_propsptr doc_props;
  1633. char *file;
  1634. const char *encoding;
  1635. id = ZEND_THIS;
  1636. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &file, &file_len) == FAILURE) {
  1637. RETURN_THROWS();
  1638. }
  1639. if (file_len == 0) {
  1640. zend_argument_value_error(1, "must not be empty");
  1641. RETURN_THROWS();
  1642. }
  1643. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1644. encoding = (const char *) htmlGetMetaEncoding(docp);
  1645. doc_props = dom_get_doc_props(intern->document);
  1646. format = doc_props->formatoutput;
  1647. bytes = htmlSaveFileFormat(file, docp, encoding, format);
  1648. if (bytes == -1) {
  1649. RETURN_FALSE;
  1650. }
  1651. RETURN_LONG(bytes);
  1652. }
  1653. /* }}} end dom_document_save_html_file */
  1654. /* {{{ Convenience method to output as html */
  1655. PHP_METHOD(DOMDocument, saveHTML)
  1656. {
  1657. zval *id, *nodep = NULL;
  1658. xmlDoc *docp;
  1659. xmlNode *node;
  1660. xmlOutputBufferPtr outBuf;
  1661. xmlBufferPtr buf;
  1662. dom_object *intern, *nodeobj;
  1663. xmlChar *mem = NULL;
  1664. int format;
  1665. dom_doc_propsptr doc_props;
  1666. id = ZEND_THIS;
  1667. if (zend_parse_parameters(ZEND_NUM_ARGS(),
  1668. "|O!", &nodep, dom_node_class_entry)
  1669. == FAILURE) {
  1670. RETURN_THROWS();
  1671. }
  1672. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1673. doc_props = dom_get_doc_props(intern->document);
  1674. format = doc_props->formatoutput;
  1675. if (nodep != NULL) {
  1676. /* Dump contents of Node */
  1677. DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
  1678. if (node->doc != docp) {
  1679. php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
  1680. RETURN_FALSE;
  1681. }
  1682. buf = xmlBufferCreate();
  1683. if (!buf) {
  1684. php_error_docref(NULL, E_WARNING, "Could not fetch buffer");
  1685. RETURN_FALSE;
  1686. }
  1687. outBuf = xmlOutputBufferCreateBuffer(buf, NULL);
  1688. if (!outBuf) {
  1689. xmlBufferFree(buf);
  1690. php_error_docref(NULL, E_WARNING, "Could not fetch output buffer");
  1691. RETURN_FALSE;
  1692. }
  1693. if (node->type == XML_DOCUMENT_FRAG_NODE) {
  1694. for (node = node->children; node; node = node->next) {
  1695. htmlNodeDumpFormatOutput(outBuf, docp, node, NULL, format);
  1696. if (outBuf->error) {
  1697. break;
  1698. }
  1699. }
  1700. } else {
  1701. htmlNodeDumpFormatOutput(outBuf, docp, node, NULL, format);
  1702. }
  1703. if (!outBuf->error) {
  1704. xmlOutputBufferFlush(outBuf);
  1705. mem = (xmlChar*) xmlBufferContent(buf);
  1706. if (!mem) {
  1707. RETVAL_FALSE;
  1708. } else {
  1709. int size = xmlBufferLength(buf);
  1710. RETVAL_STRINGL((const char*) mem, size);
  1711. }
  1712. } else {
  1713. php_error_docref(NULL, E_WARNING, "Error dumping HTML node");
  1714. RETVAL_FALSE;
  1715. }
  1716. xmlOutputBufferClose(outBuf);
  1717. xmlBufferFree(buf);
  1718. } else {
  1719. int size = 0;
  1720. htmlDocDumpMemoryFormat(docp, &mem, &size, format);
  1721. if (!size || !mem) {
  1722. RETVAL_FALSE;
  1723. } else {
  1724. RETVAL_STRINGL((const char*) mem, size);
  1725. }
  1726. if (mem)
  1727. xmlFree(mem);
  1728. }
  1729. }
  1730. /* }}} end dom_document_save_html */
  1731. #endif /* defined(LIBXML_HTML_ENABLED) */
  1732. /* {{{ Register extended class used to create base node type */
  1733. PHP_METHOD(DOMDocument, registerNodeClass)
  1734. {
  1735. zval *id;
  1736. xmlDoc *docp;
  1737. zend_class_entry *basece = dom_node_class_entry, *ce = NULL;
  1738. dom_object *intern;
  1739. id = ZEND_THIS;
  1740. if (zend_parse_parameters(ZEND_NUM_ARGS(), "CC!", &basece, &ce) == FAILURE) {
  1741. RETURN_THROWS();
  1742. }
  1743. if (ce == NULL || instanceof_function(ce, basece)) {
  1744. DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
  1745. dom_set_doc_classmap(intern->document, basece, ce);
  1746. RETURN_TRUE;
  1747. }
  1748. zend_argument_error(NULL, 2, "must be a class name derived from %s or null, %s given", ZSTR_VAL(basece->name), ZSTR_VAL(ce->name));
  1749. }
  1750. /* }}} */
  1751. /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-append
  1752. Since: DOM Living Standard (DOM4)
  1753. */
  1754. PHP_METHOD(DOMDocument, append)
  1755. {
  1756. int argc;
  1757. zval *args, *id;
  1758. dom_object *intern;
  1759. xmlNode *context;
  1760. if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
  1761. RETURN_THROWS();
  1762. }
  1763. id = ZEND_THIS;
  1764. DOM_GET_OBJ(context, id, xmlNodePtr, intern);
  1765. dom_parent_node_append(intern, args, argc);
  1766. }
  1767. /* }}} */
  1768. /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
  1769. Since: DOM Living Standard (DOM4)
  1770. */
  1771. PHP_METHOD(DOMDocument, prepend)
  1772. {
  1773. int argc;
  1774. zval *args, *id;
  1775. dom_object *intern;
  1776. xmlNode *context;
  1777. if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
  1778. RETURN_THROWS();
  1779. }
  1780. id = ZEND_THIS;
  1781. DOM_GET_OBJ(context, id, xmlNodePtr, intern);
  1782. dom_parent_node_prepend(intern, args, argc);
  1783. }
  1784. /* }}} */
  1785. #endif /* HAVE_LIBXML && HAVE_DOM */