-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path_pyhp.c
159 lines (127 loc) · 3.79 KB
/
_pyhp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
155
156
157
158
159
#include <Python.h>
#include <sapi/embed/php_embed.h>
#include "python_object_proxy.h"
#include "translate_python_value.h"
/* Getting in bed with the devil, try 1. */
/* Global reference count on the PHP environment. */
static int env_refcount = 0;
/* Global variables to capture stdout from the embedded PHP interpreter. */
static char *stdout_buf = NULL;
static size_t stdout_buf_len;
static int
pyhp_set_php_vars(PyObject *d)
{
zval *var;
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(d, &pos, &key, &value)) {
if (! PyString_Check(key)) {
PyErr_SetString(PyExc_ValueError, "Unsupported key type");
return -1;
}
if ((var = pyhp_translate_python_value(value)) == NULL)
return -1;
ZEND_SET_SYMBOL(EG(active_symbol_table), PyString_AS_STRING(key), var);
}
return 0;
}
static PyObject *
pyhp_evaluate_or_execute(int mode, PyObject *self, PyObject *args)
{
char *script, *tmp_buf;
size_t tmp_buf_len;
int zend_ret = 0;
PyObject *d, *rv;
zend_file_handle file_handle;
#ifdef ZTS
void ***tsrm_ls;
#endif
if (!PyArg_ParseTuple(args, "sO!", &script, &PyDict_Type, &d))
return NULL;
/* Prepare stdout buffer. */
tmp_buf = stdout_buf;
tmp_buf_len = stdout_buf_len;
stdout_buf = malloc(1);
if (stdout_buf == NULL) {
PyErr_NoMemory();
return NULL;
}
stdout_buf[0] = 0;
stdout_buf_len = 0;
if (env_refcount++ == 0) {
php_embed_init(0, NULL PTSRMLS_CC);
pyhp_init_python_object_proxy();
}
zend_first_try {
/* Set PHP variables. */
if (pyhp_set_php_vars(d)) {
if (stdout_buf != NULL)
free(stdout_buf);
return NULL;
}
/* Evaluate PHP script. */
if (mode == 0) {
zend_ret = zend_eval_string(script, NULL, "" TSRMLS_CC);
} else {
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = script;
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
zend_ret = php_execute_script( &file_handle TSRMLS_CC );
}
} zend_catch {
} zend_end_try();
if (--env_refcount == 0) {
php_embed_shutdown(TSRMLS_C);
}
/* Create return value from stdout buffer. */
if (stdout_buf == NULL) {
rv = NULL;
} else {
/* If error occurs, rv will be NULL. */
if (zend_ret == FAILURE) {
PyErr_SetString(PyExc_RuntimeError, "PHP script failed to execute");
rv = NULL;
} else {
rv = Py_BuildValue("s", stdout_buf);
}
free(stdout_buf);
}
stdout_buf = tmp_buf;
stdout_buf_len = tmp_buf_len;
return rv;
}
static PyObject *
pyhp_evaluate(PyObject *self, PyObject *args) {
return pyhp_evaluate_or_execute(0, self, args);
}
static PyObject *
pyhp_execute(PyObject *self, PyObject *args) {
return pyhp_evaluate_or_execute(1, self, args);
}
static PyMethodDef PyhpMethods[] = {
{"evaluate", pyhp_evaluate, METH_VARARGS,
"Evaluate PHP script."},
{"execute", pyhp_execute, METH_VARARGS,
"Execute PHP script."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static int embed_ub_write(const char *str, unsigned int str_length TSRMLS_DC) {
if(str_length > 0) {
stdout_buf = realloc(stdout_buf, stdout_buf_len + str_length + 1);
if (stdout_buf == NULL) {
PyErr_NoMemory();
return 0;
}
memcpy(stdout_buf + stdout_buf_len, str, str_length);
stdout_buf_len += str_length;
stdout_buf[stdout_buf_len] = 0;
}
return str_length;
}
PyMODINIT_FUNC
init_pyhp(void)
{
(void) Py_InitModule("_pyhp", PyhpMethods);
php_embed_module.ub_write = embed_ub_write;
}