Skip to content

Commit a778075

Browse files
committed
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()`.
1 parent 8b87e40 commit a778075

File tree

7 files changed

+142
-5
lines changed

7 files changed

+142
-5
lines changed

allowed_bindings.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ bind! {
9898
zend_objects_clone_members,
9999
zend_register_bool_constant,
100100
zend_register_double_constant,
101+
zend_register_ini_entries,
102+
zend_ini_entry_def,
101103
zend_register_internal_class_ex,
102104
zend_register_long_constant,
103105
zend_register_string_constant,
@@ -141,6 +143,10 @@ bind! {
141143
IS_PTR,
142144
MAY_BE_ANY,
143145
MAY_BE_BOOL,
146+
PHP_INI_USER,
147+
PHP_INI_PERDIR,
148+
PHP_INI_SYSTEM,
149+
PHP_INI_ALL,
144150
USING_ZTS,
145151
ZEND_ACC_ABSTRACT,
146152
ZEND_ACC_ANON_CLASS,

docsrs_bindings.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ pub const ZEND_MODULE_API_NO: u32 = 20220829;
8383
pub const USING_ZTS: u32 = 0;
8484
pub const MAY_BE_BOOL: u32 = 12;
8585
pub const MAY_BE_ANY: u32 = 1022;
86+
pub const PHP_INI_USER: u32 = 1;
87+
pub const PHP_INI_PERDIR: u32 = 2;
88+
pub const PHP_INI_SYSTEM: u32 = 4;
89+
pub const PHP_INI_ALL: u32 = 7;
8690
pub const CONST_CS: u32 = 0;
8791
pub const CONST_PERSISTENT: u32 = 1;
8892
pub const CONST_NO_FILE_CACHE: u32 = 2;
@@ -1343,6 +1347,32 @@ extern "C" {
13431347
}
13441348
#[repr(C)]
13451349
#[derive(Debug, Copy, Clone)]
1350+
pub struct _zend_ini_entry_def {
1351+
pub name: *const ::std::os::raw::c_char,
1352+
pub on_modify: ::std::option::Option<
1353+
unsafe extern "C" fn(
1354+
entry: *mut zend_ini_entry,
1355+
new_value: *mut zend_string,
1356+
mh_arg1: *mut ::std::os::raw::c_void,
1357+
mh_arg2: *mut ::std::os::raw::c_void,
1358+
mh_arg3: *mut ::std::os::raw::c_void,
1359+
stage: ::std::os::raw::c_int,
1360+
) -> ::std::os::raw::c_int,
1361+
>,
1362+
pub mh_arg1: *mut ::std::os::raw::c_void,
1363+
pub mh_arg2: *mut ::std::os::raw::c_void,
1364+
pub mh_arg3: *mut ::std::os::raw::c_void,
1365+
pub value: *const ::std::os::raw::c_char,
1366+
pub displayer: ::std::option::Option<
1367+
unsafe extern "C" fn(ini_entry: *mut zend_ini_entry, type_: ::std::os::raw::c_int),
1368+
>,
1369+
pub value_length: u32,
1370+
pub name_length: u16,
1371+
pub modifiable: u8,
1372+
}
1373+
pub type zend_ini_entry_def = _zend_ini_entry_def;
1374+
#[repr(C)]
1375+
#[derive(Debug, Copy, Clone)]
13461376
pub struct _zend_ini_entry {
13471377
pub name: *mut zend_string,
13481378
pub on_modify: ::std::option::Option<
@@ -1368,6 +1398,12 @@ pub struct _zend_ini_entry {
13681398
pub orig_modifiable: u8,
13691399
pub modified: u8,
13701400
}
1401+
extern "C" {
1402+
pub fn zend_register_ini_entries(
1403+
ini_entry: *const zend_ini_entry_def,
1404+
module_number: ::std::os::raw::c_int,
1405+
) -> zend_result;
1406+
}
13711407
extern "C" {
13721408
pub fn zend_register_bool_constant(
13731409
name: *const ::std::os::raw::c_char,

src/flags.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ use crate::ffi::{
88
CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, IS_ARRAY, IS_CALLABLE,
99
IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR,
1010
IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED,
11-
IS_UNDEF, IS_VOID, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE,
12-
ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR,
13-
ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE,
14-
ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
11+
IS_UNDEF, IS_VOID, PHP_INI_ALL, PHP_INI_PERDIR, PHP_INI_SYSTEM, PHP_INI_USER,
12+
ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED,
13+
ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED,
14+
ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL,
15+
ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
1516
ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE,
1617
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
1718
ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
@@ -171,6 +172,16 @@ bitflags! {
171172
}
172173
}
173174

175+
bitflags! {
176+
/// Represents permissions for where a configuration setting may be set.
177+
pub struct IniEntryPermission: u32 {
178+
const User = PHP_INI_USER;
179+
const PerDir = PHP_INI_PERDIR;
180+
const System = PHP_INI_SYSTEM;
181+
const All = PHP_INI_ALL;
182+
}
183+
}
184+
174185
/// Valid data types for PHP.
175186
#[repr(C, u8)]
176187
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]

src/wrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "zend_exceptions.h"
2121
#include "zend_inheritance.h"
2222
#include "zend_interfaces.h"
23+
#include "zend_ini.h"
2324

2425
zend_string *ext_php_rs_zend_string_init(const char *str, size_t len, bool persistent);
2526
void ext_php_rs_zend_string_release(zend_string *zs);

src/zend/globals.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Types related to the PHP executor globals.
22
3+
use std::collections::HashMap;
34
use std::ops::{Deref, DerefMut};
45

56
use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard};
67

78
use crate::boxed::ZBox;
8-
use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals};
9+
use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals, zend_ini_entry};
910

1011
use crate::types::{ZendHashTable, ZendObject};
1112

@@ -50,6 +51,29 @@ impl ExecutorGlobals {
5051
unsafe { self.class_table.as_ref() }
5152
}
5253

54+
/// Retrieves the ini values for all ini directives in the current executor context..
55+
pub fn ini_values(&self) -> HashMap<String, Option<String>> {
56+
let hash_table = unsafe { self.ini_directives.as_ref().unwrap() };
57+
let mut ini_hash_map: HashMap<String, Option<String>> = HashMap::new();
58+
for (_index, key, value) in hash_table.iter() {
59+
match key {
60+
Some(key) => {
61+
ini_hash_map.insert(key, unsafe {
62+
let ini_entry = &*value.ptr::<zend_ini_entry>().unwrap();
63+
if ini_entry.value.is_null() {
64+
None
65+
} else {
66+
Some((&*ini_entry.value).as_str().unwrap().to_owned())
67+
}
68+
});
69+
()
70+
}
71+
None => (),
72+
}
73+
}
74+
ini_hash_map
75+
}
76+
5377
/// Attempts to extract the last PHP exception captured by the interpreter.
5478
/// Returned inside a [`ZBox`].
5579
///

src/zend/ini_entry_def.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Builder for creating inis and methods in PHP.
2+
//! See https://www.phpinternalsbook.com/php7/extensions_design/ini_settings.html for details.
3+
4+
use std::{ffi::CString, os::raw::c_char, ptr};
5+
6+
use crate::{ffi::zend_ini_entry_def, ffi::zend_register_ini_entries, flags::IniEntryPermission};
7+
8+
/// A Zend ini entry definition.
9+
///
10+
/// To register ini definitions for extensions, the IniEntryDef builder should be used. Ini
11+
/// entries should be registered in your module's startup_function via IniEntryDef::register(Vec<IniEntryDef>).
12+
pub type IniEntryDef = zend_ini_entry_def;
13+
14+
impl IniEntryDef {
15+
/// Returns an empty ini entry, signifying the end of a ini list.
16+
pub fn new(name: String, default_value: String, permission: IniEntryPermission) -> Self {
17+
let mut template = Self::end();
18+
let name = CString::new(name).unwrap();
19+
let value = CString::new(default_value).unwrap();
20+
template.name_length = name.as_bytes().len() as _;
21+
template.name = name.into_raw();
22+
template.value_length = value.as_bytes().len() as _;
23+
template.value = value.into_raw();
24+
template.modifiable = IniEntryPermission::PerDir.bits() as _;
25+
template.modifiable = permission.bits() as _;
26+
template
27+
}
28+
29+
/// Returns an empty ini entry def, signifying the end of a ini list.
30+
pub fn end() -> Self {
31+
Self {
32+
name: ptr::null() as *const c_char,
33+
on_modify: None,
34+
mh_arg1: std::ptr::null_mut(),
35+
mh_arg2: std::ptr::null_mut(),
36+
mh_arg3: std::ptr::null_mut(),
37+
value: std::ptr::null_mut(),
38+
displayer: None,
39+
modifiable: 0,
40+
value_length: 0,
41+
name_length: 0,
42+
}
43+
}
44+
45+
/// Converts the ini entry into a raw and pointer, releasing it to the
46+
/// C world.
47+
pub fn into_raw(self) -> *mut Self {
48+
Box::into_raw(Box::new(self))
49+
}
50+
51+
pub fn register(mut entries: Vec<Self>, module_number: i32) {
52+
entries.push(Self::end());
53+
let entries = Box::into_raw(entries.into_boxed_slice()) as *const Self;
54+
55+
unsafe { zend_register_ini_entries(entries, module_number) };
56+
}
57+
}

src/zend/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod ex;
77
mod function;
88
mod globals;
99
mod handlers;
10+
mod ini_entry_def;
1011
mod module;
1112

1213
use crate::{error::Result, ffi::php_printf};
@@ -18,6 +19,7 @@ pub use ex::ExecuteData;
1819
pub use function::FunctionEntry;
1920
pub use globals::ExecutorGlobals;
2021
pub use handlers::ZendObjectHandlers;
22+
pub use ini_entry_def::IniEntryDef;
2123
pub use module::ModuleEntry;
2224

2325
// Used as the format string for `php_printf`.

0 commit comments

Comments
 (0)