diff --git a/allowed_bindings.rs b/allowed_bindings.rs index 427a6fa..62e7ca9 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -284,7 +284,13 @@ bind! { zend_is_auto_global, zend_llist_get_next_ex, zend_llist_get_prev_ex, - sapi_globals_offset, + php_register_url_stream_wrapper, + php_stream_locate_url_wrapper, + php_unregister_url_stream_wrapper, + php_unregister_url_stream_wrapper_volatile, + php_register_url_stream_wrapper_volatile, + php_stream_wrapper, + php_stream_stdio_ops, zend_atomic_bool_store, zend_interrupt_function, zend_eval_string, diff --git a/src/zend/ex.rs b/src/zend/ex.rs index cb389cb..1658e7f 100644 --- a/src/zend/ex.rs +++ b/src/zend/ex.rs @@ -1,4 +1,4 @@ -use crate::ffi::{zend_execute_data, ZEND_MM_ALIGNMENT, ZEND_MM_ALIGNMENT_MASK}; +use crate::ffi::{_zend_function, zend_execute_data, ZEND_MM_ALIGNMENT, ZEND_MM_ALIGNMENT_MASK}; use crate::{ args::ArgParser, diff --git a/src/zend/mod.rs b/src/zend/mod.rs index 099374a..a2308a4 100644 --- a/src/zend/mod.rs +++ b/src/zend/mod.rs @@ -11,6 +11,7 @@ mod ini_entry_def; mod linked_list; mod module; mod try_catch; +mod streams; use crate::{ error::Result, @@ -35,6 +36,7 @@ pub use module::ModuleEntry; #[cfg(feature = "embed")] pub(crate) use try_catch::panic_wrapper; pub use try_catch::{bailout, try_catch}; +pub use streams::*; // Used as the format string for `php_printf`. const FORMAT_STR: &[u8] = b"%s\0"; diff --git a/src/zend/streams.rs b/src/zend/streams.rs new file mode 100644 index 0000000..1045a0c --- /dev/null +++ b/src/zend/streams.rs @@ -0,0 +1,100 @@ +use std::ptr::{self, NonNull}; + +use crate::{ + ffi::{ + php_register_url_stream_wrapper, php_register_url_stream_wrapper_volatile, php_stream, + php_stream_context, php_stream_locate_url_wrapper, php_stream_wrapper, + php_stream_wrapper_ops, php_unregister_url_stream_wrapper, + php_unregister_url_stream_wrapper_volatile, zend_string, + }, + types::ZendStr, +}; + +pub type StreamWrapper = php_stream_wrapper; + +pub type StreamOpener = unsafe extern "C" fn( + *mut StreamWrapper, + *const std::ffi::c_char, + *const std::ffi::c_char, + i32, + *mut *mut zend_string, + *mut php_stream_context, + i32, + *const std::ffi::c_char, + u32, + *const std::ffi::c_char, + u32, +) -> *mut Stream; + +impl StreamWrapper { + pub fn get(name: &str) -> Option<&Self> { + unsafe { + let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0); + Some(NonNull::new(result)?.as_ref()) + } + } + + pub fn get_mut(name: &str) -> Option<&mut Self> { + unsafe { + let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0); + Some(NonNull::new(result)?.as_mut()) + } + } + + pub fn register(self, name: &str) -> Result { + // We have to convert it to a static so owned streamwrapper doesn't get dropped. + let copy = Box::new(self); + let copy = Box::leak(copy); + let name = std::ffi::CString::new(name).unwrap(); + let result = unsafe { php_register_url_stream_wrapper(name.as_ptr(), copy) }; + if result == 0 { + Ok(*copy) + } else { + Err(()) + } + } + + pub fn register_volatile(self, name: &str) -> Result { + // We have to convert it to a static so owned streamwrapper doesn't get dropped. + let copy = Box::new(self); + let copy = Box::leak(copy); + let name = ZendStr::new(name, false); + let result = + unsafe { php_register_url_stream_wrapper_volatile((*name).as_ptr() as _, copy) }; + if result == 0 { + Ok(*copy) + } else { + Err(()) + } + } + + pub fn unregister(name: &str) -> Result<(), ()> { + let name = std::ffi::CString::new(name).unwrap(); + match unsafe { php_unregister_url_stream_wrapper(name.as_ptr()) } { + 0 => Ok(()), + _ => Err(()), + } + } + + pub fn unregister_volatile(name: &str) -> Result<(), ()> { + let name = ZendStr::new(name, false); + match unsafe { php_unregister_url_stream_wrapper_volatile((*name).as_ptr() as _) } { + 0 => Ok(()), + _ => Err(()), + } + } + + pub fn wops(&self) -> &php_stream_wrapper_ops { + unsafe { &*self.wops } + } + + pub fn wops_mut(&mut self) -> &mut php_stream_wrapper_ops { + unsafe { &mut *(self.wops as *mut php_stream_wrapper_ops) } + } +} + +pub type Stream = php_stream; + +pub type StreamWrapperOps = php_stream_wrapper_ops; + +impl StreamWrapperOps {}