php_dom.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584
  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. | Marcus Borger <helly@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "php.h"
  24. #if HAVE_LIBXML && HAVE_DOM
  25. #include "ext/standard/php_rand.h"
  26. #include "php_dom.h"
  27. #include "dom_properties.h"
  28. #include "zend_interfaces.h"
  29. #include "ext/standard/info.h"
  30. #define PHP_XPATH 1
  31. #define PHP_XPTR 2
  32. /* {{{ class entries */
  33. PHP_DOM_EXPORT zend_class_entry *dom_node_class_entry;
  34. PHP_DOM_EXPORT zend_class_entry *dom_domexception_class_entry;
  35. PHP_DOM_EXPORT zend_class_entry *dom_domstringlist_class_entry;
  36. PHP_DOM_EXPORT zend_class_entry *dom_namelist_class_entry;
  37. PHP_DOM_EXPORT zend_class_entry *dom_domimplementationlist_class_entry;
  38. PHP_DOM_EXPORT zend_class_entry *dom_domimplementationsource_class_entry;
  39. PHP_DOM_EXPORT zend_class_entry *dom_domimplementation_class_entry;
  40. PHP_DOM_EXPORT zend_class_entry *dom_documentfragment_class_entry;
  41. PHP_DOM_EXPORT zend_class_entry *dom_document_class_entry;
  42. PHP_DOM_EXPORT zend_class_entry *dom_nodelist_class_entry;
  43. PHP_DOM_EXPORT zend_class_entry *dom_namednodemap_class_entry;
  44. PHP_DOM_EXPORT zend_class_entry *dom_characterdata_class_entry;
  45. PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry;
  46. PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry;
  47. PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry;
  48. PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry;
  49. PHP_DOM_EXPORT zend_class_entry *dom_typeinfo_class_entry;
  50. PHP_DOM_EXPORT zend_class_entry *dom_userdatahandler_class_entry;
  51. PHP_DOM_EXPORT zend_class_entry *dom_domerror_class_entry;
  52. PHP_DOM_EXPORT zend_class_entry *dom_domerrorhandler_class_entry;
  53. PHP_DOM_EXPORT zend_class_entry *dom_domlocator_class_entry;
  54. PHP_DOM_EXPORT zend_class_entry *dom_domconfiguration_class_entry;
  55. PHP_DOM_EXPORT zend_class_entry *dom_cdatasection_class_entry;
  56. PHP_DOM_EXPORT zend_class_entry *dom_documenttype_class_entry;
  57. PHP_DOM_EXPORT zend_class_entry *dom_notation_class_entry;
  58. PHP_DOM_EXPORT zend_class_entry *dom_entity_class_entry;
  59. PHP_DOM_EXPORT zend_class_entry *dom_entityreference_class_entry;
  60. PHP_DOM_EXPORT zend_class_entry *dom_processinginstruction_class_entry;
  61. PHP_DOM_EXPORT zend_class_entry *dom_string_extend_class_entry;
  62. #if defined(LIBXML_XPATH_ENABLED)
  63. PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
  64. #endif
  65. PHP_DOM_EXPORT zend_class_entry *dom_namespace_node_class_entry;
  66. /* }}} */
  67. zend_object_handlers dom_object_handlers;
  68. zend_object_handlers dom_nnodemap_object_handlers;
  69. #if defined(LIBXML_XPATH_ENABLED)
  70. zend_object_handlers dom_xpath_object_handlers;
  71. #endif
  72. static HashTable classes;
  73. /* {{{ prop handler tables */
  74. static HashTable dom_domstringlist_prop_handlers;
  75. static HashTable dom_namelist_prop_handlers;
  76. static HashTable dom_domimplementationlist_prop_handlers;
  77. static HashTable dom_document_prop_handlers;
  78. static HashTable dom_node_prop_handlers;
  79. static HashTable dom_nodelist_prop_handlers;
  80. static HashTable dom_namednodemap_prop_handlers;
  81. static HashTable dom_characterdata_prop_handlers;
  82. static HashTable dom_attr_prop_handlers;
  83. static HashTable dom_element_prop_handlers;
  84. static HashTable dom_text_prop_handlers;
  85. static HashTable dom_typeinfo_prop_handlers;
  86. static HashTable dom_domerror_prop_handlers;
  87. static HashTable dom_domlocator_prop_handlers;
  88. static HashTable dom_documenttype_prop_handlers;
  89. static HashTable dom_notation_prop_handlers;
  90. static HashTable dom_entity_prop_handlers;
  91. static HashTable dom_processinginstruction_prop_handlers;
  92. static HashTable dom_namespace_node_prop_handlers;
  93. #if defined(LIBXML_XPATH_ENABLED)
  94. static HashTable dom_xpath_prop_handlers;
  95. #endif
  96. /* }}} */
  97. typedef int (*dom_read_t)(dom_object *obj, zval *retval);
  98. typedef int (*dom_write_t)(dom_object *obj, zval *newval);
  99. typedef struct _dom_prop_handler {
  100. dom_read_t read_func;
  101. dom_write_t write_func;
  102. } dom_prop_handler;
  103. static zend_object_handlers* dom_get_obj_handlers(void) {
  104. return &dom_object_handlers;
  105. }
  106. /* {{{ int dom_node_is_read_only(xmlNodePtr node) */
  107. int dom_node_is_read_only(xmlNodePtr node) {
  108. switch (node->type) {
  109. case XML_ENTITY_REF_NODE:
  110. case XML_ENTITY_NODE:
  111. case XML_DOCUMENT_TYPE_NODE:
  112. case XML_NOTATION_NODE:
  113. case XML_DTD_NODE:
  114. case XML_ELEMENT_DECL:
  115. case XML_ATTRIBUTE_DECL:
  116. case XML_ENTITY_DECL:
  117. case XML_NAMESPACE_DECL:
  118. return SUCCESS;
  119. break;
  120. default:
  121. if (node->doc == NULL) {
  122. return SUCCESS;
  123. } else {
  124. return FAILURE;
  125. }
  126. }
  127. }
  128. /* }}} end dom_node_is_read_only */
  129. /* {{{ int dom_node_children_valid(xmlNodePtr node) */
  130. int dom_node_children_valid(xmlNodePtr node) {
  131. switch (node->type) {
  132. case XML_DOCUMENT_TYPE_NODE:
  133. case XML_DTD_NODE:
  134. case XML_PI_NODE:
  135. case XML_COMMENT_NODE:
  136. case XML_TEXT_NODE:
  137. case XML_CDATA_SECTION_NODE:
  138. case XML_NOTATION_NODE:
  139. return FAILURE;
  140. break;
  141. default:
  142. return SUCCESS;
  143. }
  144. }
  145. /* }}} end dom_node_children_valid */
  146. /* {{{ dom_get_doc_props() */
  147. dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
  148. {
  149. dom_doc_propsptr doc_props;
  150. if (document && document->doc_props) {
  151. return document->doc_props;
  152. } else {
  153. doc_props = emalloc(sizeof(libxml_doc_props));
  154. doc_props->formatoutput = 0;
  155. doc_props->validateonparse = 0;
  156. doc_props->resolveexternals = 0;
  157. doc_props->preservewhitespace = 1;
  158. doc_props->substituteentities = 0;
  159. doc_props->stricterror = 1;
  160. doc_props->recover = 0;
  161. doc_props->classmap = NULL;
  162. if (document) {
  163. document->doc_props = doc_props;
  164. }
  165. return doc_props;
  166. }
  167. }
  168. static void dom_copy_doc_props(php_libxml_ref_obj *source_doc, php_libxml_ref_obj *dest_doc)
  169. {
  170. dom_doc_propsptr source, dest;
  171. if (source_doc && dest_doc) {
  172. source = dom_get_doc_props(source_doc);
  173. dest = dom_get_doc_props(dest_doc);
  174. dest->formatoutput = source->formatoutput;
  175. dest->validateonparse = source->validateonparse;
  176. dest->resolveexternals = source->resolveexternals;
  177. dest->preservewhitespace = source->preservewhitespace;
  178. dest->substituteentities = source->substituteentities;
  179. dest->stricterror = source->stricterror;
  180. dest->recover = source->recover;
  181. if (source->classmap) {
  182. ALLOC_HASHTABLE(dest->classmap);
  183. zend_hash_init(dest->classmap, 0, NULL, NULL, 0);
  184. zend_hash_copy(dest->classmap, source->classmap, NULL);
  185. }
  186. }
  187. }
  188. void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce)
  189. {
  190. dom_doc_propsptr doc_props;
  191. if (document) {
  192. doc_props = dom_get_doc_props(document);
  193. if (doc_props->classmap == NULL) {
  194. if (ce == NULL) {
  195. return;
  196. }
  197. ALLOC_HASHTABLE(doc_props->classmap);
  198. zend_hash_init(doc_props->classmap, 0, NULL, NULL, 0);
  199. }
  200. if (ce) {
  201. zend_hash_update_ptr(doc_props->classmap, basece->name, ce);
  202. } else {
  203. zend_hash_del(doc_props->classmap, basece->name);
  204. }
  205. }
  206. }
  207. zend_class_entry *dom_get_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece)
  208. {
  209. dom_doc_propsptr doc_props;
  210. if (document) {
  211. doc_props = dom_get_doc_props(document);
  212. if (doc_props->classmap) {
  213. zend_class_entry *ce = zend_hash_find_ptr(doc_props->classmap, basece->name);
  214. if (ce) {
  215. return ce;
  216. }
  217. }
  218. }
  219. return basece;
  220. }
  221. /* }}} */
  222. /* {{{ dom_get_strict_error() */
  223. int dom_get_strict_error(php_libxml_ref_obj *document) {
  224. int stricterror;
  225. dom_doc_propsptr doc_props;
  226. doc_props = dom_get_doc_props(document);
  227. stricterror = doc_props->stricterror;
  228. if (document == NULL) {
  229. efree(doc_props);
  230. }
  231. return stricterror;
  232. }
  233. /* }}} */
  234. /* {{{ xmlNodePtr dom_object_get_node(dom_object *obj) */
  235. PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj)
  236. {
  237. if (obj && obj->ptr != NULL) {
  238. return ((php_libxml_node_ptr *)obj->ptr)->node;
  239. } else {
  240. return NULL;
  241. }
  242. }
  243. /* }}} end dom_object_get_node */
  244. /* {{{ dom_object *php_dom_object_get_data(xmlNodePtr obj) */
  245. PHP_DOM_EXPORT dom_object *php_dom_object_get_data(xmlNodePtr obj)
  246. {
  247. if (obj && obj->_private != NULL) {
  248. return (dom_object *) ((php_libxml_node_ptr *) obj->_private)->_private;
  249. } else {
  250. return NULL;
  251. }
  252. }
  253. /* }}} end php_dom_object_get_data */
  254. /* {{{ dom_read_na */
  255. static int dom_read_na(dom_object *obj, zval *retval)
  256. {
  257. zend_throw_error(NULL, "Cannot read property");
  258. return FAILURE;
  259. }
  260. /* }}} */
  261. /* {{{ dom_write_na */
  262. static int dom_write_na(dom_object *obj, zval *newval)
  263. {
  264. zend_throw_error(NULL, "Cannot write property");
  265. return FAILURE;
  266. }
  267. /* }}} */
  268. /* {{{ dom_register_prop_handler */
  269. static void dom_register_prop_handler(HashTable *prop_handler, char *name, size_t name_len, dom_read_t read_func, dom_write_t write_func)
  270. {
  271. dom_prop_handler hnd;
  272. zend_string *str;
  273. hnd.read_func = read_func ? read_func : dom_read_na;
  274. hnd.write_func = write_func ? write_func : dom_write_na;
  275. str = zend_string_init_interned(name, name_len, 1);
  276. zend_hash_add_mem(prop_handler, str, &hnd, sizeof(dom_prop_handler));
  277. zend_string_release_ex(str, 1);
  278. }
  279. /* }}} */
  280. static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
  281. {
  282. dom_object *obj = Z_DOMOBJ_P(object);
  283. zend_string *member_str = zval_get_string(member);
  284. zval *retval = NULL;
  285. if (!obj->prop_handler || !zend_hash_exists(obj->prop_handler, member_str)) {
  286. retval = zend_std_get_property_ptr_ptr(object, member, type, cache_slot);
  287. }
  288. zend_string_release_ex(member_str, 0);
  289. return retval;
  290. }
  291. /* }}} */
  292. /* {{{ dom_read_property */
  293. zval *dom_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)
  294. {
  295. dom_object *obj = Z_DOMOBJ_P(object);
  296. zend_string *member_str = zval_get_string(member);
  297. zval *retval;
  298. dom_prop_handler *hnd = NULL;
  299. if (obj->prop_handler != NULL) {
  300. hnd = zend_hash_find_ptr(obj->prop_handler, member_str);
  301. } else if (instanceof_function(obj->std.ce, dom_node_class_entry)) {
  302. php_error(E_WARNING, "Couldn't fetch %s. Node no longer exists", ZSTR_VAL(obj->std.ce->name));
  303. }
  304. if (hnd) {
  305. int ret = hnd->read_func(obj, rv);
  306. if (ret == SUCCESS) {
  307. retval = rv;
  308. } else {
  309. retval = &EG(uninitialized_zval);
  310. }
  311. } else {
  312. retval = zend_std_read_property(object, member, type, cache_slot, rv);
  313. }
  314. zend_string_release_ex(member_str, 0);
  315. return retval;
  316. }
  317. /* }}} */
  318. /* {{{ dom_write_property */
  319. void dom_write_property(zval *object, zval *member, zval *value, void **cache_slot)
  320. {
  321. dom_object *obj = Z_DOMOBJ_P(object);
  322. zend_string *member_str = zval_get_string(member);
  323. dom_prop_handler *hnd = NULL;
  324. if (obj->prop_handler != NULL) {
  325. hnd = zend_hash_find_ptr(obj->prop_handler, member_str);
  326. }
  327. if (hnd) {
  328. hnd->write_func(obj, value);
  329. } else {
  330. zend_std_write_property(object, member, value, cache_slot);
  331. }
  332. zend_string_release_ex(member_str, 0);
  333. }
  334. /* }}} */
  335. /* {{{ dom_property_exists */
  336. static int dom_property_exists(zval *object, zval *member, int check_empty, void **cache_slot)
  337. {
  338. dom_object *obj = Z_DOMOBJ_P(object);
  339. zend_string *member_str = zval_get_string(member);
  340. dom_prop_handler *hnd = NULL;
  341. int retval = 0;
  342. if (obj->prop_handler != NULL) {
  343. hnd = zend_hash_find_ptr(obj->prop_handler, member_str);
  344. }
  345. if (hnd) {
  346. zval tmp;
  347. if (check_empty == 2) {
  348. retval = 1;
  349. } else if (hnd->read_func(obj, &tmp) == SUCCESS) {
  350. if (check_empty == 1) {
  351. retval = zend_is_true(&tmp);
  352. } else if (check_empty == 0) {
  353. retval = (Z_TYPE(tmp) != IS_NULL);
  354. }
  355. zval_ptr_dtor(&tmp);
  356. }
  357. } else {
  358. retval = zend_std_has_property(object, member, check_empty, cache_slot);
  359. }
  360. zend_string_release_ex(member_str, 0);
  361. return retval;
  362. }
  363. /* }}} */
  364. static HashTable* dom_get_debug_info_helper(zval *object, int *is_temp) /* {{{ */
  365. {
  366. dom_object *obj = Z_DOMOBJ_P(object);
  367. HashTable *debug_info,
  368. *prop_handlers = obj->prop_handler,
  369. *std_props;
  370. zend_string *string_key;
  371. dom_prop_handler *entry;
  372. zend_string *object_str;
  373. *is_temp = 1;
  374. std_props = zend_std_get_properties(object);
  375. debug_info = zend_array_dup(std_props);
  376. if (!prop_handlers) {
  377. return debug_info;
  378. }
  379. object_str = zend_string_init("(object value omitted)", sizeof("(object value omitted)")-1, 0);
  380. ZEND_HASH_FOREACH_STR_KEY_PTR(prop_handlers, string_key, entry) {
  381. zval value;
  382. if (entry->read_func(obj, &value) == FAILURE || !string_key) {
  383. continue;
  384. }
  385. if (Z_TYPE(value) == IS_OBJECT) {
  386. zval_ptr_dtor(&value);
  387. ZVAL_NEW_STR(&value, object_str);
  388. zend_string_addref(object_str);
  389. }
  390. zend_hash_add(debug_info, string_key, &value);
  391. } ZEND_HASH_FOREACH_END();
  392. zend_string_release_ex(object_str, 0);
  393. return debug_info;
  394. }
  395. /* }}} */
  396. static HashTable* dom_get_debug_info(zval *object, int *is_temp) /* {{{ */
  397. {
  398. return dom_get_debug_info_helper(object, is_temp);
  399. }
  400. /* }}} */
  401. void *php_dom_export_node(zval *object) /* {{{ */
  402. {
  403. php_libxml_node_object *intern;
  404. xmlNodePtr nodep = NULL;
  405. intern = (php_libxml_node_object *) Z_DOMOBJ_P(object);
  406. if (intern->node) {
  407. nodep = intern->node->node;
  408. }
  409. return nodep;
  410. }
  411. /* }}} */
  412. /* {{{ proto somNode dom_import_simplexml(sxeobject node)
  413. Get a simplexml_element object from dom to allow for processing */
  414. PHP_FUNCTION(dom_import_simplexml)
  415. {
  416. zval *node;
  417. xmlNodePtr nodep = NULL;
  418. php_libxml_node_object *nodeobj;
  419. int ret;
  420. if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &node) == FAILURE) {
  421. return;
  422. }
  423. nodeobj = (php_libxml_node_object *) ((char *) Z_OBJ_P(node) - Z_OBJ_HT_P(node)->offset);
  424. nodep = php_libxml_import_node(node);
  425. if (nodep && nodeobj && (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE)) {
  426. DOM_RET_OBJ((xmlNodePtr) nodep, &ret, (dom_object *)nodeobj);
  427. } else {
  428. php_error_docref(NULL, E_WARNING, "Invalid Nodetype to import");
  429. RETURN_NULL();
  430. }
  431. }
  432. /* }}} */
  433. static dom_object* dom_objects_set_class(zend_class_entry *class_type);
  434. static zend_object *dom_objects_store_clone_obj(zval *zobject) /* {{{ */
  435. {
  436. dom_object *intern = Z_DOMOBJ_P(zobject);
  437. dom_object *clone = dom_objects_set_class(intern->std.ce);
  438. clone->std.handlers = dom_get_obj_handlers();
  439. if (instanceof_function(intern->std.ce, dom_node_class_entry)) {
  440. xmlNodePtr node = (xmlNodePtr)dom_object_get_node(intern);
  441. if (node != NULL) {
  442. xmlNodePtr cloned_node = xmlDocCopyNode(node, node->doc, 1);
  443. if (cloned_node != NULL) {
  444. /* If we cloned a document then we must create new doc proxy */
  445. if (cloned_node->doc == node->doc) {
  446. clone->document = intern->document;
  447. }
  448. php_libxml_increment_doc_ref((php_libxml_node_object *)clone, cloned_node->doc);
  449. php_libxml_increment_node_ptr((php_libxml_node_object *)clone, cloned_node, (void *)clone);
  450. if (intern->document != clone->document) {
  451. dom_copy_doc_props(intern->document, clone->document);
  452. }
  453. }
  454. }
  455. }
  456. zend_objects_clone_members(&clone->std, &intern->std);
  457. return &clone->std;
  458. }
  459. /* }}} */
  460. static void dom_copy_prop_handler(zval *zv) /* {{{ */
  461. {
  462. dom_prop_handler *hnd = Z_PTR_P(zv);
  463. Z_PTR_P(zv) = malloc(sizeof(dom_prop_handler));
  464. memcpy(Z_PTR_P(zv), hnd, sizeof(dom_prop_handler));
  465. }
  466. /* }}} */
  467. static void dom_dtor_prop_handler(zval *zv) /* {{{ */
  468. {
  469. free(Z_PTR_P(zv));
  470. }
  471. /* {{{ arginfo */
  472. ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_import_simplexml, 0, 0, 1)
  473. ZEND_ARG_INFO(0, node)
  474. ZEND_END_ARG_INFO()
  475. /* }}} */
  476. static const zend_function_entry dom_functions[] = {
  477. PHP_FE(dom_import_simplexml, arginfo_dom_import_simplexml)
  478. PHP_FE_END
  479. };
  480. static const zend_module_dep dom_deps[] = {
  481. ZEND_MOD_REQUIRED("libxml")
  482. ZEND_MOD_CONFLICTS("domxml")
  483. ZEND_MOD_END
  484. };
  485. zend_module_entry dom_module_entry = { /* {{{ */
  486. STANDARD_MODULE_HEADER_EX, NULL,
  487. dom_deps,
  488. "dom",
  489. dom_functions,
  490. PHP_MINIT(dom),
  491. PHP_MSHUTDOWN(dom),
  492. NULL,
  493. NULL,
  494. PHP_MINFO(dom),
  495. DOM_API_VERSION, /* Extension versionnumber */
  496. STANDARD_MODULE_PROPERTIES
  497. };
  498. /* }}} */
  499. #ifdef COMPILE_DL_DOM
  500. ZEND_GET_MODULE(dom)
  501. #endif
  502. void dom_objects_free_storage(zend_object *object);
  503. void dom_nnodemap_objects_free_storage(zend_object *object);
  504. static zend_object *dom_objects_store_clone_obj(zval *zobject);
  505. static void dom_nnodemap_object_dtor(zend_object *object);
  506. #if defined(LIBXML_XPATH_ENABLED)
  507. void dom_xpath_objects_free_storage(zend_object *object);
  508. #endif
  509. /* {{{ PHP_MINIT_FUNCTION(dom) */
  510. PHP_MINIT_FUNCTION(dom)
  511. {
  512. zend_class_entry ce;
  513. memcpy(&dom_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  514. dom_object_handlers.offset = XtOffsetOf(dom_object, std);
  515. dom_object_handlers.free_obj = dom_objects_free_storage;
  516. dom_object_handlers.read_property = dom_read_property;
  517. dom_object_handlers.write_property = dom_write_property;
  518. dom_object_handlers.get_property_ptr_ptr = dom_get_property_ptr_ptr;
  519. dom_object_handlers.clone_obj = dom_objects_store_clone_obj;
  520. dom_object_handlers.has_property = dom_property_exists;
  521. dom_object_handlers.get_debug_info = dom_get_debug_info;
  522. memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
  523. dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
  524. dom_nnodemap_object_handlers.dtor_obj = dom_nnodemap_object_dtor;
  525. dom_nnodemap_object_handlers.read_dimension = dom_nodelist_read_dimension;
  526. dom_nnodemap_object_handlers.has_dimension = dom_nodelist_has_dimension;
  527. zend_hash_init(&classes, 0, NULL, NULL, 1);
  528. INIT_CLASS_ENTRY(ce, "DOMException", php_dom_domexception_class_functions);
  529. dom_domexception_class_entry = zend_register_internal_class_ex(&ce, zend_ce_exception);
  530. dom_domexception_class_entry->ce_flags |= ZEND_ACC_FINAL;
  531. zend_declare_property_long(dom_domexception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PUBLIC);
  532. REGISTER_DOM_CLASS(ce, "DOMStringList", NULL, php_dom_domstringlist_class_functions, dom_domstringlist_class_entry);
  533. zend_hash_init(&dom_domstringlist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  534. dom_register_prop_handler(&dom_domstringlist_prop_handlers, "length", sizeof("length")-1, dom_domstringlist_length_read, NULL);
  535. zend_hash_add_ptr(&classes, ce.name, &dom_domstringlist_prop_handlers);
  536. REGISTER_DOM_CLASS(ce, "DOMNameList", NULL, php_dom_namelist_class_functions, dom_namelist_class_entry);
  537. zend_hash_init(&dom_namelist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  538. dom_register_prop_handler(&dom_namelist_prop_handlers, "length", sizeof("length")-1, dom_namelist_length_read, NULL);
  539. zend_hash_add_ptr(&classes, ce.name, &dom_namelist_prop_handlers);
  540. REGISTER_DOM_CLASS(ce, "DOMImplementationList", NULL, php_dom_domimplementationlist_class_functions, dom_domimplementationlist_class_entry);
  541. zend_hash_init(&dom_domimplementationlist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  542. dom_register_prop_handler(&dom_domimplementationlist_prop_handlers, "length", sizeof("length")-1, dom_domimplementationlist_length_read, NULL);
  543. zend_hash_add_ptr(&classes, ce.name, &dom_domimplementationlist_prop_handlers);
  544. REGISTER_DOM_CLASS(ce, "DOMImplementationSource", NULL, php_dom_domimplementationsource_class_functions, dom_domimplementationsource_class_entry);
  545. REGISTER_DOM_CLASS(ce, "DOMImplementation", NULL, php_dom_domimplementation_class_functions, dom_domimplementation_class_entry);
  546. REGISTER_DOM_CLASS(ce, "DOMNode", NULL, php_dom_node_class_functions, dom_node_class_entry);
  547. zend_hash_init(&dom_node_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  548. dom_register_prop_handler(&dom_node_prop_handlers, "nodeName", sizeof("nodeName")-1, dom_node_node_name_read, NULL);
  549. dom_register_prop_handler(&dom_node_prop_handlers, "nodeValue", sizeof("nodeValue")-1, dom_node_node_value_read, dom_node_node_value_write);
  550. dom_register_prop_handler(&dom_node_prop_handlers, "nodeType", sizeof("nodeType")-1, dom_node_node_type_read, NULL);
  551. dom_register_prop_handler(&dom_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
  552. dom_register_prop_handler(&dom_node_prop_handlers, "childNodes", sizeof("childNodes")-1, dom_node_child_nodes_read, NULL);
  553. dom_register_prop_handler(&dom_node_prop_handlers, "firstChild", sizeof("firstChild")-1, dom_node_first_child_read, NULL);
  554. dom_register_prop_handler(&dom_node_prop_handlers, "lastChild", sizeof("lastChild")-1, dom_node_last_child_read, NULL);
  555. dom_register_prop_handler(&dom_node_prop_handlers, "previousSibling", sizeof("previousSibling")-1, dom_node_previous_sibling_read, NULL);
  556. dom_register_prop_handler(&dom_node_prop_handlers, "nextSibling", sizeof("nextSibling")-1, dom_node_next_sibling_read, NULL);
  557. dom_register_prop_handler(&dom_node_prop_handlers, "attributes", sizeof("attributes")-1, dom_node_attributes_read, NULL);
  558. dom_register_prop_handler(&dom_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
  559. dom_register_prop_handler(&dom_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
  560. dom_register_prop_handler(&dom_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, dom_node_prefix_write);
  561. dom_register_prop_handler(&dom_node_prop_handlers, "localName", sizeof("localName")-1, dom_node_local_name_read, NULL);
  562. dom_register_prop_handler(&dom_node_prop_handlers, "baseURI", sizeof("baseURI")-1, dom_node_base_uri_read, NULL);
  563. dom_register_prop_handler(&dom_node_prop_handlers, "textContent", sizeof("textContent")-1, dom_node_text_content_read, dom_node_text_content_write);
  564. zend_hash_add_ptr(&classes, ce.name, &dom_node_prop_handlers);
  565. REGISTER_DOM_CLASS(ce, "DOMNameSpaceNode", NULL, NULL, dom_namespace_node_class_entry);
  566. zend_hash_init(&dom_namespace_node_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  567. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeName", sizeof("nodeName")-1, dom_node_node_name_read, NULL);
  568. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeValue", sizeof("nodeValue")-1, dom_node_node_value_read, NULL);
  569. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeType", sizeof("nodeType")-1, dom_node_node_type_read, NULL);
  570. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, NULL);
  571. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "localName", sizeof("localName")-1, dom_node_local_name_read, NULL);
  572. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
  573. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
  574. dom_register_prop_handler(&dom_namespace_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
  575. zend_hash_add_ptr(&classes, ce.name, &dom_namespace_node_prop_handlers);
  576. REGISTER_DOM_CLASS(ce, "DOMDocumentFragment", dom_node_class_entry, php_dom_documentfragment_class_functions, dom_documentfragment_class_entry);
  577. zend_hash_add_ptr(&classes, ce.name, &dom_node_prop_handlers);
  578. REGISTER_DOM_CLASS(ce, "DOMDocument", dom_node_class_entry, php_dom_document_class_functions, dom_document_class_entry);
  579. zend_hash_init(&dom_document_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  580. dom_register_prop_handler(&dom_document_prop_handlers, "doctype", sizeof("doctype")-1, dom_document_doctype_read, NULL);
  581. dom_register_prop_handler(&dom_document_prop_handlers, "implementation", sizeof("implementation")-1, dom_document_implementation_read, NULL);
  582. dom_register_prop_handler(&dom_document_prop_handlers, "documentElement", sizeof("documentElement")-1, dom_document_document_element_read, NULL);
  583. dom_register_prop_handler(&dom_document_prop_handlers, "actualEncoding", sizeof("actualEncoding")-1, dom_document_encoding_read, NULL);
  584. dom_register_prop_handler(&dom_document_prop_handlers, "encoding", sizeof("encoding")-1, dom_document_encoding_read, dom_document_encoding_write);
  585. dom_register_prop_handler(&dom_document_prop_handlers, "xmlEncoding", sizeof("xmlEncoding")-1, dom_document_encoding_read, NULL);
  586. dom_register_prop_handler(&dom_document_prop_handlers, "standalone", sizeof("standalone")-1, dom_document_standalone_read, dom_document_standalone_write);
  587. dom_register_prop_handler(&dom_document_prop_handlers, "xmlStandalone", sizeof("xmlStandalone")-1, dom_document_standalone_read, dom_document_standalone_write);
  588. dom_register_prop_handler(&dom_document_prop_handlers, "version", sizeof("version")-1, dom_document_version_read, dom_document_version_write);
  589. dom_register_prop_handler(&dom_document_prop_handlers, "xmlVersion", sizeof("xmlVersion")-1, dom_document_version_read, dom_document_version_write);
  590. dom_register_prop_handler(&dom_document_prop_handlers, "strictErrorChecking", sizeof("strictErrorChecking")-1, dom_document_strict_error_checking_read, dom_document_strict_error_checking_write);
  591. dom_register_prop_handler(&dom_document_prop_handlers, "documentURI", sizeof("documentURI")-1, dom_document_document_uri_read, dom_document_document_uri_write);
  592. dom_register_prop_handler(&dom_document_prop_handlers, "config", sizeof("config")-1, dom_document_config_read, NULL);
  593. dom_register_prop_handler(&dom_document_prop_handlers, "formatOutput", sizeof("formatOutput")-1, dom_document_format_output_read, dom_document_format_output_write);
  594. dom_register_prop_handler(&dom_document_prop_handlers, "validateOnParse", sizeof("validateOnParse")-1, dom_document_validate_on_parse_read, dom_document_validate_on_parse_write);
  595. dom_register_prop_handler(&dom_document_prop_handlers, "resolveExternals", sizeof("resolveExternals")-1, dom_document_resolve_externals_read, dom_document_resolve_externals_write);
  596. dom_register_prop_handler(&dom_document_prop_handlers, "preserveWhiteSpace", sizeof("preserveWhitespace")-1, dom_document_preserve_whitespace_read, dom_document_preserve_whitespace_write);
  597. dom_register_prop_handler(&dom_document_prop_handlers, "recover", sizeof("recover")-1, dom_document_recover_read, dom_document_recover_write);
  598. dom_register_prop_handler(&dom_document_prop_handlers, "substituteEntities", sizeof("substituteEntities")-1, dom_document_substitue_entities_read, dom_document_substitue_entities_write);
  599. zend_hash_merge(&dom_document_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  600. zend_hash_add_ptr(&classes, ce.name, &dom_document_prop_handlers);
  601. INIT_CLASS_ENTRY(ce, "DOMNodeList", php_dom_nodelist_class_functions);
  602. ce.create_object = dom_nnodemap_objects_new;
  603. dom_nodelist_class_entry = zend_register_internal_class_ex(&ce, NULL);
  604. dom_nodelist_class_entry->get_iterator = php_dom_get_iterator;
  605. zend_class_implements(dom_nodelist_class_entry, 2, zend_ce_traversable, zend_ce_countable);
  606. zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  607. dom_register_prop_handler(&dom_nodelist_prop_handlers, "length", sizeof("length")-1, dom_nodelist_length_read, NULL);
  608. zend_hash_add_ptr(&classes, ce.name, &dom_nodelist_prop_handlers);
  609. INIT_CLASS_ENTRY(ce, "DOMNamedNodeMap", php_dom_namednodemap_class_functions);
  610. ce.create_object = dom_nnodemap_objects_new;
  611. dom_namednodemap_class_entry = zend_register_internal_class_ex(&ce, NULL);
  612. dom_namednodemap_class_entry->get_iterator = php_dom_get_iterator;
  613. zend_class_implements(dom_namednodemap_class_entry, 2, zend_ce_traversable, zend_ce_countable);
  614. zend_hash_init(&dom_namednodemap_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  615. dom_register_prop_handler(&dom_namednodemap_prop_handlers, "length", sizeof("length")-1, dom_namednodemap_length_read, NULL);
  616. zend_hash_add_ptr(&classes, ce.name, &dom_namednodemap_prop_handlers);
  617. REGISTER_DOM_CLASS(ce, "DOMCharacterData", dom_node_class_entry, php_dom_characterdata_class_functions, dom_characterdata_class_entry);
  618. zend_hash_init(&dom_characterdata_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  619. dom_register_prop_handler(&dom_characterdata_prop_handlers, "data", sizeof("data")-1, dom_characterdata_data_read, dom_characterdata_data_write);
  620. dom_register_prop_handler(&dom_characterdata_prop_handlers, "length", sizeof("length")-1, dom_characterdata_length_read, NULL);
  621. zend_hash_merge(&dom_characterdata_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  622. zend_hash_add_ptr(&classes, ce.name, &dom_characterdata_prop_handlers);
  623. REGISTER_DOM_CLASS(ce, "DOMAttr", dom_node_class_entry, php_dom_attr_class_functions, dom_attr_class_entry);
  624. zend_hash_init(&dom_attr_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  625. dom_register_prop_handler(&dom_attr_prop_handlers, "name", sizeof("name")-1, dom_attr_name_read, NULL);
  626. dom_register_prop_handler(&dom_attr_prop_handlers, "specified", sizeof("specified")-1, dom_attr_specified_read, NULL);
  627. dom_register_prop_handler(&dom_attr_prop_handlers, "value", sizeof("value")-1, dom_attr_value_read, dom_attr_value_write);
  628. dom_register_prop_handler(&dom_attr_prop_handlers, "ownerElement", sizeof("ownerElement")-1, dom_attr_owner_element_read, NULL);
  629. dom_register_prop_handler(&dom_attr_prop_handlers, "schemaTypeInfo", sizeof("schemaTypeInfo")-1, dom_attr_schema_type_info_read, NULL);
  630. zend_hash_merge(&dom_attr_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  631. zend_hash_add_ptr(&classes, ce.name, &dom_attr_prop_handlers);
  632. REGISTER_DOM_CLASS(ce, "DOMElement", dom_node_class_entry, php_dom_element_class_functions, dom_element_class_entry);
  633. zend_hash_init(&dom_element_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  634. dom_register_prop_handler(&dom_element_prop_handlers, "tagName", sizeof("tagName")-1, dom_element_tag_name_read, NULL);
  635. dom_register_prop_handler(&dom_element_prop_handlers, "schemaTypeInfo", sizeof("schemaTypeInfo")-1, dom_element_schema_type_info_read, NULL);
  636. zend_hash_merge(&dom_element_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  637. zend_hash_add_ptr(&classes, ce.name, &dom_element_prop_handlers);
  638. REGISTER_DOM_CLASS(ce, "DOMText", dom_characterdata_class_entry, php_dom_text_class_functions, dom_text_class_entry);
  639. zend_hash_init(&dom_text_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  640. dom_register_prop_handler(&dom_text_prop_handlers, "wholeText", sizeof("wholeText")-1, dom_text_whole_text_read, NULL);
  641. zend_hash_merge(&dom_text_prop_handlers, &dom_characterdata_prop_handlers, dom_copy_prop_handler, 0);
  642. zend_hash_add_ptr(&classes, ce.name, &dom_text_prop_handlers);
  643. REGISTER_DOM_CLASS(ce, "DOMComment", dom_characterdata_class_entry, php_dom_comment_class_functions, dom_comment_class_entry);
  644. zend_hash_add_ptr(&classes, ce.name, &dom_characterdata_prop_handlers);
  645. REGISTER_DOM_CLASS(ce, "DOMTypeinfo", NULL, php_dom_typeinfo_class_functions, dom_typeinfo_class_entry);
  646. zend_hash_init(&dom_typeinfo_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  647. dom_register_prop_handler(&dom_typeinfo_prop_handlers, "typeName", sizeof("typeName")-1, dom_typeinfo_type_name_read, NULL);
  648. dom_register_prop_handler(&dom_typeinfo_prop_handlers, "typeNamespace", sizeof("typeNamespace")-1, dom_typeinfo_type_namespace_read, NULL);
  649. zend_hash_add_ptr(&classes, ce.name, &dom_typeinfo_prop_handlers);
  650. REGISTER_DOM_CLASS(ce, "DOMUserDataHandler", NULL, php_dom_userdatahandler_class_functions, dom_userdatahandler_class_entry);
  651. REGISTER_DOM_CLASS(ce, "DOMDomError", NULL, php_dom_domerror_class_functions, dom_domerror_class_entry);
  652. zend_hash_init(&dom_domerror_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  653. dom_register_prop_handler(&dom_domerror_prop_handlers, "severity", sizeof("severity")-1, dom_domerror_severity_read, NULL);
  654. dom_register_prop_handler(&dom_domerror_prop_handlers, "message", sizeof("message")-1, dom_domerror_message_read, NULL);
  655. dom_register_prop_handler(&dom_domerror_prop_handlers, "type", sizeof("type")-1, dom_domerror_type_read, NULL);
  656. dom_register_prop_handler(&dom_domerror_prop_handlers, "relatedException", sizeof("relatedException")-1, dom_domerror_related_exception_read, NULL);
  657. dom_register_prop_handler(&dom_domerror_prop_handlers, "related_data", sizeof("related_data")-1, dom_domerror_related_data_read, NULL);
  658. dom_register_prop_handler(&dom_domerror_prop_handlers, "location", sizeof("location")-1, dom_domerror_location_read, NULL);
  659. zend_hash_add_ptr(&classes, ce.name, &dom_domerror_prop_handlers);
  660. REGISTER_DOM_CLASS(ce, "DOMErrorHandler", NULL, php_dom_domerrorhandler_class_functions, dom_domerrorhandler_class_entry);
  661. REGISTER_DOM_CLASS(ce, "DOMLocator", NULL, php_dom_domlocator_class_functions, dom_domlocator_class_entry);
  662. zend_hash_init(&dom_domlocator_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  663. dom_register_prop_handler(&dom_domlocator_prop_handlers, "lineNumber", sizeof("lineNumber")-1, dom_domlocator_line_number_read, NULL);
  664. dom_register_prop_handler(&dom_domlocator_prop_handlers, "columnNumber", sizeof("columnNumber")-1, dom_domlocator_column_number_read, NULL);
  665. dom_register_prop_handler(&dom_domlocator_prop_handlers, "offset", sizeof("offset")-1, dom_domlocator_offset_read, NULL);
  666. dom_register_prop_handler(&dom_domlocator_prop_handlers, "relatedNode", sizeof("relatedNode")-1, dom_domlocator_related_node_read, NULL);
  667. dom_register_prop_handler(&dom_domlocator_prop_handlers, "uri", sizeof("uri")-1, dom_domlocator_uri_read, NULL);
  668. zend_hash_add_ptr(&classes, ce.name, &dom_domlocator_prop_handlers);
  669. REGISTER_DOM_CLASS(ce, "DOMConfiguration", NULL, php_dom_domconfiguration_class_functions, dom_domconfiguration_class_entry);
  670. REGISTER_DOM_CLASS(ce, "DOMCdataSection", dom_text_class_entry, php_dom_cdatasection_class_functions, dom_cdatasection_class_entry);
  671. zend_hash_add_ptr(&classes, ce.name, &dom_text_prop_handlers);
  672. REGISTER_DOM_CLASS(ce, "DOMDocumentType", dom_node_class_entry, php_dom_documenttype_class_functions, dom_documenttype_class_entry);
  673. zend_hash_init(&dom_documenttype_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  674. dom_register_prop_handler(&dom_documenttype_prop_handlers, "name", sizeof("name")-1, dom_documenttype_name_read, NULL);
  675. dom_register_prop_handler(&dom_documenttype_prop_handlers, "entities", sizeof("entities")-1, dom_documenttype_entities_read, NULL);
  676. dom_register_prop_handler(&dom_documenttype_prop_handlers, "notations", sizeof("notations")-1, dom_documenttype_notations_read, NULL);
  677. dom_register_prop_handler(&dom_documenttype_prop_handlers, "publicId", sizeof("publicId")-1, dom_documenttype_public_id_read, NULL);
  678. dom_register_prop_handler(&dom_documenttype_prop_handlers, "systemId", sizeof("systemId")-1, dom_documenttype_system_id_read, NULL);
  679. dom_register_prop_handler(&dom_documenttype_prop_handlers, "internalSubset", sizeof("internalSubset")-1, dom_documenttype_internal_subset_read, NULL);
  680. zend_hash_merge(&dom_documenttype_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  681. zend_hash_add_ptr(&classes, ce.name, &dom_documenttype_prop_handlers);
  682. REGISTER_DOM_CLASS(ce, "DOMNotation", dom_node_class_entry, php_dom_notation_class_functions, dom_notation_class_entry);
  683. zend_hash_init(&dom_notation_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  684. dom_register_prop_handler(&dom_notation_prop_handlers, "publicId", sizeof("publicId")-1, dom_notation_public_id_read, NULL);
  685. dom_register_prop_handler(&dom_notation_prop_handlers, "systemId", sizeof("systemId")-1, dom_notation_system_id_read, NULL);
  686. zend_hash_merge(&dom_notation_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  687. zend_hash_add_ptr(&classes, ce.name, &dom_notation_prop_handlers);
  688. REGISTER_DOM_CLASS(ce, "DOMEntity", dom_node_class_entry, php_dom_entity_class_functions, dom_entity_class_entry);
  689. zend_hash_init(&dom_entity_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  690. dom_register_prop_handler(&dom_entity_prop_handlers, "publicId", sizeof("publicId")-1, dom_entity_public_id_read, NULL);
  691. dom_register_prop_handler(&dom_entity_prop_handlers, "systemId", sizeof("systemId")-1, dom_entity_system_id_read, NULL);
  692. dom_register_prop_handler(&dom_entity_prop_handlers, "notationName", sizeof("notationName")-1, dom_entity_notation_name_read, NULL);
  693. dom_register_prop_handler(&dom_entity_prop_handlers, "actualEncoding", sizeof("actualEncoding")-1, dom_entity_actual_encoding_read, dom_entity_actual_encoding_write);
  694. dom_register_prop_handler(&dom_entity_prop_handlers, "encoding", sizeof("encoding")-1, dom_entity_encoding_read, dom_entity_encoding_write);
  695. dom_register_prop_handler(&dom_entity_prop_handlers, "version", sizeof("version")-1, dom_entity_version_read, dom_entity_version_write);
  696. zend_hash_merge(&dom_entity_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  697. zend_hash_add_ptr(&classes, ce.name, &dom_entity_prop_handlers);
  698. REGISTER_DOM_CLASS(ce, "DOMEntityReference", dom_node_class_entry, php_dom_entityreference_class_functions, dom_entityreference_class_entry);
  699. zend_hash_add_ptr(&classes, ce.name, &dom_node_prop_handlers);
  700. REGISTER_DOM_CLASS(ce, "DOMProcessingInstruction", dom_node_class_entry, php_dom_processinginstruction_class_functions, dom_processinginstruction_class_entry);
  701. zend_hash_init(&dom_processinginstruction_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  702. dom_register_prop_handler(&dom_processinginstruction_prop_handlers, "target", sizeof("target")-1, dom_processinginstruction_target_read, NULL);
  703. dom_register_prop_handler(&dom_processinginstruction_prop_handlers, "data", sizeof("data")-1, dom_processinginstruction_data_read, dom_processinginstruction_data_write);
  704. zend_hash_merge(&dom_processinginstruction_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
  705. zend_hash_add_ptr(&classes, ce.name, &dom_processinginstruction_prop_handlers);
  706. REGISTER_DOM_CLASS(ce, "DOMStringExtend", NULL, php_dom_string_extend_class_functions, dom_string_extend_class_entry);
  707. #if defined(LIBXML_XPATH_ENABLED)
  708. memcpy(&dom_xpath_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
  709. dom_xpath_object_handlers.offset = XtOffsetOf(dom_xpath_object, dom) + XtOffsetOf(dom_object, std);
  710. dom_xpath_object_handlers.free_obj = dom_xpath_objects_free_storage;
  711. INIT_CLASS_ENTRY(ce, "DOMXPath", php_dom_xpath_class_functions);
  712. ce.create_object = dom_xpath_objects_new;
  713. dom_xpath_class_entry = zend_register_internal_class_ex(&ce, NULL);
  714. zend_hash_init(&dom_xpath_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
  715. dom_register_prop_handler(&dom_xpath_prop_handlers, "document", sizeof("document")-1, dom_xpath_document_read, NULL);
  716. zend_hash_add_ptr(&classes, ce.name, &dom_xpath_prop_handlers);
  717. #endif
  718. REGISTER_LONG_CONSTANT("XML_ELEMENT_NODE", XML_ELEMENT_NODE, CONST_CS | CONST_PERSISTENT);
  719. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NODE", XML_ATTRIBUTE_NODE, CONST_CS | CONST_PERSISTENT);
  720. REGISTER_LONG_CONSTANT("XML_TEXT_NODE", XML_TEXT_NODE, CONST_CS | CONST_PERSISTENT);
  721. REGISTER_LONG_CONSTANT("XML_CDATA_SECTION_NODE", XML_CDATA_SECTION_NODE, CONST_CS | CONST_PERSISTENT);
  722. REGISTER_LONG_CONSTANT("XML_ENTITY_REF_NODE", XML_ENTITY_REF_NODE, CONST_CS | CONST_PERSISTENT);
  723. REGISTER_LONG_CONSTANT("XML_ENTITY_NODE", XML_ENTITY_NODE, CONST_CS | CONST_PERSISTENT);
  724. REGISTER_LONG_CONSTANT("XML_PI_NODE", XML_PI_NODE, CONST_CS | CONST_PERSISTENT);
  725. REGISTER_LONG_CONSTANT("XML_COMMENT_NODE", XML_COMMENT_NODE, CONST_CS | CONST_PERSISTENT);
  726. REGISTER_LONG_CONSTANT("XML_DOCUMENT_NODE", XML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
  727. REGISTER_LONG_CONSTANT("XML_DOCUMENT_TYPE_NODE", XML_DOCUMENT_TYPE_NODE, CONST_CS | CONST_PERSISTENT);
  728. REGISTER_LONG_CONSTANT("XML_DOCUMENT_FRAG_NODE", XML_DOCUMENT_FRAG_NODE, CONST_CS | CONST_PERSISTENT);
  729. REGISTER_LONG_CONSTANT("XML_NOTATION_NODE", XML_NOTATION_NODE, CONST_CS | CONST_PERSISTENT);
  730. REGISTER_LONG_CONSTANT("XML_HTML_DOCUMENT_NODE", XML_HTML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
  731. REGISTER_LONG_CONSTANT("XML_DTD_NODE", XML_DTD_NODE, CONST_CS | CONST_PERSISTENT);
  732. REGISTER_LONG_CONSTANT("XML_ELEMENT_DECL_NODE", XML_ELEMENT_DECL, CONST_CS | CONST_PERSISTENT);
  733. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_DECL_NODE", XML_ATTRIBUTE_DECL, CONST_CS | CONST_PERSISTENT);
  734. REGISTER_LONG_CONSTANT("XML_ENTITY_DECL_NODE", XML_ENTITY_DECL, CONST_CS | CONST_PERSISTENT);
  735. REGISTER_LONG_CONSTANT("XML_NAMESPACE_DECL_NODE", XML_NAMESPACE_DECL, CONST_CS | CONST_PERSISTENT);
  736. #ifdef XML_GLOBAL_NAMESPACE
  737. REGISTER_LONG_CONSTANT("XML_GLOBAL_NAMESPACE", XML_GLOBAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
  738. #endif
  739. REGISTER_LONG_CONSTANT("XML_LOCAL_NAMESPACE", XML_LOCAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
  740. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_CDATA", XML_ATTRIBUTE_CDATA, CONST_CS | CONST_PERSISTENT);
  741. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ID", XML_ATTRIBUTE_ID, CONST_CS | CONST_PERSISTENT);
  742. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREF", XML_ATTRIBUTE_IDREF, CONST_CS | CONST_PERSISTENT);
  743. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREFS", XML_ATTRIBUTE_IDREFS, CONST_CS | CONST_PERSISTENT);
  744. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENTITY", XML_ATTRIBUTE_ENTITIES, CONST_CS | CONST_PERSISTENT);
  745. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKEN", XML_ATTRIBUTE_NMTOKEN, CONST_CS | CONST_PERSISTENT);
  746. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKENS", XML_ATTRIBUTE_NMTOKENS, CONST_CS | CONST_PERSISTENT);
  747. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENUMERATION", XML_ATTRIBUTE_ENUMERATION, CONST_CS | CONST_PERSISTENT);
  748. REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NOTATION", XML_ATTRIBUTE_NOTATION, CONST_CS | CONST_PERSISTENT);
  749. /* DOMException Codes */
  750. REGISTER_LONG_CONSTANT("DOM_PHP_ERR", PHP_ERR, CONST_CS | CONST_PERSISTENT);
  751. REGISTER_LONG_CONSTANT("DOM_INDEX_SIZE_ERR", INDEX_SIZE_ERR, CONST_CS | CONST_PERSISTENT);
  752. REGISTER_LONG_CONSTANT("DOMSTRING_SIZE_ERR", DOMSTRING_SIZE_ERR, CONST_CS | CONST_PERSISTENT);
  753. REGISTER_LONG_CONSTANT("DOM_HIERARCHY_REQUEST_ERR", HIERARCHY_REQUEST_ERR, CONST_CS | CONST_PERSISTENT);
  754. REGISTER_LONG_CONSTANT("DOM_WRONG_DOCUMENT_ERR", WRONG_DOCUMENT_ERR, CONST_CS | CONST_PERSISTENT);
  755. REGISTER_LONG_CONSTANT("DOM_INVALID_CHARACTER_ERR", INVALID_CHARACTER_ERR, CONST_CS | CONST_PERSISTENT);
  756. REGISTER_LONG_CONSTANT("DOM_NO_DATA_ALLOWED_ERR", NO_DATA_ALLOWED_ERR, CONST_CS | CONST_PERSISTENT);
  757. REGISTER_LONG_CONSTANT("DOM_NO_MODIFICATION_ALLOWED_ERR", NO_MODIFICATION_ALLOWED_ERR, CONST_CS | CONST_PERSISTENT);
  758. REGISTER_LONG_CONSTANT("DOM_NOT_FOUND_ERR", NOT_FOUND_ERR, CONST_CS | CONST_PERSISTENT);
  759. REGISTER_LONG_CONSTANT("DOM_NOT_SUPPORTED_ERR", NOT_SUPPORTED_ERR, CONST_CS | CONST_PERSISTENT);
  760. REGISTER_LONG_CONSTANT("DOM_INUSE_ATTRIBUTE_ERR", INUSE_ATTRIBUTE_ERR, CONST_CS | CONST_PERSISTENT);
  761. REGISTER_LONG_CONSTANT("DOM_INVALID_STATE_ERR", INVALID_STATE_ERR, CONST_CS | CONST_PERSISTENT);
  762. REGISTER_LONG_CONSTANT("DOM_SYNTAX_ERR", SYNTAX_ERR, CONST_CS | CONST_PERSISTENT);
  763. REGISTER_LONG_CONSTANT("DOM_INVALID_MODIFICATION_ERR", INVALID_MODIFICATION_ERR, CONST_CS | CONST_PERSISTENT);
  764. REGISTER_LONG_CONSTANT("DOM_NAMESPACE_ERR", NAMESPACE_ERR, CONST_CS | CONST_PERSISTENT);
  765. REGISTER_LONG_CONSTANT("DOM_INVALID_ACCESS_ERR", INVALID_ACCESS_ERR, CONST_CS | CONST_PERSISTENT);
  766. REGISTER_LONG_CONSTANT("DOM_VALIDATION_ERR", VALIDATION_ERR, CONST_CS | CONST_PERSISTENT);
  767. php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
  768. return SUCCESS;
  769. }
  770. /* }}} */
  771. /* {{{ */
  772. PHP_MINFO_FUNCTION(dom)
  773. {
  774. php_info_print_table_start();
  775. php_info_print_table_row(2, "DOM/XML", "enabled");
  776. php_info_print_table_row(2, "DOM/XML API Version", DOM_API_VERSION);
  777. php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION);
  778. #if defined(LIBXML_HTML_ENABLED)
  779. php_info_print_table_row(2, "HTML Support", "enabled");
  780. #endif
  781. #if defined(LIBXML_XPATH_ENABLED)
  782. php_info_print_table_row(2, "XPath Support", "enabled");
  783. #endif
  784. #if defined(LIBXML_XPTR_ENABLED)
  785. php_info_print_table_row(2, "XPointer Support", "enabled");
  786. #endif
  787. #ifdef LIBXML_SCHEMAS_ENABLED
  788. php_info_print_table_row(2, "Schema Support", "enabled");
  789. php_info_print_table_row(2, "RelaxNG Support", "enabled");
  790. #endif
  791. php_info_print_table_end();
  792. }
  793. /* }}} */
  794. PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
  795. {
  796. zend_hash_destroy(&dom_domstringlist_prop_handlers);
  797. zend_hash_destroy(&dom_namelist_prop_handlers);
  798. zend_hash_destroy(&dom_domimplementationlist_prop_handlers);
  799. zend_hash_destroy(&dom_document_prop_handlers);
  800. zend_hash_destroy(&dom_node_prop_handlers);
  801. zend_hash_destroy(&dom_namespace_node_prop_handlers);
  802. zend_hash_destroy(&dom_nodelist_prop_handlers);
  803. zend_hash_destroy(&dom_namednodemap_prop_handlers);
  804. zend_hash_destroy(&dom_characterdata_prop_handlers);
  805. zend_hash_destroy(&dom_attr_prop_handlers);
  806. zend_hash_destroy(&dom_element_prop_handlers);
  807. zend_hash_destroy(&dom_text_prop_handlers);
  808. zend_hash_destroy(&dom_typeinfo_prop_handlers);
  809. zend_hash_destroy(&dom_domerror_prop_handlers);
  810. zend_hash_destroy(&dom_domlocator_prop_handlers);
  811. zend_hash_destroy(&dom_documenttype_prop_handlers);
  812. zend_hash_destroy(&dom_notation_prop_handlers);
  813. zend_hash_destroy(&dom_entity_prop_handlers);
  814. zend_hash_destroy(&dom_processinginstruction_prop_handlers);
  815. #if defined(LIBXML_XPATH_ENABLED)
  816. zend_hash_destroy(&dom_xpath_prop_handlers);
  817. #endif
  818. zend_hash_destroy(&classes);
  819. /* If you want do find memleaks in this module, compile libxml2 with --with-mem-debug and
  820. uncomment the following line, this will tell you the amount of not freed memory
  821. and the total used memory into apaches error_log */
  822. /* xmlMemoryDump();*/
  823. return SUCCESS;
  824. }
  825. /* }}} */
  826. /* {{{ node_list_unlink */
  827. void node_list_unlink(xmlNodePtr node)
  828. {
  829. dom_object *wrapper;
  830. while (node != NULL) {
  831. wrapper = php_dom_object_get_data(node);
  832. if (wrapper != NULL ) {
  833. xmlUnlinkNode(node);
  834. } else {
  835. if (node->type == XML_ENTITY_REF_NODE)
  836. break;
  837. node_list_unlink(node->children);
  838. switch (node->type) {
  839. case XML_ATTRIBUTE_DECL:
  840. case XML_DTD_NODE:
  841. case XML_DOCUMENT_TYPE_NODE:
  842. case XML_ENTITY_DECL:
  843. case XML_ATTRIBUTE_NODE:
  844. case XML_TEXT_NODE:
  845. break;
  846. default:
  847. node_list_unlink((xmlNodePtr) node->properties);
  848. }
  849. }
  850. node = node->next;
  851. }
  852. }
  853. /* }}} end node_list_unlink */
  854. #if defined(LIBXML_XPATH_ENABLED)
  855. /* {{{ dom_xpath_objects_free_storage */
  856. void dom_xpath_objects_free_storage(zend_object *object)
  857. {
  858. dom_xpath_object *intern = php_xpath_obj_from_obj(object);
  859. zend_object_std_dtor(&intern->dom.std);
  860. if (intern->dom.ptr != NULL) {
  861. xmlXPathFreeContext((xmlXPathContextPtr) intern->dom.ptr);
  862. php_libxml_decrement_doc_ref((php_libxml_node_object *) &intern->dom);
  863. }
  864. if (intern->registered_phpfunctions) {
  865. zend_hash_destroy(intern->registered_phpfunctions);
  866. FREE_HASHTABLE(intern->registered_phpfunctions);
  867. }
  868. if (intern->node_list) {
  869. zend_hash_destroy(intern->node_list);
  870. FREE_HASHTABLE(intern->node_list);
  871. }
  872. }
  873. /* }}} */
  874. #endif
  875. /* {{{ dom_objects_free_storage */
  876. void dom_objects_free_storage(zend_object *object)
  877. {
  878. dom_object *intern = php_dom_obj_from_obj(object);
  879. #if defined(__GNUC__) && __GNUC__ >= 3
  880. int retcount __attribute__((unused)); /* keep compiler quiet */
  881. #else
  882. int retcount;
  883. #endif
  884. zend_object_std_dtor(&intern->std);
  885. if (intern->ptr != NULL && ((php_libxml_node_ptr *)intern->ptr)->node != NULL) {
  886. if (((xmlNodePtr) ((php_libxml_node_ptr *)intern->ptr)->node)->type != XML_DOCUMENT_NODE && ((xmlNodePtr) ((php_libxml_node_ptr *)intern->ptr)->node)->type != XML_HTML_DOCUMENT_NODE) {
  887. php_libxml_node_decrement_resource((php_libxml_node_object *) intern);
  888. } else {
  889. php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
  890. retcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
  891. }
  892. intern->ptr = NULL;
  893. }
  894. }
  895. /* }}} */
  896. void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns) /* {{{ */
  897. {
  898. dom_nnodemap_object *mapptr = (dom_nnodemap_object *) intern->ptr;
  899. ZEND_ASSERT(basenode != NULL);
  900. ZVAL_OBJ(&mapptr->baseobj_zv, &basenode->std);
  901. Z_ADDREF(mapptr->baseobj_zv);
  902. mapptr->baseobj = basenode;
  903. mapptr->nodetype = ntype;
  904. mapptr->ht = ht;
  905. mapptr->local = local;
  906. mapptr->ns = ns;
  907. }
  908. /* }}} */
  909. static dom_object* dom_objects_set_class(zend_class_entry *class_type) /* {{{ */
  910. {
  911. dom_object *intern = zend_object_alloc(sizeof(dom_object), class_type);
  912. zend_class_entry *base_class = class_type;
  913. while ((base_class->type != ZEND_INTERNAL_CLASS || base_class->info.internal.module->module_number != dom_module_entry.module_number) && base_class->parent != NULL) {
  914. base_class = base_class->parent;
  915. }
  916. intern->prop_handler = zend_hash_find_ptr(&classes, base_class->name);
  917. zend_object_std_init(&intern->std, class_type);
  918. object_properties_init(&intern->std, class_type);
  919. return intern;
  920. }
  921. /* }}} */
  922. /* {{{ dom_objects_new */
  923. zend_object *dom_objects_new(zend_class_entry *class_type)
  924. {
  925. dom_object *intern = dom_objects_set_class(class_type);
  926. intern->std.handlers = dom_get_obj_handlers();
  927. return &intern->std;
  928. }
  929. /* }}} */
  930. #if defined(LIBXML_XPATH_ENABLED)
  931. /* {{{ zend_object dom_xpath_objects_new(zend_class_entry *class_type) */
  932. zend_object *dom_xpath_objects_new(zend_class_entry *class_type)
  933. {
  934. dom_xpath_object *intern = zend_object_alloc(sizeof(dom_xpath_object), class_type);
  935. intern->registered_phpfunctions = zend_new_array(0);
  936. intern->dom.prop_handler = &dom_xpath_prop_handlers;
  937. intern->dom.std.handlers = &dom_xpath_object_handlers;
  938. zend_object_std_init(&intern->dom.std, class_type);
  939. object_properties_init(&intern->dom.std, class_type);
  940. return &intern->dom.std;
  941. }
  942. /* }}} */
  943. #endif
  944. static void dom_nnodemap_object_dtor(zend_object *object) /* {{{ */
  945. {
  946. dom_object *intern;
  947. dom_nnodemap_object *objmap;
  948. intern = php_dom_obj_from_obj(object);
  949. objmap = (dom_nnodemap_object *)intern->ptr;
  950. if (objmap) {
  951. if (objmap->local) {
  952. xmlFree(objmap->local);
  953. }
  954. if (objmap->ns) {
  955. xmlFree(objmap->ns);
  956. }
  957. if (!Z_ISUNDEF(objmap->baseobj_zv)) {
  958. zval_ptr_dtor(&objmap->baseobj_zv);
  959. }
  960. efree(objmap);
  961. intern->ptr = NULL;
  962. }
  963. }
  964. /* }}} */
  965. void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */
  966. {
  967. dom_object *intern = php_dom_obj_from_obj(object);
  968. php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
  969. zend_object_std_dtor(&intern->std);
  970. }
  971. /* }}} */
  972. zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) /* {{{ */
  973. {
  974. dom_object *intern;
  975. dom_nnodemap_object *objmap;
  976. intern = dom_objects_set_class(class_type);
  977. intern->ptr = emalloc(sizeof(dom_nnodemap_object));
  978. objmap = (dom_nnodemap_object *)intern->ptr;
  979. ZVAL_UNDEF(&objmap->baseobj_zv);
  980. objmap->baseobj = NULL;
  981. objmap->nodetype = 0;
  982. objmap->ht = NULL;
  983. objmap->local = NULL;
  984. objmap->ns = NULL;
  985. intern->std.handlers = &dom_nnodemap_object_handlers;
  986. return &intern->std;
  987. }
  988. /* }}} */
  989. void php_dom_create_interator(zval *return_value, int ce_type) /* {{{ */
  990. {
  991. zend_class_entry *ce;
  992. if (ce_type == DOM_NAMEDNODEMAP) {
  993. ce = dom_namednodemap_class_entry;
  994. } else {
  995. ce = dom_nodelist_class_entry;
  996. }
  997. object_init_ex(return_value, ce);
  998. }
  999. /* }}} */
  1000. /* {{{ php_dom_create_object */
  1001. PHP_DOM_EXPORT zend_bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
  1002. {
  1003. zend_class_entry *ce;
  1004. dom_object *intern;
  1005. if (!obj) {
  1006. ZVAL_NULL(return_value);
  1007. return 0;
  1008. }
  1009. if ((intern = (dom_object *) php_dom_object_get_data((void *) obj))) {
  1010. GC_ADDREF(&intern->std);
  1011. ZVAL_OBJ(return_value, &intern->std);
  1012. return 1;
  1013. }
  1014. switch (obj->type) {
  1015. case XML_DOCUMENT_NODE:
  1016. case XML_HTML_DOCUMENT_NODE:
  1017. {
  1018. ce = dom_document_class_entry;
  1019. break;
  1020. }
  1021. case XML_DTD_NODE:
  1022. case XML_DOCUMENT_TYPE_NODE:
  1023. {
  1024. ce = dom_documenttype_class_entry;
  1025. break;
  1026. }
  1027. case XML_ELEMENT_NODE:
  1028. {
  1029. ce = dom_element_class_entry;
  1030. break;
  1031. }
  1032. case XML_ATTRIBUTE_NODE:
  1033. {
  1034. ce = dom_attr_class_entry;
  1035. break;
  1036. }
  1037. case XML_TEXT_NODE:
  1038. {
  1039. ce = dom_text_class_entry;
  1040. break;
  1041. }
  1042. case XML_COMMENT_NODE:
  1043. {
  1044. ce = dom_comment_class_entry;
  1045. break;
  1046. }
  1047. case XML_PI_NODE:
  1048. {
  1049. ce = dom_processinginstruction_class_entry;
  1050. break;
  1051. }
  1052. case XML_ENTITY_REF_NODE:
  1053. {
  1054. ce = dom_entityreference_class_entry;
  1055. break;
  1056. }
  1057. case XML_ENTITY_DECL:
  1058. case XML_ELEMENT_DECL:
  1059. {
  1060. ce = dom_entity_class_entry;
  1061. break;
  1062. }
  1063. case XML_CDATA_SECTION_NODE:
  1064. {
  1065. ce = dom_cdatasection_class_entry;
  1066. break;
  1067. }
  1068. case XML_DOCUMENT_FRAG_NODE:
  1069. {
  1070. ce = dom_documentfragment_class_entry;
  1071. break;
  1072. }
  1073. case XML_NOTATION_NODE:
  1074. {
  1075. ce = dom_notation_class_entry;
  1076. break;
  1077. }
  1078. case XML_NAMESPACE_DECL:
  1079. {
  1080. ce = dom_namespace_node_class_entry;
  1081. break;
  1082. }
  1083. default:
  1084. php_error_docref(NULL, E_WARNING, "Unsupported node type: %d", obj->type);
  1085. ZVAL_NULL(return_value);
  1086. return 0;
  1087. }
  1088. if (domobj && domobj->document) {
  1089. ce = dom_get_doc_classmap(domobj->document, ce);
  1090. }
  1091. object_init_ex(return_value, ce);
  1092. intern = Z_DOMOBJ_P(return_value);
  1093. if (obj->doc != NULL) {
  1094. if (domobj != NULL) {
  1095. intern->document = domobj->document;
  1096. }
  1097. php_libxml_increment_doc_ref((php_libxml_node_object *)intern, obj->doc);
  1098. }
  1099. php_libxml_increment_node_ptr((php_libxml_node_object *)intern, obj, (void *)intern);
  1100. return 0;
  1101. }
  1102. /* }}} end php_domobject_new */
  1103. void php_dom_create_implementation(zval *retval) {
  1104. object_init_ex(retval, dom_domimplementation_class_entry);
  1105. }
  1106. /* {{{ int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child) */
  1107. int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
  1108. {
  1109. xmlNodePtr nodep;
  1110. if (parent == NULL || child == NULL || child->doc != parent->doc) {
  1111. return SUCCESS;
  1112. }
  1113. nodep = parent;
  1114. while (nodep) {
  1115. if (nodep == child) {
  1116. return FAILURE;
  1117. }
  1118. nodep = nodep->parent;
  1119. }
  1120. return SUCCESS;
  1121. }
  1122. /* }}} end dom_hierarchy */
  1123. /* {{{ dom_has_feature(char *feature, char *version) */
  1124. int dom_has_feature(char *feature, char *version)
  1125. {
  1126. int retval = 0;
  1127. if (!(strcmp (version, "1.0") && strcmp (version,"2.0") && strcmp(version, ""))) {
  1128. if ((!strcasecmp(feature, "Core") && !strcmp (version, "1.0")) || !strcasecmp(feature, "XML"))
  1129. retval = 1;
  1130. }
  1131. return retval;
  1132. }
  1133. /* }}} end dom_has_feature */
  1134. xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, int *cur, int index) /* {{{ */
  1135. {
  1136. xmlNodePtr ret = NULL;
  1137. while (nodep != NULL && (*cur <= index || index == -1)) {
  1138. if (nodep->type == XML_ELEMENT_NODE) {
  1139. if (xmlStrEqual(nodep->name, (xmlChar *)local) || xmlStrEqual((xmlChar *)"*", (xmlChar *)local)) {
  1140. if (ns == NULL || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && (xmlStrEqual(nodep->ns->href, (xmlChar *)ns) || xmlStrEqual((xmlChar *)"*", (xmlChar *)ns)))) {
  1141. if (*cur == index) {
  1142. ret = nodep;
  1143. break;
  1144. }
  1145. (*cur)++;
  1146. }
  1147. }
  1148. ret = dom_get_elements_by_tag_name_ns_raw(nodep->children, ns, local, cur, index);
  1149. if (ret != NULL) {
  1150. break;
  1151. }
  1152. }
  1153. nodep = nodep->next;
  1154. }
  1155. return ret;
  1156. }
  1157. /* }}} */
  1158. /* }}} end dom_element_get_elements_by_tag_name_ns_raw */
  1159. static inline zend_bool is_empty_node(xmlNodePtr nodep)
  1160. {
  1161. xmlChar *strContent = xmlNodeGetContent(nodep);
  1162. zend_bool ret = strContent == NULL || *strContent == '\0';
  1163. xmlFree(strContent);
  1164. return ret;
  1165. }
  1166. /* {{{ void dom_normalize (xmlNodePtr nodep) */
  1167. void dom_normalize (xmlNodePtr nodep)
  1168. {
  1169. xmlNodePtr child, nextp, newnextp;
  1170. xmlAttrPtr attr;
  1171. xmlChar *strContent;
  1172. child = nodep->children;
  1173. while(child != NULL) {
  1174. switch (child->type) {
  1175. case XML_TEXT_NODE:
  1176. nextp = child->next;
  1177. while (nextp != NULL) {
  1178. if (nextp->type == XML_TEXT_NODE) {
  1179. newnextp = nextp->next;
  1180. strContent = xmlNodeGetContent(nextp);
  1181. xmlNodeAddContent(child, strContent);
  1182. xmlFree(strContent);
  1183. xmlUnlinkNode(nextp);
  1184. php_libxml_node_free_resource(nextp);
  1185. nextp = newnextp;
  1186. } else {
  1187. break;
  1188. }
  1189. }
  1190. if (is_empty_node(child)) {
  1191. nextp = child->next;
  1192. xmlUnlinkNode(child);
  1193. php_libxml_node_free_resource(child);
  1194. child = nextp;
  1195. continue;
  1196. }
  1197. break;
  1198. case XML_ELEMENT_NODE:
  1199. dom_normalize (child);
  1200. attr = child->properties;
  1201. while (attr != NULL) {
  1202. dom_normalize((xmlNodePtr) attr);
  1203. attr = attr->next;
  1204. }
  1205. break;
  1206. case XML_ATTRIBUTE_NODE:
  1207. dom_normalize (child);
  1208. break;
  1209. default:
  1210. break;
  1211. }
  1212. child = child->next;
  1213. }
  1214. }
  1215. /* }}} end dom_normalize */
  1216. /* {{{ void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) */
  1217. void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) {
  1218. xmlNs *cur;
  1219. if (doc == NULL)
  1220. return;
  1221. if (doc->oldNs == NULL) {
  1222. doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  1223. if (doc->oldNs == NULL) {
  1224. return;
  1225. }
  1226. memset(doc->oldNs, 0, sizeof(xmlNs));
  1227. doc->oldNs->type = XML_LOCAL_NAMESPACE;
  1228. doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE);
  1229. doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml");
  1230. }
  1231. cur = doc->oldNs;
  1232. while (cur->next != NULL) {
  1233. cur = cur->next;
  1234. }
  1235. cur->next = ns;
  1236. }
  1237. /* }}} end dom_set_old_ns */
  1238. /*
  1239. http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
  1240. NAMESPACE_ERR: Raised if
  1241. 1. the qualifiedName is a malformed qualified name
  1242. 2. the qualifiedName has a prefix and the namespaceURI is null
  1243. */
  1244. /* {{{ int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) */
  1245. int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) {
  1246. if (name_len == 0) {
  1247. return NAMESPACE_ERR;
  1248. }
  1249. *localname = (char *)xmlSplitQName2((xmlChar *)qname, (xmlChar **) prefix);
  1250. if (*localname == NULL) {
  1251. *localname = (char *)xmlStrdup((xmlChar *)qname);
  1252. if (*prefix == NULL && uri_len == 0) {
  1253. return 0;
  1254. }
  1255. }
  1256. /* 1 */
  1257. if (xmlValidateQName((xmlChar *) qname, 0) != 0) {
  1258. return NAMESPACE_ERR;
  1259. }
  1260. /* 2 */
  1261. if (*prefix != NULL && uri_len == 0) {
  1262. return NAMESPACE_ERR;
  1263. }
  1264. return 0;
  1265. }
  1266. /* }}} */
  1267. /*
  1268. http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
  1269. NAMESPACE_ERR: Raised if
  1270. 3. the qualifiedName has a prefix that is "xml" and the namespaceURI is different from "http://www.w3.org/XML/1998/namespace" [XML Namespaces]
  1271. 4. the qualifiedName or its prefix is "xmlns" and the namespaceURI is different from "http://www.w3.org/2000/xmlns/"
  1272. 5. the namespaceURI is "http://www.w3.org/2000/xmlns/" and neither the qualifiedName nor its prefix is "xmlns".
  1273. */
  1274. /* {{{ xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) */
  1275. xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) {
  1276. xmlNsPtr nsptr = NULL;
  1277. *errorcode = 0;
  1278. if (! ((prefix && !strcmp (prefix, "xml") && strcmp(uri, (char *)XML_XML_NAMESPACE)) ||
  1279. (prefix && !strcmp (prefix, "xmlns") && strcmp(uri, (char *)DOM_XMLNS_NAMESPACE)) ||
  1280. (prefix && !strcmp(uri, (char *)DOM_XMLNS_NAMESPACE) && strcmp (prefix, "xmlns")))) {
  1281. nsptr = xmlNewNs(nodep, (xmlChar *)uri, (xmlChar *)prefix);
  1282. }
  1283. if (nsptr == NULL) {
  1284. *errorcode = NAMESPACE_ERR;
  1285. }
  1286. return nsptr;
  1287. }
  1288. /* }}} end dom_get_ns */
  1289. /* {{{ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) */
  1290. xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) {
  1291. xmlNsPtr cur;
  1292. xmlNs *ret = NULL;
  1293. if (node == NULL)
  1294. return NULL;
  1295. if (localName == NULL || xmlStrEqual(localName, (xmlChar *)"")) {
  1296. cur = node->nsDef;
  1297. while (cur != NULL) {
  1298. if (cur->prefix == NULL && cur->href != NULL) {
  1299. ret = cur;
  1300. break;
  1301. }
  1302. cur = cur->next;
  1303. }
  1304. } else {
  1305. cur = node->nsDef;
  1306. while (cur != NULL) {
  1307. if (cur->prefix != NULL && xmlStrEqual(localName, cur->prefix)) {
  1308. ret = cur;
  1309. break;
  1310. }
  1311. cur = cur->next;
  1312. }
  1313. }
  1314. return ret;
  1315. }
  1316. /* }}} end dom_get_nsdecl */
  1317. zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */
  1318. {
  1319. zval offset_copy;
  1320. if (!offset) {
  1321. return NULL;
  1322. }
  1323. ZVAL_LONG(&offset_copy, zval_get_long(offset));
  1324. zend_call_method_with_1_params(object, Z_OBJCE_P(object), NULL, "item", rv, &offset_copy);
  1325. return rv;
  1326. } /* }}} end dom_nodelist_read_dimension */
  1327. int dom_nodelist_has_dimension(zval *object, zval *member, int check_empty)
  1328. {
  1329. zend_long offset = zval_get_long(member);
  1330. zval rv;
  1331. if (offset < 0) {
  1332. return 0;
  1333. } else {
  1334. zval *length = zend_read_property(Z_OBJCE_P(object), object, "length", sizeof("length") - 1, 0, &rv);
  1335. return length && offset < Z_LVAL_P(length);
  1336. }
  1337. } /* }}} end dom_nodelist_has_dimension */
  1338. #endif /* HAVE_DOM */
  1339. /*
  1340. * Local variables:
  1341. * tab-width: 4
  1342. * c-basic-offset: 4
  1343. * End:
  1344. * vim600: noet sw=4 ts=4 fdm=marker
  1345. * vim<600: noet sw=4 ts=4
  1346. */