mirror of
https://github.com/danog/ext-php-rs.git
synced 2025-01-22 13:01:24 +01:00
Support registering ini definitions for modules
PHP extensions that want to provide ini settings can do so using `IniEntryDef::register()`; values can then be fetched via `GlobalExecutor::ini_values()`.
This commit is contained in:
parent
8b87e4038e
commit
a7780753dc
@ -98,6 +98,8 @@ bind! {
|
||||
zend_objects_clone_members,
|
||||
zend_register_bool_constant,
|
||||
zend_register_double_constant,
|
||||
zend_register_ini_entries,
|
||||
zend_ini_entry_def,
|
||||
zend_register_internal_class_ex,
|
||||
zend_register_long_constant,
|
||||
zend_register_string_constant,
|
||||
@ -141,6 +143,10 @@ bind! {
|
||||
IS_PTR,
|
||||
MAY_BE_ANY,
|
||||
MAY_BE_BOOL,
|
||||
PHP_INI_USER,
|
||||
PHP_INI_PERDIR,
|
||||
PHP_INI_SYSTEM,
|
||||
PHP_INI_ALL,
|
||||
USING_ZTS,
|
||||
ZEND_ACC_ABSTRACT,
|
||||
ZEND_ACC_ANON_CLASS,
|
||||
|
@ -83,6 +83,10 @@ pub const ZEND_MODULE_API_NO: u32 = 20220829;
|
||||
pub const USING_ZTS: u32 = 0;
|
||||
pub const MAY_BE_BOOL: u32 = 12;
|
||||
pub const MAY_BE_ANY: u32 = 1022;
|
||||
pub const PHP_INI_USER: u32 = 1;
|
||||
pub const PHP_INI_PERDIR: u32 = 2;
|
||||
pub const PHP_INI_SYSTEM: u32 = 4;
|
||||
pub const PHP_INI_ALL: u32 = 7;
|
||||
pub const CONST_CS: u32 = 0;
|
||||
pub const CONST_PERSISTENT: u32 = 1;
|
||||
pub const CONST_NO_FILE_CACHE: u32 = 2;
|
||||
@ -1343,6 +1347,32 @@ extern "C" {
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct _zend_ini_entry_def {
|
||||
pub name: *const ::std::os::raw::c_char,
|
||||
pub on_modify: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
entry: *mut zend_ini_entry,
|
||||
new_value: *mut zend_string,
|
||||
mh_arg1: *mut ::std::os::raw::c_void,
|
||||
mh_arg2: *mut ::std::os::raw::c_void,
|
||||
mh_arg3: *mut ::std::os::raw::c_void,
|
||||
stage: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
pub mh_arg1: *mut ::std::os::raw::c_void,
|
||||
pub mh_arg2: *mut ::std::os::raw::c_void,
|
||||
pub mh_arg3: *mut ::std::os::raw::c_void,
|
||||
pub value: *const ::std::os::raw::c_char,
|
||||
pub displayer: ::std::option::Option<
|
||||
unsafe extern "C" fn(ini_entry: *mut zend_ini_entry, type_: ::std::os::raw::c_int),
|
||||
>,
|
||||
pub value_length: u32,
|
||||
pub name_length: u16,
|
||||
pub modifiable: u8,
|
||||
}
|
||||
pub type zend_ini_entry_def = _zend_ini_entry_def;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct _zend_ini_entry {
|
||||
pub name: *mut zend_string,
|
||||
pub on_modify: ::std::option::Option<
|
||||
@ -1368,6 +1398,12 @@ pub struct _zend_ini_entry {
|
||||
pub orig_modifiable: u8,
|
||||
pub modified: u8,
|
||||
}
|
||||
extern "C" {
|
||||
pub fn zend_register_ini_entries(
|
||||
ini_entry: *const zend_ini_entry_def,
|
||||
module_number: ::std::os::raw::c_int,
|
||||
) -> zend_result;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn zend_register_bool_constant(
|
||||
name: *const ::std::os::raw::c_char,
|
||||
|
19
src/flags.rs
19
src/flags.rs
@ -8,10 +8,11 @@ use crate::ffi::{
|
||||
CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, IS_ARRAY, IS_CALLABLE,
|
||||
IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR,
|
||||
IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED,
|
||||
IS_UNDEF, IS_VOID, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE,
|
||||
ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR,
|
||||
ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE,
|
||||
ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
|
||||
IS_UNDEF, IS_VOID, PHP_INI_ALL, PHP_INI_PERDIR, PHP_INI_SYSTEM, PHP_INI_USER,
|
||||
ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED,
|
||||
ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED,
|
||||
ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL,
|
||||
ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
|
||||
ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE,
|
||||
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
|
||||
ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
|
||||
@ -171,6 +172,16 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Represents permissions for where a configuration setting may be set.
|
||||
pub struct IniEntryPermission: u32 {
|
||||
const User = PHP_INI_USER;
|
||||
const PerDir = PHP_INI_PERDIR;
|
||||
const System = PHP_INI_SYSTEM;
|
||||
const All = PHP_INI_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
/// Valid data types for PHP.
|
||||
#[repr(C, u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_inheritance.h"
|
||||
#include "zend_interfaces.h"
|
||||
#include "zend_ini.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);
|
||||
|
@ -1,11 +1,12 @@
|
||||
//! Types related to the PHP executor globals.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use crate::boxed::ZBox;
|
||||
use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals};
|
||||
use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals, zend_ini_entry};
|
||||
|
||||
use crate::types::{ZendHashTable, ZendObject};
|
||||
|
||||
@ -50,6 +51,29 @@ impl ExecutorGlobals {
|
||||
unsafe { self.class_table.as_ref() }
|
||||
}
|
||||
|
||||
/// Retrieves the ini values for all ini directives in the current executor context..
|
||||
pub fn ini_values(&self) -> HashMap<String, Option<String>> {
|
||||
let hash_table = unsafe { self.ini_directives.as_ref().unwrap() };
|
||||
let mut ini_hash_map: HashMap<String, Option<String>> = HashMap::new();
|
||||
for (_index, key, value) in hash_table.iter() {
|
||||
match key {
|
||||
Some(key) => {
|
||||
ini_hash_map.insert(key, unsafe {
|
||||
let ini_entry = &*value.ptr::<zend_ini_entry>().unwrap();
|
||||
if ini_entry.value.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some((&*ini_entry.value).as_str().unwrap().to_owned())
|
||||
}
|
||||
});
|
||||
()
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
ini_hash_map
|
||||
}
|
||||
|
||||
/// Attempts to extract the last PHP exception captured by the interpreter.
|
||||
/// Returned inside a [`ZBox`].
|
||||
///
|
||||
|
57
src/zend/ini_entry_def.rs
Normal file
57
src/zend/ini_entry_def.rs
Normal file
@ -0,0 +1,57 @@
|
||||
//! Builder for creating inis and methods in PHP.
|
||||
//! See https://www.phpinternalsbook.com/php7/extensions_design/ini_settings.html for details.
|
||||
|
||||
use std::{ffi::CString, os::raw::c_char, ptr};
|
||||
|
||||
use crate::{ffi::zend_ini_entry_def, ffi::zend_register_ini_entries, flags::IniEntryPermission};
|
||||
|
||||
/// A Zend ini entry definition.
|
||||
///
|
||||
/// To register ini definitions for extensions, the IniEntryDef builder should be used. Ini
|
||||
/// entries should be registered in your module's startup_function via IniEntryDef::register(Vec<IniEntryDef>).
|
||||
pub type IniEntryDef = zend_ini_entry_def;
|
||||
|
||||
impl IniEntryDef {
|
||||
/// Returns an empty ini entry, signifying the end of a ini list.
|
||||
pub fn new(name: String, default_value: String, permission: IniEntryPermission) -> Self {
|
||||
let mut template = Self::end();
|
||||
let name = CString::new(name).unwrap();
|
||||
let value = CString::new(default_value).unwrap();
|
||||
template.name_length = name.as_bytes().len() as _;
|
||||
template.name = name.into_raw();
|
||||
template.value_length = value.as_bytes().len() as _;
|
||||
template.value = value.into_raw();
|
||||
template.modifiable = IniEntryPermission::PerDir.bits() as _;
|
||||
template.modifiable = permission.bits() as _;
|
||||
template
|
||||
}
|
||||
|
||||
/// Returns an empty ini entry def, signifying the end of a ini list.
|
||||
pub fn end() -> Self {
|
||||
Self {
|
||||
name: ptr::null() as *const c_char,
|
||||
on_modify: None,
|
||||
mh_arg1: std::ptr::null_mut(),
|
||||
mh_arg2: std::ptr::null_mut(),
|
||||
mh_arg3: std::ptr::null_mut(),
|
||||
value: std::ptr::null_mut(),
|
||||
displayer: None,
|
||||
modifiable: 0,
|
||||
value_length: 0,
|
||||
name_length: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the ini entry into a raw and pointer, releasing it to the
|
||||
/// C world.
|
||||
pub fn into_raw(self) -> *mut Self {
|
||||
Box::into_raw(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn register(mut entries: Vec<Self>, module_number: i32) {
|
||||
entries.push(Self::end());
|
||||
let entries = Box::into_raw(entries.into_boxed_slice()) as *const Self;
|
||||
|
||||
unsafe { zend_register_ini_entries(entries, module_number) };
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ mod ex;
|
||||
mod function;
|
||||
mod globals;
|
||||
mod handlers;
|
||||
mod ini_entry_def;
|
||||
mod module;
|
||||
|
||||
use crate::{error::Result, ffi::php_printf};
|
||||
@ -18,6 +19,7 @@ pub use ex::ExecuteData;
|
||||
pub use function::FunctionEntry;
|
||||
pub use globals::ExecutorGlobals;
|
||||
pub use handlers::ZendObjectHandlers;
|
||||
pub use ini_entry_def::IniEntryDef;
|
||||
pub use module::ModuleEntry;
|
||||
|
||||
// Used as the format string for `php_printf`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user