xref: /PHP-7.3/ext/recode/recode.c (revision c71433a7)
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