From ca04318cf8f2b04b258ae1c47c8b068b0e65050c Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 12 Jul 2023 20:05:37 +0200 Subject: [PATCH] Add support for SapiGlobals --- allowed_bindings.rs | 2 + docsrs_bindings.rs | 190 ++++++++++++-------------------------------- src/wrapper.c | 13 +++ src/wrapper.h | 2 + src/zend/globals.rs | 94 +++++++++++++++++++++- 5 files changed, 161 insertions(+), 140 deletions(-) diff --git a/allowed_bindings.rs b/allowed_bindings.rs index 3e1e7e7..cc17d5c 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -226,6 +226,8 @@ bind! { executor_globals, php_core_globals, core_globals, + sapi_globals_struct, + sapi_globals, php_printf, __zend_malloc, tsrm_get_ls_cache, diff --git a/docsrs_bindings.rs b/docsrs_bindings.rs index e030037..9d15781 100644 --- a/docsrs_bindings.rs +++ b/docsrs_bindings.rs @@ -1,7 +1,7 @@ /* automatically generated by rust-bindgen 0.65.1 */ -pub const ZEND_DEBUG: u32 = 1; -pub const _ZEND_TYPE_NAME_BIT: u32 = 16777216; +pub const ZEND_DEBUG: u32 = 0; +pub const _ZEND_TYPE_NAME_BIT: u32 = 8388608; pub const _ZEND_TYPE_NULLABLE_BIT: u32 = 2; pub const HT_MIN_SIZE: u32 = 8; pub const IS_UNDEF: u32 = 0; @@ -20,7 +20,7 @@ pub const IS_CALLABLE: u32 = 12; pub const IS_VOID: u32 = 14; pub const IS_MIXED: u32 = 16; pub const IS_PTR: u32 = 13; -pub const _IS_BOOL: u32 = 18; +pub const _IS_BOOL: u32 = 17; pub const Z_TYPE_FLAGS_SHIFT: u32 = 8; pub const IS_TYPE_REFCOUNTED: u32 = 1; pub const IS_TYPE_COLLECTABLE: u32 = 2; @@ -54,11 +54,13 @@ pub const ZEND_ACC_USE_GUARDS: u32 = 2048; pub const ZEND_ACC_CONSTANTS_UPDATED: u32 = 4096; pub const ZEND_ACC_NO_DYNAMIC_PROPERTIES: u32 = 8192; pub const ZEND_HAS_STATIC_IN_METHODS: u32 = 16384; +pub const ZEND_ACC_PROPERTY_TYPES_RESOLVED: u32 = 32768; +pub const ZEND_ACC_REUSE_GET_ITERATOR: u32 = 65536; pub const ZEND_ACC_RESOLVED_PARENT: u32 = 131072; pub const ZEND_ACC_RESOLVED_INTERFACES: u32 = 262144; pub const ZEND_ACC_UNRESOLVED_VARIANCE: u32 = 524288; pub const ZEND_ACC_NEARLY_LINKED: u32 = 1048576; -pub const ZEND_ACC_NOT_SERIALIZABLE: u32 = 536870912; +pub const ZEND_ACC_HAS_UNLINKED_USES: u32 = 2097152; pub const ZEND_ACC_DEPRECATED: u32 = 2048; pub const ZEND_ACC_RETURN_REFERENCE: u32 = 4096; pub const ZEND_ACC_HAS_RETURN_TYPE: u32 = 8192; @@ -77,9 +79,9 @@ pub const ZEND_ACC_DONE_PASS_TWO: u32 = 33554432; pub const ZEND_ACC_HEAP_RT_CACHE: u32 = 67108864; pub const ZEND_ACC_STRICT_TYPES: u32 = 2147483648; pub const ZEND_ISEMPTY: u32 = 1; -pub const _ZEND_SEND_MODE_SHIFT: u32 = 25; -pub const _ZEND_IS_VARIADIC_BIT: u32 = 134217728; -pub const ZEND_MODULE_API_NO: u32 = 20220829; +pub const _ZEND_SEND_MODE_SHIFT: u32 = 24; +pub const _ZEND_IS_VARIADIC_BIT: u32 = 67108864; +pub const ZEND_MODULE_API_NO: u32 = 20200930; pub const USING_ZTS: u32 = 0; pub const MAY_BE_BOOL: u32 = 12; pub const MAY_BE_ANY: u32 = 1022; @@ -180,6 +182,7 @@ pub union _zval_struct__bindgen_ty_2 { pub num_args: u32, pub fe_pos: u32, pub fe_iter_idx: u32, + pub access_flags: u32, pub property_guard: u32, pub constant_flags: u32, pub extra: u32, @@ -221,7 +224,7 @@ pub struct _zend_array { pub gc: zend_refcounted_h, pub u: _zend_array__bindgen_ty_1, pub nTableMask: u32, - pub __bindgen_anon_1: _zend_array__bindgen_ty_2, + pub arData: *mut Bucket, pub nNumUsed: u32, pub nNumOfElements: u32, pub nTableSize: u32, @@ -243,13 +246,6 @@ pub struct _zend_array__bindgen_ty_1__bindgen_ty_1 { pub nIteratorsCount: zend_uchar, pub _unused2: zend_uchar, } -#[repr(C)] -#[derive(Copy, Clone)] -pub union _zend_array__bindgen_ty_2 { - pub arHash: *mut u32, - pub arData: *mut Bucket, - pub arPacked: *mut zval, -} pub type HashPosition = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -271,7 +267,7 @@ pub struct _zend_object { #[derive(Copy, Clone)] pub struct _zend_resource { pub gc: zend_refcounted_h, - pub handle: zend_long, + pub handle: ::std::os::raw::c_int, pub type_: ::std::os::raw::c_int, pub ptr: *mut ::std::os::raw::c_void, } @@ -293,22 +289,10 @@ pub struct _zend_ast_ref { pub gc: zend_refcounted_h, } extern "C" { - pub fn _emalloc( - size: usize, - __zend_filename: *const ::std::os::raw::c_char, - __zend_lineno: u32, - __zend_orig_filename: *const ::std::os::raw::c_char, - __zend_orig_lineno: u32, - ) -> *mut ::std::os::raw::c_void; + pub fn _emalloc(size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { - pub fn _efree( - ptr: *mut ::std::os::raw::c_void, - __zend_filename: *const ::std::os::raw::c_char, - __zend_lineno: u32, - __zend_orig_filename: *const ::std::os::raw::c_char, - __zend_orig_lineno: u32, - ); + pub fn _efree(ptr: *mut ::std::os::raw::c_void); } extern "C" { pub fn __zend_malloc(len: usize) -> *mut ::std::os::raw::c_void; @@ -393,7 +377,7 @@ extern "C" { pub fn zend_hash_get_current_key_zval_ex( ht: *const HashTable, key: *mut zval, - pos: *const HashPosition, + pos: *mut HashPosition, ); } extern "C" { @@ -476,15 +460,6 @@ pub struct _zend_class_iterator_funcs { pub type zend_class_iterator_funcs = _zend_class_iterator_funcs; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct _zend_class_arrayaccess_funcs { - pub zf_offsetget: *mut zend_function, - pub zf_offsetexists: *mut zend_function, - pub zf_offsetset: *mut zend_function, - pub zf_offsetunset: *mut zend_function, -} -pub type zend_class_arrayaccess_funcs = _zend_class_arrayaccess_funcs; -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct _zend_serialize_data { _unused: [u8; 0], } @@ -528,44 +503,6 @@ pub struct _zend_trait_alias { } pub type zend_trait_alias = _zend_trait_alias; #[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_class_mutable_data { - pub default_properties_table: *mut zval, - pub constants_table: *mut HashTable, - pub ce_flags: u32, - pub backed_enum_table: *mut HashTable, -} -pub type zend_class_mutable_data = _zend_class_mutable_data; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_class_dependency { - pub name: *mut zend_string, - pub ce: *mut zend_class_entry, -} -pub type zend_class_dependency = _zend_class_dependency; -pub type zend_inheritance_cache_entry = _zend_inheritance_cache_entry; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_error_info { - pub type_: ::std::os::raw::c_int, - pub lineno: u32, - pub filename: *mut zend_string, - pub message: *mut zend_string, -} -pub type zend_error_info = _zend_error_info; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_inheritance_cache_entry { - pub next: *mut zend_inheritance_cache_entry, - pub ce: *mut zend_class_entry, - pub parent: *mut zend_class_entry, - pub dependencies: *mut zend_class_dependency, - pub dependencies_count: u32, - pub num_warnings: u32, - pub warnings: *mut *mut zend_error_info, - pub traits_and_interfaces: [*mut zend_class_entry; 1usize], -} -#[repr(C)] pub struct _zend_class_entry { pub type_: ::std::os::raw::c_char, pub name: *mut zend_string, @@ -576,12 +513,10 @@ pub struct _zend_class_entry { pub default_static_members_count: ::std::os::raw::c_int, pub default_properties_table: *mut zval, pub default_static_members_table: *mut zval, - pub static_members_table__ptr: *mut zval, + pub static_members_table__ptr: *mut *mut zval, pub function_table: HashTable, pub properties_info: HashTable, pub constants_table: HashTable, - pub mutable_data__ptr: *mut zend_class_mutable_data, - pub inheritance_cache: *mut zend_inheritance_cache_entry, pub properties_info_table: *mut *mut _zend_property_info, pub constructor: *mut zend_function, pub destructor: *mut zend_function, @@ -597,7 +532,6 @@ pub struct _zend_class_entry { pub __serialize: *mut zend_function, pub __unserialize: *mut zend_function, pub iterator_funcs_ptr: *mut zend_class_iterator_funcs, - pub arrayaccess_funcs_ptr: *mut zend_class_arrayaccess_funcs, pub __bindgen_anon_2: _zend_class_entry__bindgen_ty_2, pub get_iterator: ::std::option::Option< unsafe extern "C" fn( @@ -636,8 +570,6 @@ pub struct _zend_class_entry { pub trait_aliases: *mut *mut zend_trait_alias, pub trait_precedences: *mut *mut zend_trait_precedence, pub attributes: *mut HashTable, - pub enum_backing_type: u32, - pub backed_enum_table: *mut HashTable, pub info: _zend_class_entry__bindgen_ty_4, } #[repr(C)] @@ -779,10 +711,10 @@ pub type zend_object_get_method_t = ::std::option::Option< >; pub type zend_object_get_constructor_t = ::std::option::Option *mut zend_function>; -pub type zend_object_free_obj_t = - ::std::option::Option; pub type zend_object_dtor_obj_t = ::std::option::Option; +pub type zend_object_free_obj_t = + ::std::option::Option; pub type zend_object_clone_obj_t = ::std::option::Option *mut zend_object>; pub type zend_object_get_class_name_t = @@ -795,10 +727,10 @@ pub type zend_object_cast_t = ::std::option::Option< readobj: *mut zend_object, retval: *mut zval, type_: ::std::os::raw::c_int, - ) -> zend_result, + ) -> ::std::os::raw::c_int, >; pub type zend_object_count_elements_t = ::std::option::Option< - unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> zend_result, + unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> ::std::os::raw::c_int, >; pub type zend_object_get_closure_t = ::std::option::Option< unsafe extern "C" fn( @@ -806,8 +738,8 @@ pub type zend_object_get_closure_t = ::std::option::Option< ce_ptr: *mut *mut zend_class_entry, fptr_ptr: *mut *mut zend_function, obj_ptr: *mut *mut zend_object, - check_only: bool, - ) -> zend_result, + check_only: zend_bool, + ) -> ::std::os::raw::c_int, >; pub type zend_object_get_gc_t = ::std::option::Option< unsafe extern "C" fn( @@ -822,7 +754,7 @@ pub type zend_object_do_operation_t = ::std::option::Option< result: *mut zval, op1: *mut zval, op2: *mut zval, - ) -> zend_result, + ) -> ::std::os::raw::c_int, >; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -885,7 +817,7 @@ extern "C" { ) -> ::std::os::raw::c_int; } extern "C" { - pub fn zend_is_identical(op1: *mut zval, op2: *mut zval) -> bool; + pub fn zend_is_identical(op1: *mut zval, op2: *mut zval) -> zend_bool; } extern "C" { pub fn zend_is_true(op: *mut zval) -> ::std::os::raw::c_int; @@ -973,13 +905,13 @@ pub struct _zend_op_array { pub required_num_args: u32, pub arg_info: *mut zend_arg_info, pub attributes: *mut HashTable, - pub T: u32, - pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, pub cache_size: ::std::os::raw::c_int, pub last_var: ::std::os::raw::c_int, + pub T: u32, pub last: u32, pub opcodes: *mut zend_op, - pub static_variables_ptr__ptr: *mut HashTable, + pub run_time_cache__ptr: *mut *mut *mut ::std::os::raw::c_void, + pub static_variables_ptr__ptr: *mut *mut HashTable, pub static_variables: *mut HashTable, pub vars: *mut *mut zend_string, pub refcount: *mut u32, @@ -992,9 +924,7 @@ pub struct _zend_op_array { pub line_end: u32, pub doc_comment: *mut zend_string, pub last_literal: ::std::os::raw::c_int, - pub num_dynamic_func_defs: u32, pub literals: *mut zval, - pub dynamic_func_defs: *mut *mut zend_op_array, pub reserved: [*mut ::std::os::raw::c_void; 6usize], } pub type zif_handler = ::std::option::Option< @@ -1013,8 +943,6 @@ pub struct _zend_internal_function { pub required_num_args: u32, pub arg_info: *mut zend_internal_arg_info, pub attributes: *mut HashTable, - pub T: u32, - pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, pub handler: zif_handler, pub module: *mut _zend_module_entry, pub reserved: [*mut ::std::os::raw::c_void; 6usize], @@ -1042,8 +970,6 @@ pub struct _zend_function__bindgen_ty_1 { pub required_num_args: u32, pub arg_info: *mut zend_arg_info, pub attributes: *mut HashTable, - pub T: u32, - pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, } #[repr(C)] pub struct _zend_execute_data { @@ -1064,12 +990,6 @@ extern "C" { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct zend_atomic_bool_s { - pub value: u8, -} -pub type zend_atomic_bool = zend_atomic_bool_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct _zend_stack { pub size: ::std::os::raw::c_int, pub top: ::std::os::raw::c_int, @@ -1104,18 +1024,6 @@ extern "C" { pub type zend_vm_stack = *mut _zend_vm_stack; pub type zend_ini_entry = _zend_ini_entry; #[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_fiber_context { - _unused: [u8; 0], -} -pub type zend_fiber_context = _zend_fiber_context; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _zend_fiber { - _unused: [u8; 0], -} -pub type zend_fiber = _zend_fiber; -#[repr(C)] pub struct _zend_executor_globals { pub uninitialized_zval: zval, pub error_zval: zval, @@ -1143,10 +1051,10 @@ pub struct _zend_executor_globals { pub persistent_functions_count: u32, pub persistent_classes_count: u32, pub in_autoload: *mut HashTable, - pub full_tables_cleanup: bool, - pub no_extensions: bool, - pub vm_interrupt: zend_atomic_bool, - pub timed_out: zend_atomic_bool, + pub full_tables_cleanup: zend_bool, + pub no_extensions: zend_bool, + pub vm_interrupt: zend_bool, + pub timed_out: zend_bool, pub hard_timeout: zend_long, pub regular_list: HashTable, pub persistent_list: HashTable, @@ -1159,7 +1067,7 @@ pub struct _zend_executor_globals { pub error_handling: zend_error_handling_t, pub exception_class: *mut zend_class_entry, pub timeout_seconds: zend_long, - pub capture_warnings_during_sccp: ::std::os::raw::c_int, + pub lambda_count: ::std::os::raw::c_int, pub ini_directives: *mut HashTable, pub modified_ini_directives: *mut HashTable, pub error_reporting_ini_entry: *mut zend_ini_entry, @@ -1169,7 +1077,7 @@ pub struct _zend_executor_globals { pub opline_before_exception: *const zend_op, pub exception_op: [zend_op; 3usize], pub current_module: *mut _zend_module_entry, - pub active: bool, + pub active: zend_bool, pub flags: zend_uchar, pub assertions: zend_long, pub ht_iterators_count: u32, @@ -1180,18 +1088,9 @@ pub struct _zend_executor_globals { pub trampoline: zend_function, pub call_trampoline_op: zend_op, pub weakrefs: HashTable, - pub exception_ignore_args: bool, + pub exception_ignore_args: zend_bool, pub exception_string_param_max_len: zend_long, pub get_gc_buffer: zend_get_gc_buffer, - pub main_fiber_context: *mut zend_fiber_context, - pub current_fiber_context: *mut zend_fiber_context, - pub active_fiber: *mut zend_fiber, - pub fiber_stack_size: zend_long, - pub record_errors: bool, - pub num_errors: u32, - pub errors: *mut *mut zend_error_info, - pub filename_override: *mut zend_string, - pub lineno_override: zend_long, pub reserved: [*mut ::std::os::raw::c_void; 6usize], } pub type zend_module_entry = _zend_module_entry; @@ -1288,7 +1187,7 @@ extern "C" { callable: *mut zval, check_flags: u32, callable_name: *mut *mut zend_string, - ) -> bool; + ) -> zend_bool; } extern "C" { pub fn zend_declare_property( @@ -1491,7 +1390,7 @@ extern "C" { pub fn zend_register_bool_constant( name: *const ::std::os::raw::c_char, name_len: usize, - bval: bool, + bval: zend_bool, flags: ::std::os::raw::c_int, module_number: ::std::os::raw::c_int, ); @@ -1600,3 +1499,20 @@ extern "C" { extern "C" { pub static mut zend_ce_stringable: *mut zend_class_entry; } +extern "C" { + pub fn zend_class_serialize_deny( + object: *mut zval, + buffer: *mut *mut ::std::os::raw::c_uchar, + buf_len: *mut usize, + data: *mut zend_serialize_data, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn zend_class_unserialize_deny( + object: *mut zval, + ce: *mut zend_class_entry, + buf: *const ::std::os::raw::c_uchar, + buf_len: usize, + data: *mut zend_unserialize_data, + ) -> ::std::os::raw::c_int; +} diff --git a/src/wrapper.c b/src/wrapper.c index 7a5eba5..514882b 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -51,3 +51,16 @@ php_core_globals *ext_php_rs_process_globals() { return &core_globals; #endif } + + +sapi_globals_struct *ext_php_rs_sapi_globals() { +#ifdef ZTS +#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE + return TSRMG_FAST_BULK_STATIC(sapi_globals_offset, sapi_globals_struct); +#else + return TSRMG_FAST_BULK(sapi_globals_offset, sapi_globals_struct *); +#endif +#else + return &sapi_globals; +#endif +} diff --git a/src/wrapper.h b/src/wrapper.h index c00ab5b..0fb8287 100644 --- a/src/wrapper.h +++ b/src/wrapper.h @@ -20,6 +20,7 @@ #include "zend_exceptions.h" #include "zend_inheritance.h" #include "zend_interfaces.h" +#include "SAPI.h" zend_string *ext_php_rs_zend_string_init(const char *str, size_t len, bool persistent); void ext_php_rs_zend_string_release(zend_string *zs); @@ -31,3 +32,4 @@ void *ext_php_rs_zend_object_alloc(size_t obj_size, zend_class_entry *ce); void ext_php_rs_zend_object_release(zend_object *obj); zend_executor_globals *ext_php_rs_executor_globals(); php_core_globals *ext_php_rs_process_globals(); +sapi_globals_struct *ext_php_rs_sapi_globals(); diff --git a/src/zend/globals.rs b/src/zend/globals.rs index 7ed5eef..abf3eef 100644 --- a/src/zend/globals.rs +++ b/src/zend/globals.rs @@ -6,9 +6,9 @@ use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::boxed::ZBox; use crate::ffi::{ - _zend_executor_globals, ext_php_rs_executor_globals, ext_php_rs_process_globals, - php_core_globals, TRACK_VARS_COOKIE, TRACK_VARS_ENV, TRACK_VARS_FILES, TRACK_VARS_GET, - TRACK_VARS_POST, TRACK_VARS_REQUEST, TRACK_VARS_SERVER, + _zend_executor_globals, ext_php_rs_executor_globals, ext_php_rs_process_globals, ext_php_rs_sapi_globals, + php_core_globals, sapi_globals_struct, TRACK_VARS_COOKIE, TRACK_VARS_ENV, TRACK_VARS_FILES, TRACK_VARS_GET, + TRACK_VARS_POST, TRACK_VARS_REQUEST, TRACK_VARS_SERVER }; use crate::types::{ZendHashTable, ZendObject}; @@ -157,12 +157,100 @@ impl ProcessGlobals { } } + +/// Stores global variables used in the SAPI. +pub type SapiGlobals = sapi_globals_struct; + +impl SapiGlobals { + /// Returns a reference to the PHP process globals. + /// + /// The process globals are guarded by a RwLock. There can be multiple + /// immutable references at one time but only ever one mutable reference. + /// Attempting to retrieve the globals while already holding the global + /// guard will lead to a deadlock. Dropping the globals guard will release + /// the lock. + pub fn get() -> GlobalReadGuard { + // SAFETY: PHP executor globals are statically declared therefore should never + // return an invalid pointer. + let globals = unsafe { &*ext_php_rs_sapi_globals() }; + let guard = SAPI_GLOBALS_LOCK.read(); + GlobalReadGuard { globals, guard } + } + + /// Returns a mutable reference to the PHP executor globals. + /// + /// The executor globals are guarded by a RwLock. There can be multiple + /// immutable references at one time but only ever one mutable reference. + /// Attempting to retrieve the globals while already holding the global + /// guard will lead to a deadlock. Dropping the globals guard will release + /// the lock. + pub fn get_mut() -> GlobalWriteGuard { + // SAFETY: PHP executor globals are statically declared therefore should never + // return an invalid pointer. + let globals = unsafe { &mut *ext_php_rs_sapi_globals() }; + let guard = SAPI_GLOBALS_LOCK.write(); + GlobalWriteGuard { globals, guard } + } + + /// Get the HTTP Server variables. Equivalent of $_SERVER. + pub fn http_server_vars(&self) -> Option<&ZendHashTable> { + if self.http_globals[TRACK_VARS_SERVER as usize].is_array() { + self.http_globals[TRACK_VARS_SERVER as usize].array() + } else { + None + } + } + + /// Get the HTTP POST variables. Equivalent of $_POST. + pub fn http_post_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_POST as usize] + .array() + .expect("Type is not a ZendArray") + } + + /// Get the HTTP GET variables. Equivalent of $_GET. + pub fn http_get_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_GET as usize] + .array() + .expect("Type is not a ZendArray") + } + + /// Get the HTTP Cookie variables. Equivalent of $_COOKIE. + pub fn http_cookie_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_COOKIE as usize] + .array() + .expect("Type is not a ZendArray") + } + + /// Get the HTTP Request variables. Equivalent of $_REQUEST. + pub fn http_request_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_REQUEST as usize] + .array() + .expect("Type is not a ZendArray") + } + + /// Get the HTTP Environment variables. Equivalent of $_ENV. + pub fn http_env_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_ENV as usize] + .array() + .expect("Type is not a ZendArray") + } + + /// Get the HTTP Files variables. Equivalent of $_FILES. + pub fn http_files_vars(&self) -> &ZendHashTable { + self.http_globals[TRACK_VARS_FILES as usize] + .array() + .expect("Type is not a ZendArray") + } +} + /// Executor globals rwlock. /// /// PHP provides no indication if the executor globals are being accessed so /// this is only effective on the Rust side. static GLOBALS_LOCK: RwLock<()> = const_rwlock(()); static PROCESS_GLOBALS_LOCK: RwLock<()> = const_rwlock(()); +static SAPI_GLOBALS_LOCK: RwLock<()> = const_rwlock(()); /// Wrapper guard that contains a reference to a given type `T`. Dropping a /// guard releases the lock on the relevant rwlock.