helly           Sun Mar  5 17:39:49 2006 UTC

  Added files:                 (Branch: PHP_5_1)
    /php-src/ext/spl/tests      array_019.phpt iterator_030.phpt 
                                iterator_031.phpt iterator_032.phpt 
                                iterator_033.phpt iterator_034.phpt 
                                sxe_005.phpt 

  Modified files:              
    /php-src/ext/spl    spl.php spl_array.c spl_directory.c spl_engine.c 
                        spl_engine.h spl_iterators.c spl_iterators.h 
                        spl_sxe.c 
  Log:
  - Fix issues with not/double calling of constructors of SPL iterators
  - Fix issues with info-class/file-class in SPL directory handling classes
  - Add SimpleXMLElement::count()
  - Drop erroneous RecursiveDirectoryIterator::getSubPathInfo()
  - Drop dead code
  - Add tests
  - Update docu
  
  
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl.php?r1=1.49.2.10&r2=1.49.2.11&diff_format=u
Index: php-src/ext/spl/spl.php
diff -u php-src/ext/spl/spl.php:1.49.2.10 php-src/ext/spl/spl.php:1.49.2.11
--- php-src/ext/spl/spl.php:1.49.2.10   Mon Feb 20 22:21:54 2006
+++ php-src/ext/spl/spl.php     Sun Mar  5 17:39:49 2006
@@ -887,8 +887,8 @@
         */
        function setFileClass(string class_name = "SplFileObject");
 
-       /** @param class_name name of class used with getFileInfo(), 
getPathInfo(), 
-        *                    getSubPathInfo(). Must be derived from 
SplFileInfo.
+       /** @param class_name name of class used with getFileInfo(), 
getPathInfo().
+        *                    Must be derived from SplFileInfo.
         */
        function setInfoClass(string class_name = "SplFileInfo");
 }
@@ -971,13 +971,6 @@
        /** @return the current sub path
         */
        function getSubPathname();
-
-       /** @return SplFileInfo created for the current sub path
-        * @param class_name name of class to instantiate
-        * @see SplFileInfo::setInfoClass()
-        */
-       function getSubPathInfo(string $class_name = NULL);
-
 }
 
 /** @ingroup SPL
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_array.c?r1=1.71.2.9&r2=1.71.2.10&diff_format=u
Index: php-src/ext/spl/spl_array.c
diff -u php-src/ext/spl/spl_array.c:1.71.2.9 
php-src/ext/spl/spl_array.c:1.71.2.10
--- php-src/ext/spl/spl_array.c:1.71.2.9        Sun Feb 12 16:44:36 2006
+++ php-src/ext/spl/spl_array.c Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_array.c,v 1.71.2.9 2006/02/12 16:44:36 helly Exp $ */
+/* $Id: spl_array.c,v 1.71.2.10 2006/03/05 17:39:49 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -472,6 +472,7 @@
        
        if (Z_TYPE_P(intern->array) == IS_OBJECT) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot append 
properties to objects, use %s::offsetSet() instead", Z_OBJCE_P(object)->name);
+               return;
        }
 
        spl_array_write_dimension(object, NULL, append_value TSRMLS_CC);
@@ -701,7 +702,6 @@
 {
        spl_array_it       *iterator = (spl_array_it *)iter;
        spl_array_object   *object   = iterator->object;
-
        HashTable          *aht      = spl_array_get_hash_table(object, 0 
TSRMLS_CC);
 
        if (!aht) {
@@ -909,8 +909,8 @@
 {
        zval *object = getThis(), *tmp, **array;
        spl_array_object *intern = 
(spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
-    
-    array_init(return_value);
+
+       array_init(return_value);
        zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 
0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array) == 
FAILURE) {
@@ -1195,7 +1195,7 @@
        if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) 
== FAILURE) {
                return;
        }
-       
+
        if (Z_TYPE_PP(entry) == IS_OBJECT && 
instanceof_function(Z_OBJCE_PP(entry), Z_OBJCE_P(getThis()) TSRMLS_CC)) {
                RETURN_ZVAL(*entry, 0, 0);
        }
@@ -1303,6 +1303,7 @@
        REGISTER_SPL_IMPLEMENTS(ArrayObject, Aggregate);
        REGISTER_SPL_IMPLEMENTS(ArrayObject, ArrayAccess);
        memcpy(&spl_handler_ArrayObject, zend_get_std_object_handlers(), 
sizeof(zend_object_handlers));
+
        spl_handler_ArrayObject.clone_obj = spl_array_object_clone;
        spl_handler_ArrayObject.read_dimension = spl_array_read_dimension;
        spl_handler_ArrayObject.write_dimension = spl_array_write_dimension;
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_directory.c?r1=1.45.2.21&r2=1.45.2.22&diff_format=u
Index: php-src/ext/spl/spl_directory.c
diff -u php-src/ext/spl/spl_directory.c:1.45.2.21 
php-src/ext/spl/spl_directory.c:1.45.2.22
--- php-src/ext/spl/spl_directory.c:1.45.2.21   Tue Feb 28 01:33:32 2006
+++ php-src/ext/spl/spl_directory.c     Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_directory.c,v 1.45.2.21 2006/02/28 01:33:32 helly Exp $ */
+/* $Id: spl_directory.c,v 1.45.2.22 2006/03/05 17:39:49 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -748,26 +748,30 @@
        spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zend_class_entry *ce = spl_ce_SplFileObject;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
FAILURE) {
-               return;
+       php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException 
TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
SUCCESS) {
+               intern->file_class = ce;
        }
 
-       intern->file_class = ce;
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
 /* }}} */
 
 /* {{{ proto SplFileObject SplFileInfo::setInfoClass([string class_name])
-   Class to use in getFileInfo(), getPathInfo(), getSubPathInfo() */
+   Class to use in getFileInfo(), getPathInfo() */
 SPL_METHOD(SplFileInfo, setInfoClass)
 {
        spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zend_class_entry *ce = spl_ce_SplFileInfo;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
FAILURE) {
-               return;
+       php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException 
TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
SUCCESS) {
+               intern->info_class = ce;
        }
 
-       intern->info_class = ce;
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
 /* }}} */
 
@@ -778,11 +782,13 @@
        spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zend_class_entry *ce = intern->info_class;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
FAILURE) {
-               return;
+       php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException 
TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
SUCCESS) {
+               spl_filesystem_object_create_type(ht, intern, SPL_FS_INFO, ce, 
return_value TSRMLS_CC);
        }
 
-       spl_filesystem_object_create_type(ht, intern, SPL_FS_INFO, ce, 
return_value TSRMLS_CC);
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
 /* }}} */
 
@@ -793,11 +799,13 @@
        spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zend_class_entry *ce = intern->info_class;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
FAILURE) {
-               return;
+       php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException 
TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
SUCCESS) {
+               spl_filesystem_object_create_info(intern, intern->path, 
intern->path_len, 1, ce, return_value TSRMLS_CC);
        }
 
-       spl_filesystem_object_create_info(intern, intern->path, 
intern->path_len, 1, ce, return_value TSRMLS_CC);
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
 /* }}} */
 
@@ -810,7 +818,7 @@
        int len;
        long flags = SPL_FILE_DIR_CURRENT_AS_FILEINFO;
 
-       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
+       php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException 
TSRMLS_CC);
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, 
&len, &flags) == FAILURE) {
                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
@@ -950,28 +958,6 @@
 }
 /* }}} */
 
-/* {{{ proto SplFileInfo RecursiveDirectoryIterator::getSubPathInfo([string 
$class_info])
-   Create SplFileInfo for sub path */
-SPL_METHOD(RecursiveDirectoryIterator, getSubPathInfo)
-{
-       spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       char *sub_name;
-       int len;
-       zend_class_entry *ce = intern->info_class;
-       
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == 
FAILURE) {
-               return;
-       }
-
-       if (intern->u.dir.sub_path) {
-               len = spprintf(&sub_name, 0, "%s%c%s", intern->u.dir.sub_path, 
DEFAULT_SLASH, intern->u.dir.entry.d_name);
-               spl_filesystem_object_create_info(intern, sub_name, len, 0, ce, 
return_value TSRMLS_CC);
-       } else {
-               spl_filesystem_object_create_info(intern, intern->path, 
intern->path_len, 1, ce, return_value TSRMLS_CC);
-       }
-}
-/* }}} */
-
 /* define an overloaded iterator structure */
 typedef struct {
        zend_object_iterator  intern;
@@ -1329,7 +1315,6 @@
        SPL_ME(RecursiveDirectoryIterator, getChildren,   NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPath,    NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPathname,NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveDirectoryIterator, 
getSubPathInfo,arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_engine.c?r1=1.20.2.1&r2=1.20.2.2&diff_format=u
Index: php-src/ext/spl/spl_engine.c
diff -u php-src/ext/spl/spl_engine.c:1.20.2.1 
php-src/ext/spl/spl_engine.c:1.20.2.2
--- php-src/ext/spl/spl_engine.c:1.20.2.1       Sun Jan  1 12:50:13 2006
+++ php-src/ext/spl/spl_engine.c        Sun Mar  5 17:39:49 2006
@@ -43,20 +43,6 @@
 }
 /* }}} */
 
-/* {{{ spl_is_instance_of */
-int spl_is_instance_of(zval **obj, zend_class_entry *ce TSRMLS_DC)
-{
-       /* Ensure everything needed is available before checking for the type.
-        */
-       zend_class_entry *instance_ce;
-
-       if (obj && (instance_ce = spl_get_class_entry(*obj TSRMLS_CC)) != NULL) 
{
-               return instanceof_function(instance_ce, ce TSRMLS_CC);
-       }
-       return 0;
-}
-/* }}} */
-
 /*
  * Local variables:
  * tab-width: 4
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_engine.h?r1=1.19.2.1&r2=1.19.2.2&diff_format=u
Index: php-src/ext/spl/spl_engine.h
diff -u php-src/ext/spl/spl_engine.h:1.19.2.1 
php-src/ext/spl/spl_engine.h:1.19.2.2
--- php-src/ext/spl/spl_engine.h:1.19.2.1       Sun Jan  1 12:50:13 2006
+++ php-src/ext/spl/spl_engine.h        Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_engine.h,v 1.19.2.1 2006/01/01 12:50:13 sniper Exp $ */
+/* $Id: spl_engine.h,v 1.19.2.2 2006/03/05 17:39:49 helly Exp $ */
 
 #ifndef SPL_ENGINE_H
 #define SPL_ENGINE_H
@@ -58,8 +58,6 @@
 }
 /* }}} */
 
-int spl_is_instance_of(zval **obj, zend_class_entry *ce TSRMLS_DC);
-
 #endif /* SPL_ENGINE_H */
 
 /*
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_iterators.c?r1=1.73.2.22&r2=1.73.2.23&diff_format=u
Index: php-src/ext/spl/spl_iterators.c
diff -u php-src/ext/spl/spl_iterators.c:1.73.2.22 
php-src/ext/spl/spl_iterators.c:1.73.2.23
--- php-src/ext/spl/spl_iterators.c:1.73.2.22   Mon Feb  6 11:28:41 2006
+++ php-src/ext/spl/spl_iterators.c     Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_iterators.c,v 1.73.2.22 2006/02/06 11:28:41 tony2001 Exp $ */
+/* $Id: spl_iterators.c,v 1.73.2.23 2006/03/05 17:39:49 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -815,18 +815,32 @@
 }
 #endif
 
+#define SPL_CHECK_CTOR(intern, classname) \
+       if (intern->dit_type == DIT_Unknown) { \
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Classes derived from %v must call %v::__construct()", \
+                               (spl_ce_##classname)->name, 
(spl_ce_##classname)->name); \
+               return; \
+       }
+
+#define APPENDIT_CHECK_CTOR(intern) SPL_CHECK_CTOR(intern, AppendIterator)
+
 static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more 
TSRMLS_DC);
 
-static inline spl_dual_it_object* 
spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_inner, 
dual_it_type dit_type)
+static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, 
zend_class_entry *ce_base, zend_class_entry *ce_inner, dual_it_type dit_type)
 {
        zval                 *zobject, *retval;
        spl_dual_it_object   *intern;
        zend_class_entry     *ce = NULL;
        int                   inc_refcount = 1;
 
-       php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException 
TSRMLS_CC);
-
        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() 
TSRMLS_CC);
+       
+       if (intern->dit_type != DIT_Unknown) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "%v::getIterator() must be called exactly once per instance", 
ce_base->name);
+               return NULL;
+       }
+
+       php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException 
TSRMLS_CC);
 
        intern->dit_type = dit_type;
        switch (dit_type) {
@@ -931,9 +945,9 @@
 
 /* {{{ proto FilterIterator::__construct(Iterator it) 
    Create an Iterator from another iterator */
-SPL_METHOD(dual_it, __construct)
+SPL_METHOD(FilterIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_Default);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator);
 } /* }}} */
 
 /* {{{ proto Iterator FilterIterator::getInnerIterator() 
@@ -1173,7 +1187,7 @@
    Create a RecursiveFilterIterator from a RecursiveIterator */
 SPL_METHOD(RecursiveFilterIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_RecursiveIterator, DIT_Default);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_RecursiveFilterIterator, spl_ce_RecursiveIterator, 
DIT_RecursiveFilterIterator);
 } /* }}} */
 
 /* {{{ proto boolean RecursiveFilterIterator::hasChildren()
@@ -1199,7 +1213,7 @@
        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() 
TSRMLS_CC);
 
        zend_call_method_with_0_params(&intern->inner.zobject, 
intern->inner.ce, NULL, "getchildren", &retval);
-       spl_instantiate_arg_ex1(spl_ce_RecursiveFilterIterator, &return_value, 
0, retval TSRMLS_CC);
+       spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval 
TSRMLS_CC);
        zval_ptr_dtor(&retval);
 } /* }}} */
 
@@ -1207,7 +1221,7 @@
    Create a ParentIterator from a RecursiveIterator */
 SPL_METHOD(ParentIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_RecursiveIterator, DIT_Default);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_ParentIterator, spl_ce_RecursiveIterator, DIT_ParentIterator);
 } /* }}} */
 
 /* {{{ proto boolean ParentIterator::hasChildren()
@@ -1233,7 +1247,7 @@
        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() 
TSRMLS_CC);
 
        zend_call_method_with_0_params(&intern->inner.zobject, 
intern->inner.ce, NULL, "getchildren", &retval);
-       spl_instantiate_arg_ex1(spl_ce_ParentIterator, &return_value, 0, retval 
TSRMLS_CC);
+       spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval 
TSRMLS_CC);
        zval_ptr_dtor(&retval);
 } /* }}} */
 
@@ -1274,6 +1288,7 @@
        intern = emalloc(sizeof(spl_dual_it_object));
        memset(intern, 0, sizeof(spl_dual_it_object));
        intern->std.ce = class_type;
+       intern->dit_type = DIT_Unknown;
 
        ALLOC_HASHTABLE(intern->std.properties);
        zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -1291,7 +1306,7 @@
 ZEND_END_ARG_INFO();
 
 static zend_function_entry spl_funcs_FilterIterator[] = {
-       SPL_ME(dual_it,         __construct,      
arginfo_filter_it___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(FilterIterator,  __construct,      
arginfo_filter_it___construct, ZEND_ACC_PUBLIC)
        SPL_ME(FilterIterator,  rewind,           NULL, ZEND_ACC_PUBLIC)
        SPL_ME(dual_it,         valid,            NULL, ZEND_ACC_PUBLIC)
        SPL_ME(dual_it,         key,              NULL, ZEND_ACC_PUBLIC)
@@ -1343,7 +1358,7 @@
                zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 
TSRMLS_CC, "Cannot seek to %ld which is below the offset %ld", pos, 
intern->u.limit.offset);
                return;
        }
-       if (pos > intern->u.limit.offset + intern->u.limit.count && 
intern->u.limit.count != -1) {
+       if (pos >= intern->u.limit.offset + intern->u.limit.count && 
intern->u.limit.count != -1) {
                zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 
TSRMLS_CC, "Cannot seek to %ld which is behind offest %ld plus count %ld", pos, 
intern->u.limit.offset, intern->u.limit.count);
                return;
        }
@@ -1376,7 +1391,7 @@
    Construct a LimitIterator from an Iterator with a given starting offset and 
optionally a maximum count */
 SPL_METHOD(LimitIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_LimitIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_LimitIterator, zend_ce_iterator, DIT_LimitIterator);
 } /* }}} */
 
 /* {{{ proto void LimitIterator::rewind() 
@@ -1568,7 +1583,7 @@
    Construct a CachingIterator from an Iterator */
 SPL_METHOD(CachingIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_CachingIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_CachingIterator, zend_ce_iterator, DIT_CachingIterator);
 } /* }}} */
 
 /* {{{ proto void CachingIterator::rewind()
@@ -1669,7 +1684,7 @@
    Create an iterator from a RecursiveIterator */
 SPL_METHOD(RecursiveCachingIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_RecursiveIterator, DIT_RecursiveCachingIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_RecursiveCachingIterator, spl_ce_RecursiveIterator, 
DIT_RecursiveCachingIterator);
 } /* }}} */
 
 /* {{{ proto bolean RecursiveCachingIterator::hasChildren()
@@ -1715,7 +1730,7 @@
    Create an iterator from anything that is traversable */
 SPL_METHOD(IteratorIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_traversable, DIT_IteratorIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_IteratorIterator, zend_ce_traversable, DIT_IteratorIterator);
 } /* }}} */
 
 static
@@ -1738,7 +1753,7 @@
    Create an iterator from another iterator */
 SPL_METHOD(NoRewindIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_NoRewindIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_NoRewindIterator, zend_ce_iterator, DIT_NoRewindIterator);
 } /* }}} */
 
 /* {{{ proto void NoRewindIterator::rewind()
@@ -1822,7 +1837,7 @@
    Create an iterator from another iterator */
 SPL_METHOD(InfiniteIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_InfiniteIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_InfiniteIterator, zend_ce_iterator, DIT_InfiniteIterator);
 } /* }}} */
 
 /* {{{ proto InfiniteIterator::next()
@@ -1916,7 +1931,6 @@
                intern->inner.object = zend_object_store_get_object(*it 
TSRMLS_CC);
                intern->inner.iterator = 
intern->inner.ce->get_iterator(intern->inner.ce, *it TSRMLS_CC);
                spl_dual_it_rewind(intern TSRMLS_CC);
-               
intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator 
TSRMLS_CC);
                return SUCCESS;
        } else {
                return FAILURE;
@@ -1926,6 +1940,7 @@
 void spl_append_it_fetch(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/
 {
        while (spl_dual_it_valid(intern TSRMLS_CC) != SUCCESS) {
+               
intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator 
TSRMLS_CC);
                if (spl_append_it_next_iterator(intern TSRMLS_CC) != SUCCESS) {
                        return;
                }
@@ -1945,7 +1960,7 @@
    Create an AppendIterator */
 SPL_METHOD(AppendIterator, __construct)
 {
-       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
zend_ce_iterator, DIT_AppendIterator);
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
spl_ce_AppendIterator, zend_ce_iterator, DIT_AppendIterator);
 } /* }}} */
 
 /* {{{ proto void AppendIterator::append(Iterator it)
@@ -1956,8 +1971,10 @@
        zval *it;
 
        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() 
TSRMLS_CC);
+       
+       APPENDIT_CHECK_CTOR(intern);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &it, 
zend_ce_iterator) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, 
zend_ce_iterator) == FAILURE) {
                return;
        }
        spl_array_iterator_append(intern->u.append.zarrayit, it TSRMLS_CC);
@@ -2071,7 +2088,7 @@
 }
 /* }}} */
 
-/* {{{ int iterator_count(Travesable it) 
+/* {{{ int iterator_count(Traversable it) 
    Count the elements in an iterator */
 PHP_FUNCTION(iterator_count)
 {
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_iterators.h?r1=1.18.2.6&r2=1.18.2.7&diff_format=u
Index: php-src/ext/spl/spl_iterators.h
diff -u php-src/ext/spl/spl_iterators.h:1.18.2.6 
php-src/ext/spl/spl_iterators.h:1.18.2.7
--- php-src/ext/spl/spl_iterators.h:1.18.2.6    Sun Jan  1 12:50:14 2006
+++ php-src/ext/spl/spl_iterators.h     Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_iterators.h,v 1.18.2.6 2006/01/01 12:50:14 sniper Exp $ */
+/* $Id: spl_iterators.h,v 1.18.2.7 2006/03/05 17:39:49 helly Exp $ */
 
 #ifndef SPL_ITERATORS_H
 #define SPL_ITERATORS_H
@@ -53,6 +53,9 @@
 
 typedef enum {
        DIT_Default = 0,
+       DIT_FilterIterator = DIT_Default,
+       DIT_RecursiveFilterIterator = DIT_Default,
+       DIT_ParentIterator = DIT_Default,
        DIT_LimitIterator,
        DIT_CachingIterator,
        DIT_RecursiveCachingIterator,
@@ -60,6 +63,7 @@
        DIT_NoRewindIterator,
        DIT_InfiniteIterator,
        DIT_AppendIterator,
+       DIT_Unknown = ~0
 } dual_it_type;
 
 enum {
http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_sxe.c?r1=1.8.2.3&r2=1.8.2.4&diff_format=u
Index: php-src/ext/spl/spl_sxe.c
diff -u php-src/ext/spl/spl_sxe.c:1.8.2.3 php-src/ext/spl/spl_sxe.c:1.8.2.4
--- php-src/ext/spl/spl_sxe.c:1.8.2.3   Sun Jan  1 12:50:14 2006
+++ php-src/ext/spl/spl_sxe.c   Sun Mar  5 17:39:49 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_sxe.c,v 1.8.2.3 2006/01/01 12:50:14 sniper Exp $ */
+/* $Id: spl_sxe.c,v 1.8.2.4 2006/03/05 17:39:49 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -32,6 +32,7 @@
 #include "spl_engine.h"
 #include "spl_iterators.h"
 #include "spl_sxe.h"
+#include "spl_array.h"
 
 zend_class_entry *spl_ce_SimpleXMLIterator = NULL;
 zend_class_entry *spl_ce_SimpleXMLElement;
@@ -85,7 +86,7 @@
                RETURN_STRINGL((char*)curnode->name, xmlStrlen(curnode->name), 
1);
        }
     
-    RETURN_FALSE;
+       RETURN_FALSE;
 }
 /* }}} */
 
@@ -106,7 +107,7 @@
        php_sxe_object *child;
        xmlNodePtr      node;
 
-       if (!sxe->iter.data) {
+       if (!sxe->iter.data || sxe->iter.type == SXE_ITER_ATTRLIST) {
                RETURN_FALSE;
        }
        child = php_sxe_fetch_object(sxe->iter.data TSRMLS_CC);
@@ -128,13 +129,22 @@
 {
        php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 
-       if (!sxe->iter.data) {
+       if (!sxe->iter.data || sxe->iter.type == SXE_ITER_ATTRLIST) {
                return; /* return NULL */
        }
        return_value->type = IS_OBJECT;
        return_value->value.obj = zend_objects_store_clone_obj(sxe->iter.data 
TSRMLS_CC);
 }
 
+SPL_METHOD(SimpleXMLIterator, count) /* {{{ */
+{
+       long count = 0;
+
+       Z_OBJ_HANDLER_P(getThis(), count_elements)(getThis(), &count TSRMLS_CC);
+       
+       RETURN_LONG(count);
+}
+
 static zend_function_entry spl_funcs_SimpleXMLIterator[] = {
        SPL_ME(SimpleXMLIterator, rewind,                 NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SimpleXMLIterator, valid,                  NULL, ZEND_ACC_PUBLIC)
@@ -143,6 +153,7 @@
        SPL_ME(SimpleXMLIterator, next,                   NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SimpleXMLIterator, hasChildren,            NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SimpleXMLIterator, getChildren,            NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SimpleXMLIterator, count,                  NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 /* }}} */
@@ -150,17 +161,18 @@
 SPL_API PHP_MINIT_FUNCTION(spl_sxe) /* {{{ */
 {
        zend_class_entry **pce;
-       
+
        if (zend_hash_find(CG(class_table), "simplexmlelement", 
sizeof("SimpleXMLElement"), (void **) &pce) == FAILURE) {
                spl_ce_SimpleXMLElement  = NULL;
                spl_ce_SimpleXMLIterator = NULL;
                return SUCCESS; /* SimpleXML must be initialized before */
        }
-       
+
        spl_ce_SimpleXMLElement = *pce;
 
        REGISTER_SPL_SUB_CLASS_EX(SimpleXMLIterator, SimpleXMLElement, 
spl_ce_SimpleXMLElement->create_object, spl_funcs_SimpleXMLIterator);
        REGISTER_SPL_IMPLEMENTS(SimpleXMLIterator, RecursiveIterator);
+       REGISTER_SPL_IMPLEMENTS(SimpleXMLIterator, Countable);
 
        return SUCCESS;
 }

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/array_019.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/array_019.phpt
+++ php-src/ext/spl/tests/array_019.phpt
--TEST--
SPL: ArrayIterator and foreach by reference
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

$ar = new ArrayObject(array(1));            foreach($ar as &$v) var_dump($v);
$ar = new ArrayIterator(array(2));          foreach($ar as &$v) var_dump($v);
$ar = new RecursiveArrayIterator(array(3)); foreach($ar as &$v) var_dump($v);

class ArrayIteratorEx extends ArrayIterator
{
        function current()
        {
                return ArrayIterator::current();
        }
}

$ar = new ArrayIteratorEx(array(4)); foreach($ar as $v) var_dump($v);
$ar = new ArrayIteratorEx(array(5)); foreach($ar as &$v) var_dump($v);

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
int(1)
int(2)
int(3)
int(4)

Fatal error: An iterator cannot be used with foreach by reference in 
%sarray_019.php on line %d

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/iterator_030.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/iterator_030.phpt
+++ php-src/ext/spl/tests/iterator_030.phpt
--TEST--
SPL: EmptyIterator access
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

$it = new EmptyIterator;

var_dump($it->valid());
$it->rewind();
var_dump($it->valid());
$it->next();
var_dump($it->valid());

try
{
        var_dump($it->key());
}
catch(BadMethodCallException $e)
{
        echo $e->getMessage() . "\n";
}

try
{
        var_dump($it->current());
}
catch(BadMethodCallException $e)
{
        echo $e->getMessage() . "\n";
}

var_dump($it->valid());

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
bool(false)
bool(false)
bool(false)
Accessing the key of an EmptyIterator
Accessing the value of an EmptyIterator
bool(false)
===DONE===

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/iterator_031.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/iterator_031.phpt
+++ php-src/ext/spl/tests/iterator_031.phpt
--TEST--
SPL: AppendIterator::append() rewinds when neccessary
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

class MyArrayIterator extends ArrayIterator
{
        function rewind()
        {
                echo __METHOD__ . "\n";
                parent::rewind();
        }
}

$it = new MyArrayIterator(array(1,2));

foreach($it as $k=>$v)
{
        echo "$k=>$v\n";
}

class MyAppendIterator extends AppendIterator
{
        function __construct()
        {
                echo __METHOD__ . "\n";
        }

        function rewind()
        {
                echo __METHOD__ . "\n";
                parent::rewind();
        }

        function valid()
        {
                echo __METHOD__ . "\n";
                return parent::valid();
        }
        
        function append(Iterator $what)
        {
                echo __METHOD__ . "\n";
                parent::append($what);
        }
        
        function parent__construct()
        {
                parent::__construct();
        }
}

$ap = new MyAppendIterator;

try
{
        $ap->append($it);
}
catch(BadMethodCallException $e)
{
        echo $e->getMessage() . "\n";
}

$ap->parent__construct();

try
{
        $ap->parent__construct($it);
}
catch(BadMethodCallException $e)
{
        echo $e->getMessage() . "\n";
}

$ap->append($it);
$ap->append($it);
$ap->append($it);

foreach($ap as $k=>$v)
{
        echo "$k=>$v\n";
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
MyArrayIterator::rewind
0=>1
1=>2
MyAppendIterator::__construct
MyAppendIterator::append
Classes derived from AppendIterator must call AppendIterator::__construct()
AppendIterator::getIterator() must be called exactly once per instance
MyAppendIterator::append
MyArrayIterator::rewind
MyAppendIterator::append
MyAppendIterator::append
MyAppendIterator::rewind
MyArrayIterator::rewind
MyAppendIterator::valid
0=>1
MyAppendIterator::valid
1=>2
MyArrayIterator::rewind
MyAppendIterator::valid
0=>1
MyAppendIterator::valid
1=>2
MyArrayIterator::rewind
MyAppendIterator::valid
0=>1
MyAppendIterator::valid
1=>2
MyAppendIterator::valid
===DONE===

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/iterator_032.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/iterator_032.phpt
+++ php-src/ext/spl/tests/iterator_032.phpt
--TEST--
SPL: LimitIterator::getPosition()
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

$it = new LimitIterator(new ArrayIterator(array(1,2,3,4)), 1, 2);

foreach($it as $k=>$v)
{
        echo "$k=>$v\n";
        var_dump($it->getPosition());
}

try
{
        $it->seek(0);
}
catch(OutOfBoundsException $e)
{
        echo $e->getMessage() . "\n";
}

$it->seek(2);
var_dump($it->current());

try
{
        $it->seek(3);
}
catch(OutOfBoundsException $e)
{
        echo $e->getMessage() . "\n";
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
1=>2
int(1)
2=>3
int(2)
Cannot seek to 0 which is below the offset 1
int(3)
Cannot seek to 3 which is behind offest 1 plus count 2
===DONE===

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/iterator_033.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/iterator_033.phpt
+++ php-src/ext/spl/tests/iterator_033.phpt
--TEST--
SPL: ParentIterator
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

$it = new ParentIterator(new RecursiveArrayIterator(array(1,array(21,22, 
array(231)),3)));

foreach(new RecursiveIteratorIterator($it) as $k=>$v)
{
        var_dump($k);
        var_dump($v);
}

echo "==SECOND==\n";

foreach(new RecursiveIteratorIterator($it, 1) as $k=>$v)
{
        var_dump($k);
        var_dump($v);
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
==SECOND==
int(1)
array(3) {
  [0]=>
  int(21)
  [1]=>
  int(22)
  [2]=>
  array(1) {
    [0]=>
    int(231)
  }
}
int(2)
array(1) {
  [0]=>
  int(231)
}
===DONE===

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/iterator_034.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/iterator_034.phpt
+++ php-src/ext/spl/tests/iterator_034.phpt
--TEST--
SPL: RecursiveIteratorIterator and break deep
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php

class MyRecursiveArrayIterator extends RecursiveArrayIterator
{
        function valid()
        {
                if (!parent::valid())
                {
                        echo __METHOD__ . "() = false\n";
                        return false;
                }
                else
                {
                        return true;
                }
        }

        function getChildren()
        {
                echo __METHOD__ . "()\n";
                return parent::getChildren();
        }
        
        function rewind()
        {
                echo __METHOD__ . "()\n";
                parent::rewind();
        }
}

class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
{
        private $max_depth;
        private $over = 0;

        function __construct($it, $max_depth)
        {
                $this->max_depth = $max_depth;
                parent::__construct($it);
        }

        function rewind()
        {
                echo __METHOD__ . "() - BEGIN\n";
                parent::rewind();
                echo __METHOD__ . "() - DONE\n";
        }

        function valid()
        {
                echo __METHOD__ . "()\n";
                return parent::valid();
        }

        function current()
        {
                echo __METHOD__ . "()\n";
                return parent::current();
        }

        function key()
        {
                echo __METHOD__ . "()\n";
                return parent::key();
        }

        function next()
        {
                echo __METHOD__ . "()\n";
                parent::next();
        }

        function callHasChildren()
        {
                $has = parent::callHasChildren();
                $res = $this->getDepth() < $this->max_depth && $has;
                echo __METHOD__ . "(".$this->getDepth().") = 
".($res?"yes":"no")."/".($has?"yes":"no")."\n";
                return $res;
        }

        function beginChildren()
        {
                echo __METHOD__ . "(".$this->getDepth().")\n";
                parent::beginChildren();
        }

        function endChildren()
        {
                echo __METHOD__ . "(".$this->getDepth().")\n";
                parent::endChildren();
        }
}

$p = 0;
$it = new RecursiveArrayIteratorIterator(new 
MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), 
array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2);
foreach($it as $k=>$v)
{
        if (is_array($v)) $v = join('',$v);
        echo "$k=>$v\n";
        if ($p++ == 5)
        {
                echo "===BREAK===\n";
                break;
        }
}

echo "===FOREND===\n";

$it->rewind();

echo "===CHECK===\n";

var_dump($it->valid());
var_dump($it->current());

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
RecursiveArrayIteratorIterator::rewind() - BEGIN
MyRecursiveArrayIterator::rewind()
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
RecursiveArrayIteratorIterator::rewind() - DONE
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
0=>a
RecursiveArrayIteratorIterator::next()
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
MyRecursiveArrayIterator::getChildren()
MyRecursiveArrayIterator::rewind()
RecursiveArrayIteratorIterator::beginChildren(1)
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
0=>ba
RecursiveArrayIteratorIterator::next()
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
MyRecursiveArrayIterator::getChildren()
MyRecursiveArrayIterator::rewind()
RecursiveArrayIteratorIterator::beginChildren(2)
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
0=>bba
RecursiveArrayIteratorIterator::next()
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
1=>bbb
RecursiveArrayIteratorIterator::next()
MyRecursiveArrayIterator::valid() = false
RecursiveArrayIteratorIterator::endChildren(2)
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
MyRecursiveArrayIterator::getChildren()
MyRecursiveArrayIterator::rewind()
RecursiveArrayIteratorIterator::beginChildren(2)
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
0=>bcaa
RecursiveArrayIteratorIterator::next()
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
RecursiveArrayIteratorIterator::valid()
RecursiveArrayIteratorIterator::current()
RecursiveArrayIteratorIterator::key()
1=>bcba
===BREAK===
===FOREND===
RecursiveArrayIteratorIterator::rewind() - BEGIN
RecursiveArrayIteratorIterator::endChildren(1)
RecursiveArrayIteratorIterator::endChildren(0)
MyRecursiveArrayIterator::rewind()
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
RecursiveArrayIteratorIterator::rewind() - DONE
===CHECK===
RecursiveArrayIteratorIterator::valid()
bool(true)
RecursiveArrayIteratorIterator::current()
string(1) "a"
===DONE===

http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/sxe_005.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/sxe_005.phpt
+++ php-src/ext/spl/tests/sxe_005.phpt
--TEST--
SPL: SimpleXMLIterator and getChildren()
--SKIPIF--
<?php 
if (!extension_loaded("spl")) print "skip";
if (!extension_loaded('simplexml')) print 'skip';
if (!extension_loaded("libxml")) print "skip LibXML not present";
if (!class_exists('RecursiveIteratorIterator')) print 'skip 
RecursiveIteratorIterator not available';
?>
--FILE--
<?php 

$xml =<<<EOF
<?xml version='1.0'?>
<sxe>
 <elem1/>
 <elem2/>
 <elem2/>
</sxe>
EOF;

class SXETest extends SimpleXMLIterator
{
        function count()
        {
                echo __METHOD__ . "\n";
                return parent::count();
        }
}

$sxe = new SXETest($xml);

var_dump(count($sxe));
var_dump(count($sxe->elem1));
var_dump(count($sxe->elem2));

?>
===DONE===
--EXPECT--
SXETest::count
int(3)
SXETest::count
int(1)
SXETest::count
int(2)
===DONE===

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to