php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #56114 Patches to make APC work on PHP5
Submitted: 2004-06-30 01:20 UTC Modified: 2004-09-07 00:42 UTC
From: kameshj at fastmail dot fm Assigned:
Status: Not a bug Package: APC (PECL)
PHP Version: 5CVS-2004-06-30 (dev) OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kameshj at fastmail dot fm
New email:
PHP Version: OS:

 

 [2004-06-30 01:20 UTC] kameshj at fastmail dot fm
Description:
------------
Patch for APC to work with PHP5. But this patch wioll make it not 
work for PHP 4. Ideally There should be ifdef checks for PHP 
versions. 
--- apc_cache.c	2004-05-04 16:37:15.000000000 +0530 
+++ ../APC-2.0.3orig/APC-2.0.3/apc_cache.c	2004-03-12 
07:18:09.000000000 +0530 
@@ -173,7 +173,7 @@ 
         int i; 
         apc_class_t* classes = entry->classes; 
         for (i=0; classes[i].class_entry != NULL; i++) { 
-            classes[i].class_entry->refcount = BIG_VALUE; 
+            classes[i].class_entry->refcount[0] = BIG_VALUE; 
         } 
     } 
 } 
--- apc_compile.c	2004-06-29 17:36:04.000000000 +0530 
+++ apc_compile.c.orig.k	2004-06-29 17:27:16.000000000 
+0530 
@@ -20,7 +20,6 @@ 
 #include "apc_globals.h" 
 #include "apc_zend.h" 
 #include "apc_optimizer.h" 
-#include "apc_sma.h" 
  
 typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t); 
 typedef void  (*ht_free_fun_t)(void*, apc_free_t); 
@@ -40,10 +39,8 @@ 
  */ 
 static zval** my_copy_zval_ptr(zval**, zval**, apc_malloc_t); 
 static zval* my_copy_zval(zval*, zval*, apc_malloc_t); 
-static zend_property_info* 
my_copy_zend_property_info(zend_property_info*, 
zend_property_info*, apc_malloc_t); 
 static znode* my_copy_znode(znode*, znode*, apc_malloc_t); 
 static zend_op* my_copy_zend_op(zend_op*, zend_op*, 
apc_malloc_t); 
-static zend_arg_info* my_copy_arg_info(zend_function* src, 
zend_function* dst, apc_malloc_t allocate TSRMLS_DC); 
 static zend_function* my_copy_function(zend_function*, 
zend_function*, apc_malloc_t); 
 static zend_function_entry* 
my_copy_function_entry(zend_function_entry*, 
zend_function_entry*, apc_malloc_t); 
 static zend_class_entry* 
my_copy_class_entry(zend_class_entry*, zend_class_entry*, 
apc_malloc_t); 
@@ -106,6 +103,7 @@ 
                        type == IS_NULL || 
                        type == IS_CONSTANT || 
                        type == IS_STRING || 
+                       type == FLAG_IS_BC || 
                        type == IS_ARRAY || 
                        type == IS_CONSTANT_ARRAY || 
                        type == IS_OBJECT); 
@@ -139,7 +137,7 @@ 
     for (i = 0; i < op_array->last; i++) { 
         zend_op* op = &op_array->opcodes[i]; 
  
-        if (((op->opcode == ZEND_DECLARE_CLASS)||
(op->opcode == ZEND_DECLARE_FUNCTION)) && 
+        if (op->opcode == 
ZEND_DECLARE_FUNCTION_OR_CLASS && 
             op->extended_value == 
ZEND_DECLARE_INHERITED_CLASS) 
         { 
             if (op->op1.u.constant.value.str.len == key_size && 
@@ -185,19 +183,6 @@ 
 } 
 /* }}} */ 
  
-/* {{{ my_copy_zend_property_info */ 
-static zend_property_info* 
my_copy_zend_property_info(zend_property_info* dst, 
zend_property_info* src, apc_malloc_t allocate) 
-{ 
-    if(!dst) { 
-        CHECK(dst = (zend_property_info *) 
allocate(sizeof(zend_property_info))); 
-    } 
-    memcpy(dst, src, sizeof(src[0])); 
-    if(src->name) { 
-        CHECK(dst->name = apc_xstrdup(src->name, allocate)); 
-    } 
-    return dst;     
-} 
-/* }}} */ 
 /* {{{ my_copy_zval */ 
 static zval* my_copy_zval(zval* dst, zval* src, apc_malloc_t 
allocate) 
 { 
@@ -216,6 +201,7 @@ 
  
     case IS_CONSTANT: 
     case IS_STRING: 
+    case FLAG_IS_BC: 
         if (src->value.str.val) 
             CHECK(dst->value.str.val = 
apc_xmemcpy(src->value.str.val, 
                                                    src->value.str.len+1, 
@@ -233,12 +219,12 @@ 
         break; 
  
     case IS_OBJECT: 
-        CHECK(dst->value.obj.handlers->get_class_entry = 
-            my_copy_class_entry(NULL, 
src->value.obj.handlers->get_class_entry, allocate)); 
+        CHECK(dst->value.obj.ce = 
+            my_copy_class_entry(NULL, src->value.obj.ce, 
allocate)); 
  
-        CHECK(dst->value.obj.handlers->get_properties = 
+        CHECK(dst->value.obj.properties = 
             my_copy_hashtable(NULL, 
-                              src->value.obj.handlers->get_properties, 
+                              src->value.obj.properties, 
                               (ht_copy_fun_t) my_copy_zval_ptr, 
                               1, 
                               allocate)); 
@@ -291,25 +277,28 @@ 
 /* {{{ my_copy_function */ 
 static zend_function* my_copy_function(zend_function* dst, 
zend_function* src, apc_malloc_t allocate) 
 { 
-    TSRMLS_FETCH(); 
+	TSRMLS_FETCH(); 
+ 
     assert(src != NULL); 
  
     CHECK(dst = my_bitwise_copy_function(dst, src, allocate)); 
  
     switch (src->type) { 
-        case ZEND_INTERNAL_FUNCTION: 
-        case ZEND_OVERLOADED_FUNCTION: 
-            assert(0); 
+    case ZEND_INTERNAL_FUNCTION: 
+    case ZEND_OVERLOADED_FUNCTION: 
+        assert(0); 
          
-        case ZEND_USER_FUNCTION: 
-        case ZEND_EVAL_CODE: 
-            CHECK(apc_copy_op_array(&dst->op_array, 
&src->op_array, allocate TSRMLS_CC)); 
-            dst->common.arg_info = my_copy_arg_info(src, dst, 
allocate TSRMLS_CC); 
-            break; 
+    case ZEND_USER_FUNCTION: 
+    case ZEND_EVAL_CODE: 
+        CHECK(apc_copy_op_array(&dst->op_array, 
+                                &src->op_array, 
+                                allocate TSRMLS_CC)); 
+        break; 
  
-        default: 
-            assert(0); 
+    default: 
+        assert(0); 
     } 
+ 
     return dst; 
 } 
 /* }}} */ 
@@ -330,11 +319,11 @@ 
         CHECK(dst->fname = apc_xstrdup(src->fname, allocate)); 
     } 
  
-    /*if (src->func_arg_types) { 
+    if (src->func_arg_types) { 
         CHECK(dst->func_arg_types = 
apc_xmemcpy(src->func_arg_types, 
                                                 src->func_arg_types[0]+1, 
                                                 allocate)); 
-    }*/ 
+    } 
  
     return dst; 
 } 
@@ -356,6 +345,9 @@ 
         CHECK(dst->name = apc_xstrdup(src->name, allocate)); 
     } 
  
+    CHECK(dst->refcount = apc_xmemcpy(src->refcount, 
+                                      sizeof(src->refcount[0]), 
+                                      allocate)); 
  
     CHECK(my_copy_hashtable(&dst->function_table, 
                             &src->function_table, 
@@ -369,23 +361,6 @@ 
                             1, 
                             allocate)); 
  
-    CHECK(my_copy_hashtable(&dst->properties_info, 
-                            &src->properties_info, 
-                            (ht_copy_fun_t) 
my_copy_zend_property_info, 
-                            1, 
-                            allocate)); 
- 
-    CHECK(dst->static_members = my_copy_hashtable(NULL, 
-                            src->static_members, 
-                            (ht_copy_fun_t) my_copy_zval_ptr, 
-                            1, 
-                            allocate)); 
-    if(src->constructor) 
-    { 
-        CHECK(dst->constructor = my_copy_function(NULL, 
-                            src->constructor, 
-                            allocate)); 
-    } 
     if (src->builtin_functions) { 
         int i, n; 
  
@@ -504,6 +479,7 @@ 
 zend_op_array* apc_copy_op_array(zend_op_array* dst, 
zend_op_array* src, apc_malloc_t allocate TSRMLS_DC) 
 { 
     int i; 
+ 
     assert(src != NULL); 
  
     if (!dst) { 
@@ -517,12 +493,12 @@ 
     memcpy(dst, src, sizeof(src[0])); 
  
     /* copy the arg types array (if set) */ 
-    /*if (src->arg_types) { 
+    if (src->arg_types) { 
         CHECK(dst->arg_types = 
             apc_xmemcpy(src->arg_types, 
                         sizeof(src->arg_types[0]) * (src->arg_types[0]
+1), 
                         allocate)); 
-    }*/ 
+    } 
  
     if (src->function_name) { 
         CHECK(dst->function_name = 
apc_xstrdup(src->function_name, allocate)); 
@@ -539,19 +515,6 @@ 
     CHECK(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) 
* src->last)); 
     for (i = 0; i < src->last; i++) { 
         CHECK(my_copy_zend_op(dst->opcodes+i, src->opcodes
+i, allocate)); 
-        switch((dst->opcodes+i)->opcode) { 
-            case ZEND_JMP: 
-                //zend_uint srcoplinenum = (((src->opcodes
+i)->op1.u.jmp_addr) - src->opcodes); 
-                (dst->opcodes+i)->op1.u.jmp_addr = dst->opcodes + 
(((src->opcodes+i)->op1.u.jmp_addr) - src->opcodes); 
-                break; 
-            case ZEND_JMPZ: 
-            case ZEND_JMPNZ: 
-            case ZEND_JMPZ_EX: 
-            case ZEND_JMPNZ_EX: 
-                //zend_uint srcoplinenum = (((src->opcodes
+i)->op2.u.jmp_addr) - src->opcodes); 
-                (dst->opcodes+i)->op2.u.jmp_addr = dst->opcodes + 
(((src->opcodes+i)->op2.u.jmp_addr) - src->opcodes); 
-                break; 
-        } 
     } 
  
     /* copy the break-continue array */ 
@@ -571,36 +534,13 @@ 
 } 
 /* }}} */ 
  
-/* {{{ my_copy_arg_info */ 
-zend_arg_info* my_copy_arg_info(zend_function* src, 
zend_function* dst, apc_malloc_t allocate TSRMLS_DC) 
-{ 
-    //allocate the memory for all arguments for dst and copy the 
src arg_info in to it and return starting of the memory 
-    int i=0; 
-    assert(src != NULL); 
-    zend_arg_info *temparginfo; 
-    if(src->common.num_args == 0) { 
-        return NULL; 
-    } 
-    CHECK(temparginfo = (zend_arg_info*) 
allocate(sizeof(zend_arg_info) * src->common.num_args)); 
-    memcpy(temparginfo, src->common.arg_info, 
sizeof(zend_arg_info) * src->common.num_args); 
-    while(i < src->common.num_args) { 
-        if (src->common.arg_info[i].name) { 
-            CHECK(temparginfo[i].name = 
apc_xstrdup(src->common.arg_info[i].name, allocate)); 
-        } 
-        if (src->common.arg_info[i].class_name) { 
-            CHECK(temparginfo[i].class_name = 
apc_xstrdup(src->common.arg_info[i].class_name, allocate)); 
-        } 
-        i++; 
-    } 
-    return temparginfo; 
-} 
-/* }}} */ 
 /* {{{ apc_copy_new_functions */ 
 apc_function_t* apc_copy_new_functions(int old_count, 
apc_malloc_t allocate TSRMLS_DC) 
 { 
     apc_function_t* array; 
     int new_count;              /* number of new functions in table */ 
     int i; 
+ 
     new_count = zend_hash_num_elements(CG(function_table)) 
- old_count; 
     assert(new_count >= 0); 
  
@@ -674,7 +614,7 @@ 
     for (i = 0; i < new_count; i++) { 
         char* key; 
         uint key_size; 
-        zend_class_entry** elem; 
+        zend_class_entry* elem; 
  
         array[i].class_entry = NULL; 
  
@@ -689,7 +629,7 @@ 
  
         CHECK(array[i].name = apc_xmemcpy(key, (int) key_size, 
allocate)); 
         array[i].name_len = (int) key_size-1; 
-        CHECK(array[i].class_entry = my_copy_class_entry(NULL, 
*elem, allocate)); 
+        CHECK(array[i].class_entry = my_copy_class_entry(NULL, 
elem, allocate)); 
  
         /* 
          * If the class has a pointer to its parent class, save the 
parent 
@@ -699,9 +639,9 @@ 
          * class at execution-time. 
          */ 
  
-        if ((*elem)->parent) { 
+        if (elem->parent) { 
             CHECK(array[i].parent_name = 
-                apc_xstrdup((*elem)->parent->name, allocate)); 
+                apc_xstrdup(elem->parent->name, allocate)); 
             array[i].is_derived = 1; 
         } 
         else { 
@@ -739,6 +679,7 @@ 
  
     case IS_CONSTANT: 
     case IS_STRING: 
+    case FLAG_IS_BC: 
         deallocate(src->value.str.val); 
         break; 
      
@@ -750,9 +691,9 @@ 
         break; 
  
     case IS_OBJECT: 
-        
my_destroy_class_entry(src->value.obj.handlers->get_class_entry, 
deallocate); 
-        deallocate(src->value.obj.handlers->get_class_entry); 
-        
my_free_hashtable(src->value.obj.handlers->get_properties, 
+        my_destroy_class_entry(src->value.obj.ce, deallocate); 
+        deallocate(src->value.obj.ce); 
+        my_free_hashtable(src->value.obj.properties, 
                           (ht_free_fun_t) my_free_zval_ptr, 
                           deallocate); 
         break; 
@@ -808,9 +749,9 @@ 
     assert(src != NULL); 
  
     deallocate(src->fname); 
-    /*if (src->func_arg_types) { 
+    if (src->func_arg_types) { 
         deallocate(src->func_arg_types); 
-    }*/ 
+    } 
 } 
 /* }}} */ 
  
@@ -869,9 +810,9 @@ 
  
     assert(src != NULL); 
  
-    /*if (src->arg_types) { 
+    if (src->arg_types) { 
         deallocate(src->arg_types); 
-    }*/ 
+    } 
  
     deallocate(src->function_name); 
     deallocate(src->filename); 
--- apc_debug.c	2004-05-04 18:25:51.000000000 +0530 
+++ ../APC-2.0.3orig/APC-2.0.3/apc_debug.c	2003-06-29 
08:23:31.000000000 +0530 
@@ -81,9 +81,6 @@ 
     static const char S_ZEND_INCLUDE_OR_EVAL[] = 
"INCLUDE_OR_EVAL"; 
     static const char S_ZEND_UNSET_VAR[] = "UNSET_VAR"; 
     static const char S_ZEND_UNSET_DIM_OBJ[] = 
"UNSET_DIM_OBJ"; 
-    static const char S_ZEND_ISSET_ISEMPTY_VAR[] = 
"ISSET_ISEMPTY_VAR"; 
-    static const char S_ZEND_ISSET_ISEMPTY_DIM_OBJ[] = 
"ISSET_ISEMPTY_DIM_OBJ"; 
-    static const char S_ZEND_ISSET_ISEMPTY_PROP_OBJ[] = 
"ISSET_ISEMPTY_PROP_OBJ"; 
     static const char S_ZEND_ISSET_ISEMPTY[] = 
"ISSET_ISEMPTY"; 
     static const char S_ZEND_FE_RESET[] = "FE_RESET"; 
     static const char S_ZEND_FE_FETCH[] = "FE_FETCH"; 
@@ -108,8 +105,7 @@ 
     static const char S_ZEND_FETCH_OBJ_UNSET[] = 
"FETCH_OBJ_UNSET"; 
     static const char S_ZEND_FETCH_DIM_TMP_VAR[] = 
"FETCH_DIM_TMP_VAR"; 
     static const char S_ZEND_FETCH_CONSTANT[] = 
"FETCH_CONSTANT"; 
-    static const char S_ZEND_DECLARE_FUNCTION[] = 
"DECLARE_FUNCTION"; 
-    static const char S_ZEND_DECLARE_CLASS[] = 
"DECLARE_CLASS"; 
+    static const char 
S_ZEND_DECLARE_FUNCTION_OR_CLASS[] = 
"DECLARE_FUNCTION_OR_CLASS"; 
     static const char S_ZEND_EXT_STMT[] = "EXT_STMT"; 
     static const char S_ZEND_EXT_FCALL_BEGIN[] = 
"EXT_FCALL_BEGIN"; 
     static const char S_ZEND_EXT_FCALL_END[] = 
"EXT_FCALL_END"; 
@@ -274,12 +270,8 @@ 
         return S_ZEND_UNSET_VAR; 
       case ZEND_UNSET_DIM_OBJ: 
         return S_ZEND_UNSET_DIM_OBJ; 
-      case ZEND_ISSET_ISEMPTY_VAR: 
-        return S_ZEND_ISSET_ISEMPTY_VAR; 
-      case ZEND_ISSET_ISEMPTY_DIM_OBJ: 
-        return S_ZEND_ISSET_ISEMPTY_DIM_OBJ; 
-      case ZEND_ISSET_ISEMPTY_PROP_OBJ: 
-        return S_ZEND_ISSET_ISEMPTY_PROP_OBJ; 
+      case ZEND_ISSET_ISEMPTY: 
+        return S_ZEND_ISSET_ISEMPTY; 
       case ZEND_FE_RESET: 
         return S_ZEND_FE_RESET; 
       case ZEND_FE_FETCH: 
@@ -326,10 +318,8 @@ 
         return S_ZEND_FETCH_DIM_TMP_VAR; 
       case ZEND_FETCH_CONSTANT: 
         return S_ZEND_FETCH_CONSTANT; 
-      case ZEND_DECLARE_FUNCTION: 
-        return S_ZEND_DECLARE_FUNCTION; 
-      case ZEND_DECLARE_CLASS: 
-        return S_ZEND_DECLARE_CLASS; 
+      case ZEND_DECLARE_FUNCTION_OR_CLASS: 
+        return S_ZEND_DECLARE_FUNCTION_OR_CLASS; 
       case ZEND_EXT_STMT: 
         return S_ZEND_EXT_STMT; 
       case ZEND_EXT_FCALL_BEGIN: 
--- apc_main.c	2004-05-28 08:44:13.000000000 +0530 
+++ apc_main.c.orig1	2004-05-28 08:40:55.000000000 
+0530 
@@ -60,7 +60,7 @@ 
 static int install_class(apc_class_t cl TSRMLS_DC) 
 { 
     zend_class_entry* class_entry = cl.class_entry; 
-    zend_class_entry **parent; 
+    zend_class_entry* parent; 
     int status; 
  
     class_entry = 
@@ -78,14 +78,14 @@ 
             class_entry->parent = NULL; 
         } 
         else { 
-            class_entry->parent = *parent; 
+            class_entry->parent = parent; 
         } 
     } 
  
     status = zend_hash_add(EG(class_table), 
                            cl.name, 
                            cl.name_len+1, 
-                           &class_entry, 
+                           class_entry, 
                            sizeof(zend_class_entry), 
                            NULL); 
     return status; 
--- apc_optimizer.c	2004-05-04 18:16:27.000000000 +0530 
+++ ../APC-2.0.3orig/APC-2.0.3/apc_optimizer.c	2003-08-05 
00:32:31.000000000 +0530 
@@ -559,7 +559,8 @@ 
         zend_op* incr_op = &ops[j]; 
         zend_op* free_op = &ops[k]; 
  
-        if( load_op->op1.u.constant.type == IS_STRING       && 
+        if (load_op->op2.u.fetch_type == ZEND_FETCH_LOCAL   
&& 
+            load_op->op1.u.constant.type == IS_STRING       && 
             load_op->op1.op_type == IS_CONST                && 
             load_op->result.op_type != IS_CONST             && 
             incr_op->op1.op_type != IS_CONST                && 
@@ -603,7 +604,8 @@ 
         zend_op* incr_op = &ops[j]; 
         zend_op* free_op = &ops[k]; 
  
-        if (load_op->op1.u.constant.type == IS_STRING       && 
+        if (load_op->op2.u.fetch_type == ZEND_FETCH_LOCAL   
&& 
+            load_op->op1.u.constant.type == IS_STRING       && 
             load_op->op1.op_type == IS_CONST                && 
             load_op->result.op_type != IS_CONST             && 
             incr_op->op1.op_type != IS_CONST                && 
--- php_apc.c	2004-05-04 18:36:41.000000000 +0530 
+++ ../APC-2.0.3orig/APC-2.0.3/php_apc.c	2004-03-24 
21:19:13.000000000 +0530 
@@ -79,12 +79,12 @@ 
 } 
  
 PHP_INI_BEGIN() 
-STD_PHP_INI_ENTRY("apc.enabled",        "1",    
PHP_INI_SYSTEM, OnUpdateLong,            enabled,        
zend_apc_globals, apc_globals) 
-STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    
PHP_INI_SYSTEM, OnUpdateLong,            shm_segments,   
zend_apc_globals, apc_globals) 
-STD_PHP_INI_ENTRY("apc.shm_size",       "30",   
PHP_INI_SYSTEM, OnUpdateLong,            shm_size,       
zend_apc_globals, apc_globals) 
-STD_PHP_INI_ENTRY("apc.optimization",   "0",    
PHP_INI_SYSTEM, OnUpdateLong,            optimization,   
zend_apc_globals, apc_globals) 
-STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", 
PHP_INI_SYSTEM, OnUpdateLong,            num_files_hint, 
zend_apc_globals, apc_globals) 
-STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", 
PHP_INI_SYSTEM, OnUpdateLong,            gc_ttl,         
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.enabled",        "1",    
PHP_INI_SYSTEM, OnUpdateInt,            enabled,        
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    
PHP_INI_SYSTEM, OnUpdateInt,            shm_segments,   
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.shm_size",       "30",   
PHP_INI_SYSTEM, OnUpdateInt,            shm_size,       
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.optimization",   "0",    
PHP_INI_SYSTEM, OnUpdateInt,            optimization,   
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", 
PHP_INI_SYSTEM, OnUpdateInt,            num_files_hint, 
zend_apc_globals, apc_globals) 
+STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", 
PHP_INI_SYSTEM, OnUpdateInt,            gc_ttl,         
zend_apc_globals, apc_globals) 
 #if APC_MMAP 
 STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  
PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask, 
zend_apc_globals, apc_globals) 
 #endif 
 


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-06-30 09:25 UTC] gschlossnagle@php.net
This can't be functional.  You have no handling of 
constructor/destructors/clones/interfaces.  You've 
actually _removed_ support for some features.  Please 
don't bother submitting patches that don't even take a 
shot at implementing php5 OO support.  It wastes your 
time and mine.
 [2004-09-07 00:42 UTC] rasmus@php.net
This won't work
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 05:01:33 2024 UTC