mirror of
https://github.com/danog/ext-php-rs.git
synced 2024-12-11 08:40:10 +01:00
Add StreamWrapper API
This allows extensions to register and unregister custom stream wrappers
This commit is contained in:
parent
c9db20c2e9
commit
1c550852ab
@ -263,5 +263,13 @@ bind! {
|
||||
sapi_header_struct,
|
||||
zend_is_auto_global,
|
||||
zend_llist_get_next_ex,
|
||||
zend_llist_get_prev_ex
|
||||
zend_llist_get_prev_ex,
|
||||
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,
|
||||
zend_llist_get_prev_ex,
|
||||
php_stream_stdio_ops
|
||||
}
|
||||
|
@ -1986,6 +1986,36 @@ impl _php_stream {
|
||||
__bindgen_bitfield_unit
|
||||
}
|
||||
}
|
||||
extern "C" {
|
||||
pub static mut php_stream_stdio_ops: php_stream_ops;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn php_register_url_stream_wrapper(
|
||||
protocol: *const ::std::os::raw::c_char,
|
||||
wrapper: *const php_stream_wrapper,
|
||||
) -> zend_result;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn php_unregister_url_stream_wrapper(
|
||||
protocol: *const ::std::os::raw::c_char,
|
||||
) -> zend_result;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn php_register_url_stream_wrapper_volatile(
|
||||
protocol: *mut zend_string,
|
||||
wrapper: *mut php_stream_wrapper,
|
||||
) -> zend_result;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn php_unregister_url_stream_wrapper_volatile(protocol: *mut zend_string) -> zend_result;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn php_stream_locate_url_wrapper(
|
||||
path: *const ::std::os::raw::c_char,
|
||||
path_for_open: *mut *const ::std::os::raw::c_char,
|
||||
options: ::std::os::raw::c_int,
|
||||
) -> *mut php_stream_wrapper;
|
||||
}
|
||||
pub type php_core_globals = _php_core_globals;
|
||||
#[repr(C)]
|
||||
pub struct _php_core_globals {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ffi::{zend_execute_data, ZEND_MM_ALIGNMENT, ZEND_MM_ALIGNMENT_MASK};
|
||||
use crate::ffi::{zend_execute_data, ZEND_MM_ALIGNMENT, ZEND_MM_ALIGNMENT_MASK, _zend_function};
|
||||
|
||||
use crate::{
|
||||
args::ArgParser,
|
||||
@ -231,6 +231,18 @@ impl ExecuteData {
|
||||
let size = std::mem::size_of::<T>();
|
||||
((size as isize) + ZEND_MM_ALIGNMENT as isize - 1) & ZEND_MM_ALIGNMENT_MASK as isize
|
||||
}
|
||||
|
||||
pub fn previous(&self) -> Option<&Self> {
|
||||
unsafe {
|
||||
self.prev_execute_data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function(&self) -> Option<&_zend_function> {
|
||||
unsafe {
|
||||
self.func.as_ref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::{fmt::Debug, os::raw::c_char, ptr};
|
||||
|
||||
use crate::ffi::zend_function_entry;
|
||||
use crate::{ffi::{zend_function_entry, zend_function}, flags::FunctionType};
|
||||
|
||||
/// A Zend function entry.
|
||||
pub type FunctionEntry = zend_function_entry;
|
||||
@ -36,3 +36,11 @@ impl FunctionEntry {
|
||||
Box::into_raw(Box::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
pub type Function = zend_function;
|
||||
|
||||
impl Function {
|
||||
pub fn type_(&self) -> FunctionType {
|
||||
FunctionType::from(unsafe { self.type_ })
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ mod globals;
|
||||
mod handlers;
|
||||
mod linked_list;
|
||||
mod module;
|
||||
mod streams;
|
||||
|
||||
use crate::{error::Result, ffi::php_printf};
|
||||
use std::ffi::CString;
|
||||
@ -24,6 +25,7 @@ pub use globals::FileGlobals;
|
||||
pub use handlers::ZendObjectHandlers;
|
||||
pub use linked_list::ZendLinkedList;
|
||||
pub use module::ModuleEntry;
|
||||
pub use streams::*;
|
||||
|
||||
// Used as the format string for `php_printf`.
|
||||
const FORMAT_STR: &[u8] = b"%s\0";
|
||||
|
100
src/zend/streams.rs
Normal file
100
src/zend/streams.rs
Normal file
@ -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<Self, ()> {
|
||||
// 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<Self, ()> {
|
||||
// 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 {}
|
Loading…
Reference in New Issue
Block a user