php_embed 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/ext/php_embed/convert.c +222 -231
- data/ext/php_embed/convert.h +5 -9
- data/ext/php_embed/extconf.rb +107 -4
- data/ext/php_embed/php.c +195 -205
- data/ext/php_embed/php.ini +1861 -0
- data/ext/php_embed/php_embed.h +21 -0
- data/ext/php_embed/value.c +191 -130
- data/ext/php_embed/value.h +2 -5
- data/lib/php_embed/version.rb +1 -1
- data/spec/require.php +5 -0
- data/spec/value_spec.rb +22 -0
- metadata +6 -2
data/ext/php_embed/convert.h
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
#ifndef
|
2
|
-
#define
|
1
|
+
#ifndef PHP_EMBED_CONVERT_HEADER
|
2
|
+
#define PHP_EMBED_CONVERT_HEADER
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
VALUE zval_to_hash(zval* zv);
|
9
|
-
VALUE zval_to_array(zval* zv);
|
4
|
+
VALUE zval_to_hash(zval *zv);
|
5
|
+
VALUE zval_to_array(zval *zv);
|
10
6
|
|
11
7
|
VALUE convert_value_to_php_string(VALUE v);
|
12
|
-
zval*
|
8
|
+
zval *value_to_zval(VALUE v);
|
13
9
|
|
14
10
|
#endif
|
data/ext/php_embed/extconf.rb
CHANGED
@@ -1,10 +1,113 @@
|
|
1
|
-
require
|
1
|
+
require 'mkmf'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
PHP_VERSION = '5.4.10'
|
9
|
+
PHP_SRC_URL = "http://php.net/distributions/php-#{PHP_VERSION}.tar.bz2"
|
10
|
+
|
11
|
+
def download_src(destfile)
|
12
|
+
print "download php source\n"
|
13
|
+
FileUtils.copy_stream(open(PHP_SRC_URL), destfile)
|
14
|
+
end
|
15
|
+
|
16
|
+
def decompression(archive)
|
17
|
+
print "decompression php source\n"
|
18
|
+
`tar xf #{archive}`
|
19
|
+
abort 'tar failure' if $?.exitstatus != 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def configure(prefix)
|
23
|
+
print "configure\n"
|
24
|
+
|
25
|
+
opts = %w(
|
26
|
+
--disable-cgi
|
27
|
+
--without-pear
|
28
|
+
--enable-sockets
|
29
|
+
--enable-ftp
|
30
|
+
--with-mysql=mysqlnd
|
31
|
+
--with-mysqli=mysqlnd
|
32
|
+
--with-pdo-mysql=mysqlnd
|
33
|
+
--enable-pcntl
|
34
|
+
--enable-mbstring
|
35
|
+
--disable-debug
|
36
|
+
--disable-libxml
|
37
|
+
--disable-dom
|
38
|
+
--disable-simplexml
|
39
|
+
--disable-xml
|
40
|
+
--disable-xmlreader
|
41
|
+
--disable-xmlwriter
|
42
|
+
--disable-phar
|
43
|
+
--enable-embed
|
44
|
+
).join(' ')
|
45
|
+
opts += " --prefix=#{prefix}"
|
46
|
+
opts += " --with-libdir=lib64" if `uname -p`.chomp == 'x86_64'
|
47
|
+
|
48
|
+
`./configure #{opts}`
|
49
|
+
abort 'configure failure' if $?.exitstatus != 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def make_and_install
|
53
|
+
print "make\n"
|
54
|
+
`make`
|
55
|
+
abort 'make failure' if $?.exitstatus != 0
|
56
|
+
|
57
|
+
print "make install\n"
|
58
|
+
`make install`
|
59
|
+
abort 'make install failure' if $?.exitstatus != 0
|
60
|
+
end
|
61
|
+
|
62
|
+
def prepare_compile_php(prefix)
|
63
|
+
abort 'need tar' unless find_executable 'tar'
|
64
|
+
abort 'need make' unless find_executable 'make'
|
65
|
+
end
|
66
|
+
|
67
|
+
def compile_php(prefix)
|
68
|
+
Dir.mkdir 'src' unless Dir.exists? 'src'
|
69
|
+
Dir.chdir('src') do
|
70
|
+
src_filename = "php-#{PHP_VERSION}.tar.bz2"
|
71
|
+
download_src(src_filename) unless File.exists? src_filename
|
72
|
+
decompression(src_filename)
|
73
|
+
end
|
74
|
+
|
75
|
+
src_dir = "src/php-#{PHP_VERSION}"
|
76
|
+
if !Dir.exists? src_dir
|
77
|
+
abort 'soruce directory not exists'
|
78
|
+
end
|
79
|
+
|
80
|
+
FileUtils.mkpath "#{prefix}/etc/conf.d"
|
81
|
+
|
82
|
+
Dir.chdir(src_dir) do
|
83
|
+
configure(prefix)
|
84
|
+
make_and_install
|
85
|
+
end
|
86
|
+
|
87
|
+
FileUtils.copy 'php.ini', "#{prefix}/lib/"
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
|
2
92
|
|
3
93
|
dir_config('php')
|
4
|
-
|
5
|
-
|
94
|
+
php_config = find_executable('php-config')
|
95
|
+
have_libphp = have_library('php5', 'php_embed_init')
|
96
|
+
|
97
|
+
if !php_config || !have_libphp
|
98
|
+
php_version = arg_config('--compile-php')
|
99
|
+
abort 'libphp5 or php-config not found: try --compile-php' unless php_version
|
100
|
+
|
101
|
+
prefix = Pathname.getwd.join('php')
|
102
|
+
|
103
|
+
prepare_compile_php(prefix.to_s)
|
104
|
+
compile_php(prefix.to_s)
|
105
|
+
|
106
|
+
php_config = prefix.join('bin', 'php-config').to_s
|
107
|
+
find_library('php5', 'php_embed_init', prefix.join('lib').to_s)
|
6
108
|
end
|
7
109
|
|
8
|
-
$CPPFLAGS =
|
110
|
+
$CPPFLAGS = `#{php_config} --includes`.chomp + ' ' + $CPPFLAGS
|
9
111
|
|
10
112
|
create_makefile("php_embed/php")
|
113
|
+
|
data/ext/php_embed/php.c
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
#include <stdio.h>
|
2
|
-
#include <ruby.h>
|
3
2
|
#include <sapi/embed/php_embed.h>
|
4
|
-
#include "
|
5
|
-
#include "convert.h"
|
3
|
+
#include "php_embed.h"
|
6
4
|
|
7
5
|
static VALUE callback_output = Qnil;
|
8
6
|
static VALUE callback_error = Qnil;
|
9
7
|
|
8
|
+
void ***tsrm_ls;
|
10
9
|
|
11
10
|
VALUE mPhpEmbed;
|
12
11
|
|
@@ -16,19 +15,21 @@ VALUE rb_ePhpEmbedMissingError;
|
|
16
15
|
|
17
16
|
static int php_ub_write(const char *str, unsigned int str_length TSRMLS_DC)
|
18
17
|
{
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
if (!NIL_P(callback_output)) {
|
19
|
+
VALUE args = rb_ary_new();
|
20
|
+
rb_ary_push(args, rb_str_new(str, str_length));
|
21
|
+
rb_proc_call(callback_output, args);
|
22
|
+
}
|
23
|
+
return str_length;
|
25
24
|
}
|
26
|
-
|
25
|
+
|
26
|
+
static void php_log_message(char *message TSRMLS_DC)
|
27
27
|
{
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
if (!NIL_P(callback_error)) {
|
29
|
+
rb_proc_call(callback_error, rb_ary_new3(1, rb_str_new(message, strlen(message))));
|
30
|
+
}
|
31
31
|
}
|
32
|
+
|
32
33
|
static void php_sapi_error(int type, const char *fmt, ...)
|
33
34
|
{
|
34
35
|
va_list va;
|
@@ -38,243 +39,232 @@ static void php_sapi_error(int type, const char *fmt, ...)
|
|
38
39
|
va_end(va);
|
39
40
|
}
|
40
41
|
|
41
|
-
int eval_php_code(char*
|
42
|
-
|
42
|
+
int eval_php_code(char *code) {
|
43
|
+
int ret = 0;
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
zend_try {
|
46
|
+
ret = zend_eval_string(code, NULL, (char *)"" TSRMLS_CC);
|
47
|
+
} zend_catch {
|
47
48
|
|
48
|
-
|
49
|
+
} zend_end_try();
|
49
50
|
|
50
|
-
|
51
|
+
return ret == FAILURE;
|
51
52
|
}
|
52
53
|
|
53
|
-
int eval_and_return_php_code(char*
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
zend_try {
|
58
|
-
if (zend_eval_string(code, &retval, (char*)"" TSRMLS_CC) == FAILURE) {
|
59
|
-
err = 1;
|
60
|
-
} else {
|
61
|
-
//*return_value = zval_to_value(&retval);
|
62
|
-
*return_value = new_php_embed_value(&retval);
|
63
|
-
zval_dtor(&retval);
|
64
|
-
}
|
54
|
+
int eval_and_return_php_code(char *code, VALUE *return_value) {
|
55
|
+
int retval = SUCCESS;
|
56
|
+
zval evaluated;
|
65
57
|
|
66
|
-
|
58
|
+
zend_try {
|
59
|
+
if (zend_eval_string(code, &evaluated, (char *)"" TSRMLS_CC) == FAILURE) {
|
60
|
+
retval = FAILURE;
|
61
|
+
} else {
|
62
|
+
*return_value = new_php_embed_value(&evaluated);
|
63
|
+
zval_dtor(&evaluated);
|
64
|
+
}
|
65
|
+
} zend_catch {
|
67
66
|
|
68
|
-
|
67
|
+
} zend_end_try();
|
69
68
|
|
70
|
-
|
69
|
+
return retval;
|
71
70
|
}
|
72
71
|
|
73
72
|
VALUE php_eval(VALUE self, VALUE code) {
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
if (eval_php_code(StringValuePtr(code))) {
|
74
|
+
rb_raise(rb_ePhpEmbedSyntaxError, "invalid code");
|
75
|
+
}
|
77
76
|
|
78
|
-
|
77
|
+
return Qnil;
|
79
78
|
}
|
80
79
|
|
81
80
|
|
82
|
-
zend_function*
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
zend_function *php_find_function(char *name) {
|
82
|
+
char *lcname;
|
83
|
+
int name_len;
|
84
|
+
int found;
|
85
|
+
zend_function *func;
|
87
86
|
|
88
|
-
|
89
|
-
|
87
|
+
name_len = strlen(name);
|
88
|
+
lcname = zend_str_tolower_dup(name, name_len);
|
90
89
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
name = lcname;
|
91
|
+
if (lcname[0] == '\\') {
|
92
|
+
name = &lcname[1];
|
93
|
+
name_len--;
|
94
|
+
}
|
96
95
|
|
97
|
-
|
98
|
-
|
96
|
+
found = (zend_hash_find(EG(function_table), name, name_len+1, (void**)&func) == SUCCESS);
|
97
|
+
efree(lcname);
|
99
98
|
|
100
|
-
|
101
|
-
|
102
|
-
|
99
|
+
if (found) {
|
100
|
+
return func;
|
101
|
+
}
|
103
102
|
|
104
|
-
|
103
|
+
return NULL;
|
105
104
|
}
|
106
105
|
|
106
|
+
VALUE php_call(int argc, VALUE *argv, VALUE self) {
|
107
|
+
VALUE name, args, retval;
|
108
|
+
zend_function *func;
|
109
|
+
int call_result, i;
|
110
|
+
zval *retval_ptr;
|
111
|
+
zend_fcall_info fci;
|
112
|
+
zend_fcall_info_cache fcc;
|
113
|
+
zval ***call_args;
|
114
|
+
zval **zval_array;
|
115
|
+
|
116
|
+
rb_scan_args(argc, argv, "1*", &name, &args);
|
117
|
+
|
118
|
+
if (TYPE(name) == T_SYMBOL) {
|
119
|
+
name = rb_sym_to_s(name);
|
120
|
+
}
|
107
121
|
|
122
|
+
if (TYPE(name) != T_STRING) {
|
123
|
+
rb_raise(rb_eArgError, "invalid function name");
|
124
|
+
}
|
108
125
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
fcc.calling_scope = EG(scope);
|
155
|
-
fcc.called_scope = NULL;
|
156
|
-
fcc.object_ptr = NULL;
|
157
|
-
|
158
|
-
call_result = zend_call_function(&fci, &fcc TSRMLS_CC);
|
159
|
-
retval = new_php_embed_value(retval_ptr);
|
160
|
-
|
161
|
-
free(call_args);
|
162
|
-
|
163
|
-
for(i=0; i<argc-1; ++i) {
|
164
|
-
zval_dtor(zval_array[i]);
|
165
|
-
FREE_ZVAL(zval_array[i]);
|
166
|
-
}
|
167
|
-
free(zval_array);
|
168
|
-
|
169
|
-
if (FAILURE == call_result) {
|
170
|
-
rb_raise(rb_ePhpEmbedStanderdError, "function call fairure");
|
171
|
-
}
|
172
|
-
|
173
|
-
return retval;
|
126
|
+
|
127
|
+
func = php_find_function(StringValueCStr(name));
|
128
|
+
if (!func) {
|
129
|
+
rb_raise(rb_ePhpEmbedMissingError, "function not found");
|
130
|
+
}
|
131
|
+
|
132
|
+
zval_array = (zval **)malloc(sizeof(zval *) * argc-1);
|
133
|
+
call_args = (zval ***)malloc(sizeof(zval **) * argc-1);
|
134
|
+
for(i=0; i<argc-1; ++i) {
|
135
|
+
zval_array[i] = value_to_zval(RARRAY_PTR(args)[i]);
|
136
|
+
call_args[i] = &zval_array[i];
|
137
|
+
}
|
138
|
+
|
139
|
+
fci.size = sizeof(fci);
|
140
|
+
fci.function_table = NULL;
|
141
|
+
fci.function_name = NULL;
|
142
|
+
fci.symbol_table = NULL;
|
143
|
+
fci.object_ptr = NULL;
|
144
|
+
fci.retval_ptr_ptr = &retval_ptr;
|
145
|
+
fci.param_count = argc-1;
|
146
|
+
fci.params = call_args;
|
147
|
+
fci.no_separation = 1;
|
148
|
+
|
149
|
+
fcc.initialized = 1;
|
150
|
+
fcc.function_handler = func;
|
151
|
+
fcc.calling_scope = EG(scope);
|
152
|
+
fcc.called_scope = NULL;
|
153
|
+
fcc.object_ptr = NULL;
|
154
|
+
|
155
|
+
call_result = zend_call_function(&fci, &fcc TSRMLS_CC);
|
156
|
+
retval = new_php_embed_value(retval_ptr);
|
157
|
+
|
158
|
+
free(call_args);
|
159
|
+
|
160
|
+
for(i=0; i<argc-1; ++i) {
|
161
|
+
zval_dtor(zval_array[i]);
|
162
|
+
FREE_ZVAL(zval_array[i]);
|
163
|
+
}
|
164
|
+
free(zval_array);
|
165
|
+
|
166
|
+
if (call_result == FAILURE) {
|
167
|
+
rb_raise(rb_ePhpEmbedStanderdError, "function call fairure");
|
168
|
+
}
|
169
|
+
|
170
|
+
return retval;
|
174
171
|
}
|
175
172
|
|
176
173
|
VALUE php_require(VALUE self, VALUE file) {
|
177
|
-
|
178
|
-
|
174
|
+
VALUE retval = Qtrue;
|
175
|
+
zend_file_handle handle;
|
179
176
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
177
|
+
if (TYPE(file) == T_STRING) {
|
178
|
+
rb_raise(rb_eArgError, "file must be string");
|
179
|
+
return Qnil;
|
180
|
+
}
|
181
|
+
|
182
|
+
handle.type = ZEND_HANDLE_FILENAME;
|
183
|
+
handle.filename = RSTRING_PTR(file);
|
184
|
+
handle.opened_path = NULL;
|
185
|
+
handle.free_filename = 0;
|
186
|
+
|
187
|
+
zend_try {
|
188
|
+
zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, &handle);
|
189
|
+
} zend_catch {
|
190
|
+
retval = Qfalse;
|
191
|
+
} zend_end_try();
|
192
|
+
|
193
|
+
return retval;
|
197
194
|
}
|
198
195
|
|
199
196
|
VALUE php_fetch_variable(VALUE self, VALUE name) {
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
197
|
+
zval *data = NULL;
|
198
|
+
if (zend_hash_find(&EG(symbol_table), StringValuePtr(name), RSTRING_LEN(name), (void **)&data) == FAILURE) {
|
199
|
+
/* Name not found in $GLOBALS */
|
200
|
+
}
|
201
|
+
if (data == NULL) {
|
202
|
+
/* Value is NULL (not possible for symbol_table?) */
|
203
|
+
}
|
204
|
+
|
205
|
+
return Qnil;
|
209
206
|
}
|
210
207
|
|
211
208
|
VALUE php_set_output_handler(VALUE self, VALUE callback) {
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
209
|
+
if (rb_obj_is_proc(callback)) {
|
210
|
+
callback_output = callback;
|
211
|
+
} else {
|
212
|
+
rb_raise(rb_eArgError, "callback must be proc");
|
213
|
+
}
|
214
|
+
|
215
|
+
return Qnil;
|
219
216
|
}
|
220
217
|
|
221
218
|
VALUE php_set_error_handler(VALUE self, VALUE callback) {
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
219
|
+
if (rb_obj_is_proc(callback)) {
|
220
|
+
callback_error = callback;
|
221
|
+
} else {
|
222
|
+
rb_raise(rb_eArgError, "callback must be proc");
|
223
|
+
}
|
224
|
+
|
225
|
+
return Qnil;
|
229
226
|
}
|
230
227
|
|
231
228
|
void initialize_php_embed() {
|
232
|
-
|
233
|
-
|
234
|
-
|
229
|
+
const char *argv[2] = {"ruby", NULL};
|
230
|
+
php_embed_init(1, (char **)argv PTSRMLS_CC);
|
231
|
+
EG(bailout)=NULL;
|
235
232
|
}
|
236
233
|
|
237
234
|
void shutdown_php_embed() {
|
238
|
-
|
235
|
+
php_embed_shutdown(TSRMLS_C);
|
239
236
|
}
|
240
237
|
|
241
238
|
|
242
239
|
Init_php() {
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
, (char*)"1", sizeof("1")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
|
274
|
-
} zend_catch {
|
275
|
-
} zend_end_try();
|
276
|
-
*/
|
240
|
+
mPhpEmbed = rb_define_module("PhpEmbed");
|
241
|
+
init_php_value();
|
242
|
+
|
243
|
+
rb_define_singleton_method(mPhpEmbed, "eval", php_eval, 1);
|
244
|
+
rb_define_singleton_method(mPhpEmbed, "call", php_call, -1);
|
245
|
+
rb_define_singleton_method(mPhpEmbed, "require", php_require, 1);
|
246
|
+
rb_define_singleton_method(mPhpEmbed, "fetchVariable", php_fetch_variable, 1);
|
247
|
+
rb_define_singleton_method(mPhpEmbed, "setOutputHandler", php_set_output_handler, 1);
|
248
|
+
rb_define_singleton_method(mPhpEmbed, "setErrorHandler", php_set_error_handler, 1);
|
249
|
+
|
250
|
+
php_embed_module.ub_write = php_ub_write;
|
251
|
+
php_embed_module.log_message = php_log_message;
|
252
|
+
php_embed_module.sapi_error = php_sapi_error;
|
253
|
+
|
254
|
+
initialize_php_embed();
|
255
|
+
atexit(shutdown_php_embed);
|
256
|
+
|
257
|
+
|
258
|
+
rb_ePhpEmbedStanderdError = rb_define_class_under(mPhpEmbed, "StanderdError", rb_eException);
|
259
|
+
rb_ePhpEmbedSyntaxError = rb_define_class_under(mPhpEmbed, "SyntaxError", rb_ePhpEmbedStanderdError);
|
260
|
+
rb_ePhpEmbedMissingError = rb_define_class_under(mPhpEmbed, "MissingError", rb_ePhpEmbedStanderdError);
|
261
|
+
/*
|
262
|
+
zend_try {
|
263
|
+
zend_alter_ini_entry((char*)"display_errors", sizeof("display_errors")
|
264
|
+
, (char*)"0", sizeof("0")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
|
265
|
+
zend_alter_ini_entry((char*)"log_errors", sizeof("log_errors")
|
266
|
+
, (char*)"1", sizeof("1")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
|
267
|
+
} zend_catch {
|
268
|
+
} zend_end_try();
|
269
|
+
*/
|
277
270
|
}
|
278
|
-
|
279
|
-
|
280
|
-
|