8
8
* from an ~user directory to be able to make changes to the globalle running
9
9
* apache process, and for example make changes to catch data from other websites
10
10
* running on the same host.
11
- *
12
- * However, people who are in a position to write C++ and deploy code however,
11
+ *
12
+ * However, people who are in a position to write C++ and deploy code however,
13
13
* already _ARE_ in a position to do dangerous things. For them we do not want
14
14
* these safety checks. In fact, we want to offer raw access, so that they can
15
15
* open modules - no matter what. So we had to make our own copy of the dl()
16
16
* function, and because we're here in C++ context, we do it a little nicer
17
17
* than the original C++ code. This module class is a utility class used by
18
18
* our own dl() implementation.
19
- *
19
+ *
20
20
* @author Emiel Bruijntjes <[email protected] >
21
21
* @copyright 2015 Copernica BV
22
22
*/
25
25
* Set up namespace
26
26
*/
27
27
namespace Php {
28
-
28
+
29
29
/* *
30
30
* Class definition
31
31
*/
@@ -37,13 +37,13 @@ class Module
37
37
* @var void*
38
38
*/
39
39
void *_handle;
40
-
40
+
41
41
/* *
42
42
* The module entry
43
43
* @var zend_module_entry
44
44
*/
45
45
zend_module_entry *_entry = nullptr ;
46
-
46
+
47
47
48
48
/* *
49
49
* Internal helper class with persistent modules
@@ -56,32 +56,32 @@ class Module
56
56
* @var std::set
57
57
*/
58
58
std::set<void *> _handles;
59
-
59
+
60
60
public:
61
61
/* *
62
62
* Constructor
63
63
*/
64
64
Persistent () {}
65
-
65
+
66
66
/* *
67
67
* Destructor
68
68
*/
69
- virtual ~Persistent ()
69
+ virtual ~Persistent ()
70
70
{
71
71
// remove all handles
72
72
while (!_handles.empty ())
73
73
{
74
74
// get first handle
75
75
auto iter = _handles.begin ();
76
-
76
+
77
77
// remove the handle
78
78
DL_UNLOAD (*iter);
79
-
79
+
80
80
// remove from set
81
81
_handles.erase (iter);
82
82
}
83
83
}
84
-
84
+
85
85
/* *
86
86
* Check whether a handle is already persistently opened
87
87
* @param handle
@@ -91,7 +91,7 @@ class Module
91
91
{
92
92
return _handles.find (handle) != _handles.end ();
93
93
}
94
-
94
+
95
95
/* *
96
96
* Add a library persistently
97
97
* @param module
@@ -112,39 +112,39 @@ class Module
112
112
public:
113
113
/* *
114
114
* Constructor
115
- *
115
+ *
116
116
* A module can be loaded persistently. This means that the variables in
117
117
* the module will keep in scope for as long as Apache runs, even though
118
118
* the extension is not active in other page views
119
- *
119
+ *
120
120
* @param module Name of the module
121
121
* @param persistent Should it be loaded persistently
122
122
*/
123
123
Module (const char *module, bool persistent)
124
124
{
125
125
// the path we're going to load
126
126
ExtensionPath path (module);
127
-
127
+
128
128
// load the module
129
129
_handle = DL_LOAD (path);
130
-
130
+
131
131
// handle should be valid
132
132
if (!_handle) return ;
133
-
133
+
134
134
// if we have to open it persistently, we open it for a second time so that
135
135
// the refcounter always stays 1 or higher
136
136
if (persistent && !_persistent.contains (_handle)) _persistent.add (module);
137
-
137
+
138
138
// we have to call the get_module() function
139
139
Symbol<zend_module_entry*()> get_module (_handle, " get_module" );
140
-
140
+
141
141
// was the get_module() function found
142
142
if (!get_module) return ;
143
143
144
144
// retrieve the module entry
145
145
_entry = get_module ();
146
146
}
147
-
147
+
148
148
/* *
149
149
* Destructor
150
150
*/
@@ -153,7 +153,7 @@ class Module
153
153
// if the handle is still valid, we have to unload it
154
154
if (_handle) DL_UNLOAD ((DL_HANDLE)_handle);
155
155
}
156
-
156
+
157
157
/* *
158
158
* Check if the module is valid
159
159
* @return bool
@@ -162,14 +162,14 @@ class Module
162
162
{
163
163
// module-entry must exist
164
164
if (!_handle || !_entry) return false ;
165
-
165
+
166
166
// check api compatibility
167
167
if (_entry->zend_api != ZEND_MODULE_API_NO) return false ;
168
-
168
+
169
169
// and other stuff
170
170
return strcmp (_entry->build_id , ZEND_MODULE_BUILD_ID) == 0 ;
171
171
}
172
-
172
+
173
173
/* *
174
174
* Start the module
175
175
* @return bool
@@ -178,22 +178,26 @@ class Module
178
178
{
179
179
// this is not possible if the module is invalid in the first place
180
180
if (!valid ()) return false ;
181
-
181
+
182
182
// the Zend engine sets a number of properties in the entry class, we do that here too
183
183
// note that it would be better to call zend_next_free_module() to find the next module
184
184
// number, but some users complain that this function is not always available
185
185
_entry->type = MODULE_TEMPORARY;
186
186
_entry->module_number = zend_hash_num_elements (&module_registry) + 1 ;
187
187
_entry->handle = _handle;
188
-
188
+
189
189
// @todo does loading an extension even work in a multi-threading setup?
190
-
190
+
191
191
// register the module, this apparently returns a copied entry pointer
192
+ #if PHP_VERSION_ID < 80400
192
193
auto *entry = zend_register_module_ex (_entry);
194
+ #else
195
+ auto *entry = zend_register_module_ex (_entry, MODULE_PERSISTENT);
196
+ #endif
193
197
194
198
// forget the entry, so that a new call to start() will fail too
195
199
_entry = nullptr ;
196
-
200
+
197
201
// leap out on failure
198
202
if (entry == NULL ) return false ;
199
203
@@ -206,18 +210,18 @@ class Module
206
210
// call the startup function
207
211
if (entry->request_startup_func (MODULE_TEMPORARY, entry->module_number ) == FAILURE) return false ;
208
212
}
209
-
213
+
210
214
// all is ok, we can forget about the handle now, so that is won't get destructed
211
215
_handle = nullptr ;
212
216
213
217
// enable full-table-cleanup, because inside the Zend-engine this is done too
214
218
EG (full_tables_cleanup) = 1 ;
215
-
219
+
216
220
// we're ready
217
221
return true ;
218
222
}
219
223
};
220
-
224
+
221
225
/* *
222
226
* End of namespace
223
227
*/
0 commit comments