Skip to content

Commit b876077

Browse files
authored
Merge pull request #278 from joelwurtz/feat/sapi
[Feature] custom SAPI
2 parents f9a3bea + 3cb7b8f commit b876077

File tree

16 files changed

+439
-122
lines changed

16 files changed

+439
-122
lines changed

allowed_bindings.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,14 @@ bind! {
294294
zend_eval_string,
295295
zend_file_handle,
296296
zend_stream_init_filename,
297+
zend_destroy_file_handle,
297298
php_execute_script,
298299
zend_register_module_ex,
299-
_zend_bailout
300+
_zend_bailout,
301+
sapi_startup,
302+
sapi_shutdown,
303+
php_module_startup,
304+
php_module_shutdown,
305+
php_request_startup,
306+
php_request_shutdown
300307
}

docsrs_bindings.rs

Lines changed: 138 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,9 @@ extern "C" {
746746
filename: *const ::std::os::raw::c_char,
747747
);
748748
}
749+
extern "C" {
750+
pub fn zend_destroy_file_handle(file_handle: *mut zend_file_handle);
751+
}
749752
pub type zend_stat_t = stat;
750753
#[repr(C)]
751754
#[derive(Debug, Copy, Clone)]
@@ -2333,117 +2336,6 @@ extern "C" {
23332336
module_number: ::std::os::raw::c_int,
23342337
);
23352338
}
2336-
extern "C" {
2337-
pub fn php_info_print_table_header(num_cols: ::std::os::raw::c_int, ...);
2338-
}
2339-
extern "C" {
2340-
pub fn php_info_print_table_row(num_cols: ::std::os::raw::c_int, ...);
2341-
}
2342-
extern "C" {
2343-
pub fn php_info_print_table_start();
2344-
}
2345-
extern "C" {
2346-
pub fn php_info_print_table_end();
2347-
}
2348-
#[repr(C)]
2349-
#[derive(Debug, Copy, Clone)]
2350-
pub struct hostent {
2351-
pub h_name: *mut ::std::os::raw::c_char,
2352-
pub h_aliases: *mut *mut ::std::os::raw::c_char,
2353-
pub h_addrtype: ::std::os::raw::c_int,
2354-
pub h_length: ::std::os::raw::c_int,
2355-
pub h_addr_list: *mut *mut ::std::os::raw::c_char,
2356-
}
2357-
#[repr(C)]
2358-
#[derive(Debug, Copy, Clone)]
2359-
pub struct php_file_globals {
2360-
pub pclose_ret: ::std::os::raw::c_int,
2361-
pub def_chunk_size: usize,
2362-
pub auto_detect_line_endings: bool,
2363-
pub default_socket_timeout: zend_long,
2364-
pub user_agent: *mut ::std::os::raw::c_char,
2365-
pub from_address: *mut ::std::os::raw::c_char,
2366-
pub user_stream_current_filename: *const ::std::os::raw::c_char,
2367-
pub default_context: *mut php_stream_context,
2368-
pub stream_wrappers: *mut HashTable,
2369-
pub stream_filters: *mut HashTable,
2370-
pub wrapper_errors: *mut HashTable,
2371-
pub pclose_wait: ::std::os::raw::c_int,
2372-
pub tmp_host_info: hostent,
2373-
pub tmp_host_buf: *mut ::std::os::raw::c_char,
2374-
pub tmp_host_buf_len: usize,
2375-
}
2376-
extern "C" {
2377-
pub static mut file_globals: php_file_globals;
2378-
}
2379-
extern "C" {
2380-
pub static mut zend_ce_throwable: *mut zend_class_entry;
2381-
}
2382-
extern "C" {
2383-
pub static mut zend_ce_exception: *mut zend_class_entry;
2384-
}
2385-
extern "C" {
2386-
pub static mut zend_ce_error_exception: *mut zend_class_entry;
2387-
}
2388-
extern "C" {
2389-
pub static mut zend_ce_compile_error: *mut zend_class_entry;
2390-
}
2391-
extern "C" {
2392-
pub static mut zend_ce_parse_error: *mut zend_class_entry;
2393-
}
2394-
extern "C" {
2395-
pub static mut zend_ce_type_error: *mut zend_class_entry;
2396-
}
2397-
extern "C" {
2398-
pub static mut zend_ce_argument_count_error: *mut zend_class_entry;
2399-
}
2400-
extern "C" {
2401-
pub static mut zend_ce_value_error: *mut zend_class_entry;
2402-
}
2403-
extern "C" {
2404-
pub static mut zend_ce_arithmetic_error: *mut zend_class_entry;
2405-
}
2406-
extern "C" {
2407-
pub static mut zend_ce_division_by_zero_error: *mut zend_class_entry;
2408-
}
2409-
extern "C" {
2410-
pub static mut zend_ce_unhandled_match_error: *mut zend_class_entry;
2411-
}
2412-
extern "C" {
2413-
pub fn zend_throw_exception_ex(
2414-
exception_ce: *mut zend_class_entry,
2415-
code: zend_long,
2416-
format: *const ::std::os::raw::c_char,
2417-
...
2418-
) -> *mut zend_object;
2419-
}
2420-
extern "C" {
2421-
pub fn zend_throw_exception_object(exception: *mut zval);
2422-
}
2423-
extern "C" {
2424-
pub fn zend_do_implement_interface(ce: *mut zend_class_entry, iface: *mut zend_class_entry);
2425-
}
2426-
extern "C" {
2427-
pub static mut zend_ce_traversable: *mut zend_class_entry;
2428-
}
2429-
extern "C" {
2430-
pub static mut zend_ce_aggregate: *mut zend_class_entry;
2431-
}
2432-
extern "C" {
2433-
pub static mut zend_ce_iterator: *mut zend_class_entry;
2434-
}
2435-
extern "C" {
2436-
pub static mut zend_ce_arrayaccess: *mut zend_class_entry;
2437-
}
2438-
extern "C" {
2439-
pub static mut zend_ce_serializable: *mut zend_class_entry;
2440-
}
2441-
extern "C" {
2442-
pub static mut zend_ce_countable: *mut zend_class_entry;
2443-
}
2444-
extern "C" {
2445-
pub static mut zend_ce_stringable: *mut zend_class_entry;
2446-
}
24472339
#[repr(C)]
24482340
#[derive(Debug, Copy, Clone)]
24492341
pub struct sapi_header_struct {
@@ -2514,6 +2406,12 @@ pub type sapi_globals_struct = _sapi_globals_struct;
25142406
extern "C" {
25152407
pub static mut sapi_globals: sapi_globals_struct;
25162408
}
2409+
extern "C" {
2410+
pub fn sapi_startup(sf: *mut sapi_module_struct);
2411+
}
2412+
extern "C" {
2413+
pub fn sapi_shutdown();
2414+
}
25172415
pub const sapi_header_op_enum_SAPI_HEADER_REPLACE: sapi_header_op_enum = 0;
25182416
pub const sapi_header_op_enum_SAPI_HEADER_ADD: sapi_header_op_enum = 1;
25192417
pub const sapi_header_op_enum_SAPI_HEADER_DELETE: sapi_header_op_enum = 2;
@@ -2632,3 +2530,132 @@ pub struct _sapi_post_entry {
26322530
),
26332531
>,
26342532
}
2533+
extern "C" {
2534+
pub fn php_request_startup() -> zend_result;
2535+
}
2536+
extern "C" {
2537+
pub fn php_request_shutdown(dummy: *mut ::std::os::raw::c_void);
2538+
}
2539+
extern "C" {
2540+
pub fn php_module_startup(
2541+
sf: *mut sapi_module_struct,
2542+
additional_module: *mut zend_module_entry,
2543+
) -> zend_result;
2544+
}
2545+
extern "C" {
2546+
pub fn php_module_shutdown();
2547+
}
2548+
extern "C" {
2549+
pub fn php_execute_script(primary_file: *mut zend_file_handle) -> bool;
2550+
}
2551+
extern "C" {
2552+
pub fn php_info_print_table_header(num_cols: ::std::os::raw::c_int, ...);
2553+
}
2554+
extern "C" {
2555+
pub fn php_info_print_table_row(num_cols: ::std::os::raw::c_int, ...);
2556+
}
2557+
extern "C" {
2558+
pub fn php_info_print_table_start();
2559+
}
2560+
extern "C" {
2561+
pub fn php_info_print_table_end();
2562+
}
2563+
#[repr(C)]
2564+
#[derive(Debug, Copy, Clone)]
2565+
pub struct hostent {
2566+
pub h_name: *mut ::std::os::raw::c_char,
2567+
pub h_aliases: *mut *mut ::std::os::raw::c_char,
2568+
pub h_addrtype: ::std::os::raw::c_int,
2569+
pub h_length: ::std::os::raw::c_int,
2570+
pub h_addr_list: *mut *mut ::std::os::raw::c_char,
2571+
}
2572+
#[repr(C)]
2573+
#[derive(Debug, Copy, Clone)]
2574+
pub struct php_file_globals {
2575+
pub pclose_ret: ::std::os::raw::c_int,
2576+
pub def_chunk_size: usize,
2577+
pub auto_detect_line_endings: bool,
2578+
pub default_socket_timeout: zend_long,
2579+
pub user_agent: *mut ::std::os::raw::c_char,
2580+
pub from_address: *mut ::std::os::raw::c_char,
2581+
pub user_stream_current_filename: *const ::std::os::raw::c_char,
2582+
pub default_context: *mut php_stream_context,
2583+
pub stream_wrappers: *mut HashTable,
2584+
pub stream_filters: *mut HashTable,
2585+
pub wrapper_errors: *mut HashTable,
2586+
pub pclose_wait: ::std::os::raw::c_int,
2587+
pub tmp_host_info: hostent,
2588+
pub tmp_host_buf: *mut ::std::os::raw::c_char,
2589+
pub tmp_host_buf_len: usize,
2590+
}
2591+
extern "C" {
2592+
pub static mut file_globals: php_file_globals;
2593+
}
2594+
extern "C" {
2595+
pub static mut zend_ce_throwable: *mut zend_class_entry;
2596+
}
2597+
extern "C" {
2598+
pub static mut zend_ce_exception: *mut zend_class_entry;
2599+
}
2600+
extern "C" {
2601+
pub static mut zend_ce_error_exception: *mut zend_class_entry;
2602+
}
2603+
extern "C" {
2604+
pub static mut zend_ce_compile_error: *mut zend_class_entry;
2605+
}
2606+
extern "C" {
2607+
pub static mut zend_ce_parse_error: *mut zend_class_entry;
2608+
}
2609+
extern "C" {
2610+
pub static mut zend_ce_type_error: *mut zend_class_entry;
2611+
}
2612+
extern "C" {
2613+
pub static mut zend_ce_argument_count_error: *mut zend_class_entry;
2614+
}
2615+
extern "C" {
2616+
pub static mut zend_ce_value_error: *mut zend_class_entry;
2617+
}
2618+
extern "C" {
2619+
pub static mut zend_ce_arithmetic_error: *mut zend_class_entry;
2620+
}
2621+
extern "C" {
2622+
pub static mut zend_ce_division_by_zero_error: *mut zend_class_entry;
2623+
}
2624+
extern "C" {
2625+
pub static mut zend_ce_unhandled_match_error: *mut zend_class_entry;
2626+
}
2627+
extern "C" {
2628+
pub fn zend_throw_exception_ex(
2629+
exception_ce: *mut zend_class_entry,
2630+
code: zend_long,
2631+
format: *const ::std::os::raw::c_char,
2632+
...
2633+
) -> *mut zend_object;
2634+
}
2635+
extern "C" {
2636+
pub fn zend_throw_exception_object(exception: *mut zval);
2637+
}
2638+
extern "C" {
2639+
pub fn zend_do_implement_interface(ce: *mut zend_class_entry, iface: *mut zend_class_entry);
2640+
}
2641+
extern "C" {
2642+
pub static mut zend_ce_traversable: *mut zend_class_entry;
2643+
}
2644+
extern "C" {
2645+
pub static mut zend_ce_aggregate: *mut zend_class_entry;
2646+
}
2647+
extern "C" {
2648+
pub static mut zend_ce_iterator: *mut zend_class_entry;
2649+
}
2650+
extern "C" {
2651+
pub static mut zend_ce_arrayaccess: *mut zend_class_entry;
2652+
}
2653+
extern "C" {
2654+
pub static mut zend_ce_serializable: *mut zend_class_entry;
2655+
}
2656+
extern "C" {
2657+
pub static mut zend_ce_countable: *mut zend_class_entry;
2658+
}
2659+
extern "C" {
2660+
pub static mut zend_ce_stringable: *mut zend_class_entry;
2661+
}

src/builders/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
mod class;
55
mod function;
66
mod module;
7+
#[cfg(feature = "embed")]
8+
mod sapi;
79

810
pub use class::ClassBuilder;
911
pub use function::FunctionBuilder;
1012
pub use module::ModuleBuilder;
13+
#[cfg(feature = "embed")]
14+
pub use sapi::SapiBuilder;

src/builders/sapi.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::ffi::sapi_header_struct;
2+
use crate::{embed::SapiModule, error::Result};
3+
4+
use std::ffi::{c_char, c_void};
5+
use std::{ffi::CString, ptr};
6+
7+
pub struct SapiBuilder {
8+
name: String,
9+
pretty_name: String,
10+
module: SapiModule,
11+
}
12+
13+
impl SapiBuilder {
14+
pub fn new<T: Into<String>, U: Into<String>>(name: T, pretty_name: U) -> Self {
15+
Self {
16+
name: name.into(),
17+
pretty_name: pretty_name.into(),
18+
module: SapiModule {
19+
name: ptr::null_mut(),
20+
pretty_name: ptr::null_mut(),
21+
startup: None,
22+
shutdown: None,
23+
activate: None,
24+
deactivate: None,
25+
ub_write: None,
26+
flush: None,
27+
get_stat: None,
28+
getenv: None,
29+
sapi_error: None,
30+
header_handler: None,
31+
send_headers: None,
32+
send_header: None,
33+
read_post: None,
34+
read_cookies: None,
35+
register_server_variables: None,
36+
log_message: None,
37+
get_request_time: None,
38+
terminate_process: None,
39+
php_ini_path_override: ptr::null_mut(),
40+
default_post_reader: None,
41+
treat_data: None,
42+
executable_location: ptr::null_mut(),
43+
php_ini_ignore: 0,
44+
php_ini_ignore_cwd: 0,
45+
get_fd: None,
46+
force_http_10: None,
47+
get_target_uid: None,
48+
get_target_gid: None,
49+
input_filter: None,
50+
ini_defaults: None,
51+
phpinfo_as_text: 0,
52+
ini_entries: ptr::null_mut(),
53+
additional_functions: ptr::null(),
54+
input_filter_init: None,
55+
},
56+
}
57+
}
58+
59+
pub fn ub_write_function(mut self, func: SapiUbWriteFunc) -> Self {
60+
self.module.ub_write = Some(func);
61+
self
62+
}
63+
64+
/// Sets the send header function for this SAPI
65+
///
66+
/// # Arguments
67+
///
68+
/// * `func` - The function to be called on shutdown.
69+
pub fn send_header_function(mut self, func: SapiSendHeaderFunc) -> Self {
70+
self.module.send_header = Some(func);
71+
self
72+
}
73+
74+
/// Builds the extension and returns a `SapiModule`.
75+
///
76+
/// Returns a result containing the sapi module if successful.
77+
pub fn build(mut self) -> Result<SapiModule> {
78+
self.module.name = CString::new(self.name)?.into_raw();
79+
self.module.pretty_name = CString::new(self.pretty_name)?.into_raw();
80+
81+
if self.module.send_header.is_none() {
82+
self.module.send_header = Some(dummy_send_header);
83+
}
84+
85+
Ok(self.module)
86+
}
87+
}
88+
89+
/// A function to be called when PHP send a header
90+
pub type SapiSendHeaderFunc =
91+
extern "C" fn(header: *mut sapi_header_struct, server_context: *mut c_void);
92+
93+
/// A function to be called when PHP write to the output buffer
94+
pub type SapiUbWriteFunc = extern "C" fn(str: *const c_char, str_length: usize) -> usize;
95+
96+
extern "C" fn dummy_send_header(_header: *mut sapi_header_struct, _server_context: *mut c_void) {}

0 commit comments

Comments
 (0)