1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Christian Stocker <chregu@php.net> | 16 | Rob Richards <rrichards@php.net> | 17 +----------------------------------------------------------------------+ 18*/ 19 20/* $Id$ */ 21 22#ifdef HAVE_CONFIG_H 23#include "config.h" 24#endif 25 26#include "php.h" 27#if HAVE_LIBXML && HAVE_DOM 28#include "php_dom.h" 29#include "dom_ce.h" 30 31typedef struct _nodeIterator nodeIterator; 32struct _nodeIterator { 33 int cur; 34 int index; 35 xmlNode *node; 36}; 37 38typedef struct _notationIterator notationIterator; 39struct _notationIterator { 40 int cur; 41 int index; 42 xmlNotation *notation; 43}; 44 45static void itemHashScanner (void *payload, void *data, xmlChar *name) /* {{{ */ 46{ 47 nodeIterator *priv = (nodeIterator *)data; 48 49 if(priv->cur < priv->index) { 50 priv->cur++; 51 } else { 52 if(priv->node == NULL) { 53 priv->node = (xmlNode *)payload; 54 } 55 } 56} 57/* }}} */ 58 59xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) /* {{{ */ 60{ 61 xmlEntityPtr ret; 62 63 ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); 64 memset(ret, 0, sizeof(xmlEntity)); 65 ret->type = XML_NOTATION_NODE; 66 ret->name = xmlStrdup(name); 67 ret->ExternalID = xmlStrdup(ExternalID); 68 ret->SystemID = xmlStrdup(SystemID); 69 ret->length = 0; 70 ret->content = NULL; 71 ret->URI = NULL; 72 ret->orig = NULL; 73 ret->children = NULL; 74 ret->parent = NULL; 75 ret->doc = NULL; 76 ret->_private = NULL; 77 ret->last = NULL; 78 ret->prev = NULL; 79 return((xmlNodePtr) ret); 80} 81/* }}} */ 82 83xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index) /* {{{ */ 84{ 85 xmlNode *nodep = NULL; 86 nodeIterator *iter; 87 int htsize; 88 89 if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) { 90 iter = emalloc(sizeof(nodeIterator)); 91 iter->cur = 0; 92 iter->index = index; 93 iter->node = NULL; 94 xmlHashScan(ht, itemHashScanner, iter); 95 nodep = iter->node; 96 efree(iter); 97 return nodep; 98 } else { 99 return NULL; 100 } 101} 102/* }}} */ 103 104xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index) /* {{{ */ 105{ 106 notationIterator *iter; 107 xmlNotation *notep = NULL; 108 int htsize; 109 110 if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) { 111 iter = emalloc(sizeof(notationIterator)); 112 iter->cur = 0; 113 iter->index = index; 114 iter->notation = NULL; 115 xmlHashScan(ht, itemHashScanner, iter); 116 notep = iter->notation; 117 efree(iter); 118 return create_notation(notep->name, notep->PublicID, notep->SystemID); 119 } else { 120 return NULL; 121 } 122} 123/* }}} */ 124 125static void php_dom_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ 126{ 127 php_dom_iterator *iterator = (php_dom_iterator *)iter; 128 129 zval_ptr_dtor((zval**)&iterator->intern.data); 130 131 if (iterator->curobj) { 132 zval_ptr_dtor((zval**)&iterator->curobj); 133 } 134 135 efree(iterator); 136} 137/* }}} */ 138 139static int php_dom_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ 140{ 141 142 php_dom_iterator *iterator = (php_dom_iterator *)iter; 143 144 if (iterator->curobj) { 145 return SUCCESS; 146 } else { 147 return FAILURE; 148 } 149} 150/* }}} */ 151 152static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ 153{ 154 php_dom_iterator *iterator = (php_dom_iterator *)iter; 155 156 *data = &iterator->curobj; 157} 158/* }}} */ 159 160static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ 161{ 162 php_dom_iterator *iterator = (php_dom_iterator *)iter; 163 zval *object = (zval *)iterator->intern.data; 164 165 if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) { 166 ZVAL_LONG(key, iter->index); 167 } else { 168 dom_object *intern = (dom_object *)zend_object_store_get_object(iterator->curobj TSRMLS_CC); 169 170 if (intern != NULL && intern->ptr != NULL) { 171 xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; 172 ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1); 173 } else { 174 ZVAL_NULL(key); 175 } 176 } 177} 178/* }}} */ 179 180static void php_dom_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ 181{ 182 zval *curobj, *curattr = NULL; 183 zval *object; 184 xmlNodePtr curnode = NULL, basenode; 185 dom_object *intern; 186 dom_object *nnmap; 187 dom_nnodemap_object *objmap; 188 int ret, previndex=0; 189 HashTable *nodeht; 190 zval **entry; 191 192 php_dom_iterator *iterator = (php_dom_iterator *)iter; 193 194 object = (zval *)iterator->intern.data; 195 nnmap = (dom_object *)zend_object_store_get_object(object TSRMLS_CC); 196 objmap = (dom_nnodemap_object *)nnmap->ptr; 197 198 curobj = iterator->curobj; 199 intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC); 200 if (intern != NULL && intern->ptr != NULL) { 201 if (objmap->nodetype != XML_ENTITY_NODE && 202 objmap->nodetype != XML_NOTATION_NODE) { 203 if (objmap->nodetype == DOM_NODESET) { 204 nodeht = HASH_OF(objmap->baseobjptr); 205 zend_hash_move_forward(nodeht); 206 if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) { 207 curattr = *entry; 208 Z_ADDREF_P(curattr); 209 } 210 } else { 211 curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; 212 if (objmap->nodetype == XML_ATTRIBUTE_NODE || 213 objmap->nodetype == XML_ELEMENT_NODE) { 214 curnode = curnode->next; 215 } else { 216 /* Nav the tree evey time as this is LIVE */ 217 basenode = dom_object_get_node(objmap->baseobj); 218 if (basenode && (basenode->type == XML_DOCUMENT_NODE || 219 basenode->type == XML_HTML_DOCUMENT_NODE)) { 220 basenode = xmlDocGetRootElement((xmlDoc *) basenode); 221 } else if (basenode) { 222 basenode = basenode->children; 223 } else { 224 goto err; 225 } 226 curnode = dom_get_elements_by_tag_name_ns_raw(basenode, objmap->ns, objmap->local, &previndex, iter->index); 227 } 228 } 229 } else { 230 if (objmap->nodetype == XML_ENTITY_NODE) { 231 curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index); 232 } else { 233 curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index); 234 } 235 } 236 } 237err: 238 zval_ptr_dtor((zval**)&curobj); 239 if (curnode) { 240 MAKE_STD_ZVAL(curattr); 241 curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC); 242 } 243 244 iterator->curobj = curattr; 245} 246/* }}} */ 247 248zend_object_iterator_funcs php_dom_iterator_funcs = { 249 php_dom_iterator_dtor, 250 php_dom_iterator_valid, 251 php_dom_iterator_current_data, 252 php_dom_iterator_current_key, 253 php_dom_iterator_move_forward, 254 NULL 255}; 256 257zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ 258{ 259 dom_object *intern; 260 dom_nnodemap_object *objmap; 261 xmlNodePtr nodep, curnode=NULL; 262 zval *curattr = NULL; 263 int ret, curindex = 0; 264 HashTable *nodeht; 265 zval **entry; 266 php_dom_iterator *iterator; 267 268 if (by_ref) { 269 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); 270 } 271 iterator = emalloc(sizeof(php_dom_iterator)); 272 273 Z_ADDREF_P(object); 274 iterator->intern.data = (void*)object; 275 iterator->intern.funcs = &php_dom_iterator_funcs; 276 277 intern = (dom_object *)zend_object_store_get_object(object TSRMLS_CC); 278 objmap = (dom_nnodemap_object *)intern->ptr; 279 if (objmap != NULL) { 280 if (objmap->nodetype != XML_ENTITY_NODE && 281 objmap->nodetype != XML_NOTATION_NODE) { 282 if (objmap->nodetype == DOM_NODESET) { 283 nodeht = HASH_OF(objmap->baseobjptr); 284 zend_hash_internal_pointer_reset(nodeht); 285 if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) { 286 curattr = *entry; 287 Z_ADDREF_P(curattr); 288 } 289 } else { 290 nodep = (xmlNode *)dom_object_get_node(objmap->baseobj); 291 if (!nodep) { 292 goto err; 293 } 294 if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) { 295 if (objmap->nodetype == XML_ATTRIBUTE_NODE) { 296 curnode = (xmlNodePtr) nodep->properties; 297 } else { 298 curnode = (xmlNodePtr) nodep->children; 299 } 300 } else { 301 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { 302 nodep = xmlDocGetRootElement((xmlDoc *) nodep); 303 } else { 304 nodep = nodep->children; 305 } 306 curnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &curindex, 0); 307 } 308 } 309 } else { 310 if (objmap->nodetype == XML_ENTITY_NODE) { 311 curnode = php_dom_libxml_hash_iter(objmap->ht, 0); 312 } else { 313 curnode = php_dom_libxml_notation_iter(objmap->ht, 0); 314 } 315 } 316 } 317err: 318 if (curnode) { 319 MAKE_STD_ZVAL(curattr); 320 curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC); 321 } 322 323 iterator->curobj = curattr; 324 325 return (zend_object_iterator*)iterator; 326} 327/* }}} */ 328 329#endif 330 331/* 332 * Local variables: 333 * tab-width: 4 334 * c-basic-offset: 4 335 * End: 336 * vim600: noet sw=4 ts=4 fdm=marker 337 * vim<600: noet sw=4 ts=4 338 */ 339