1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Kristian Koehntopp <kris@koehntopp.de> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* {{{ includes & prototypes */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_streams.h"
27
28 #if HAVE_LIBRECODE
29
30 /* For recode 3.5 */
31 #if HAVE_BROKEN_RECODE
32 extern char *program_name;
33 char *program_name = "php";
34 #endif
35
36 #ifdef HAVE_STDBOOL_H
37 # include <stdbool.h>
38 #else
39 typedef enum {false = 0, true = 1} bool;
40 #endif
41
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <unistd.h>
45 #include <recode.h>
46
47 #include "php_recode.h"
48 #include "ext/standard/info.h"
49 #include "ext/standard/file.h"
50 #include "ext/standard/php_string.h"
51
52 /* }}} */
53
54 ZEND_BEGIN_MODULE_GLOBALS(recode)
55 RECODE_OUTER outer;
56 ZEND_END_MODULE_GLOBALS(recode)
57
58 #ifdef ZTS
59 # define ReSG(v) TSRMG(recode_globals_id, zend_recode_globals *, v)
60 #else
61 # define ReSG(v) (recode_globals.v)
62 #endif
63
64 ZEND_DECLARE_MODULE_GLOBALS(recode)
65 static PHP_GINIT_FUNCTION(recode);
66
67 /* {{{ arginfo */
68 ZEND_BEGIN_ARG_INFO_EX(arginfo_recode_string, 0, 0, 2)
69 ZEND_ARG_INFO(0, request)
70 ZEND_ARG_INFO(0, str)
71 ZEND_END_ARG_INFO()
72
73 ZEND_BEGIN_ARG_INFO_EX(arginfo_recode_file, 0, 0, 3)
74 ZEND_ARG_INFO(0, request)
75 ZEND_ARG_INFO(0, input)
76 ZEND_ARG_INFO(0, output)
77 ZEND_END_ARG_INFO()
78 /* }}} */
79
80 /* {{{ module stuff */
81 static const zend_function_entry php_recode_functions[] = {
82 PHP_FE(recode_string, arginfo_recode_string)
83 PHP_FE(recode_file, arginfo_recode_file)
84 PHP_FALIAS(recode, recode_string, arginfo_recode_string)
85 PHP_FE_END
86 }; /* }}} */
87
88 zend_module_entry recode_module_entry = {
89 STANDARD_MODULE_HEADER,
90 "recode",
91 php_recode_functions,
92 PHP_MINIT(recode),
93 PHP_MSHUTDOWN(recode),
94 NULL,
95 NULL,
96 PHP_MINFO(recode),
97 PHP_RECODE_VERSION,
98 PHP_MODULE_GLOBALS(recode),
99 PHP_GINIT(recode),
100 NULL,
101 NULL,
102 STANDARD_MODULE_PROPERTIES_EX
103 };
104
105 #ifdef COMPILE_DL_RECODE
106 ZEND_GET_MODULE(recode)
107 #endif
108
PHP_GINIT_FUNCTION(recode)109 static PHP_GINIT_FUNCTION(recode)
110 {
111 recode_globals->outer = NULL;
112 }
113
PHP_MINIT_FUNCTION(recode)114 PHP_MINIT_FUNCTION(recode)
115 {
116 ReSG(outer) = recode_new_outer(false);
117 if (ReSG(outer) == NULL) {
118 return FAILURE;
119 }
120
121 return SUCCESS;
122 }
123
PHP_MSHUTDOWN_FUNCTION(recode)124 PHP_MSHUTDOWN_FUNCTION(recode)
125 {
126 if (ReSG(outer)) {
127 recode_delete_outer(ReSG(outer));
128 }
129 return SUCCESS;
130 }
131
PHP_MINFO_FUNCTION(recode)132 PHP_MINFO_FUNCTION(recode)
133 {
134 php_info_print_table_start();
135 php_info_print_table_row(2, "Recode Support", "enabled");
136 php_info_print_table_end();
137 }
138
139 /* {{{ proto string recode_string(string request, string str)
140 Recode string str according to request string */
PHP_FUNCTION(recode_string)141 PHP_FUNCTION(recode_string)
142 {
143 RECODE_REQUEST request = NULL;
144 char *r = NULL;
145 size_t r_len = 0, r_alen = 0;
146 size_t req_len, str_len;
147 char *req, *str;
148
149 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &req, &req_len, &str, &str_len) == FAILURE) {
150 return;
151 }
152
153 request = recode_new_request(ReSG(outer));
154
155 if (request == NULL) {
156 php_error_docref(NULL, E_WARNING, "Cannot allocate request structure");
157 RETURN_FALSE;
158 }
159
160 if (!recode_scan_request(request, req)) {
161 php_error_docref(NULL, E_WARNING, "Illegal recode request '%s'", req);
162 goto error_exit;
163 }
164
165 recode_buffer_to_buffer(request, str, str_len, &r, &r_len, &r_alen);
166 if (!r) {
167 php_error_docref(NULL, E_WARNING, "Recoding failed.");
168 error_exit:
169 RETVAL_FALSE;
170 } else {
171 RETVAL_STRINGL(r, r_len);
172 free(r);
173 }
174
175 recode_delete_request(request);
176
177 return;
178 }
179 /* }}} */
180
181 /* {{{ proto bool recode_file(string request, resource input, resource output)
182 Recode file input into file output according to request */
PHP_FUNCTION(recode_file)183 PHP_FUNCTION(recode_file)
184 {
185 RECODE_REQUEST request = NULL;
186 char *req;
187 size_t req_len;
188 zval *input, *output;
189 php_stream *instream, *outstream;
190 FILE *in_fp, *out_fp;
191
192 if (zend_parse_parameters(ZEND_NUM_ARGS(), "srr", &req, &req_len, &input, &output) == FAILURE) {
193 return;
194 }
195
196 php_stream_from_zval(instream, input);
197 php_stream_from_zval(outstream, output);
198
199 if (FAILURE == php_stream_cast(instream, PHP_STREAM_AS_STDIO, (void**)&in_fp, REPORT_ERRORS)) {
200 RETURN_FALSE;
201 }
202
203 if (FAILURE == php_stream_cast(outstream, PHP_STREAM_AS_STDIO, (void**)&out_fp, REPORT_ERRORS)) {
204 RETURN_FALSE;
205 }
206
207 request = recode_new_request(ReSG(outer));
208 if (request == NULL) {
209 php_error_docref(NULL, E_WARNING, "Cannot allocate request structure");
210 RETURN_FALSE;
211 }
212
213 if (!recode_scan_request(request, req)) {
214 php_error_docref(NULL, E_WARNING, "Illegal recode request '%s'", req);
215 goto error_exit;
216 }
217
218 if (!recode_file_to_file(request, in_fp, out_fp)) {
219 php_error_docref(NULL, E_WARNING, "Recoding failed.");
220 goto error_exit;
221 }
222
223 recode_delete_request(request);
224 RETURN_TRUE;
225
226 error_exit:
227 recode_delete_request(request);
228 RETURN_FALSE;
229 }
230 /* }}} */
231
232 #endif
233
234 /*
235 * Local variables:
236 * tab-width: 4
237 * c-basic-offset: 4
238 * End:
239 */
240